xref: /openbmc/linux/drivers/scsi/FlashPoint.c (revision 25985edcedea6396277003854657b5f3cb31a628)
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 {
32d63a4cccSAlexey Dobriyan 	unsigned long 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;
37c823feebSAlexey Dobriyan 	unsigned short si_fw_revision;
38c823feebSAlexey Dobriyan 	unsigned short si_per_targ_init_sync;
39c823feebSAlexey Dobriyan 	unsigned short si_per_targ_fast_nego;
40c823feebSAlexey Dobriyan 	unsigned short si_per_targ_ultra_nego;
41c823feebSAlexey Dobriyan 	unsigned short si_per_targ_no_disc;
42c823feebSAlexey Dobriyan 	unsigned short si_per_targ_wide_nego;
43c823feebSAlexey Dobriyan 	unsigned short si_flags;
44db038cf8SAlexey Dobriyan 	unsigned char si_card_family;
45db038cf8SAlexey Dobriyan 	unsigned char si_bustype;
46db038cf8SAlexey Dobriyan 	unsigned char si_card_model[3];
47db038cf8SAlexey Dobriyan 	unsigned char si_relative_cardnum;
48db038cf8SAlexey Dobriyan 	unsigned char si_reserved[4];
49d63a4cccSAlexey Dobriyan 	unsigned long si_OS_reserved;
50db038cf8SAlexey Dobriyan 	unsigned char si_XlatInfo[4];
51d63a4cccSAlexey Dobriyan 	unsigned long si_reserved2[5];
52d63a4cccSAlexey Dobriyan 	unsigned long 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 
731da177e4SLinus Torvalds #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;
79d63a4cccSAlexey Dobriyan 	unsigned long DataLength;
80d63a4cccSAlexey Dobriyan 	unsigned long 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;
89d63a4cccSAlexey Dobriyan 	unsigned long Reserved2;
90d63a4cccSAlexey Dobriyan 	unsigned long SensePointer;
911da177e4SLinus Torvalds 
921da177e4SLinus Torvalds 	CALL_BK_FN SccbCallback;	/* VOID (*SccbCallback)(); */
93d63a4cccSAlexey Dobriyan 	unsigned long SccbIOPort;	/* Identifies board base port */
94db038cf8SAlexey Dobriyan 	unsigned char SccbStatus;
95db038cf8SAlexey Dobriyan 	unsigned char SCCBRes2;
96c823feebSAlexey Dobriyan 	unsigned short SccbOSFlags;
971da177e4SLinus Torvalds 
98d63a4cccSAlexey Dobriyan 	unsigned long Sccb_XferCnt;	/* actual transfer count */
99d63a4cccSAlexey Dobriyan 	unsigned long Sccb_ATC;
100d63a4cccSAlexey Dobriyan 	unsigned long SccbVirtDataPtr;	/* virtual addr for OS/2 */
101d63a4cccSAlexey Dobriyan 	unsigned long Sccb_res1;
102c823feebSAlexey Dobriyan 	unsigned short Sccb_MGRFlags;
103c823feebSAlexey Dobriyan 	unsigned short 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;
110d63a4cccSAlexey Dobriyan 	unsigned long Sccb_savedATC;
111db038cf8SAlexey Dobriyan 	unsigned char Save_Cdb[6];
112db038cf8SAlexey Dobriyan 	unsigned char Save_CdbLen;
113db038cf8SAlexey Dobriyan 	unsigned char Sccb_XferState;
114d63a4cccSAlexey Dobriyan 	unsigned long 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. */
228d63a4cccSAlexey Dobriyan 	unsigned long niBaseAddr;	/* Port Address of card */
229db038cf8SAlexey Dobriyan 	unsigned char niSysConf;	/* Adapter Configuration byte - Byte 16 of eeprom map */
230db038cf8SAlexey Dobriyan 	unsigned char niScsiConf;	/* SCSI Configuration byte - Byte 17 of eeprom map */
231db038cf8SAlexey Dobriyan 	unsigned char niScamConf;	/* SCAM Configuration byte - Byte 20 of eeprom map */
232db038cf8SAlexey Dobriyan 	unsigned char niAdapId;	/* Host Adapter ID - Byte 24 of eerpom map */
233db038cf8SAlexey Dobriyan 	unsigned char niSyncTbl[MAX_SCSI_TAR / 2];	/* Sync/Wide byte of targets */
234db038cf8SAlexey Dobriyan 	unsigned char niScamTbl[MAX_SCSI_TAR][4];	/* Compressed Scam name string of Targets */
23568d0c1aeSAlexey Dobriyan };
2361da177e4SLinus Torvalds 
2371da177e4SLinus Torvalds #define	MODEL_LT		1
2381da177e4SLinus Torvalds #define	MODEL_DL		2
2391da177e4SLinus Torvalds #define	MODEL_LW		3
2401da177e4SLinus Torvalds #define	MODEL_DW		4
2411da177e4SLinus Torvalds 
24213e6851aSAlexey Dobriyan struct sccb_card {
24369eb2ea4SAlexey Dobriyan 	struct sccb *currentSCCB;
2447f101662SAlexey Dobriyan 	struct sccb_mgr_info *cardInfo;
2451da177e4SLinus Torvalds 
246d63a4cccSAlexey Dobriyan 	unsigned long ioPort;
2471da177e4SLinus Torvalds 
248c823feebSAlexey Dobriyan 	unsigned short cmdCounter;
249db038cf8SAlexey Dobriyan 	unsigned char discQCount;
250db038cf8SAlexey Dobriyan 	unsigned char tagQ_Lst;
251db038cf8SAlexey Dobriyan 	unsigned char cardIndex;
252db038cf8SAlexey Dobriyan 	unsigned char scanIndex;
253db038cf8SAlexey Dobriyan 	unsigned char globalFlags;
254db038cf8SAlexey Dobriyan 	unsigned char ourId;
25568d0c1aeSAlexey Dobriyan 	struct nvram_info *pNvRamInfo;
25669eb2ea4SAlexey Dobriyan 	struct sccb *discQ_Tbl[QUEUE_DEPTH];
2571da177e4SLinus Torvalds 
25813e6851aSAlexey Dobriyan };
2591da177e4SLinus Torvalds 
2601da177e4SLinus Torvalds #define F_TAG_STARTED		0x01
2611da177e4SLinus Torvalds #define F_CONLUN_IO			0x02
2621da177e4SLinus Torvalds #define F_DO_RENEGO			0x04
2631da177e4SLinus Torvalds #define F_NO_FILTER			0x08
2641da177e4SLinus Torvalds #define F_GREEN_PC			0x10
2651da177e4SLinus Torvalds #define F_HOST_XFER_ACT		0x20
2661da177e4SLinus Torvalds #define F_NEW_SCCB_CMD		0x40
2671da177e4SLinus Torvalds #define F_UPDATE_EEPROM		0x80
2681da177e4SLinus Torvalds 
2691da177e4SLinus Torvalds #define  ID_STRING_LENGTH  32
2701da177e4SLinus Torvalds #define  TYPE_CODE0        0x63	/*Level2 Mstr (bits 7-6),  */
2711da177e4SLinus Torvalds 
2721da177e4SLinus Torvalds #define  SLV_TYPE_CODE0    0xA3	/*Priority Bit set (bits 7-6),  */
2731da177e4SLinus Torvalds 
2741da177e4SLinus Torvalds #define  ASSIGN_ID   0x00
2751da177e4SLinus Torvalds #define  SET_P_FLAG  0x01
2761da177e4SLinus Torvalds #define  CFG_CMPLT   0x03
2771da177e4SLinus Torvalds #define  DOM_MSTR    0x0F
2781da177e4SLinus Torvalds #define  SYNC_PTRN   0x1F
2791da177e4SLinus Torvalds 
2801da177e4SLinus Torvalds #define  ID_0_7      0x18
2811da177e4SLinus Torvalds #define  ID_8_F      0x11
2821da177e4SLinus Torvalds #define  MISC_CODE   0x14
2831da177e4SLinus Torvalds #define  CLR_P_FLAG  0x18
2841da177e4SLinus Torvalds 
2851da177e4SLinus Torvalds #define  INIT_SELTD  0x01
2861da177e4SLinus Torvalds #define  LEVEL2_TAR  0x02
2871da177e4SLinus Torvalds 
2885c04a7b8SAlexey Dobriyan enum scam_id_st { ID0, ID1, ID2, ID3, ID4, ID5, ID6, ID7, ID8, ID9, ID10, ID11,
2895c04a7b8SAlexey Dobriyan 	    ID12,
2901da177e4SLinus Torvalds 	ID13, ID14, ID15, ID_UNUSED, ID_UNASSIGNED, ID_ASSIGNED, LEGACY,
2915c04a7b8SAlexey Dobriyan 	CLR_PRIORITY, NO_ID_AVAIL
2925c04a7b8SAlexey Dobriyan };
2931da177e4SLinus Torvalds 
2941da177e4SLinus Torvalds typedef struct SCCBscam_info {
2951da177e4SLinus Torvalds 
296db038cf8SAlexey Dobriyan 	unsigned char id_string[ID_STRING_LENGTH];
2971da177e4SLinus Torvalds 	enum scam_id_st state;
2981da177e4SLinus Torvalds 
29985ae97d8SAlexey Dobriyan } SCCBSCAM_INFO;
3001da177e4SLinus Torvalds 
3011da177e4SLinus Torvalds #define  SCSI_REQUEST_SENSE      0x03
3021da177e4SLinus Torvalds #define  SCSI_READ               0x08
3031da177e4SLinus Torvalds #define  SCSI_WRITE              0x0A
3041da177e4SLinus Torvalds #define  SCSI_START_STOP_UNIT    0x1B
3051da177e4SLinus Torvalds #define  SCSI_READ_EXTENDED      0x28
3061da177e4SLinus Torvalds #define  SCSI_WRITE_EXTENDED     0x2A
3071da177e4SLinus Torvalds #define  SCSI_WRITE_AND_VERIFY   0x2E
3081da177e4SLinus Torvalds 
3091da177e4SLinus Torvalds #define  SSGOOD                  0x00
3101da177e4SLinus Torvalds #define  SSCHECK                 0x02
3111da177e4SLinus Torvalds #define  SSQ_FULL                0x28
3121da177e4SLinus Torvalds 
3131da177e4SLinus Torvalds #define  SMCMD_COMP              0x00
3141da177e4SLinus Torvalds #define  SMEXT                   0x01
3151da177e4SLinus Torvalds #define  SMSAVE_DATA_PTR         0x02
3161da177e4SLinus Torvalds #define  SMREST_DATA_PTR         0x03
3171da177e4SLinus Torvalds #define  SMDISC                  0x04
3181da177e4SLinus Torvalds #define  SMABORT                 0x06
3191da177e4SLinus Torvalds #define  SMREJECT                0x07
3201da177e4SLinus Torvalds #define  SMNO_OP                 0x08
3211da177e4SLinus Torvalds #define  SMPARITY                0x09
3221da177e4SLinus Torvalds #define  SMDEV_RESET             0x0C
3231da177e4SLinus Torvalds #define	SMABORT_TAG					0x0D
3241da177e4SLinus Torvalds #define	SMINIT_RECOVERY			0x0F
3251da177e4SLinus Torvalds #define	SMREL_RECOVERY				0x10
3261da177e4SLinus Torvalds 
3271da177e4SLinus Torvalds #define  SMIDENT                 0x80
3281da177e4SLinus Torvalds #define  DISC_PRIV               0x40
3291da177e4SLinus Torvalds 
3301da177e4SLinus Torvalds #define  SMSYNC                  0x01
3311da177e4SLinus Torvalds #define  SMWDTR                  0x03
3321da177e4SLinus Torvalds #define  SM8BIT                  0x00
3331da177e4SLinus Torvalds #define  SM16BIT                 0x01
3341da177e4SLinus Torvalds #define  SMIGNORWR               0x23	/* Ignore Wide Residue */
3351da177e4SLinus Torvalds 
3361da177e4SLinus Torvalds #define  SIX_BYTE_CMD            0x06
3371da177e4SLinus Torvalds #define  TWELVE_BYTE_CMD         0x0C
3381da177e4SLinus Torvalds 
3391da177e4SLinus Torvalds #define  ASYNC                   0x00
3401da177e4SLinus Torvalds #define  MAX_OFFSET              0x0F	/* Maxbyteoffset for Sync Xfers */
3411da177e4SLinus Torvalds 
3421da177e4SLinus Torvalds #define  EEPROM_WD_CNT     256
3431da177e4SLinus Torvalds 
3441da177e4SLinus Torvalds #define  EEPROM_CHECK_SUM  0
3451da177e4SLinus Torvalds #define  FW_SIGNATURE      2
3461da177e4SLinus Torvalds #define  MODEL_NUMB_0      4
3471da177e4SLinus Torvalds #define  MODEL_NUMB_2      6
3481da177e4SLinus Torvalds #define  MODEL_NUMB_4      8
3491da177e4SLinus Torvalds #define  SYSTEM_CONFIG     16
3501da177e4SLinus Torvalds #define  SCSI_CONFIG       17
3511da177e4SLinus Torvalds #define  BIOS_CONFIG       18
3521da177e4SLinus Torvalds #define  SCAM_CONFIG       20
3531da177e4SLinus Torvalds #define  ADAPTER_SCSI_ID   24
3541da177e4SLinus Torvalds 
3551da177e4SLinus Torvalds #define  IGNORE_B_SCAN     32
3561da177e4SLinus Torvalds #define  SEND_START_ENA    34
3571da177e4SLinus Torvalds #define  DEVICE_ENABLE     36
3581da177e4SLinus Torvalds 
3591da177e4SLinus Torvalds #define  SYNC_RATE_TBL     38
3601da177e4SLinus Torvalds #define  SYNC_RATE_TBL01   38
3611da177e4SLinus Torvalds #define  SYNC_RATE_TBL23   40
3621da177e4SLinus Torvalds #define  SYNC_RATE_TBL45   42
3631da177e4SLinus Torvalds #define  SYNC_RATE_TBL67   44
3641da177e4SLinus Torvalds #define  SYNC_RATE_TBL89   46
3651da177e4SLinus Torvalds #define  SYNC_RATE_TBLab   48
3661da177e4SLinus Torvalds #define  SYNC_RATE_TBLcd   50
3671da177e4SLinus Torvalds #define  SYNC_RATE_TBLef   52
3681da177e4SLinus Torvalds 
3691da177e4SLinus Torvalds #define  EE_SCAMBASE      256
3701da177e4SLinus Torvalds 
3711da177e4SLinus Torvalds #define  SCAM_ENABLED   BIT(2)
3721da177e4SLinus Torvalds #define  SCAM_LEVEL2    BIT(3)
3731da177e4SLinus Torvalds 
3741cafc30fSJiri Slaby #define	RENEGO_ENA		BIT(10)
3751cafc30fSJiri Slaby #define	CONNIO_ENA		BIT(11)
3761cafc30fSJiri Slaby #define  GREEN_PC_ENA   BIT(12)
3771da177e4SLinus Torvalds 
3781da177e4SLinus Torvalds #define  AUTO_RATE_00   00
3791da177e4SLinus Torvalds #define  AUTO_RATE_05   01
3801da177e4SLinus Torvalds #define  AUTO_RATE_10   02
3811da177e4SLinus Torvalds #define  AUTO_RATE_20   03
3821da177e4SLinus Torvalds 
3831da177e4SLinus Torvalds #define  WIDE_NEGO_BIT     BIT(7)
3841da177e4SLinus Torvalds #define  DISC_ENABLE_BIT   BIT(6)
3851da177e4SLinus Torvalds 
3861da177e4SLinus Torvalds #define  hp_vendor_id_0       0x00	/* LSB */
3871da177e4SLinus Torvalds #define  ORION_VEND_0   0x4B
3881da177e4SLinus Torvalds 
3891da177e4SLinus Torvalds #define  hp_vendor_id_1       0x01	/* MSB */
3901da177e4SLinus Torvalds #define  ORION_VEND_1   0x10
3911da177e4SLinus Torvalds 
3921da177e4SLinus Torvalds #define  hp_device_id_0       0x02	/* LSB */
3931da177e4SLinus Torvalds #define  ORION_DEV_0    0x30
3941da177e4SLinus Torvalds 
3951da177e4SLinus Torvalds #define  hp_device_id_1       0x03	/* MSB */
3961da177e4SLinus Torvalds #define  ORION_DEV_1    0x81
3971da177e4SLinus Torvalds 
3981da177e4SLinus Torvalds 	/* Sub Vendor ID and Sub Device ID only available in
3991da177e4SLinus Torvalds 	   Harpoon Version 2 and higher */
4001da177e4SLinus Torvalds 
4011da177e4SLinus Torvalds #define  hp_sub_device_id_0   0x06	/* LSB */
4021da177e4SLinus Torvalds 
4031da177e4SLinus Torvalds #define  hp_semaphore         0x0C
4041da177e4SLinus Torvalds #define SCCB_MGR_ACTIVE    BIT(0)
4051da177e4SLinus Torvalds #define TICKLE_ME          BIT(1)
4061da177e4SLinus Torvalds #define SCCB_MGR_PRESENT   BIT(3)
4071da177e4SLinus Torvalds #define BIOS_IN_USE        BIT(4)
4081da177e4SLinus Torvalds 
4091da177e4SLinus Torvalds #define  hp_sys_ctrl          0x0F
4101da177e4SLinus Torvalds 
4111da177e4SLinus Torvalds #define  STOP_CLK          BIT(0)	/*Turn off BusMaster Clock */
4121da177e4SLinus Torvalds #define  DRVR_RST          BIT(1)	/*Firmware Reset to 80C15 chip */
4131da177e4SLinus Torvalds #define  HALT_MACH         BIT(3)	/*Halt State Machine      */
4141da177e4SLinus Torvalds #define  HARD_ABORT        BIT(4)	/*Hard Abort              */
4151da177e4SLinus Torvalds 
4161da177e4SLinus Torvalds #define  hp_host_blk_cnt      0x13
4171da177e4SLinus Torvalds 
4181da177e4SLinus Torvalds #define  XFER_BLK64        0x06	/*     1 1 0 64 byte per block */
4191da177e4SLinus Torvalds 
4201da177e4SLinus Torvalds #define  BM_THRESHOLD      0x40	/* PCI mode can only xfer 16 bytes */
4211da177e4SLinus Torvalds 
4221da177e4SLinus Torvalds #define  hp_int_mask          0x17
4231da177e4SLinus Torvalds 
4241da177e4SLinus Torvalds #define  INT_CMD_COMPL     BIT(0)	/* DMA command complete   */
4251da177e4SLinus Torvalds #define  INT_EXT_STATUS    BIT(1)	/* Extended Status Set    */
4261da177e4SLinus Torvalds 
4271da177e4SLinus Torvalds #define  hp_xfer_cnt_lo       0x18
4281da177e4SLinus Torvalds #define  hp_xfer_cnt_hi       0x1A
4291da177e4SLinus Torvalds #define  hp_xfer_cmd          0x1B
4301da177e4SLinus Torvalds 
4311da177e4SLinus Torvalds #define  XFER_HOST_DMA     0x00	/*     0 0 0 Transfer Host -> DMA */
4321da177e4SLinus Torvalds #define  XFER_DMA_HOST     0x01	/*     0 0 1 Transfer DMA  -> Host */
4331da177e4SLinus Torvalds 
4341da177e4SLinus Torvalds #define  XFER_HOST_AUTO    0x00	/*     0 0 Auto Transfer Size   */
4351da177e4SLinus Torvalds 
4361da177e4SLinus Torvalds #define  XFER_DMA_8BIT     0x20	/*     0 1 8 BIT  Transfer Size */
4371da177e4SLinus Torvalds 
4381da177e4SLinus Torvalds #define  DISABLE_INT       BIT(7)	/*Do not interrupt at end of cmd. */
4391da177e4SLinus Torvalds 
4401da177e4SLinus Torvalds #define  HOST_WRT_CMD      ((DISABLE_INT + XFER_HOST_DMA + XFER_HOST_AUTO + XFER_DMA_8BIT))
4411da177e4SLinus Torvalds #define  HOST_RD_CMD       ((DISABLE_INT + XFER_DMA_HOST + XFER_HOST_AUTO + XFER_DMA_8BIT))
4421da177e4SLinus Torvalds 
4431da177e4SLinus Torvalds #define  hp_host_addr_lo      0x1C
4441da177e4SLinus Torvalds #define  hp_host_addr_hmi     0x1E
4451da177e4SLinus Torvalds 
4461da177e4SLinus Torvalds #define  hp_ee_ctrl           0x22
4471da177e4SLinus Torvalds 
4481da177e4SLinus Torvalds #define  EXT_ARB_ACK       BIT(7)
4491da177e4SLinus Torvalds #define  SCSI_TERM_ENA_H   BIT(6)	/* SCSI high byte terminator */
4501da177e4SLinus Torvalds #define  SEE_MS            BIT(5)
4511da177e4SLinus Torvalds #define  SEE_CS            BIT(3)
4521da177e4SLinus Torvalds #define  SEE_CLK           BIT(2)
4531da177e4SLinus Torvalds #define  SEE_DO            BIT(1)
4541da177e4SLinus Torvalds #define  SEE_DI            BIT(0)
4551da177e4SLinus Torvalds 
4561da177e4SLinus Torvalds #define  EE_READ           0x06
4571da177e4SLinus Torvalds #define  EE_WRITE          0x05
4581da177e4SLinus Torvalds #define  EWEN              0x04
4591da177e4SLinus Torvalds #define  EWEN_ADDR         0x03C0
4601da177e4SLinus Torvalds #define  EWDS              0x04
4611da177e4SLinus Torvalds #define  EWDS_ADDR         0x0000
4621da177e4SLinus Torvalds 
4631da177e4SLinus Torvalds #define  hp_bm_ctrl           0x26
4641da177e4SLinus Torvalds 
4651da177e4SLinus Torvalds #define  SCSI_TERM_ENA_L   BIT(0)	/*Enable/Disable external terminators */
4661da177e4SLinus Torvalds #define  FLUSH_XFER_CNTR   BIT(1)	/*Flush transfer counter */
4671da177e4SLinus Torvalds #define  FORCE1_XFER       BIT(5)	/*Always xfer one byte in byte mode */
4681da177e4SLinus Torvalds #define  FAST_SINGLE       BIT(6)	/*?? */
4691da177e4SLinus Torvalds 
4701da177e4SLinus Torvalds #define  BMCTRL_DEFAULT    (FORCE1_XFER|FAST_SINGLE|SCSI_TERM_ENA_L)
4711da177e4SLinus Torvalds 
4721da177e4SLinus Torvalds #define  hp_sg_addr           0x28
4731da177e4SLinus Torvalds #define  hp_page_ctrl         0x29
4741da177e4SLinus Torvalds 
4751da177e4SLinus Torvalds #define  SCATTER_EN        BIT(0)
4761da177e4SLinus Torvalds #define  SGRAM_ARAM        BIT(1)
4771da177e4SLinus Torvalds #define  G_INT_DISABLE     BIT(3)	/* Enable/Disable all Interrupts */
4781da177e4SLinus Torvalds #define  NARROW_SCSI_CARD  BIT(4)	/* NARROW/WIDE SCSI config pin */
4791da177e4SLinus Torvalds 
4801da177e4SLinus Torvalds #define  hp_pci_stat_cfg      0x2D
4811da177e4SLinus Torvalds 
4821da177e4SLinus Torvalds #define  REC_MASTER_ABORT  BIT(5)	/*received Master abort */
4831da177e4SLinus Torvalds 
4841da177e4SLinus Torvalds #define  hp_rev_num           0x33
4851da177e4SLinus Torvalds 
4861da177e4SLinus Torvalds #define  hp_stack_data        0x34
4871da177e4SLinus Torvalds #define  hp_stack_addr        0x35
4881da177e4SLinus Torvalds 
4891da177e4SLinus Torvalds #define  hp_ext_status        0x36
4901da177e4SLinus Torvalds 
4911da177e4SLinus Torvalds #define  BM_FORCE_OFF      BIT(0)	/*Bus Master is forced to get off */
4921da177e4SLinus Torvalds #define  PCI_TGT_ABORT     BIT(0)	/*PCI bus master transaction aborted */
4931da177e4SLinus Torvalds #define  PCI_DEV_TMOUT     BIT(1)	/*PCI Device Time out */
4941da177e4SLinus Torvalds #define  CMD_ABORTED       BIT(4)	/*Command aborted */
4951da177e4SLinus Torvalds #define  BM_PARITY_ERR     BIT(5)	/*parity error on data received   */
4961da177e4SLinus Torvalds #define  PIO_OVERRUN       BIT(6)	/*Slave data overrun */
4971da177e4SLinus Torvalds #define  BM_CMD_BUSY       BIT(7)	/*Bus master transfer command busy */
4981da177e4SLinus Torvalds #define  BAD_EXT_STATUS    (BM_FORCE_OFF | PCI_DEV_TMOUT | CMD_ABORTED | \
4991da177e4SLinus Torvalds                                   BM_PARITY_ERR | PIO_OVERRUN)
5001da177e4SLinus Torvalds 
5011da177e4SLinus Torvalds #define  hp_int_status        0x37
5021da177e4SLinus Torvalds 
5031da177e4SLinus Torvalds #define  EXT_STATUS_ON     BIT(1)	/*Extended status is valid */
5041da177e4SLinus Torvalds #define  SCSI_INTERRUPT    BIT(2)	/*Global indication of a SCSI int. */
5051da177e4SLinus Torvalds #define  INT_ASSERTED      BIT(5)	/* */
5061da177e4SLinus Torvalds 
5071da177e4SLinus Torvalds #define  hp_fifo_cnt          0x38
5081da177e4SLinus Torvalds 
5091da177e4SLinus Torvalds #define  hp_intena		 0x40
5101da177e4SLinus Torvalds 
5111cafc30fSJiri Slaby #define  RESET		 BIT(7)
5121cafc30fSJiri Slaby #define  PROG_HLT		 BIT(6)
5131cafc30fSJiri Slaby #define  PARITY		 BIT(5)
5141cafc30fSJiri Slaby #define  FIFO		 BIT(4)
5151cafc30fSJiri Slaby #define  SEL		 BIT(3)
5161cafc30fSJiri Slaby #define  SCAM_SEL		 BIT(2)
5171cafc30fSJiri Slaby #define  RSEL		 BIT(1)
5181cafc30fSJiri Slaby #define  TIMEOUT		 BIT(0)
5191cafc30fSJiri Slaby #define  BUS_FREE		 BIT(15)
5201cafc30fSJiri Slaby #define  XFER_CNT_0	 BIT(14)
5211cafc30fSJiri Slaby #define  PHASE		 BIT(13)
5221cafc30fSJiri Slaby #define  IUNKWN		 BIT(12)
5231cafc30fSJiri Slaby #define  ICMD_COMP	 BIT(11)
5241cafc30fSJiri Slaby #define  ITICKLE		 BIT(10)
5251cafc30fSJiri Slaby #define  IDO_STRT		 BIT(9)
5261cafc30fSJiri Slaby #define  ITAR_DISC	 BIT(8)
5271cafc30fSJiri Slaby #define  AUTO_INT		 (BIT(12)+BIT(11)+BIT(10)+BIT(9)+BIT(8))
5281da177e4SLinus Torvalds #define  CLR_ALL_INT	 0xFFFF
5291da177e4SLinus Torvalds #define  CLR_ALL_INT_1	 0xFF00
5301da177e4SLinus Torvalds 
5311da177e4SLinus Torvalds #define  hp_intstat		 0x42
5321da177e4SLinus Torvalds 
5331da177e4SLinus Torvalds #define  hp_scsisig           0x44
5341da177e4SLinus Torvalds 
5351da177e4SLinus Torvalds #define  SCSI_SEL          BIT(7)
5361da177e4SLinus Torvalds #define  SCSI_BSY          BIT(6)
5371da177e4SLinus Torvalds #define  SCSI_REQ          BIT(5)
5381da177e4SLinus Torvalds #define  SCSI_ACK          BIT(4)
5391da177e4SLinus Torvalds #define  SCSI_ATN          BIT(3)
5401da177e4SLinus Torvalds #define  SCSI_CD           BIT(2)
5411da177e4SLinus Torvalds #define  SCSI_MSG          BIT(1)
5421da177e4SLinus Torvalds #define  SCSI_IOBIT        BIT(0)
5431da177e4SLinus Torvalds 
5441da177e4SLinus Torvalds #define  S_SCSI_PHZ        (BIT(2)+BIT(1)+BIT(0))
5451da177e4SLinus Torvalds #define  S_MSGO_PH         (BIT(2)+BIT(1)       )
5461da177e4SLinus Torvalds #define  S_MSGI_PH         (BIT(2)+BIT(1)+BIT(0))
5471da177e4SLinus Torvalds #define  S_DATAI_PH        (              BIT(0))
5481da177e4SLinus Torvalds #define  S_DATAO_PH        0x00
5491da177e4SLinus Torvalds #define  S_ILL_PH          (       BIT(1)       )
5501da177e4SLinus Torvalds 
5511da177e4SLinus Torvalds #define  hp_scsictrl_0        0x45
5521da177e4SLinus Torvalds 
5531da177e4SLinus Torvalds #define  SEL_TAR           BIT(6)
5541da177e4SLinus Torvalds #define  ENA_ATN           BIT(4)
5551da177e4SLinus Torvalds #define  ENA_RESEL         BIT(2)
5561da177e4SLinus Torvalds #define  SCSI_RST          BIT(1)
5571da177e4SLinus Torvalds #define  ENA_SCAM_SEL      BIT(0)
5581da177e4SLinus Torvalds 
5591da177e4SLinus Torvalds #define  hp_portctrl_0        0x46
5601da177e4SLinus Torvalds 
5611da177e4SLinus Torvalds #define  SCSI_PORT         BIT(7)
5621da177e4SLinus Torvalds #define  SCSI_INBIT        BIT(6)
5631da177e4SLinus Torvalds #define  DMA_PORT          BIT(5)
5641da177e4SLinus Torvalds #define  DMA_RD            BIT(4)
5651da177e4SLinus Torvalds #define  HOST_PORT         BIT(3)
5661da177e4SLinus Torvalds #define  HOST_WRT          BIT(2)
5671da177e4SLinus Torvalds #define  SCSI_BUS_EN       BIT(1)
5681da177e4SLinus Torvalds #define  START_TO          BIT(0)
5691da177e4SLinus Torvalds 
5701da177e4SLinus Torvalds #define  hp_scsireset         0x47
5711da177e4SLinus Torvalds 
5721da177e4SLinus Torvalds #define  SCSI_INI          BIT(6)
5731da177e4SLinus Torvalds #define  SCAM_EN           BIT(5)
5741da177e4SLinus Torvalds #define  DMA_RESET         BIT(3)
5751da177e4SLinus Torvalds #define  HPSCSI_RESET      BIT(2)
5761da177e4SLinus Torvalds #define  PROG_RESET        BIT(1)
5771da177e4SLinus Torvalds #define  FIFO_CLR          BIT(0)
5781da177e4SLinus Torvalds 
5791da177e4SLinus Torvalds #define  hp_xfercnt_0         0x48
5801da177e4SLinus Torvalds #define  hp_xfercnt_2         0x4A
5811da177e4SLinus Torvalds 
5821da177e4SLinus Torvalds #define  hp_fifodata_0        0x4C
5831da177e4SLinus Torvalds #define  hp_addstat           0x4E
5841da177e4SLinus Torvalds 
5851da177e4SLinus Torvalds #define  SCAM_TIMER        BIT(7)
5861da177e4SLinus Torvalds #define  SCSI_MODE8        BIT(3)
5871da177e4SLinus Torvalds #define  SCSI_PAR_ERR      BIT(0)
5881da177e4SLinus Torvalds 
5891da177e4SLinus Torvalds #define  hp_prgmcnt_0         0x4F
5901da177e4SLinus Torvalds 
5911da177e4SLinus Torvalds #define  hp_selfid_0          0x50
5921da177e4SLinus Torvalds #define  hp_selfid_1          0x51
5931da177e4SLinus Torvalds #define  hp_arb_id            0x52
5941da177e4SLinus Torvalds 
5951da177e4SLinus Torvalds #define  hp_select_id         0x53
5961da177e4SLinus Torvalds 
5971da177e4SLinus Torvalds #define  hp_synctarg_base     0x54
5981da177e4SLinus Torvalds #define  hp_synctarg_12       0x54
5991da177e4SLinus Torvalds #define  hp_synctarg_13       0x55
6001da177e4SLinus Torvalds #define  hp_synctarg_14       0x56
6011da177e4SLinus Torvalds #define  hp_synctarg_15       0x57
6021da177e4SLinus Torvalds 
6031da177e4SLinus Torvalds #define  hp_synctarg_8        0x58
6041da177e4SLinus Torvalds #define  hp_synctarg_9        0x59
6051da177e4SLinus Torvalds #define  hp_synctarg_10       0x5A
6061da177e4SLinus Torvalds #define  hp_synctarg_11       0x5B
6071da177e4SLinus Torvalds 
6081da177e4SLinus Torvalds #define  hp_synctarg_4        0x5C
6091da177e4SLinus Torvalds #define  hp_synctarg_5        0x5D
6101da177e4SLinus Torvalds #define  hp_synctarg_6        0x5E
6111da177e4SLinus Torvalds #define  hp_synctarg_7        0x5F
6121da177e4SLinus Torvalds 
6131da177e4SLinus Torvalds #define  hp_synctarg_0        0x60
6141da177e4SLinus Torvalds #define  hp_synctarg_1        0x61
6151da177e4SLinus Torvalds #define  hp_synctarg_2        0x62
6161da177e4SLinus Torvalds #define  hp_synctarg_3        0x63
6171da177e4SLinus Torvalds 
6181da177e4SLinus Torvalds #define  NARROW_SCSI       BIT(4)
6191da177e4SLinus Torvalds #define  DEFAULT_OFFSET    0x0F
6201da177e4SLinus Torvalds 
6211da177e4SLinus Torvalds #define  hp_autostart_0       0x64
6221da177e4SLinus Torvalds #define  hp_autostart_1       0x65
6231da177e4SLinus Torvalds #define  hp_autostart_3       0x67
6241da177e4SLinus Torvalds 
6251da177e4SLinus Torvalds #define  AUTO_IMMED    BIT(5)
6261da177e4SLinus Torvalds #define  SELECT   BIT(6)
6271da177e4SLinus Torvalds #define  END_DATA (BIT(7)+BIT(6))
6281da177e4SLinus Torvalds 
6291da177e4SLinus Torvalds #define  hp_gp_reg_0          0x68
6301da177e4SLinus Torvalds #define  hp_gp_reg_1          0x69
6311da177e4SLinus Torvalds #define  hp_gp_reg_3          0x6B
6321da177e4SLinus Torvalds 
6331da177e4SLinus Torvalds #define  hp_seltimeout        0x6C
6341da177e4SLinus Torvalds 
6351da177e4SLinus Torvalds #define  TO_4ms            0x67	/* 3.9959ms */
6361da177e4SLinus Torvalds 
6371da177e4SLinus Torvalds #define  TO_5ms            0x03	/* 4.9152ms */
6381da177e4SLinus Torvalds #define  TO_10ms           0x07	/* 11.xxxms */
6391da177e4SLinus Torvalds #define  TO_250ms          0x99	/* 250.68ms */
6401da177e4SLinus Torvalds #define  TO_290ms          0xB1	/* 289.99ms */
6411da177e4SLinus Torvalds 
6421da177e4SLinus Torvalds #define  hp_clkctrl_0         0x6D
6431da177e4SLinus Torvalds 
6441da177e4SLinus Torvalds #define  PWR_DWN           BIT(6)
6451da177e4SLinus Torvalds #define  ACTdeassert       BIT(4)
6461da177e4SLinus Torvalds #define  CLK_40MHZ         (BIT(1) + BIT(0))
6471da177e4SLinus Torvalds 
6481da177e4SLinus Torvalds #define  CLKCTRL_DEFAULT   (ACTdeassert | CLK_40MHZ)
6491da177e4SLinus Torvalds 
6501da177e4SLinus Torvalds #define  hp_fiforead          0x6E
6511da177e4SLinus Torvalds #define  hp_fifowrite         0x6F
6521da177e4SLinus Torvalds 
6531da177e4SLinus Torvalds #define  hp_offsetctr         0x70
6541da177e4SLinus Torvalds #define  hp_xferstat          0x71
6551da177e4SLinus Torvalds 
6561da177e4SLinus Torvalds #define  FIFO_EMPTY        BIT(6)
6571da177e4SLinus Torvalds 
6581da177e4SLinus Torvalds #define  hp_portctrl_1        0x72
6591da177e4SLinus Torvalds 
6601da177e4SLinus Torvalds #define  CHK_SCSI_P        BIT(3)
6611da177e4SLinus Torvalds #define  HOST_MODE8        BIT(0)
6621da177e4SLinus Torvalds 
6631da177e4SLinus Torvalds #define  hp_xfer_pad          0x73
6641da177e4SLinus Torvalds 
6651da177e4SLinus Torvalds #define  ID_UNLOCK         BIT(3)
6661da177e4SLinus Torvalds 
6671da177e4SLinus Torvalds #define  hp_scsidata_0        0x74
6681da177e4SLinus Torvalds #define  hp_scsidata_1        0x75
6691da177e4SLinus Torvalds 
6701da177e4SLinus Torvalds #define  hp_aramBase          0x80
6711da177e4SLinus Torvalds #define  BIOS_DATA_OFFSET     0x60
6721da177e4SLinus Torvalds #define  BIOS_RELATIVE_CARD   0x64
6731da177e4SLinus Torvalds 
6741cafc30fSJiri Slaby #define  AR3      (BIT(9) + BIT(8))
6751cafc30fSJiri Slaby #define  SDATA    BIT(10)
6761da177e4SLinus Torvalds 
6771cafc30fSJiri Slaby #define  CRD_OP   BIT(11)	/* Cmp Reg. w/ Data */
6781da177e4SLinus Torvalds 
6791cafc30fSJiri Slaby #define  CRR_OP   BIT(12)	/* Cmp Reg. w. Reg. */
6801da177e4SLinus Torvalds 
6811cafc30fSJiri Slaby #define  CPE_OP   (BIT(14)+BIT(11))	/* Cmp SCSI phs & Branch EQ */
6821da177e4SLinus Torvalds 
6831cafc30fSJiri Slaby #define  CPN_OP   (BIT(14)+BIT(12))	/* Cmp SCSI phs & Branch NOT EQ */
6841da177e4SLinus Torvalds 
6851da177e4SLinus Torvalds #define  ADATA_OUT   0x00
6861cafc30fSJiri Slaby #define  ADATA_IN    BIT(8)
6871cafc30fSJiri Slaby #define  ACOMMAND    BIT(10)
6881cafc30fSJiri Slaby #define  ASTATUS     (BIT(10)+BIT(8))
6891cafc30fSJiri Slaby #define  AMSG_OUT    (BIT(10)+BIT(9))
6901cafc30fSJiri Slaby #define  AMSG_IN     (BIT(10)+BIT(9)+BIT(8))
6911da177e4SLinus Torvalds 
6921cafc30fSJiri Slaby #define  BRH_OP   BIT(13)	/* Branch */
6931da177e4SLinus Torvalds 
6941da177e4SLinus Torvalds #define  ALWAYS   0x00
6951cafc30fSJiri Slaby #define  EQUAL    BIT(8)
6961cafc30fSJiri Slaby #define  NOT_EQ   BIT(9)
6971da177e4SLinus Torvalds 
6981cafc30fSJiri Slaby #define  TCB_OP   (BIT(13)+BIT(11))	/* Test condition & branch */
6991da177e4SLinus Torvalds 
7001cafc30fSJiri Slaby #define  FIFO_0      BIT(10)
7011da177e4SLinus Torvalds 
7021cafc30fSJiri Slaby #define  MPM_OP   BIT(15)	/* Match phase and move data */
7031da177e4SLinus Torvalds 
7041cafc30fSJiri Slaby #define  MRR_OP   BIT(14)	/* Move DReg. to Reg. */
7051da177e4SLinus Torvalds 
7061da177e4SLinus Torvalds #define  S_IDREG  (BIT(2)+BIT(1)+BIT(0))
7071da177e4SLinus Torvalds 
7081da177e4SLinus Torvalds #define  D_AR0    0x00
7091da177e4SLinus Torvalds #define  D_AR1    BIT(0)
7101da177e4SLinus Torvalds #define  D_BUCKET (BIT(2) + BIT(1) + BIT(0))
7111da177e4SLinus Torvalds 
7121cafc30fSJiri Slaby #define  RAT_OP      (BIT(14)+BIT(13)+BIT(11))
7131da177e4SLinus Torvalds 
7141cafc30fSJiri Slaby #define  SSI_OP      (BIT(15)+BIT(11))
7151da177e4SLinus Torvalds 
7161da177e4SLinus Torvalds #define  SSI_ITAR_DISC	(ITAR_DISC >> 8)
7171da177e4SLinus Torvalds #define  SSI_IDO_STRT	(IDO_STRT >> 8)
7181da177e4SLinus Torvalds 
7191da177e4SLinus Torvalds #define  SSI_ICMD_COMP	(ICMD_COMP >> 8)
7201da177e4SLinus Torvalds #define  SSI_ITICKLE	(ITICKLE >> 8)
7211da177e4SLinus Torvalds 
7221da177e4SLinus Torvalds #define  SSI_IUNKWN	(IUNKWN >> 8)
7231da177e4SLinus Torvalds #define  SSI_INO_CC	(IUNKWN >> 8)
7241da177e4SLinus Torvalds #define  SSI_IRFAIL	(IUNKWN >> 8)
7251da177e4SLinus Torvalds 
7261da177e4SLinus Torvalds #define  NP    0x10		/*Next Phase */
7271da177e4SLinus Torvalds #define  NTCMD 0x02		/*Non- Tagged Command start */
7281da177e4SLinus Torvalds #define  CMDPZ 0x04		/*Command phase */
7291da177e4SLinus Torvalds #define  DINT  0x12		/*Data Out/In interrupt */
7301da177e4SLinus Torvalds #define  DI    0x13		/*Data Out */
7311da177e4SLinus Torvalds #define  DC    0x19		/*Disconnect Message */
7321da177e4SLinus Torvalds #define  ST    0x1D		/*Status Phase */
7331da177e4SLinus Torvalds #define  UNKNWN 0x24		/*Unknown bus action */
7341da177e4SLinus Torvalds #define  CC    0x25		/*Command Completion failure */
7351da177e4SLinus Torvalds #define  TICK  0x26		/*New target reselected us. */
7361da177e4SLinus Torvalds #define  SELCHK 0x28		/*Select & Check SCSI ID latch reg */
7371da177e4SLinus Torvalds 
7381da177e4SLinus Torvalds #define  ID_MSG_STRT    hp_aramBase + 0x00
7391da177e4SLinus Torvalds #define  NON_TAG_ID_MSG hp_aramBase + 0x06
7401da177e4SLinus Torvalds #define  CMD_STRT       hp_aramBase + 0x08
7411da177e4SLinus Torvalds #define  SYNC_MSGS      hp_aramBase + 0x08
7421da177e4SLinus Torvalds 
7431da177e4SLinus Torvalds #define  TAG_STRT          0x00
7441da177e4SLinus Torvalds #define  DISCONNECT_START  0x10/2
7451da177e4SLinus Torvalds #define  END_DATA_START    0x14/2
7461da177e4SLinus Torvalds #define  CMD_ONLY_STRT     CMDPZ/2
7471da177e4SLinus Torvalds #define  SELCHK_STRT     SELCHK/2
7481da177e4SLinus Torvalds 
7491da177e4SLinus Torvalds #define GET_XFER_CNT(port, xfercnt) {RD_HARP32(port,hp_xfercnt_0,xfercnt); xfercnt &= 0xFFFFFF;}
7501da177e4SLinus Torvalds /* #define GET_XFER_CNT(port, xfercnt) (xfercnt = RD_HARPOON(port+hp_xfercnt_2), \
7511da177e4SLinus Torvalds                                  xfercnt <<= 16,\
752c823feebSAlexey Dobriyan                                  xfercnt |= RDW_HARPOON((unsigned short)(port+hp_xfercnt_0)))
7531da177e4SLinus Torvalds  */
754c823feebSAlexey Dobriyan #define HP_SETUP_ADDR_CNT(port,addr,count) (WRW_HARPOON((port+hp_host_addr_lo), (unsigned short)(addr & 0x0000FFFFL)),\
7551da177e4SLinus Torvalds          addr >>= 16,\
756c823feebSAlexey Dobriyan          WRW_HARPOON((port+hp_host_addr_hmi), (unsigned short)(addr & 0x0000FFFFL)),\
7571da177e4SLinus Torvalds          WR_HARP32(port,hp_xfercnt_0,count),\
758c823feebSAlexey Dobriyan          WRW_HARPOON((port+hp_xfer_cnt_lo), (unsigned short)(count & 0x0000FFFFL)),\
7591da177e4SLinus Torvalds          count >>= 16,\
7601da177e4SLinus Torvalds          WR_HARPOON(port+hp_xfer_cnt_hi, (count & 0xFF)))
7611da177e4SLinus Torvalds 
7621da177e4SLinus Torvalds #define ACCEPT_MSG(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
7631da177e4SLinus Torvalds                           WR_HARPOON(port+hp_scsisig, S_ILL_PH);}
7641da177e4SLinus Torvalds 
7651da177e4SLinus Torvalds #define ACCEPT_MSG_ATN(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
7661da177e4SLinus Torvalds                           WR_HARPOON(port+hp_scsisig, (S_ILL_PH|SCSI_ATN));}
7671da177e4SLinus Torvalds 
7681da177e4SLinus Torvalds #define DISABLE_AUTO(port) (WR_HARPOON(port+hp_scsireset, PROG_RESET),\
7691da177e4SLinus Torvalds                         WR_HARPOON(port+hp_scsireset, 0x00))
7701da177e4SLinus Torvalds 
7711da177e4SLinus Torvalds #define ARAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
7721da177e4SLinus Torvalds                              (RD_HARPOON(p_port+hp_page_ctrl) | SGRAM_ARAM)))
7731da177e4SLinus Torvalds 
7741da177e4SLinus Torvalds #define SGRAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
7751da177e4SLinus Torvalds                              (RD_HARPOON(p_port+hp_page_ctrl) & ~SGRAM_ARAM)))
7761da177e4SLinus Torvalds 
7771da177e4SLinus Torvalds #define MDISABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
7781da177e4SLinus Torvalds                              (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE)))
7791da177e4SLinus Torvalds 
7801da177e4SLinus Torvalds #define MENABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
7811da177e4SLinus Torvalds                              (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE)))
7821da177e4SLinus Torvalds 
7835c04a7b8SAlexey Dobriyan static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card,
7845c04a7b8SAlexey Dobriyan 				 unsigned char syncFlag);
785d63a4cccSAlexey Dobriyan static void FPT_ssel(unsigned long port, unsigned char p_card);
7865c04a7b8SAlexey Dobriyan static void FPT_sres(unsigned long port, unsigned char p_card,
7875c04a7b8SAlexey Dobriyan 		     struct sccb_card *pCurrCard);
7885c04a7b8SAlexey Dobriyan static void FPT_shandem(unsigned long port, unsigned char p_card,
7895c04a7b8SAlexey Dobriyan 			struct sccb *pCurrSCCB);
790d63a4cccSAlexey Dobriyan static void FPT_stsyncn(unsigned long port, unsigned char p_card);
7915c04a7b8SAlexey Dobriyan static void FPT_sisyncr(unsigned long port, unsigned char sync_pulse,
7925c04a7b8SAlexey Dobriyan 			unsigned char offset);
7935c04a7b8SAlexey Dobriyan static void FPT_sssyncv(unsigned long p_port, unsigned char p_id,
7945c04a7b8SAlexey Dobriyan 			unsigned char p_sync_value,
795f31dc0cdSAlexey Dobriyan 			struct sccb_mgr_tar_info *currTar_Info);
796d63a4cccSAlexey Dobriyan static void FPT_sresb(unsigned long port, unsigned char p_card);
797d63a4cccSAlexey Dobriyan static void FPT_sxfrp(unsigned long p_port, unsigned char p_card);
798d63a4cccSAlexey Dobriyan static void FPT_schkdd(unsigned long port, unsigned char p_card);
799d63a4cccSAlexey Dobriyan static unsigned char FPT_RdStack(unsigned long port, unsigned char index);
8005c04a7b8SAlexey Dobriyan static void FPT_WrStack(unsigned long portBase, unsigned char index,
8015c04a7b8SAlexey Dobriyan 			unsigned char data);
802d63a4cccSAlexey Dobriyan static unsigned char FPT_ChkIfChipInitialized(unsigned long ioPort);
8031da177e4SLinus Torvalds 
804d63a4cccSAlexey Dobriyan static void FPT_SendMsg(unsigned long port, unsigned char message);
805db038cf8SAlexey Dobriyan static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
806db038cf8SAlexey Dobriyan 				   unsigned char error_code);
8071da177e4SLinus Torvalds 
80869eb2ea4SAlexey Dobriyan static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card);
80968d0c1aeSAlexey Dobriyan static void FPT_RNVRamData(struct nvram_info *pNvRamInfo);
8101da177e4SLinus Torvalds 
811d63a4cccSAlexey Dobriyan static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card);
812d63a4cccSAlexey Dobriyan static void FPT_stwidn(unsigned long port, unsigned char p_card);
813d63a4cccSAlexey Dobriyan static void FPT_siwidr(unsigned long port, unsigned char width);
8141da177e4SLinus Torvalds 
8155c04a7b8SAlexey Dobriyan static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
816db038cf8SAlexey Dobriyan 				unsigned char p_card);
8175c04a7b8SAlexey Dobriyan static void FPT_queueDisconnect(struct sccb *p_SCCB, unsigned char p_card);
8185c04a7b8SAlexey Dobriyan static void FPT_queueCmdComplete(struct sccb_card *pCurrCard,
8195c04a7b8SAlexey Dobriyan 				 struct sccb *p_SCCB, unsigned char p_card);
8205c04a7b8SAlexey Dobriyan static void FPT_queueSearchSelect(struct sccb_card *pCurrCard,
8215c04a7b8SAlexey Dobriyan 				  unsigned char p_card);
822db038cf8SAlexey Dobriyan static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code);
82369eb2ea4SAlexey Dobriyan static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char card);
8245c04a7b8SAlexey Dobriyan static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB,
8255c04a7b8SAlexey Dobriyan 				       unsigned char p_card);
82669eb2ea4SAlexey Dobriyan static void FPT_utilUpdateResidual(struct sccb *p_SCCB);
827c823feebSAlexey Dobriyan static unsigned short FPT_CalcCrc16(unsigned char buffer[]);
828db038cf8SAlexey Dobriyan static unsigned char FPT_CalcLrc(unsigned char buffer[]);
8291da177e4SLinus Torvalds 
830d63a4cccSAlexey Dobriyan static void FPT_Wait1Second(unsigned long p_port);
831d63a4cccSAlexey Dobriyan static void FPT_Wait(unsigned long p_port, unsigned char p_delay);
832d63a4cccSAlexey Dobriyan static void FPT_utilEEWriteOnOff(unsigned long p_port, unsigned char p_mode);
8335c04a7b8SAlexey Dobriyan static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data,
8345c04a7b8SAlexey Dobriyan 			    unsigned short ee_addr);
8355c04a7b8SAlexey Dobriyan static unsigned short FPT_utilEERead(unsigned long p_port,
8365c04a7b8SAlexey Dobriyan 				     unsigned short ee_addr);
8375c04a7b8SAlexey Dobriyan static unsigned short FPT_utilEEReadOrg(unsigned long p_port,
8385c04a7b8SAlexey Dobriyan 					unsigned short ee_addr);
8395c04a7b8SAlexey Dobriyan static void FPT_utilEESendCmdAddr(unsigned long p_port, unsigned char ee_cmd,
8405c04a7b8SAlexey Dobriyan 				  unsigned short ee_addr);
8411da177e4SLinus Torvalds 
842d63a4cccSAlexey Dobriyan static void FPT_phaseDataOut(unsigned long port, unsigned char p_card);
843d63a4cccSAlexey Dobriyan static void FPT_phaseDataIn(unsigned long port, unsigned char p_card);
844d63a4cccSAlexey Dobriyan static void FPT_phaseCommand(unsigned long port, unsigned char p_card);
845d63a4cccSAlexey Dobriyan static void FPT_phaseStatus(unsigned long port, unsigned char p_card);
846d63a4cccSAlexey Dobriyan static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card);
847d63a4cccSAlexey Dobriyan static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card);
848d63a4cccSAlexey Dobriyan static void FPT_phaseIllegal(unsigned long port, unsigned char p_card);
8491da177e4SLinus Torvalds 
850d63a4cccSAlexey Dobriyan static void FPT_phaseDecode(unsigned long port, unsigned char p_card);
851d63a4cccSAlexey Dobriyan static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card);
852d63a4cccSAlexey Dobriyan static void FPT_phaseBusFree(unsigned long p_port, unsigned char p_card);
8531da177e4SLinus Torvalds 
854d63a4cccSAlexey Dobriyan static void FPT_XbowInit(unsigned long port, unsigned char scamFlg);
855d63a4cccSAlexey Dobriyan static void FPT_BusMasterInit(unsigned long p_port);
856d63a4cccSAlexey Dobriyan static void FPT_DiagEEPROM(unsigned long p_port);
8571da177e4SLinus Torvalds 
8585c04a7b8SAlexey Dobriyan static void FPT_dataXferProcessor(unsigned long port,
8595c04a7b8SAlexey Dobriyan 				  struct sccb_card *pCurrCard);
8605c04a7b8SAlexey Dobriyan static void FPT_busMstrSGDataXferStart(unsigned long port,
8615c04a7b8SAlexey Dobriyan 				       struct sccb *pCurrSCCB);
8625c04a7b8SAlexey Dobriyan static void FPT_busMstrDataXferStart(unsigned long port,
8635c04a7b8SAlexey Dobriyan 				     struct sccb *pCurrSCCB);
8645c04a7b8SAlexey Dobriyan static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card,
8655c04a7b8SAlexey Dobriyan 				  struct sccb *pCurrSCCB);
86669eb2ea4SAlexey Dobriyan static void FPT_hostDataXferRestart(struct sccb *currSCCB);
8671da177e4SLinus Torvalds 
8685c04a7b8SAlexey Dobriyan static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port,
8695c04a7b8SAlexey Dobriyan 					 unsigned char p_card,
8705c04a7b8SAlexey Dobriyan 					 struct sccb_card *pCurrCard,
8715c04a7b8SAlexey Dobriyan 					 unsigned short p_int);
8721da177e4SLinus Torvalds 
87347b5d69cSJames Bottomley  static void FPT_SccbMgrTableInitAll(void);
8745c04a7b8SAlexey Dobriyan static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard,
8755c04a7b8SAlexey Dobriyan 				     unsigned char p_card);
8765c04a7b8SAlexey Dobriyan static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
8775c04a7b8SAlexey Dobriyan 				       unsigned char target);
8781da177e4SLinus Torvalds 
8795c04a7b8SAlexey Dobriyan static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
8805c04a7b8SAlexey Dobriyan 		      unsigned char p_power_up);
8811da177e4SLinus Torvalds 
882d63a4cccSAlexey Dobriyan static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type);
883d63a4cccSAlexey Dobriyan static void FPT_scbusf(unsigned long p_port);
884d63a4cccSAlexey Dobriyan static void FPT_scsel(unsigned long p_port);
885d63a4cccSAlexey Dobriyan static void FPT_scasid(unsigned char p_card, unsigned long p_port);
886d63a4cccSAlexey Dobriyan static unsigned char FPT_scxferc(unsigned long p_port, unsigned char p_data);
8875c04a7b8SAlexey Dobriyan static unsigned char FPT_scsendi(unsigned long p_port,
8885c04a7b8SAlexey Dobriyan 				 unsigned char p_id_string[]);
8895c04a7b8SAlexey Dobriyan static unsigned char FPT_sciso(unsigned long p_port,
8905c04a7b8SAlexey Dobriyan 			       unsigned char p_id_string[]);
891d63a4cccSAlexey Dobriyan static void FPT_scwirod(unsigned long p_port, unsigned char p_data_bit);
892d63a4cccSAlexey Dobriyan static void FPT_scwiros(unsigned long p_port, unsigned char p_data_bit);
893db038cf8SAlexey Dobriyan static unsigned char FPT_scvalq(unsigned char p_quintet);
894d63a4cccSAlexey Dobriyan static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id);
895d63a4cccSAlexey Dobriyan static void FPT_scwtsel(unsigned long p_port);
8965c04a7b8SAlexey Dobriyan static void FPT_inisci(unsigned char p_card, unsigned long p_port,
8975c04a7b8SAlexey Dobriyan 		       unsigned char p_our_id);
898d63a4cccSAlexey Dobriyan static void FPT_scsavdi(unsigned char p_card, unsigned long p_port);
8995c04a7b8SAlexey Dobriyan static unsigned char FPT_scmachid(unsigned char p_card,
9005c04a7b8SAlexey Dobriyan 				  unsigned char p_id_string[]);
9011da177e4SLinus Torvalds 
902d63a4cccSAlexey Dobriyan static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card);
903d63a4cccSAlexey Dobriyan static void FPT_autoLoadDefaultMap(unsigned long p_port);
9041da177e4SLinus Torvalds 
9055c04a7b8SAlexey Dobriyan static struct sccb_mgr_tar_info FPT_sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] =
9065c04a7b8SAlexey Dobriyan     { {{0}} };
90713e6851aSAlexey Dobriyan static struct sccb_card FPT_BL_Card[MAX_CARDS] = { {0} };
90847b5d69cSJames Bottomley  static SCCBSCAM_INFO FPT_scamInfo[MAX_SCSI_TAR] = { {{0}} };
90968d0c1aeSAlexey Dobriyan static struct nvram_info FPT_nvRamInfo[MAX_MB_CARDS] = { {0} };
9101da177e4SLinus Torvalds 
911db038cf8SAlexey Dobriyan static unsigned char FPT_mbCards = 0;
9125c04a7b8SAlexey Dobriyan static unsigned char FPT_scamHAString[] =
9135c04a7b8SAlexey Dobriyan     { 0x63, 0x07, 'B', 'U', 'S', 'L', 'O', 'G', 'I', 'C',
9145c04a7b8SAlexey Dobriyan 	' ', 'B', 'T', '-', '9', '3', '0',
9155c04a7b8SAlexey Dobriyan 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
9165c04a7b8SAlexey Dobriyan 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
9175c04a7b8SAlexey Dobriyan };
9181da177e4SLinus Torvalds 
919c823feebSAlexey Dobriyan static unsigned short FPT_default_intena = 0;
9201da177e4SLinus Torvalds 
9215c04a7b8SAlexey Dobriyan static void (*FPT_s_PhaseTbl[8]) (unsigned long, unsigned char) = {
9225c04a7b8SAlexey Dobriyan 0};
9231da177e4SLinus Torvalds 
9241da177e4SLinus Torvalds /*---------------------------------------------------------------------
9251da177e4SLinus Torvalds  *
926d8b6b8bdSAlexey Dobriyan  * Function: FlashPoint_ProbeHostAdapter
9271da177e4SLinus Torvalds  *
9281da177e4SLinus Torvalds  * Description: Setup and/or Search for cards and return info to caller.
9291da177e4SLinus Torvalds  *
9301da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
9311da177e4SLinus Torvalds 
9327f101662SAlexey Dobriyan static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo)
9331da177e4SLinus Torvalds {
934db038cf8SAlexey Dobriyan 	static unsigned char first_time = 1;
9351da177e4SLinus Torvalds 
936db038cf8SAlexey Dobriyan 	unsigned char i, j, id, ScamFlg;
937c823feebSAlexey Dobriyan 	unsigned short temp, temp2, temp3, temp4, temp5, temp6;
938d63a4cccSAlexey Dobriyan 	unsigned long ioport;
93968d0c1aeSAlexey Dobriyan 	struct nvram_info *pCurrNvRam;
9401da177e4SLinus Torvalds 
9411da177e4SLinus Torvalds 	ioport = pCardInfo->si_baseaddr;
9421da177e4SLinus Torvalds 
9431da177e4SLinus Torvalds 	if (RD_HARPOON(ioport + hp_vendor_id_0) != ORION_VEND_0)
9445c1b85e2SAlexey Dobriyan 		return (int)FAILURE;
9451da177e4SLinus Torvalds 
9461da177e4SLinus Torvalds 	if ((RD_HARPOON(ioport + hp_vendor_id_1) != ORION_VEND_1))
9475c1b85e2SAlexey Dobriyan 		return (int)FAILURE;
9481da177e4SLinus Torvalds 
9491da177e4SLinus Torvalds 	if ((RD_HARPOON(ioport + hp_device_id_0) != ORION_DEV_0))
9505c1b85e2SAlexey Dobriyan 		return (int)FAILURE;
9511da177e4SLinus Torvalds 
9521da177e4SLinus Torvalds 	if ((RD_HARPOON(ioport + hp_device_id_1) != ORION_DEV_1))
9535c1b85e2SAlexey Dobriyan 		return (int)FAILURE;
9541da177e4SLinus Torvalds 
9551da177e4SLinus Torvalds 	if (RD_HARPOON(ioport + hp_rev_num) != 0x0f) {
9561da177e4SLinus Torvalds 
9571da177e4SLinus Torvalds /* For new Harpoon then check for sub_device ID LSB
9581da177e4SLinus Torvalds    the bits(0-3) must be all ZERO for compatible with
9591da177e4SLinus Torvalds    current version of SCCBMgr, else skip this Harpoon
9601da177e4SLinus Torvalds 	device. */
9611da177e4SLinus Torvalds 
9621da177e4SLinus Torvalds 		if (RD_HARPOON(ioport + hp_sub_device_id_0) & 0x0f)
9635c1b85e2SAlexey Dobriyan 			return (int)FAILURE;
9641da177e4SLinus Torvalds 	}
9651da177e4SLinus Torvalds 
9665c04a7b8SAlexey Dobriyan 	if (first_time) {
96747b5d69cSJames Bottomley  		FPT_SccbMgrTableInitAll();
9681da177e4SLinus Torvalds 		first_time = 0;
96947b5d69cSJames Bottomley  		FPT_mbCards = 0;
9701da177e4SLinus Torvalds 	}
9711da177e4SLinus Torvalds 
97247b5d69cSJames Bottomley  	if (FPT_RdStack(ioport, 0) != 0x00) {
9735c04a7b8SAlexey Dobriyan 		if (FPT_ChkIfChipInitialized(ioport) == 0) {
9741da177e4SLinus Torvalds 			pCurrNvRam = NULL;
9751da177e4SLinus Torvalds 			WR_HARPOON(ioport + hp_semaphore, 0x00);
97647b5d69cSJames Bottomley  			FPT_XbowInit(ioport, 0);	/*Must Init the SCSI before attempting */
97747b5d69cSJames Bottomley  			FPT_DiagEEPROM(ioport);
9785c04a7b8SAlexey Dobriyan 		} else {
97947b5d69cSJames Bottomley  			if (FPT_mbCards < MAX_MB_CARDS) {
98047b5d69cSJames Bottomley  				pCurrNvRam = &FPT_nvRamInfo[FPT_mbCards];
98147b5d69cSJames Bottomley  				FPT_mbCards++;
9821da177e4SLinus Torvalds 				pCurrNvRam->niBaseAddr = ioport;
98347b5d69cSJames Bottomley  				FPT_RNVRamData(pCurrNvRam);
9841da177e4SLinus Torvalds 			} else
9855c1b85e2SAlexey Dobriyan 				return (int)FAILURE;
9861da177e4SLinus Torvalds 		}
9871da177e4SLinus Torvalds 	} else
9881da177e4SLinus Torvalds 		pCurrNvRam = NULL;
9891da177e4SLinus Torvalds 
9901da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT);
9911da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_sys_ctrl, 0x00);
9921da177e4SLinus Torvalds 
9931da177e4SLinus Torvalds 	if (pCurrNvRam)
9941da177e4SLinus Torvalds 		pCardInfo->si_id = pCurrNvRam->niAdapId;
9951da177e4SLinus Torvalds 	else
9965c04a7b8SAlexey Dobriyan 		pCardInfo->si_id =
9975c04a7b8SAlexey Dobriyan 		    (unsigned
9985c04a7b8SAlexey Dobriyan 		     char)(FPT_utilEERead(ioport,
9995c04a7b8SAlexey Dobriyan 					  (ADAPTER_SCSI_ID /
10005c04a7b8SAlexey Dobriyan 					   2)) & (unsigned char)0x0FF);
10011da177e4SLinus Torvalds 
10021da177e4SLinus Torvalds 	pCardInfo->si_lun = 0x00;
10031da177e4SLinus Torvalds 	pCardInfo->si_fw_revision = ORION_FW_REV;
10041da177e4SLinus Torvalds 	temp2 = 0x0000;
10051da177e4SLinus Torvalds 	temp3 = 0x0000;
10061da177e4SLinus Torvalds 	temp4 = 0x0000;
10071da177e4SLinus Torvalds 	temp5 = 0x0000;
10081da177e4SLinus Torvalds 	temp6 = 0x0000;
10091da177e4SLinus Torvalds 
10101da177e4SLinus Torvalds 	for (id = 0; id < (16 / 2); id++) {
10111da177e4SLinus Torvalds 
10121da177e4SLinus Torvalds 		if (pCurrNvRam) {
1013c823feebSAlexey Dobriyan 			temp = (unsigned short)pCurrNvRam->niSyncTbl[id];
10141da177e4SLinus Torvalds 			temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
10151da177e4SLinus Torvalds 			    (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
10161da177e4SLinus Torvalds 		} else
10175c04a7b8SAlexey Dobriyan 			temp =
10185c04a7b8SAlexey Dobriyan 			    FPT_utilEERead(ioport,
10195c04a7b8SAlexey Dobriyan 					   (unsigned short)((SYNC_RATE_TBL / 2)
10205c04a7b8SAlexey Dobriyan 							    + id));
10211da177e4SLinus Torvalds 
10221da177e4SLinus Torvalds 		for (i = 0; i < 2; temp >>= 8, i++) {
10231da177e4SLinus Torvalds 
10241da177e4SLinus Torvalds 			temp2 >>= 1;
10251da177e4SLinus Torvalds 			temp3 >>= 1;
10261da177e4SLinus Torvalds 			temp4 >>= 1;
10271da177e4SLinus Torvalds 			temp5 >>= 1;
10281da177e4SLinus Torvalds 			temp6 >>= 1;
10295c04a7b8SAlexey Dobriyan 			switch (temp & 0x3) {
10301da177e4SLinus Torvalds 			case AUTO_RATE_20:	/* Synchronous, 20 mega-transfers/second */
10311da177e4SLinus Torvalds 				temp6 |= 0x8000;	/* Fall through */
10321da177e4SLinus Torvalds 			case AUTO_RATE_10:	/* Synchronous, 10 mega-transfers/second */
10331da177e4SLinus Torvalds 				temp5 |= 0x8000;	/* Fall through */
10341da177e4SLinus Torvalds 			case AUTO_RATE_05:	/* Synchronous, 5 mega-transfers/second */
10351da177e4SLinus Torvalds 				temp2 |= 0x8000;	/* Fall through */
10361da177e4SLinus Torvalds 			case AUTO_RATE_00:	/* Asynchronous */
10371da177e4SLinus Torvalds 				break;
10381da177e4SLinus Torvalds 			}
10391da177e4SLinus Torvalds 
10401da177e4SLinus Torvalds 			if (temp & DISC_ENABLE_BIT)
10411da177e4SLinus Torvalds 				temp3 |= 0x8000;
10421da177e4SLinus Torvalds 
10431da177e4SLinus Torvalds 			if (temp & WIDE_NEGO_BIT)
10441da177e4SLinus Torvalds 				temp4 |= 0x8000;
10451da177e4SLinus Torvalds 
10461da177e4SLinus Torvalds 		}
10471da177e4SLinus Torvalds 	}
10481da177e4SLinus Torvalds 
10491da177e4SLinus Torvalds 	pCardInfo->si_per_targ_init_sync = temp2;
10501da177e4SLinus Torvalds 	pCardInfo->si_per_targ_no_disc = temp3;
10511da177e4SLinus Torvalds 	pCardInfo->si_per_targ_wide_nego = temp4;
10521da177e4SLinus Torvalds 	pCardInfo->si_per_targ_fast_nego = temp5;
10531da177e4SLinus Torvalds 	pCardInfo->si_per_targ_ultra_nego = temp6;
10541da177e4SLinus Torvalds 
10551da177e4SLinus Torvalds 	if (pCurrNvRam)
10561da177e4SLinus Torvalds 		i = pCurrNvRam->niSysConf;
10571da177e4SLinus Torvalds 	else
10585c04a7b8SAlexey Dobriyan 		i = (unsigned
10595c04a7b8SAlexey Dobriyan 		     char)(FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)));
10601da177e4SLinus Torvalds 
10611da177e4SLinus Torvalds 	if (pCurrNvRam)
10621da177e4SLinus Torvalds 		ScamFlg = pCurrNvRam->niScamConf;
10631da177e4SLinus Torvalds 	else
10645c04a7b8SAlexey Dobriyan 		ScamFlg =
10655c04a7b8SAlexey Dobriyan 		    (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
10661da177e4SLinus Torvalds 
10671da177e4SLinus Torvalds 	pCardInfo->si_flags = 0x0000;
10681da177e4SLinus Torvalds 
10691da177e4SLinus Torvalds 	if (i & 0x01)
10701da177e4SLinus Torvalds 		pCardInfo->si_flags |= SCSI_PARITY_ENA;
10711da177e4SLinus Torvalds 
10721da177e4SLinus Torvalds 	if (!(i & 0x02))
10731da177e4SLinus Torvalds 		pCardInfo->si_flags |= SOFT_RESET;
10741da177e4SLinus Torvalds 
10751da177e4SLinus Torvalds 	if (i & 0x10)
10761da177e4SLinus Torvalds 		pCardInfo->si_flags |= EXTENDED_TRANSLATION;
10771da177e4SLinus Torvalds 
10781da177e4SLinus Torvalds 	if (ScamFlg & SCAM_ENABLED)
10791da177e4SLinus Torvalds 		pCardInfo->si_flags |= FLAG_SCAM_ENABLED;
10801da177e4SLinus Torvalds 
10811da177e4SLinus Torvalds 	if (ScamFlg & SCAM_LEVEL2)
10821da177e4SLinus Torvalds 		pCardInfo->si_flags |= FLAG_SCAM_LEVEL2;
10831da177e4SLinus Torvalds 
10841da177e4SLinus Torvalds 	j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
10851da177e4SLinus Torvalds 	if (i & 0x04) {
10861da177e4SLinus Torvalds 		j |= SCSI_TERM_ENA_L;
10871da177e4SLinus Torvalds 	}
10881da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_bm_ctrl, j);
10891da177e4SLinus Torvalds 
10901da177e4SLinus Torvalds 	j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
10911da177e4SLinus Torvalds 	if (i & 0x08) {
10921da177e4SLinus Torvalds 		j |= SCSI_TERM_ENA_H;
10931da177e4SLinus Torvalds 	}
10941da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_ee_ctrl, j);
10951da177e4SLinus Torvalds 
10961da177e4SLinus Torvalds 	if (!(RD_HARPOON(ioport + hp_page_ctrl) & NARROW_SCSI_CARD))
10971da177e4SLinus Torvalds 
10981da177e4SLinus Torvalds 		pCardInfo->si_flags |= SUPPORT_16TAR_32LUN;
10991da177e4SLinus Torvalds 
11001da177e4SLinus Torvalds 	pCardInfo->si_card_family = HARPOON_FAMILY;
11011da177e4SLinus Torvalds 	pCardInfo->si_bustype = BUSTYPE_PCI;
11021da177e4SLinus Torvalds 
11031da177e4SLinus Torvalds 	if (pCurrNvRam) {
11041da177e4SLinus Torvalds 		pCardInfo->si_card_model[0] = '9';
11051da177e4SLinus Torvalds 		switch (pCurrNvRam->niModel & 0x0f) {
11061da177e4SLinus Torvalds 		case MODEL_LT:
11071da177e4SLinus Torvalds 			pCardInfo->si_card_model[1] = '3';
11081da177e4SLinus Torvalds 			pCardInfo->si_card_model[2] = '0';
11091da177e4SLinus Torvalds 			break;
11101da177e4SLinus Torvalds 		case MODEL_LW:
11111da177e4SLinus Torvalds 			pCardInfo->si_card_model[1] = '5';
11121da177e4SLinus Torvalds 			pCardInfo->si_card_model[2] = '0';
11131da177e4SLinus Torvalds 			break;
11141da177e4SLinus Torvalds 		case MODEL_DL:
11151da177e4SLinus Torvalds 			pCardInfo->si_card_model[1] = '3';
11161da177e4SLinus Torvalds 			pCardInfo->si_card_model[2] = '2';
11171da177e4SLinus Torvalds 			break;
11181da177e4SLinus Torvalds 		case MODEL_DW:
11191da177e4SLinus Torvalds 			pCardInfo->si_card_model[1] = '5';
11201da177e4SLinus Torvalds 			pCardInfo->si_card_model[2] = '2';
11211da177e4SLinus Torvalds 			break;
11221da177e4SLinus Torvalds 		}
11231da177e4SLinus Torvalds 	} else {
112447b5d69cSJames Bottomley  		temp = FPT_utilEERead(ioport, (MODEL_NUMB_0 / 2));
1125db038cf8SAlexey Dobriyan 		pCardInfo->si_card_model[0] = (unsigned char)(temp >> 8);
112647b5d69cSJames Bottomley  		temp = FPT_utilEERead(ioport, (MODEL_NUMB_2 / 2));
11271da177e4SLinus Torvalds 
1128db038cf8SAlexey Dobriyan 		pCardInfo->si_card_model[1] = (unsigned char)(temp & 0x00FF);
1129db038cf8SAlexey Dobriyan 		pCardInfo->si_card_model[2] = (unsigned char)(temp >> 8);
11301da177e4SLinus Torvalds 	}
11311da177e4SLinus Torvalds 
11325c04a7b8SAlexey Dobriyan 	if (pCardInfo->si_card_model[1] == '3') {
11331da177e4SLinus Torvalds 		if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
11341da177e4SLinus Torvalds 			pCardInfo->si_flags |= LOW_BYTE_TERM;
11355c04a7b8SAlexey Dobriyan 	} else if (pCardInfo->si_card_model[2] == '0') {
11361da177e4SLinus Torvalds 		temp = RD_HARPOON(ioport + hp_xfer_pad);
11371da177e4SLinus Torvalds 		WR_HARPOON(ioport + hp_xfer_pad, (temp & ~BIT(4)));
11381da177e4SLinus Torvalds 		if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
11391da177e4SLinus Torvalds 			pCardInfo->si_flags |= LOW_BYTE_TERM;
11401da177e4SLinus Torvalds 		WR_HARPOON(ioport + hp_xfer_pad, (temp | BIT(4)));
11411da177e4SLinus Torvalds 		if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
11421da177e4SLinus Torvalds 			pCardInfo->si_flags |= HIGH_BYTE_TERM;
11431da177e4SLinus Torvalds 		WR_HARPOON(ioport + hp_xfer_pad, temp);
11445c04a7b8SAlexey Dobriyan 	} else {
11451da177e4SLinus Torvalds 		temp = RD_HARPOON(ioport + hp_ee_ctrl);
11461da177e4SLinus Torvalds 		temp2 = RD_HARPOON(ioport + hp_xfer_pad);
11471da177e4SLinus Torvalds 		WR_HARPOON(ioport + hp_ee_ctrl, (temp | SEE_CS));
11481da177e4SLinus Torvalds 		WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4)));
11491da177e4SLinus Torvalds 		temp3 = 0;
11505c04a7b8SAlexey Dobriyan 		for (i = 0; i < 8; i++) {
11511da177e4SLinus Torvalds 			temp3 <<= 1;
11521da177e4SLinus Torvalds 			if (!(RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7)))
11531da177e4SLinus Torvalds 				temp3 |= 1;
11541da177e4SLinus Torvalds 			WR_HARPOON(ioport + hp_xfer_pad, (temp2 & ~BIT(4)));
11551da177e4SLinus Torvalds 			WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4)));
11561da177e4SLinus Torvalds 		}
11571da177e4SLinus Torvalds 		WR_HARPOON(ioport + hp_ee_ctrl, temp);
11581da177e4SLinus Torvalds 		WR_HARPOON(ioport + hp_xfer_pad, temp2);
11591da177e4SLinus Torvalds 		if (!(temp3 & BIT(7)))
11601da177e4SLinus Torvalds 			pCardInfo->si_flags |= LOW_BYTE_TERM;
11611da177e4SLinus Torvalds 		if (!(temp3 & BIT(6)))
11621da177e4SLinus Torvalds 			pCardInfo->si_flags |= HIGH_BYTE_TERM;
11631da177e4SLinus Torvalds 	}
11641da177e4SLinus Torvalds 
11651da177e4SLinus Torvalds 	ARAM_ACCESS(ioport);
11661da177e4SLinus Torvalds 
11671da177e4SLinus Torvalds 	for (i = 0; i < 4; i++) {
11681da177e4SLinus Torvalds 
11691da177e4SLinus Torvalds 		pCardInfo->si_XlatInfo[i] =
11701da177e4SLinus Torvalds 		    RD_HARPOON(ioport + hp_aramBase + BIOS_DATA_OFFSET + i);
11711da177e4SLinus Torvalds 	}
11721da177e4SLinus Torvalds 
11731da177e4SLinus Torvalds 	/* return with -1 if no sort, else return with
11741da177e4SLinus Torvalds 	   logical card number sorted by BIOS (zero-based) */
11751da177e4SLinus Torvalds 
11761da177e4SLinus Torvalds 	pCardInfo->si_relative_cardnum =
11775c04a7b8SAlexey Dobriyan 	    (unsigned
11785c04a7b8SAlexey Dobriyan 	     char)(RD_HARPOON(ioport + hp_aramBase + BIOS_RELATIVE_CARD) - 1);
11791da177e4SLinus Torvalds 
11801da177e4SLinus Torvalds 	SGRAM_ACCESS(ioport);
11811da177e4SLinus Torvalds 
118247b5d69cSJames Bottomley  	FPT_s_PhaseTbl[0] = FPT_phaseDataOut;
118347b5d69cSJames Bottomley  	FPT_s_PhaseTbl[1] = FPT_phaseDataIn;
118447b5d69cSJames Bottomley  	FPT_s_PhaseTbl[2] = FPT_phaseIllegal;
118547b5d69cSJames Bottomley  	FPT_s_PhaseTbl[3] = FPT_phaseIllegal;
118647b5d69cSJames Bottomley  	FPT_s_PhaseTbl[4] = FPT_phaseCommand;
118747b5d69cSJames Bottomley  	FPT_s_PhaseTbl[5] = FPT_phaseStatus;
118847b5d69cSJames Bottomley  	FPT_s_PhaseTbl[6] = FPT_phaseMsgOut;
118947b5d69cSJames Bottomley  	FPT_s_PhaseTbl[7] = FPT_phaseMsgIn;
11901da177e4SLinus Torvalds 
11911da177e4SLinus Torvalds 	pCardInfo->si_present = 0x01;
11921da177e4SLinus Torvalds 
11935c1b85e2SAlexey Dobriyan 	return 0;
11941da177e4SLinus Torvalds }
11951da177e4SLinus Torvalds 
11961da177e4SLinus Torvalds /*---------------------------------------------------------------------
11971da177e4SLinus Torvalds  *
1198d8b6b8bdSAlexey Dobriyan  * Function: FlashPoint_HardwareResetHostAdapter
11991da177e4SLinus Torvalds  *
12001da177e4SLinus Torvalds  * Description: Setup adapter for normal operation (hard reset).
12011da177e4SLinus Torvalds  *
12021da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
12031da177e4SLinus Torvalds 
12045c04a7b8SAlexey Dobriyan static unsigned long FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info
12055c04a7b8SAlexey Dobriyan 							 *pCardInfo)
12061da177e4SLinus Torvalds {
120713e6851aSAlexey Dobriyan 	struct sccb_card *CurrCard = NULL;
120868d0c1aeSAlexey Dobriyan 	struct nvram_info *pCurrNvRam;
1209db038cf8SAlexey Dobriyan 	unsigned char i, j, thisCard, ScamFlg;
1210c823feebSAlexey Dobriyan 	unsigned short temp, sync_bit_map, id;
1211d63a4cccSAlexey Dobriyan 	unsigned long ioport;
12121da177e4SLinus Torvalds 
12131da177e4SLinus Torvalds 	ioport = pCardInfo->si_baseaddr;
12141da177e4SLinus Torvalds 
12151da177e4SLinus Torvalds 	for (thisCard = 0; thisCard <= MAX_CARDS; thisCard++) {
12161da177e4SLinus Torvalds 
12171da177e4SLinus Torvalds 		if (thisCard == MAX_CARDS) {
12181da177e4SLinus Torvalds 
12195c1b85e2SAlexey Dobriyan 			return FAILURE;
12201da177e4SLinus Torvalds 		}
12211da177e4SLinus Torvalds 
122247b5d69cSJames Bottomley  		if (FPT_BL_Card[thisCard].ioPort == ioport) {
12231da177e4SLinus Torvalds 
122447b5d69cSJames Bottomley  			CurrCard = &FPT_BL_Card[thisCard];
122547b5d69cSJames Bottomley  			FPT_SccbMgrTableInitCard(CurrCard, thisCard);
12261da177e4SLinus Torvalds 			break;
12271da177e4SLinus Torvalds 		}
12281da177e4SLinus Torvalds 
122947b5d69cSJames Bottomley  		else if (FPT_BL_Card[thisCard].ioPort == 0x00) {
12301da177e4SLinus Torvalds 
123147b5d69cSJames Bottomley  			FPT_BL_Card[thisCard].ioPort = ioport;
123247b5d69cSJames Bottomley  			CurrCard = &FPT_BL_Card[thisCard];
12331da177e4SLinus Torvalds 
123447b5d69cSJames Bottomley  			if (FPT_mbCards)
123547b5d69cSJames Bottomley  				for (i = 0; i < FPT_mbCards; i++) {
12365c04a7b8SAlexey Dobriyan 					if (CurrCard->ioPort ==
12375c04a7b8SAlexey Dobriyan 					    FPT_nvRamInfo[i].niBaseAddr)
12385c04a7b8SAlexey Dobriyan 						CurrCard->pNvRamInfo =
12395c04a7b8SAlexey Dobriyan 						    &FPT_nvRamInfo[i];
12401da177e4SLinus Torvalds 				}
124147b5d69cSJames Bottomley  			FPT_SccbMgrTableInitCard(CurrCard, thisCard);
12421da177e4SLinus Torvalds 			CurrCard->cardIndex = thisCard;
12431da177e4SLinus Torvalds 			CurrCard->cardInfo = pCardInfo;
12441da177e4SLinus Torvalds 
12451da177e4SLinus Torvalds 			break;
12461da177e4SLinus Torvalds 		}
12471da177e4SLinus Torvalds 	}
12481da177e4SLinus Torvalds 
12491da177e4SLinus Torvalds 	pCurrNvRam = CurrCard->pNvRamInfo;
12501da177e4SLinus Torvalds 
12511da177e4SLinus Torvalds 	if (pCurrNvRam) {
12521da177e4SLinus Torvalds 		ScamFlg = pCurrNvRam->niScamConf;
12535c04a7b8SAlexey Dobriyan 	} else {
12545c04a7b8SAlexey Dobriyan 		ScamFlg =
12555c04a7b8SAlexey Dobriyan 		    (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
12561da177e4SLinus Torvalds 	}
12571da177e4SLinus Torvalds 
125847b5d69cSJames Bottomley  	FPT_BusMasterInit(ioport);
125947b5d69cSJames Bottomley  	FPT_XbowInit(ioport, ScamFlg);
12601da177e4SLinus Torvalds 
126147b5d69cSJames Bottomley  	FPT_autoLoadDefaultMap(ioport);
12621da177e4SLinus Torvalds 
12635c04a7b8SAlexey Dobriyan 	for (i = 0, id = 0x01; i != pCardInfo->si_id; i++, id <<= 1) {
12645c04a7b8SAlexey Dobriyan 	}
12651da177e4SLinus Torvalds 
12661da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_selfid_0, id);
12671da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_selfid_1, 0x00);
12681da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_arb_id, pCardInfo->si_id);
12691da177e4SLinus Torvalds 	CurrCard->ourId = pCardInfo->si_id;
12701da177e4SLinus Torvalds 
1271db038cf8SAlexey Dobriyan 	i = (unsigned char)pCardInfo->si_flags;
12721da177e4SLinus Torvalds 	if (i & SCSI_PARITY_ENA)
12731da177e4SLinus Torvalds 		WR_HARPOON(ioport + hp_portctrl_1, (HOST_MODE8 | CHK_SCSI_P));
12741da177e4SLinus Torvalds 
12751da177e4SLinus Torvalds 	j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
12761da177e4SLinus Torvalds 	if (i & LOW_BYTE_TERM)
12771da177e4SLinus Torvalds 		j |= SCSI_TERM_ENA_L;
12781da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_bm_ctrl, j);
12791da177e4SLinus Torvalds 
12801da177e4SLinus Torvalds 	j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
12811da177e4SLinus Torvalds 	if (i & HIGH_BYTE_TERM)
12821da177e4SLinus Torvalds 		j |= SCSI_TERM_ENA_H;
12831da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_ee_ctrl, j);
12841da177e4SLinus Torvalds 
12851da177e4SLinus Torvalds 	if (!(pCardInfo->si_flags & SOFT_RESET)) {
12861da177e4SLinus Torvalds 
128747b5d69cSJames Bottomley  		FPT_sresb(ioport, thisCard);
12881da177e4SLinus Torvalds 
128947b5d69cSJames Bottomley  		FPT_scini(thisCard, pCardInfo->si_id, 0);
12901da177e4SLinus Torvalds 	}
12911da177e4SLinus Torvalds 
12921da177e4SLinus Torvalds 	if (pCardInfo->si_flags & POST_ALL_UNDERRRUNS)
12931da177e4SLinus Torvalds 		CurrCard->globalFlags |= F_NO_FILTER;
12941da177e4SLinus Torvalds 
12951da177e4SLinus Torvalds 	if (pCurrNvRam) {
12961da177e4SLinus Torvalds 		if (pCurrNvRam->niSysConf & 0x10)
12971da177e4SLinus Torvalds 			CurrCard->globalFlags |= F_GREEN_PC;
12985c04a7b8SAlexey Dobriyan 	} else {
129947b5d69cSJames Bottomley  		if (FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)) & GREEN_PC_ENA)
13001da177e4SLinus Torvalds 			CurrCard->globalFlags |= F_GREEN_PC;
13011da177e4SLinus Torvalds 	}
13021da177e4SLinus Torvalds 
13031da177e4SLinus Torvalds 	/* Set global flag to indicate Re-Negotiation to be done on all
13041da177e4SLinus Torvalds 	   ckeck condition */
13051da177e4SLinus Torvalds 	if (pCurrNvRam) {
13061da177e4SLinus Torvalds 		if (pCurrNvRam->niScsiConf & 0x04)
13071da177e4SLinus Torvalds 			CurrCard->globalFlags |= F_DO_RENEGO;
13085c04a7b8SAlexey Dobriyan 	} else {
130947b5d69cSJames Bottomley  		if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & RENEGO_ENA)
13101da177e4SLinus Torvalds 			CurrCard->globalFlags |= F_DO_RENEGO;
13111da177e4SLinus Torvalds 	}
13121da177e4SLinus Torvalds 
13131da177e4SLinus Torvalds 	if (pCurrNvRam) {
13141da177e4SLinus Torvalds 		if (pCurrNvRam->niScsiConf & 0x08)
13151da177e4SLinus Torvalds 			CurrCard->globalFlags |= F_CONLUN_IO;
13165c04a7b8SAlexey Dobriyan 	} else {
131747b5d69cSJames Bottomley  		if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & CONNIO_ENA)
13181da177e4SLinus Torvalds 			CurrCard->globalFlags |= F_CONLUN_IO;
13191da177e4SLinus Torvalds 	}
13201da177e4SLinus Torvalds 
13211da177e4SLinus Torvalds 	temp = pCardInfo->si_per_targ_no_disc;
13221da177e4SLinus Torvalds 
13231da177e4SLinus Torvalds 	for (i = 0, id = 1; i < MAX_SCSI_TAR; i++, id <<= 1) {
13241da177e4SLinus Torvalds 
13251da177e4SLinus Torvalds 		if (temp & id)
132647b5d69cSJames Bottomley  			FPT_sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC;
13271da177e4SLinus Torvalds 	}
13281da177e4SLinus Torvalds 
13291da177e4SLinus Torvalds 	sync_bit_map = 0x0001;
13301da177e4SLinus Torvalds 
13311da177e4SLinus Torvalds 	for (id = 0; id < (MAX_SCSI_TAR / 2); id++) {
13321da177e4SLinus Torvalds 
13331da177e4SLinus Torvalds 		if (pCurrNvRam) {
1334c823feebSAlexey Dobriyan 			temp = (unsigned short)pCurrNvRam->niSyncTbl[id];
13351da177e4SLinus Torvalds 			temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
13361da177e4SLinus Torvalds 			    (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
13371da177e4SLinus Torvalds 		} else
13385c04a7b8SAlexey Dobriyan 			temp =
13395c04a7b8SAlexey Dobriyan 			    FPT_utilEERead(ioport,
13405c04a7b8SAlexey Dobriyan 					   (unsigned short)((SYNC_RATE_TBL / 2)
13415c04a7b8SAlexey Dobriyan 							    + id));
13421da177e4SLinus Torvalds 
13431da177e4SLinus Torvalds 		for (i = 0; i < 2; temp >>= 8, i++) {
13441da177e4SLinus Torvalds 
13451da177e4SLinus Torvalds 			if (pCardInfo->si_per_targ_init_sync & sync_bit_map) {
13461da177e4SLinus Torvalds 
13475c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[thisCard][id * 2 +
13485c04a7b8SAlexey Dobriyan 							 i].TarEEValue =
13495c04a7b8SAlexey Dobriyan 				    (unsigned char)temp;
13501da177e4SLinus Torvalds 			}
13511da177e4SLinus Torvalds 
13521da177e4SLinus Torvalds 			else {
13535c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[thisCard][id * 2 +
13545c04a7b8SAlexey Dobriyan 							 i].TarStatus |=
13555c04a7b8SAlexey Dobriyan 				    SYNC_SUPPORTED;
13565c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[thisCard][id * 2 +
13575c04a7b8SAlexey Dobriyan 							 i].TarEEValue =
1358db038cf8SAlexey Dobriyan 				    (unsigned char)(temp & ~EE_SYNC_MASK);
13591da177e4SLinus Torvalds 			}
13601da177e4SLinus Torvalds 
13611da177e4SLinus Torvalds /*         if ((pCardInfo->si_per_targ_wide_nego & sync_bit_map) ||
13621da177e4SLinus Torvalds             (id*2+i >= 8)){
13631da177e4SLinus Torvalds */
13641da177e4SLinus Torvalds 			if (pCardInfo->si_per_targ_wide_nego & sync_bit_map) {
13651da177e4SLinus Torvalds 
13665c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[thisCard][id * 2 +
13675c04a7b8SAlexey Dobriyan 							 i].TarEEValue |=
13685c04a7b8SAlexey Dobriyan 				    EE_WIDE_SCSI;
13691da177e4SLinus Torvalds 
13701da177e4SLinus Torvalds 			}
13711da177e4SLinus Torvalds 
13721da177e4SLinus Torvalds 			else {	/* NARROW SCSI */
13735c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[thisCard][id * 2 +
13745c04a7b8SAlexey Dobriyan 							 i].TarStatus |=
13755c04a7b8SAlexey Dobriyan 				    WIDE_NEGOCIATED;
13761da177e4SLinus Torvalds 			}
13771da177e4SLinus Torvalds 
13781da177e4SLinus Torvalds 			sync_bit_map <<= 1;
13791da177e4SLinus Torvalds 
13801da177e4SLinus Torvalds 		}
13811da177e4SLinus Torvalds 	}
13821da177e4SLinus Torvalds 
13831da177e4SLinus Torvalds 	WR_HARPOON((ioport + hp_semaphore),
13845c04a7b8SAlexey Dobriyan 		   (unsigned char)(RD_HARPOON((ioport + hp_semaphore)) |
13855c04a7b8SAlexey Dobriyan 				   SCCB_MGR_PRESENT));
13861da177e4SLinus Torvalds 
13875c1b85e2SAlexey Dobriyan 	return (unsigned long)CurrCard;
13881da177e4SLinus Torvalds }
13891da177e4SLinus Torvalds 
1390d63a4cccSAlexey Dobriyan static void FlashPoint_ReleaseHostAdapter(unsigned long pCurrCard)
13911da177e4SLinus Torvalds {
1392db038cf8SAlexey Dobriyan 	unsigned char i;
1393d63a4cccSAlexey Dobriyan 	unsigned long portBase;
1394d63a4cccSAlexey Dobriyan 	unsigned long regOffset;
1395d63a4cccSAlexey Dobriyan 	unsigned long scamData;
1396d63a4cccSAlexey Dobriyan 	unsigned long *pScamTbl;
139768d0c1aeSAlexey Dobriyan 	struct nvram_info *pCurrNvRam;
13981da177e4SLinus Torvalds 
139913e6851aSAlexey Dobriyan 	pCurrNvRam = ((struct sccb_card *)pCurrCard)->pNvRamInfo;
14001da177e4SLinus Torvalds 
14011da177e4SLinus Torvalds 	if (pCurrNvRam) {
140247b5d69cSJames Bottomley  		FPT_WrStack(pCurrNvRam->niBaseAddr, 0, pCurrNvRam->niModel);
140347b5d69cSJames Bottomley  		FPT_WrStack(pCurrNvRam->niBaseAddr, 1, pCurrNvRam->niSysConf);
140447b5d69cSJames Bottomley  		FPT_WrStack(pCurrNvRam->niBaseAddr, 2, pCurrNvRam->niScsiConf);
140547b5d69cSJames Bottomley  		FPT_WrStack(pCurrNvRam->niBaseAddr, 3, pCurrNvRam->niScamConf);
140647b5d69cSJames Bottomley  		FPT_WrStack(pCurrNvRam->niBaseAddr, 4, pCurrNvRam->niAdapId);
14071da177e4SLinus Torvalds 
14081da177e4SLinus Torvalds 		for (i = 0; i < MAX_SCSI_TAR / 2; i++)
14095c04a7b8SAlexey Dobriyan 			FPT_WrStack(pCurrNvRam->niBaseAddr,
14105c04a7b8SAlexey Dobriyan 				    (unsigned char)(i + 5),
14115c04a7b8SAlexey Dobriyan 				    pCurrNvRam->niSyncTbl[i]);
14121da177e4SLinus Torvalds 
14131da177e4SLinus Torvalds 		portBase = pCurrNvRam->niBaseAddr;
14141da177e4SLinus Torvalds 
14151da177e4SLinus Torvalds 		for (i = 0; i < MAX_SCSI_TAR; i++) {
14161da177e4SLinus Torvalds 			regOffset = hp_aramBase + 64 + i * 4;
1417d63a4cccSAlexey Dobriyan 			pScamTbl = (unsigned long *)&pCurrNvRam->niScamTbl[i];
14181da177e4SLinus Torvalds 			scamData = *pScamTbl;
14191da177e4SLinus Torvalds 			WR_HARP32(portBase, regOffset, scamData);
14201da177e4SLinus Torvalds 		}
14211da177e4SLinus Torvalds 
14221da177e4SLinus Torvalds 	} else {
142313e6851aSAlexey Dobriyan 		FPT_WrStack(((struct sccb_card *)pCurrCard)->ioPort, 0, 0);
14241da177e4SLinus Torvalds 	}
14251da177e4SLinus Torvalds }
14261da177e4SLinus Torvalds 
142768d0c1aeSAlexey Dobriyan static void FPT_RNVRamData(struct nvram_info *pNvRamInfo)
14281da177e4SLinus Torvalds {
1429db038cf8SAlexey Dobriyan 	unsigned char i;
1430d63a4cccSAlexey Dobriyan 	unsigned long portBase;
1431d63a4cccSAlexey Dobriyan 	unsigned long regOffset;
1432d63a4cccSAlexey Dobriyan 	unsigned long scamData;
1433d63a4cccSAlexey Dobriyan 	unsigned long *pScamTbl;
14341da177e4SLinus Torvalds 
143547b5d69cSJames Bottomley  	pNvRamInfo->niModel = FPT_RdStack(pNvRamInfo->niBaseAddr, 0);
143647b5d69cSJames Bottomley  	pNvRamInfo->niSysConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 1);
143747b5d69cSJames Bottomley  	pNvRamInfo->niScsiConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 2);
143847b5d69cSJames Bottomley  	pNvRamInfo->niScamConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 3);
143947b5d69cSJames Bottomley  	pNvRamInfo->niAdapId = FPT_RdStack(pNvRamInfo->niBaseAddr, 4);
14401da177e4SLinus Torvalds 
14411da177e4SLinus Torvalds 	for (i = 0; i < MAX_SCSI_TAR / 2; i++)
14425c04a7b8SAlexey Dobriyan 		pNvRamInfo->niSyncTbl[i] =
14435c04a7b8SAlexey Dobriyan 		    FPT_RdStack(pNvRamInfo->niBaseAddr, (unsigned char)(i + 5));
14441da177e4SLinus Torvalds 
14451da177e4SLinus Torvalds 	portBase = pNvRamInfo->niBaseAddr;
14461da177e4SLinus Torvalds 
14471da177e4SLinus Torvalds 	for (i = 0; i < MAX_SCSI_TAR; i++) {
14481da177e4SLinus Torvalds 		regOffset = hp_aramBase + 64 + i * 4;
14491da177e4SLinus Torvalds 		RD_HARP32(portBase, regOffset, scamData);
1450d63a4cccSAlexey Dobriyan 		pScamTbl = (unsigned long *)&pNvRamInfo->niScamTbl[i];
14511da177e4SLinus Torvalds 		*pScamTbl = scamData;
14521da177e4SLinus Torvalds 	}
14531da177e4SLinus Torvalds 
14541da177e4SLinus Torvalds }
14551da177e4SLinus Torvalds 
1456d63a4cccSAlexey Dobriyan static unsigned char FPT_RdStack(unsigned long portBase, unsigned char index)
14571da177e4SLinus Torvalds {
14581da177e4SLinus Torvalds 	WR_HARPOON(portBase + hp_stack_addr, index);
14595c1b85e2SAlexey Dobriyan 	return RD_HARPOON(portBase + hp_stack_data);
14601da177e4SLinus Torvalds }
14611da177e4SLinus Torvalds 
14625c04a7b8SAlexey Dobriyan static void FPT_WrStack(unsigned long portBase, unsigned char index,
14635c04a7b8SAlexey Dobriyan 			unsigned char data)
14641da177e4SLinus Torvalds {
14651da177e4SLinus Torvalds 	WR_HARPOON(portBase + hp_stack_addr, index);
14661da177e4SLinus Torvalds 	WR_HARPOON(portBase + hp_stack_data, data);
14671da177e4SLinus Torvalds }
14681da177e4SLinus Torvalds 
1469d63a4cccSAlexey Dobriyan static unsigned char FPT_ChkIfChipInitialized(unsigned long ioPort)
14701da177e4SLinus Torvalds {
147147b5d69cSJames Bottomley  	if ((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != FPT_RdStack(ioPort, 4))
14725c1b85e2SAlexey Dobriyan 		return 0;
14731da177e4SLinus Torvalds 	if ((RD_HARPOON(ioPort + hp_clkctrl_0) & CLKCTRL_DEFAULT)
14741da177e4SLinus Torvalds 	    != CLKCTRL_DEFAULT)
14755c1b85e2SAlexey Dobriyan 		return 0;
14761da177e4SLinus Torvalds 	if ((RD_HARPOON(ioPort + hp_seltimeout) == TO_250ms) ||
14771da177e4SLinus Torvalds 	    (RD_HARPOON(ioPort + hp_seltimeout) == TO_290ms))
14785c1b85e2SAlexey Dobriyan 		return 1;
14795c1b85e2SAlexey Dobriyan 	return 0;
14801da177e4SLinus Torvalds 
14811da177e4SLinus Torvalds }
14825c04a7b8SAlexey Dobriyan 
14831da177e4SLinus Torvalds /*---------------------------------------------------------------------
14841da177e4SLinus Torvalds  *
1485d8b6b8bdSAlexey Dobriyan  * Function: FlashPoint_StartCCB
14861da177e4SLinus Torvalds  *
14871da177e4SLinus Torvalds  * Description: Start a command pointed to by p_Sccb. When the
14881da177e4SLinus Torvalds  *              command is completed it will be returned via the
14891da177e4SLinus Torvalds  *              callback function.
14901da177e4SLinus Torvalds  *
14911da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
149269eb2ea4SAlexey Dobriyan static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb *p_Sccb)
14931da177e4SLinus Torvalds {
1494d63a4cccSAlexey Dobriyan 	unsigned long ioport;
1495db038cf8SAlexey Dobriyan 	unsigned char thisCard, lun;
149669eb2ea4SAlexey Dobriyan 	struct sccb *pSaveSccb;
14971da177e4SLinus Torvalds 	CALL_BK_FN callback;
14981da177e4SLinus Torvalds 
149913e6851aSAlexey Dobriyan 	thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
150013e6851aSAlexey Dobriyan 	ioport = ((struct sccb_card *)pCurrCard)->ioPort;
15011da177e4SLinus Torvalds 
15021377d8ddSAdrian Bunk 	if ((p_Sccb->TargID >= MAX_SCSI_TAR) || (p_Sccb->Lun >= MAX_LUN)) {
15031da177e4SLinus Torvalds 
15041da177e4SLinus Torvalds 		p_Sccb->HostStatus = SCCB_COMPLETE;
15051da177e4SLinus Torvalds 		p_Sccb->SccbStatus = SCCB_ERROR;
15061da177e4SLinus Torvalds 		callback = (CALL_BK_FN) p_Sccb->SccbCallback;
15071da177e4SLinus Torvalds 		if (callback)
15081da177e4SLinus Torvalds 			callback(p_Sccb);
15091da177e4SLinus Torvalds 
15101da177e4SLinus Torvalds 		return;
15111da177e4SLinus Torvalds 	}
15121da177e4SLinus Torvalds 
151347b5d69cSJames Bottomley  	FPT_sinits(p_Sccb, thisCard);
15141da177e4SLinus Torvalds 
15155c04a7b8SAlexey Dobriyan 	if (!((struct sccb_card *)pCurrCard)->cmdCounter) {
15165c04a7b8SAlexey Dobriyan 		WR_HARPOON(ioport + hp_semaphore,
15175c04a7b8SAlexey Dobriyan 			   (RD_HARPOON(ioport + hp_semaphore)
15181da177e4SLinus Torvalds 			    | SCCB_MGR_ACTIVE));
15191da177e4SLinus Torvalds 
15205c04a7b8SAlexey Dobriyan 		if (((struct sccb_card *)pCurrCard)->globalFlags & F_GREEN_PC) {
15211da177e4SLinus Torvalds 			WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT);
15221da177e4SLinus Torvalds 			WR_HARPOON(ioport + hp_sys_ctrl, 0x00);
15231da177e4SLinus Torvalds 		}
15241da177e4SLinus Torvalds 	}
15251da177e4SLinus Torvalds 
152613e6851aSAlexey Dobriyan 	((struct sccb_card *)pCurrCard)->cmdCounter++;
15271da177e4SLinus Torvalds 
15281da177e4SLinus Torvalds 	if (RD_HARPOON(ioport + hp_semaphore) & BIOS_IN_USE) {
15291da177e4SLinus Torvalds 
15305c04a7b8SAlexey Dobriyan 		WR_HARPOON(ioport + hp_semaphore,
15315c04a7b8SAlexey Dobriyan 			   (RD_HARPOON(ioport + hp_semaphore)
15321da177e4SLinus Torvalds 			    | TICKLE_ME));
15335c04a7b8SAlexey Dobriyan 		if (p_Sccb->OperationCode == RESET_COMMAND) {
15345c04a7b8SAlexey Dobriyan 			pSaveSccb =
15355c04a7b8SAlexey Dobriyan 			    ((struct sccb_card *)pCurrCard)->currentSCCB;
153613e6851aSAlexey Dobriyan 			((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb;
153747b5d69cSJames Bottomley  			FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
15385c04a7b8SAlexey Dobriyan 			((struct sccb_card *)pCurrCard)->currentSCCB =
15395c04a7b8SAlexey Dobriyan 			    pSaveSccb;
15405c04a7b8SAlexey Dobriyan 		} else {
154147b5d69cSJames Bottomley  			FPT_queueAddSccb(p_Sccb, thisCard);
15421da177e4SLinus Torvalds 		}
15431da177e4SLinus Torvalds 	}
15441da177e4SLinus Torvalds 
15451da177e4SLinus Torvalds 	else if ((RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) {
15461da177e4SLinus Torvalds 
15475c04a7b8SAlexey Dobriyan 		if (p_Sccb->OperationCode == RESET_COMMAND) {
15485c04a7b8SAlexey Dobriyan 			pSaveSccb =
15495c04a7b8SAlexey Dobriyan 			    ((struct sccb_card *)pCurrCard)->currentSCCB;
155013e6851aSAlexey Dobriyan 			((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb;
155147b5d69cSJames Bottomley  			FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
15525c04a7b8SAlexey Dobriyan 			((struct sccb_card *)pCurrCard)->currentSCCB =
15535c04a7b8SAlexey Dobriyan 			    pSaveSccb;
15545c04a7b8SAlexey Dobriyan 		} else {
155547b5d69cSJames Bottomley  			FPT_queueAddSccb(p_Sccb, thisCard);
15561da177e4SLinus Torvalds 		}
15571da177e4SLinus Torvalds 	}
15581da177e4SLinus Torvalds 
15591da177e4SLinus Torvalds 	else {
15601da177e4SLinus Torvalds 
15611da177e4SLinus Torvalds 		MDISABLE_INT(ioport);
15621da177e4SLinus Torvalds 
15635c04a7b8SAlexey Dobriyan 		if ((((struct sccb_card *)pCurrCard)->globalFlags & F_CONLUN_IO)
15645c04a7b8SAlexey Dobriyan 		    &&
15655c04a7b8SAlexey Dobriyan 		    ((FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].
15665c04a7b8SAlexey Dobriyan 		      TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
15671da177e4SLinus Torvalds 			lun = p_Sccb->Lun;
15681da177e4SLinus Torvalds 		else
15691da177e4SLinus Torvalds 			lun = 0;
157013e6851aSAlexey Dobriyan 		if ((((struct sccb_card *)pCurrCard)->currentSCCB == NULL) &&
15715c04a7b8SAlexey Dobriyan 		    (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarSelQ_Cnt == 0)
15725c04a7b8SAlexey Dobriyan 		    && (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarLUNBusy[lun]
157347b5d69cSJames Bottomley  			== 0)) {
15741da177e4SLinus Torvalds 
157513e6851aSAlexey Dobriyan 			((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb;
157647b5d69cSJames Bottomley  			FPT_ssel(p_Sccb->SccbIOPort, thisCard);
15771da177e4SLinus Torvalds 		}
15781da177e4SLinus Torvalds 
15791da177e4SLinus Torvalds 		else {
15801da177e4SLinus Torvalds 
15815c04a7b8SAlexey Dobriyan 			if (p_Sccb->OperationCode == RESET_COMMAND) {
15825c04a7b8SAlexey Dobriyan 				pSaveSccb =
15835c04a7b8SAlexey Dobriyan 				    ((struct sccb_card *)pCurrCard)->
15845c04a7b8SAlexey Dobriyan 				    currentSCCB;
15855c04a7b8SAlexey Dobriyan 				((struct sccb_card *)pCurrCard)->currentSCCB =
15865c04a7b8SAlexey Dobriyan 				    p_Sccb;
15875c04a7b8SAlexey Dobriyan 				FPT_queueSelectFail(&FPT_BL_Card[thisCard],
15885c04a7b8SAlexey Dobriyan 						    thisCard);
15895c04a7b8SAlexey Dobriyan 				((struct sccb_card *)pCurrCard)->currentSCCB =
15905c04a7b8SAlexey Dobriyan 				    pSaveSccb;
15915c04a7b8SAlexey Dobriyan 			} else {
159247b5d69cSJames Bottomley  				FPT_queueAddSccb(p_Sccb, thisCard);
15931da177e4SLinus Torvalds 			}
15941da177e4SLinus Torvalds 		}
15951da177e4SLinus Torvalds 
15961da177e4SLinus Torvalds 		MENABLE_INT(ioport);
15971da177e4SLinus Torvalds 	}
15981da177e4SLinus Torvalds 
15991da177e4SLinus Torvalds }
16001da177e4SLinus Torvalds 
16011da177e4SLinus Torvalds /*---------------------------------------------------------------------
16021da177e4SLinus Torvalds  *
1603d8b6b8bdSAlexey Dobriyan  * Function: FlashPoint_AbortCCB
16041da177e4SLinus Torvalds  *
16051da177e4SLinus Torvalds  * Description: Abort the command pointed to by p_Sccb.  When the
16061da177e4SLinus Torvalds  *              command is completed it will be returned via the
16071da177e4SLinus Torvalds  *              callback function.
16081da177e4SLinus Torvalds  *
16091da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
161069eb2ea4SAlexey Dobriyan static int FlashPoint_AbortCCB(unsigned long pCurrCard, struct sccb *p_Sccb)
16111da177e4SLinus Torvalds {
1612d63a4cccSAlexey Dobriyan 	unsigned long ioport;
16131da177e4SLinus Torvalds 
1614db038cf8SAlexey Dobriyan 	unsigned char thisCard;
16151da177e4SLinus Torvalds 	CALL_BK_FN callback;
1616db038cf8SAlexey Dobriyan 	unsigned char TID;
161769eb2ea4SAlexey Dobriyan 	struct sccb *pSaveSCCB;
1618f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
16191da177e4SLinus Torvalds 
162013e6851aSAlexey Dobriyan 	ioport = ((struct sccb_card *)pCurrCard)->ioPort;
16211da177e4SLinus Torvalds 
162213e6851aSAlexey Dobriyan 	thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
16231da177e4SLinus Torvalds 
16245c04a7b8SAlexey Dobriyan 	if (!(RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) {
16251da177e4SLinus Torvalds 
16265c04a7b8SAlexey Dobriyan 		if (FPT_queueFindSccb(p_Sccb, thisCard)) {
16271da177e4SLinus Torvalds 
162813e6851aSAlexey Dobriyan 			((struct sccb_card *)pCurrCard)->cmdCounter--;
16291da177e4SLinus Torvalds 
163013e6851aSAlexey Dobriyan 			if (!((struct sccb_card *)pCurrCard)->cmdCounter)
16315c04a7b8SAlexey Dobriyan 				WR_HARPOON(ioport + hp_semaphore,
16325c04a7b8SAlexey Dobriyan 					   (RD_HARPOON(ioport + hp_semaphore)
16335c04a7b8SAlexey Dobriyan 					    & (unsigned
16345c04a7b8SAlexey Dobriyan 					       char)(~(SCCB_MGR_ACTIVE |
16355c04a7b8SAlexey Dobriyan 						       TICKLE_ME))));
16361da177e4SLinus Torvalds 
16371da177e4SLinus Torvalds 			p_Sccb->SccbStatus = SCCB_ABORT;
16381da177e4SLinus Torvalds 			callback = p_Sccb->SccbCallback;
16391da177e4SLinus Torvalds 			callback(p_Sccb);
16401da177e4SLinus Torvalds 
16415c1b85e2SAlexey Dobriyan 			return 0;
16421da177e4SLinus Torvalds 		}
16431da177e4SLinus Torvalds 
16445c04a7b8SAlexey Dobriyan 		else {
16455c04a7b8SAlexey Dobriyan 			if (((struct sccb_card *)pCurrCard)->currentSCCB ==
16465c04a7b8SAlexey Dobriyan 			    p_Sccb) {
16471da177e4SLinus Torvalds 				p_Sccb->SccbStatus = SCCB_ABORT;
16485c1b85e2SAlexey Dobriyan 				return 0;
16491da177e4SLinus Torvalds 
16501da177e4SLinus Torvalds 			}
16511da177e4SLinus Torvalds 
16525c04a7b8SAlexey Dobriyan 			else {
16531da177e4SLinus Torvalds 
16541da177e4SLinus Torvalds 				TID = p_Sccb->TargID;
16551da177e4SLinus Torvalds 
16565c04a7b8SAlexey Dobriyan 				if (p_Sccb->Sccb_tag) {
16571da177e4SLinus Torvalds 					MDISABLE_INT(ioport);
16585c04a7b8SAlexey Dobriyan 					if (((struct sccb_card *)pCurrCard)->
16595c04a7b8SAlexey Dobriyan 					    discQ_Tbl[p_Sccb->Sccb_tag] ==
16605c04a7b8SAlexey Dobriyan 					    p_Sccb) {
16611da177e4SLinus Torvalds 						p_Sccb->SccbStatus = SCCB_ABORT;
16625c04a7b8SAlexey Dobriyan 						p_Sccb->Sccb_scsistat =
16635c04a7b8SAlexey Dobriyan 						    ABORT_ST;
16645c04a7b8SAlexey Dobriyan 						p_Sccb->Sccb_scsimsg =
16655c04a7b8SAlexey Dobriyan 						    SMABORT_TAG;
16661da177e4SLinus Torvalds 
16675c04a7b8SAlexey Dobriyan 						if (((struct sccb_card *)
16685c04a7b8SAlexey Dobriyan 						     pCurrCard)->currentSCCB ==
16695c04a7b8SAlexey Dobriyan 						    NULL) {
16705c04a7b8SAlexey Dobriyan 							((struct sccb_card *)
16715c04a7b8SAlexey Dobriyan 							 pCurrCard)->
16725c04a7b8SAlexey Dobriyan 					currentSCCB = p_Sccb;
16735c04a7b8SAlexey Dobriyan 							FPT_ssel(ioport,
16745c04a7b8SAlexey Dobriyan 								 thisCard);
16755c04a7b8SAlexey Dobriyan 						} else {
16765c04a7b8SAlexey Dobriyan 							pSaveSCCB =
16775c04a7b8SAlexey Dobriyan 							    ((struct sccb_card
16785c04a7b8SAlexey Dobriyan 							      *)pCurrCard)->
16795c04a7b8SAlexey Dobriyan 							    currentSCCB;
16805c04a7b8SAlexey Dobriyan 							((struct sccb_card *)
16815c04a7b8SAlexey Dobriyan 							 pCurrCard)->
16825c04a7b8SAlexey Dobriyan 					currentSCCB = p_Sccb;
168313e6851aSAlexey Dobriyan 							FPT_queueSelectFail((struct sccb_card *)pCurrCard, thisCard);
16845c04a7b8SAlexey Dobriyan 							((struct sccb_card *)
16855c04a7b8SAlexey Dobriyan 							 pCurrCard)->
16865c04a7b8SAlexey Dobriyan 					currentSCCB = pSaveSCCB;
16871da177e4SLinus Torvalds 						}
16881da177e4SLinus Torvalds 					}
16891da177e4SLinus Torvalds 					MENABLE_INT(ioport);
16905c1b85e2SAlexey Dobriyan 					return 0;
16915c04a7b8SAlexey Dobriyan 				} else {
16925c04a7b8SAlexey Dobriyan 					currTar_Info =
16935c04a7b8SAlexey Dobriyan 					    &FPT_sccbMgrTbl[thisCard][p_Sccb->
16945c04a7b8SAlexey Dobriyan 								      TargID];
16951da177e4SLinus Torvalds 
16965c04a7b8SAlexey Dobriyan 					if (FPT_BL_Card[thisCard].
16975c04a7b8SAlexey Dobriyan 					    discQ_Tbl[currTar_Info->
16985c04a7b8SAlexey Dobriyan 						      LunDiscQ_Idx[p_Sccb->Lun]]
16995c04a7b8SAlexey Dobriyan 					    == p_Sccb) {
17001da177e4SLinus Torvalds 						p_Sccb->SccbStatus = SCCB_ABORT;
17015c1b85e2SAlexey Dobriyan 						return 0;
17021da177e4SLinus Torvalds 					}
17031da177e4SLinus Torvalds 				}
17041da177e4SLinus Torvalds 			}
17051da177e4SLinus Torvalds 		}
17061da177e4SLinus Torvalds 	}
17075c1b85e2SAlexey Dobriyan 	return -1;
17081da177e4SLinus Torvalds }
17091da177e4SLinus Torvalds 
17101da177e4SLinus Torvalds /*---------------------------------------------------------------------
17111da177e4SLinus Torvalds  *
1712d8b6b8bdSAlexey Dobriyan  * Function: FlashPoint_InterruptPending
17131da177e4SLinus Torvalds  *
17141da177e4SLinus Torvalds  * Description: Do a quick check to determine if there is a pending
17151da177e4SLinus Torvalds  *              interrupt for this card and disable the IRQ Pin if so.
17161da177e4SLinus Torvalds  *
17171da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
1718d63a4cccSAlexey Dobriyan static unsigned char FlashPoint_InterruptPending(unsigned long pCurrCard)
17191da177e4SLinus Torvalds {
1720d63a4cccSAlexey Dobriyan 	unsigned long ioport;
17211da177e4SLinus Torvalds 
172213e6851aSAlexey Dobriyan 	ioport = ((struct sccb_card *)pCurrCard)->ioPort;
17231da177e4SLinus Torvalds 
17245c04a7b8SAlexey Dobriyan 	if (RD_HARPOON(ioport + hp_int_status) & INT_ASSERTED) {
17255c1b85e2SAlexey Dobriyan 		return 1;
17261da177e4SLinus Torvalds 	}
17271da177e4SLinus Torvalds 
17281da177e4SLinus Torvalds 	else
17291da177e4SLinus Torvalds 
17305c1b85e2SAlexey Dobriyan 		return 0;
17311da177e4SLinus Torvalds }
17321da177e4SLinus Torvalds 
17331da177e4SLinus Torvalds /*---------------------------------------------------------------------
17341da177e4SLinus Torvalds  *
1735d8b6b8bdSAlexey Dobriyan  * Function: FlashPoint_HandleInterrupt
17361da177e4SLinus Torvalds  *
17371da177e4SLinus Torvalds  * Description: This is our entry point when an interrupt is generated
17381da177e4SLinus Torvalds  *              by the card and the upper level driver passes it on to
17391da177e4SLinus Torvalds  *              us.
17401da177e4SLinus Torvalds  *
17411da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
1742d63a4cccSAlexey Dobriyan static int FlashPoint_HandleInterrupt(unsigned long pCurrCard)
17431da177e4SLinus Torvalds {
174469eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
1745db038cf8SAlexey Dobriyan 	unsigned char thisCard, result, bm_status, bm_int_st;
1746c823feebSAlexey Dobriyan 	unsigned short hp_int;
1747db038cf8SAlexey Dobriyan 	unsigned char i, target;
1748d63a4cccSAlexey Dobriyan 	unsigned long ioport;
17491da177e4SLinus Torvalds 
175013e6851aSAlexey Dobriyan 	thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
175113e6851aSAlexey Dobriyan 	ioport = ((struct sccb_card *)pCurrCard)->ioPort;
17521da177e4SLinus Torvalds 
17531da177e4SLinus Torvalds 	MDISABLE_INT(ioport);
17541da177e4SLinus Torvalds 
17551da177e4SLinus Torvalds 	if ((bm_int_st = RD_HARPOON(ioport + hp_int_status)) & EXT_STATUS_ON)
17565c04a7b8SAlexey Dobriyan 		bm_status =
17575c04a7b8SAlexey Dobriyan 		    RD_HARPOON(ioport +
17585c04a7b8SAlexey Dobriyan 			       hp_ext_status) & (unsigned char)BAD_EXT_STATUS;
17591da177e4SLinus Torvalds 	else
17601da177e4SLinus Torvalds 		bm_status = 0;
17611da177e4SLinus Torvalds 
17621da177e4SLinus Torvalds 	WR_HARPOON(ioport + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
17631da177e4SLinus Torvalds 
17645c04a7b8SAlexey Dobriyan 	while ((hp_int =
17655c04a7b8SAlexey Dobriyan 		RDW_HARPOON((ioport +
17665c04a7b8SAlexey Dobriyan 			     hp_intstat)) & FPT_default_intena) | bm_status) {
17671da177e4SLinus Torvalds 
176813e6851aSAlexey Dobriyan 		currSCCB = ((struct sccb_card *)pCurrCard)->currentSCCB;
17691da177e4SLinus Torvalds 
17701da177e4SLinus Torvalds 		if (hp_int & (FIFO | TIMEOUT | RESET | SCAM_SEL) || bm_status) {
17715c04a7b8SAlexey Dobriyan 			result =
17725c04a7b8SAlexey Dobriyan 			    FPT_SccbMgr_bad_isr(ioport, thisCard,
17735c04a7b8SAlexey Dobriyan 						((struct sccb_card *)pCurrCard),
17745c04a7b8SAlexey Dobriyan 						hp_int);
17755c04a7b8SAlexey Dobriyan 			WRW_HARPOON((ioport + hp_intstat),
17765c04a7b8SAlexey Dobriyan 				    (FIFO | TIMEOUT | RESET | SCAM_SEL));
17771da177e4SLinus Torvalds 			bm_status = 0;
17781da177e4SLinus Torvalds 
17791da177e4SLinus Torvalds 			if (result) {
17801da177e4SLinus Torvalds 
17811da177e4SLinus Torvalds 				MENABLE_INT(ioport);
17825c1b85e2SAlexey Dobriyan 				return result;
17831da177e4SLinus Torvalds 			}
17841da177e4SLinus Torvalds 		}
17851da177e4SLinus Torvalds 
17861da177e4SLinus Torvalds 		else if (hp_int & ICMD_COMP) {
17871da177e4SLinus Torvalds 
17881da177e4SLinus Torvalds 			if (!(hp_int & BUS_FREE)) {
17891da177e4SLinus Torvalds 				/* Wait for the BusFree before starting a new command.  We
17901da177e4SLinus Torvalds 				   must also check for being reselected since the BusFree
17911da177e4SLinus Torvalds 				   may not show up if another device reselects us in 1.5us or
17921da177e4SLinus Torvalds 				   less.  SRR Wednesday, 3/8/1995.
17931da177e4SLinus Torvalds 				 */
17945c04a7b8SAlexey Dobriyan 				while (!
17955c04a7b8SAlexey Dobriyan 				       (RDW_HARPOON((ioport + hp_intstat)) &
17965c04a7b8SAlexey Dobriyan 					(BUS_FREE | RSEL))) ;
17971da177e4SLinus Torvalds 			}
17981da177e4SLinus Torvalds 
17995c04a7b8SAlexey Dobriyan 			if (((struct sccb_card *)pCurrCard)->
18005c04a7b8SAlexey Dobriyan 			    globalFlags & F_HOST_XFER_ACT)
18011da177e4SLinus Torvalds 
180247b5d69cSJames Bottomley  				FPT_phaseChkFifo(ioport, thisCard);
18031da177e4SLinus Torvalds 
18041da177e4SLinus Torvalds /*         WRW_HARPOON((ioport+hp_intstat),
18051da177e4SLinus Torvalds             (BUS_FREE | ICMD_COMP | ITAR_DISC | XFER_CNT_0));
18061da177e4SLinus Torvalds          */
18071da177e4SLinus Torvalds 
18081da177e4SLinus Torvalds 			WRW_HARPOON((ioport + hp_intstat), CLR_ALL_INT_1);
18091da177e4SLinus Torvalds 
181047b5d69cSJames Bottomley  			FPT_autoCmdCmplt(ioport, thisCard);
18111da177e4SLinus Torvalds 
18121da177e4SLinus Torvalds 		}
18131da177e4SLinus Torvalds 
18145c04a7b8SAlexey Dobriyan 		else if (hp_int & ITAR_DISC) {
18151da177e4SLinus Torvalds 
18165c04a7b8SAlexey Dobriyan 			if (((struct sccb_card *)pCurrCard)->
18175c04a7b8SAlexey Dobriyan 			    globalFlags & F_HOST_XFER_ACT) {
18181da177e4SLinus Torvalds 
181947b5d69cSJames Bottomley  				FPT_phaseChkFifo(ioport, thisCard);
18201da177e4SLinus Torvalds 
18211da177e4SLinus Torvalds 			}
18221da177e4SLinus Torvalds 
18231da177e4SLinus Torvalds 			if (RD_HARPOON(ioport + hp_gp_reg_1) == SMSAVE_DATA_PTR) {
18241da177e4SLinus Torvalds 
18251da177e4SLinus Torvalds 				WR_HARPOON(ioport + hp_gp_reg_1, 0x00);
18261da177e4SLinus Torvalds 				currSCCB->Sccb_XferState |= F_NO_DATA_YET;
18271da177e4SLinus Torvalds 
18281da177e4SLinus Torvalds 				currSCCB->Sccb_savedATC = currSCCB->Sccb_ATC;
18291da177e4SLinus Torvalds 			}
18301da177e4SLinus Torvalds 
18311da177e4SLinus Torvalds 			currSCCB->Sccb_scsistat = DISCONNECT_ST;
183247b5d69cSJames Bottomley  			FPT_queueDisconnect(currSCCB, thisCard);
18331da177e4SLinus Torvalds 
18341da177e4SLinus Torvalds 			/* Wait for the BusFree before starting a new command.  We
18351da177e4SLinus Torvalds 			   must also check for being reselected since the BusFree
18361da177e4SLinus Torvalds 			   may not show up if another device reselects us in 1.5us or
18371da177e4SLinus Torvalds 			   less.  SRR Wednesday, 3/8/1995.
18381da177e4SLinus Torvalds 			 */
18395c04a7b8SAlexey Dobriyan 			while (!
18405c04a7b8SAlexey Dobriyan 			       (RDW_HARPOON((ioport + hp_intstat)) &
18415c04a7b8SAlexey Dobriyan 				(BUS_FREE | RSEL))
18425c04a7b8SAlexey Dobriyan 			       && !((RDW_HARPOON((ioport + hp_intstat)) & PHASE)
18435c04a7b8SAlexey Dobriyan 				    && RD_HARPOON((ioport + hp_scsisig)) ==
18445c04a7b8SAlexey Dobriyan 				    (SCSI_BSY | SCSI_REQ | SCSI_CD | SCSI_MSG |
18455c04a7b8SAlexey Dobriyan 				     SCSI_IOBIT))) ;
18461da177e4SLinus Torvalds 
18471da177e4SLinus Torvalds 			/*
18481da177e4SLinus Torvalds 			   The additional loop exit condition above detects a timing problem
18491da177e4SLinus Torvalds 			   with the revision D/E harpoon chips.  The caller should reset the
18501da177e4SLinus Torvalds 			   host adapter to recover when 0xFE is returned.
18511da177e4SLinus Torvalds 			 */
18525c04a7b8SAlexey Dobriyan 			if (!
18535c04a7b8SAlexey Dobriyan 			    (RDW_HARPOON((ioport + hp_intstat)) &
18545c04a7b8SAlexey Dobriyan 			     (BUS_FREE | RSEL))) {
18551da177e4SLinus Torvalds 				MENABLE_INT(ioport);
18561da177e4SLinus Torvalds 				return 0xFE;
18571da177e4SLinus Torvalds 			}
18581da177e4SLinus Torvalds 
18595c04a7b8SAlexey Dobriyan 			WRW_HARPOON((ioport + hp_intstat),
18605c04a7b8SAlexey Dobriyan 				    (BUS_FREE | ITAR_DISC));
18611da177e4SLinus Torvalds 
18625c04a7b8SAlexey Dobriyan 			((struct sccb_card *)pCurrCard)->globalFlags |=
18635c04a7b8SAlexey Dobriyan 			    F_NEW_SCCB_CMD;
18641da177e4SLinus Torvalds 
18651da177e4SLinus Torvalds 		}
18661da177e4SLinus Torvalds 
18671da177e4SLinus Torvalds 		else if (hp_int & RSEL) {
18681da177e4SLinus Torvalds 
18695c04a7b8SAlexey Dobriyan 			WRW_HARPOON((ioport + hp_intstat),
18705c04a7b8SAlexey Dobriyan 				    (PROG_HLT | RSEL | PHASE | BUS_FREE));
18711da177e4SLinus Torvalds 
18725c04a7b8SAlexey Dobriyan 			if (RDW_HARPOON((ioport + hp_intstat)) & ITAR_DISC) {
18735c04a7b8SAlexey Dobriyan 				if (((struct sccb_card *)pCurrCard)->
18745c04a7b8SAlexey Dobriyan 				    globalFlags & F_HOST_XFER_ACT) {
187547b5d69cSJames Bottomley  					FPT_phaseChkFifo(ioport, thisCard);
18761da177e4SLinus Torvalds 				}
18771da177e4SLinus Torvalds 
18785c04a7b8SAlexey Dobriyan 				if (RD_HARPOON(ioport + hp_gp_reg_1) ==
18795c04a7b8SAlexey Dobriyan 				    SMSAVE_DATA_PTR) {
18801da177e4SLinus Torvalds 					WR_HARPOON(ioport + hp_gp_reg_1, 0x00);
18815c04a7b8SAlexey Dobriyan 					currSCCB->Sccb_XferState |=
18825c04a7b8SAlexey Dobriyan 					    F_NO_DATA_YET;
18835c04a7b8SAlexey Dobriyan 					currSCCB->Sccb_savedATC =
18845c04a7b8SAlexey Dobriyan 					    currSCCB->Sccb_ATC;
18851da177e4SLinus Torvalds 				}
18861da177e4SLinus Torvalds 
18875c04a7b8SAlexey Dobriyan 				WRW_HARPOON((ioport + hp_intstat),
18885c04a7b8SAlexey Dobriyan 					    (BUS_FREE | ITAR_DISC));
18891da177e4SLinus Torvalds 				currSCCB->Sccb_scsistat = DISCONNECT_ST;
189047b5d69cSJames Bottomley  				FPT_queueDisconnect(currSCCB, thisCard);
18911da177e4SLinus Torvalds 			}
18921da177e4SLinus Torvalds 
18935c04a7b8SAlexey Dobriyan 			FPT_sres(ioport, thisCard,
18945c04a7b8SAlexey Dobriyan 				 ((struct sccb_card *)pCurrCard));
189547b5d69cSJames Bottomley  			FPT_phaseDecode(ioport, thisCard);
18961da177e4SLinus Torvalds 
18971da177e4SLinus Torvalds 		}
18981da177e4SLinus Torvalds 
18995c04a7b8SAlexey Dobriyan 		else if ((hp_int & IDO_STRT) && (!(hp_int & BUS_FREE))) {
19001da177e4SLinus Torvalds 
19015c04a7b8SAlexey Dobriyan 			WRW_HARPOON((ioport + hp_intstat),
19025c04a7b8SAlexey Dobriyan 				    (IDO_STRT | XFER_CNT_0));
190347b5d69cSJames Bottomley  			FPT_phaseDecode(ioport, thisCard);
19041da177e4SLinus Torvalds 
19051da177e4SLinus Torvalds 		}
19061da177e4SLinus Torvalds 
19075c04a7b8SAlexey Dobriyan 		else if ((hp_int & IUNKWN) || (hp_int & PROG_HLT)) {
19085c04a7b8SAlexey Dobriyan 			WRW_HARPOON((ioport + hp_intstat),
19095c04a7b8SAlexey Dobriyan 				    (PHASE | IUNKWN | PROG_HLT));
19105c04a7b8SAlexey Dobriyan 			if ((RD_HARPOON(ioport + hp_prgmcnt_0) & (unsigned char)
19115c04a7b8SAlexey Dobriyan 			     0x3f) < (unsigned char)SELCHK) {
191247b5d69cSJames Bottomley  				FPT_phaseDecode(ioport, thisCard);
19135c04a7b8SAlexey Dobriyan 			} else {
19141da177e4SLinus Torvalds 				/* Harpoon problem some SCSI target device respond to selection
19151da177e4SLinus Torvalds 				   with short BUSY pulse (<400ns) this will make the Harpoon is not able
19161da177e4SLinus Torvalds 				   to latch the correct Target ID into reg. x53.
19171da177e4SLinus Torvalds 				   The work around require to correct this reg. But when write to this
19181da177e4SLinus Torvalds 				   reg. (0x53) also increment the FIFO write addr reg (0x6f), thus we
19191da177e4SLinus Torvalds 				   need to read this reg first then restore it later. After update to 0x53 */
19201da177e4SLinus Torvalds 
19215c04a7b8SAlexey Dobriyan 				i = (unsigned
19225c04a7b8SAlexey Dobriyan 				     char)(RD_HARPOON(ioport + hp_fifowrite));
19235c04a7b8SAlexey Dobriyan 				target =
19245c04a7b8SAlexey Dobriyan 				    (unsigned
19255c04a7b8SAlexey Dobriyan 				     char)(RD_HARPOON(ioport + hp_gp_reg_3));
19265c04a7b8SAlexey Dobriyan 				WR_HARPOON(ioport + hp_xfer_pad,
19275c04a7b8SAlexey Dobriyan 					   (unsigned char)ID_UNLOCK);
19285c04a7b8SAlexey Dobriyan 				WR_HARPOON(ioport + hp_select_id,
19295c04a7b8SAlexey Dobriyan 					   (unsigned char)(target | target <<
19305c04a7b8SAlexey Dobriyan 							   4));
19315c04a7b8SAlexey Dobriyan 				WR_HARPOON(ioport + hp_xfer_pad,
19325c04a7b8SAlexey Dobriyan 					   (unsigned char)0x00);
19331da177e4SLinus Torvalds 				WR_HARPOON(ioport + hp_fifowrite, i);
19345c04a7b8SAlexey Dobriyan 				WR_HARPOON(ioport + hp_autostart_3,
19355c04a7b8SAlexey Dobriyan 					   (AUTO_IMMED + TAG_STRT));
19361da177e4SLinus Torvalds 			}
19371da177e4SLinus Torvalds 		}
19381da177e4SLinus Torvalds 
19391da177e4SLinus Torvalds 		else if (hp_int & XFER_CNT_0) {
19401da177e4SLinus Torvalds 
19411da177e4SLinus Torvalds 			WRW_HARPOON((ioport + hp_intstat), XFER_CNT_0);
19421da177e4SLinus Torvalds 
194347b5d69cSJames Bottomley  			FPT_schkdd(ioport, thisCard);
19441da177e4SLinus Torvalds 
19451da177e4SLinus Torvalds 		}
19461da177e4SLinus Torvalds 
19471da177e4SLinus Torvalds 		else if (hp_int & BUS_FREE) {
19481da177e4SLinus Torvalds 
19491da177e4SLinus Torvalds 			WRW_HARPOON((ioport + hp_intstat), BUS_FREE);
19501da177e4SLinus Torvalds 
19515c04a7b8SAlexey Dobriyan 			if (((struct sccb_card *)pCurrCard)->
19525c04a7b8SAlexey Dobriyan 			    globalFlags & F_HOST_XFER_ACT) {
19531da177e4SLinus Torvalds 
19545c04a7b8SAlexey Dobriyan 				FPT_hostDataXferAbort(ioport, thisCard,
19555c04a7b8SAlexey Dobriyan 						      currSCCB);
19561da177e4SLinus Torvalds 			}
19571da177e4SLinus Torvalds 
195847b5d69cSJames Bottomley  			FPT_phaseBusFree(ioport, thisCard);
19591da177e4SLinus Torvalds 		}
19601da177e4SLinus Torvalds 
19611da177e4SLinus Torvalds 		else if (hp_int & ITICKLE) {
19621da177e4SLinus Torvalds 
19631da177e4SLinus Torvalds 			WRW_HARPOON((ioport + hp_intstat), ITICKLE);
19645c04a7b8SAlexey Dobriyan 			((struct sccb_card *)pCurrCard)->globalFlags |=
19655c04a7b8SAlexey Dobriyan 			    F_NEW_SCCB_CMD;
19661da177e4SLinus Torvalds 		}
19671da177e4SLinus Torvalds 
19685c04a7b8SAlexey Dobriyan 		if (((struct sccb_card *)pCurrCard)->
19695c04a7b8SAlexey Dobriyan 		    globalFlags & F_NEW_SCCB_CMD) {
19701da177e4SLinus Torvalds 
19715c04a7b8SAlexey Dobriyan 			((struct sccb_card *)pCurrCard)->globalFlags &=
19725c04a7b8SAlexey Dobriyan 			    ~F_NEW_SCCB_CMD;
19731da177e4SLinus Torvalds 
19745c04a7b8SAlexey Dobriyan 			if (((struct sccb_card *)pCurrCard)->currentSCCB ==
19755c04a7b8SAlexey Dobriyan 			    NULL) {
19761da177e4SLinus Torvalds 
19775c04a7b8SAlexey Dobriyan 				FPT_queueSearchSelect(((struct sccb_card *)
19785c04a7b8SAlexey Dobriyan 						       pCurrCard), thisCard);
19791da177e4SLinus Torvalds 			}
19801da177e4SLinus Torvalds 
19815c04a7b8SAlexey Dobriyan 			if (((struct sccb_card *)pCurrCard)->currentSCCB !=
19825c04a7b8SAlexey Dobriyan 			    NULL) {
19835c04a7b8SAlexey Dobriyan 				((struct sccb_card *)pCurrCard)->globalFlags &=
19845c04a7b8SAlexey Dobriyan 				    ~F_NEW_SCCB_CMD;
198547b5d69cSJames Bottomley  				FPT_ssel(ioport, thisCard);
19861da177e4SLinus Torvalds 			}
19871da177e4SLinus Torvalds 
19881da177e4SLinus Torvalds 			break;
19891da177e4SLinus Torvalds 
19901da177e4SLinus Torvalds 		}
19911da177e4SLinus Torvalds 
19921da177e4SLinus Torvalds 	}			/*end while */
19931da177e4SLinus Torvalds 
19941da177e4SLinus Torvalds 	MENABLE_INT(ioport);
19951da177e4SLinus Torvalds 
19965c1b85e2SAlexey Dobriyan 	return 0;
19971da177e4SLinus Torvalds }
19981da177e4SLinus Torvalds 
19991da177e4SLinus Torvalds /*---------------------------------------------------------------------
20001da177e4SLinus Torvalds  *
20011da177e4SLinus Torvalds  * Function: Sccb_bad_isr
20021da177e4SLinus Torvalds  *
20031da177e4SLinus Torvalds  * Description: Some type of interrupt has occurred which is slightly
20041da177e4SLinus Torvalds  *              out of the ordinary.  We will now decode it fully, in
20051da177e4SLinus Torvalds  *              this routine.  This is broken up in an attempt to save
20061da177e4SLinus Torvalds  *              processing time.
20071da177e4SLinus Torvalds  *
20081da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
20095c04a7b8SAlexey Dobriyan static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port,
20105c04a7b8SAlexey Dobriyan 					 unsigned char p_card,
20115c04a7b8SAlexey Dobriyan 					 struct sccb_card *pCurrCard,
20125c04a7b8SAlexey Dobriyan 					 unsigned short p_int)
20131da177e4SLinus Torvalds {
2014db038cf8SAlexey Dobriyan 	unsigned char temp, ScamFlg;
2015f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
201668d0c1aeSAlexey Dobriyan 	struct nvram_info *pCurrNvRam;
20171da177e4SLinus Torvalds 
20181da177e4SLinus Torvalds 	if (RD_HARPOON(p_port + hp_ext_status) &
20195c04a7b8SAlexey Dobriyan 	    (BM_FORCE_OFF | PCI_DEV_TMOUT | BM_PARITY_ERR | PIO_OVERRUN)) {
20201da177e4SLinus Torvalds 
20215c04a7b8SAlexey Dobriyan 		if (pCurrCard->globalFlags & F_HOST_XFER_ACT) {
20221da177e4SLinus Torvalds 
20235c04a7b8SAlexey Dobriyan 			FPT_hostDataXferAbort(p_port, p_card,
20245c04a7b8SAlexey Dobriyan 					      pCurrCard->currentSCCB);
20251da177e4SLinus Torvalds 		}
20261da177e4SLinus Torvalds 
20271da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_pci_stat_cfg) & REC_MASTER_ABORT)
20281da177e4SLinus Torvalds 		{
20291da177e4SLinus Torvalds 			WR_HARPOON(p_port + hp_pci_stat_cfg,
20305c04a7b8SAlexey Dobriyan 				   (RD_HARPOON(p_port + hp_pci_stat_cfg) &
20315c04a7b8SAlexey Dobriyan 				    ~REC_MASTER_ABORT));
20321da177e4SLinus Torvalds 
20331da177e4SLinus Torvalds 			WR_HARPOON(p_port + hp_host_blk_cnt, 0x00);
20341da177e4SLinus Torvalds 
20351da177e4SLinus Torvalds 		}
20361da177e4SLinus Torvalds 
20375c04a7b8SAlexey Dobriyan 		if (pCurrCard->currentSCCB != NULL) {
20381da177e4SLinus Torvalds 
20391da177e4SLinus Torvalds 			if (!pCurrCard->currentSCCB->HostStatus)
20405c04a7b8SAlexey Dobriyan 				pCurrCard->currentSCCB->HostStatus =
20415c04a7b8SAlexey Dobriyan 				    SCCB_BM_ERR;
20421da177e4SLinus Torvalds 
204347b5d69cSJames Bottomley  			FPT_sxfrp(p_port, p_card);
20441da177e4SLinus Torvalds 
2045db038cf8SAlexey Dobriyan 			temp = (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
20461da177e4SLinus Torvalds 					       (EXT_ARB_ACK | SCSI_TERM_ENA_H));
20475c04a7b8SAlexey Dobriyan 			WR_HARPOON(p_port + hp_ee_ctrl,
20485c04a7b8SAlexey Dobriyan 				   ((unsigned char)temp | SEE_MS | SEE_CS));
20491da177e4SLinus Torvalds 			WR_HARPOON(p_port + hp_ee_ctrl, temp);
20501da177e4SLinus Torvalds 
20515c04a7b8SAlexey Dobriyan 			if (!
20525c04a7b8SAlexey Dobriyan 			    (RDW_HARPOON((p_port + hp_intstat)) &
20535c04a7b8SAlexey Dobriyan 			     (BUS_FREE | RESET))) {
205447b5d69cSJames Bottomley  				FPT_phaseDecode(p_port, p_card);
20551da177e4SLinus Torvalds 			}
20561da177e4SLinus Torvalds 		}
20571da177e4SLinus Torvalds 	}
20581da177e4SLinus Torvalds 
20595c04a7b8SAlexey Dobriyan 	else if (p_int & RESET) {
20601da177e4SLinus Torvalds 
20611da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
20621da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
20631da177e4SLinus Torvalds 		if (pCurrCard->currentSCCB != NULL) {
20641da177e4SLinus Torvalds 
20651da177e4SLinus Torvalds 			if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
20661da177e4SLinus Torvalds 
20675c04a7b8SAlexey Dobriyan 				FPT_hostDataXferAbort(p_port, p_card,
20685c04a7b8SAlexey Dobriyan 						      pCurrCard->currentSCCB);
20691da177e4SLinus Torvalds 		}
20701da177e4SLinus Torvalds 
20711da177e4SLinus Torvalds 		DISABLE_AUTO(p_port);
20721da177e4SLinus Torvalds 
207347b5d69cSJames Bottomley  		FPT_sresb(p_port, p_card);
20741da177e4SLinus Torvalds 
20755c04a7b8SAlexey Dobriyan 		while (RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST) {
20765c04a7b8SAlexey Dobriyan 		}
20771da177e4SLinus Torvalds 
20781da177e4SLinus Torvalds 		pCurrNvRam = pCurrCard->pNvRamInfo;
20791da177e4SLinus Torvalds 		if (pCurrNvRam) {
20801da177e4SLinus Torvalds 			ScamFlg = pCurrNvRam->niScamConf;
20815c04a7b8SAlexey Dobriyan 		} else {
20825c04a7b8SAlexey Dobriyan 			ScamFlg =
20835c04a7b8SAlexey Dobriyan 			    (unsigned char)FPT_utilEERead(p_port,
20845c04a7b8SAlexey Dobriyan 							  SCAM_CONFIG / 2);
20851da177e4SLinus Torvalds 		}
20861da177e4SLinus Torvalds 
208747b5d69cSJames Bottomley  		FPT_XbowInit(p_port, ScamFlg);
20881da177e4SLinus Torvalds 
208947b5d69cSJames Bottomley  		FPT_scini(p_card, pCurrCard->ourId, 0);
20901da177e4SLinus Torvalds 
20915c1b85e2SAlexey Dobriyan 		return 0xFF;
20921da177e4SLinus Torvalds 	}
20931da177e4SLinus Torvalds 
20941da177e4SLinus Torvalds 	else if (p_int & FIFO) {
20951da177e4SLinus Torvalds 
20961da177e4SLinus Torvalds 		WRW_HARPOON((p_port + hp_intstat), FIFO);
20971da177e4SLinus Torvalds 
20981da177e4SLinus Torvalds 		if (pCurrCard->currentSCCB != NULL)
209947b5d69cSJames Bottomley  			FPT_sxfrp(p_port, p_card);
21001da177e4SLinus Torvalds 	}
21011da177e4SLinus Torvalds 
21025c04a7b8SAlexey Dobriyan 	else if (p_int & TIMEOUT) {
21031da177e4SLinus Torvalds 
21041da177e4SLinus Torvalds 		DISABLE_AUTO(p_port);
21051da177e4SLinus Torvalds 
21061da177e4SLinus Torvalds 		WRW_HARPOON((p_port + hp_intstat),
21075c04a7b8SAlexey Dobriyan 			    (PROG_HLT | TIMEOUT | SEL | BUS_FREE | PHASE |
21085c04a7b8SAlexey Dobriyan 			     IUNKWN));
21091da177e4SLinus Torvalds 
21101da177e4SLinus Torvalds 		pCurrCard->currentSCCB->HostStatus = SCCB_SELECTION_TIMEOUT;
21111da177e4SLinus Torvalds 
21125c04a7b8SAlexey Dobriyan 		currTar_Info =
21135c04a7b8SAlexey Dobriyan 		    &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
21145c04a7b8SAlexey Dobriyan 		if ((pCurrCard->globalFlags & F_CONLUN_IO)
21155c04a7b8SAlexey Dobriyan 		    && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
21165c04a7b8SAlexey Dobriyan 			TAG_Q_TRYING))
21175c04a7b8SAlexey Dobriyan 			currTar_Info->TarLUNBusy[pCurrCard->currentSCCB->Lun] =
21185c04a7b8SAlexey Dobriyan 			    0;
21191da177e4SLinus Torvalds 		else
212047b5d69cSJames Bottomley  			currTar_Info->TarLUNBusy[0] = 0;
21211da177e4SLinus Torvalds 
21225c04a7b8SAlexey Dobriyan 		if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
21231da177e4SLinus Torvalds 			currTar_Info->TarSyncCtrl = 0;
21241da177e4SLinus Torvalds 			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
21251da177e4SLinus Torvalds 		}
21261da177e4SLinus Torvalds 
21275c04a7b8SAlexey Dobriyan 		if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
21281da177e4SLinus Torvalds 			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
21291da177e4SLinus Torvalds 		}
21301da177e4SLinus Torvalds 
21315c04a7b8SAlexey Dobriyan 		FPT_sssyncv(p_port, pCurrCard->currentSCCB->TargID, NARROW_SCSI,
21325c04a7b8SAlexey Dobriyan 			    currTar_Info);
21331da177e4SLinus Torvalds 
213447b5d69cSJames Bottomley  		FPT_queueCmdComplete(pCurrCard, pCurrCard->currentSCCB, p_card);
21351da177e4SLinus Torvalds 
21361da177e4SLinus Torvalds 	}
21371da177e4SLinus Torvalds 
21385c04a7b8SAlexey Dobriyan 	else if (p_int & SCAM_SEL) {
21391da177e4SLinus Torvalds 
214047b5d69cSJames Bottomley  		FPT_scarb(p_port, LEVEL2_TAR);
214147b5d69cSJames Bottomley  		FPT_scsel(p_port);
214247b5d69cSJames Bottomley  		FPT_scasid(p_card, p_port);
21431da177e4SLinus Torvalds 
214447b5d69cSJames Bottomley  		FPT_scbusf(p_port);
21451da177e4SLinus Torvalds 
21461da177e4SLinus Torvalds 		WRW_HARPOON((p_port + hp_intstat), SCAM_SEL);
21471da177e4SLinus Torvalds 	}
21481da177e4SLinus Torvalds 
21495c1b85e2SAlexey Dobriyan 	return 0x00;
21501da177e4SLinus Torvalds }
21511da177e4SLinus Torvalds 
21521da177e4SLinus Torvalds /*---------------------------------------------------------------------
21531da177e4SLinus Torvalds  *
21541da177e4SLinus Torvalds  * Function: SccbMgrTableInit
21551da177e4SLinus Torvalds  *
21561da177e4SLinus Torvalds  * Description: Initialize all Sccb manager data structures.
21571da177e4SLinus Torvalds  *
21581da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
21591da177e4SLinus Torvalds 
216047b5d69cSJames Bottomley  static void FPT_SccbMgrTableInitAll()
21611da177e4SLinus Torvalds {
2162db038cf8SAlexey Dobriyan 	unsigned char thisCard;
21631da177e4SLinus Torvalds 
21645c04a7b8SAlexey Dobriyan 	for (thisCard = 0; thisCard < MAX_CARDS; thisCard++) {
216547b5d69cSJames Bottomley  		FPT_SccbMgrTableInitCard(&FPT_BL_Card[thisCard], thisCard);
21661da177e4SLinus Torvalds 
216747b5d69cSJames Bottomley  		FPT_BL_Card[thisCard].ioPort = 0x00;
216847b5d69cSJames Bottomley  		FPT_BL_Card[thisCard].cardInfo = NULL;
216947b5d69cSJames Bottomley  		FPT_BL_Card[thisCard].cardIndex = 0xFF;
217047b5d69cSJames Bottomley  		FPT_BL_Card[thisCard].ourId = 0x00;
217147b5d69cSJames Bottomley  		FPT_BL_Card[thisCard].pNvRamInfo = NULL;
21721da177e4SLinus Torvalds 	}
21731da177e4SLinus Torvalds }
21741da177e4SLinus Torvalds 
21751da177e4SLinus Torvalds /*---------------------------------------------------------------------
21761da177e4SLinus Torvalds  *
21771da177e4SLinus Torvalds  * Function: SccbMgrTableInit
21781da177e4SLinus Torvalds  *
21791da177e4SLinus Torvalds  * Description: Initialize all Sccb manager data structures.
21801da177e4SLinus Torvalds  *
21811da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
21821da177e4SLinus Torvalds 
21835c04a7b8SAlexey Dobriyan static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard,
21845c04a7b8SAlexey Dobriyan 				     unsigned char p_card)
21851da177e4SLinus Torvalds {
2186db038cf8SAlexey Dobriyan 	unsigned char scsiID, qtag;
21871da177e4SLinus Torvalds 
21885c04a7b8SAlexey Dobriyan 	for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
218947b5d69cSJames Bottomley  		FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
21901da177e4SLinus Torvalds 	}
21911da177e4SLinus Torvalds 
21925c04a7b8SAlexey Dobriyan 	for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
219347b5d69cSJames Bottomley  		FPT_sccbMgrTbl[p_card][scsiID].TarStatus = 0;
219447b5d69cSJames Bottomley  		FPT_sccbMgrTbl[p_card][scsiID].TarEEValue = 0;
219547b5d69cSJames Bottomley  		FPT_SccbMgrTableInitTarget(p_card, scsiID);
21961da177e4SLinus Torvalds 	}
21971da177e4SLinus Torvalds 
21981da177e4SLinus Torvalds 	pCurrCard->scanIndex = 0x00;
21991da177e4SLinus Torvalds 	pCurrCard->currentSCCB = NULL;
22001da177e4SLinus Torvalds 	pCurrCard->globalFlags = 0x00;
22011da177e4SLinus Torvalds 	pCurrCard->cmdCounter = 0x00;
22021da177e4SLinus Torvalds 	pCurrCard->tagQ_Lst = 0x01;
22031da177e4SLinus Torvalds 	pCurrCard->discQCount = 0;
22041da177e4SLinus Torvalds 
22051da177e4SLinus Torvalds }
22061da177e4SLinus Torvalds 
22071da177e4SLinus Torvalds /*---------------------------------------------------------------------
22081da177e4SLinus Torvalds  *
22091da177e4SLinus Torvalds  * Function: SccbMgrTableInit
22101da177e4SLinus Torvalds  *
22111da177e4SLinus Torvalds  * Description: Initialize all Sccb manager data structures.
22121da177e4SLinus Torvalds  *
22131da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
22141da177e4SLinus Torvalds 
22155c04a7b8SAlexey Dobriyan static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
22165c04a7b8SAlexey Dobriyan 				       unsigned char target)
22171da177e4SLinus Torvalds {
22181da177e4SLinus Torvalds 
2219db038cf8SAlexey Dobriyan 	unsigned char lun, qtag;
2220f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
22211da177e4SLinus Torvalds 
222247b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][target];
22231da177e4SLinus Torvalds 
22241da177e4SLinus Torvalds 	currTar_Info->TarSelQ_Cnt = 0;
22251da177e4SLinus Torvalds 	currTar_Info->TarSyncCtrl = 0;
22261da177e4SLinus Torvalds 
22271da177e4SLinus Torvalds 	currTar_Info->TarSelQ_Head = NULL;
22281da177e4SLinus Torvalds 	currTar_Info->TarSelQ_Tail = NULL;
22291da177e4SLinus Torvalds 	currTar_Info->TarTagQ_Cnt = 0;
223047b5d69cSJames Bottomley  	currTar_Info->TarLUN_CA = 0;
22311da177e4SLinus Torvalds 
22325c04a7b8SAlexey Dobriyan 	for (lun = 0; lun < MAX_LUN; lun++) {
223347b5d69cSJames Bottomley  		currTar_Info->TarLUNBusy[lun] = 0;
22341da177e4SLinus Torvalds 		currTar_Info->LunDiscQ_Idx[lun] = 0;
22351da177e4SLinus Torvalds 	}
22361da177e4SLinus Torvalds 
22375c04a7b8SAlexey Dobriyan 	for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
22385c04a7b8SAlexey Dobriyan 		if (FPT_BL_Card[p_card].discQ_Tbl[qtag] != NULL) {
22395c04a7b8SAlexey Dobriyan 			if (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
22405c04a7b8SAlexey Dobriyan 			    target) {
224147b5d69cSJames Bottomley  				FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
224247b5d69cSJames Bottomley  				FPT_BL_Card[p_card].discQCount--;
22431da177e4SLinus Torvalds 			}
22441da177e4SLinus Torvalds 		}
22451da177e4SLinus Torvalds 	}
22461da177e4SLinus Torvalds }
22471da177e4SLinus Torvalds 
22481da177e4SLinus Torvalds /*---------------------------------------------------------------------
22491da177e4SLinus Torvalds  *
22501da177e4SLinus Torvalds  * Function: sfetm
22511da177e4SLinus Torvalds  *
22521da177e4SLinus Torvalds  * Description: Read in a message byte from the SCSI bus, and check
22531da177e4SLinus Torvalds  *              for a parity error.
22541da177e4SLinus Torvalds  *
22551da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
22561da177e4SLinus Torvalds 
225769eb2ea4SAlexey Dobriyan static unsigned char FPT_sfm(unsigned long port, struct sccb *pCurrSCCB)
22581da177e4SLinus Torvalds {
2259db038cf8SAlexey Dobriyan 	unsigned char message;
2260c823feebSAlexey Dobriyan 	unsigned short TimeOutLoop;
22611da177e4SLinus Torvalds 
22621da177e4SLinus Torvalds 	TimeOutLoop = 0;
22631da177e4SLinus Torvalds 	while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
22645c04a7b8SAlexey Dobriyan 	       (TimeOutLoop++ < 20000)) {
22655c04a7b8SAlexey Dobriyan 	}
22661da177e4SLinus Torvalds 
22671da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
22681da177e4SLinus Torvalds 
22691da177e4SLinus Torvalds 	message = RD_HARPOON(port + hp_scsidata_0);
22701da177e4SLinus Torvalds 
22711da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsisig, SCSI_ACK + S_MSGI_PH);
22721da177e4SLinus Torvalds 
22731da177e4SLinus Torvalds 	if (TimeOutLoop > 20000)
22741da177e4SLinus Torvalds 		message = 0x00;	/* force message byte = 0 if Time Out on Req */
22751da177e4SLinus Torvalds 
22761da177e4SLinus Torvalds 	if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
22775c04a7b8SAlexey Dobriyan 	    (RD_HARPOON(port + hp_addstat) & SCSI_PAR_ERR)) {
22781da177e4SLinus Torvalds 		WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
22791da177e4SLinus Torvalds 		WR_HARPOON(port + hp_xferstat, 0);
22801da177e4SLinus Torvalds 		WR_HARPOON(port + hp_fiforead, 0);
22811da177e4SLinus Torvalds 		WR_HARPOON(port + hp_fifowrite, 0);
22825c04a7b8SAlexey Dobriyan 		if (pCurrSCCB != NULL) {
22831da177e4SLinus Torvalds 			pCurrSCCB->Sccb_scsimsg = SMPARITY;
22841da177e4SLinus Torvalds 		}
22851da177e4SLinus Torvalds 		message = 0x00;
22865c04a7b8SAlexey Dobriyan 		do {
22871da177e4SLinus Torvalds 			ACCEPT_MSG_ATN(port);
22881da177e4SLinus Torvalds 			TimeOutLoop = 0;
22891da177e4SLinus Torvalds 			while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
22905c04a7b8SAlexey Dobriyan 			       (TimeOutLoop++ < 20000)) {
22915c04a7b8SAlexey Dobriyan 			}
22925c04a7b8SAlexey Dobriyan 			if (TimeOutLoop > 20000) {
22931da177e4SLinus Torvalds 				WRW_HARPOON((port + hp_intstat), PARITY);
22945c1b85e2SAlexey Dobriyan 				return message;
22951da177e4SLinus Torvalds 			}
22965c04a7b8SAlexey Dobriyan 			if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) !=
22975c04a7b8SAlexey Dobriyan 			    S_MSGI_PH) {
22981da177e4SLinus Torvalds 				WRW_HARPOON((port + hp_intstat), PARITY);
22995c1b85e2SAlexey Dobriyan 				return message;
23001da177e4SLinus Torvalds 			}
23011da177e4SLinus Torvalds 			WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
23021da177e4SLinus Torvalds 
23031da177e4SLinus Torvalds 			RD_HARPOON(port + hp_scsidata_0);
23041da177e4SLinus Torvalds 
23051da177e4SLinus Torvalds 			WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
23061da177e4SLinus Torvalds 
23071da177e4SLinus Torvalds 		} while (1);
23081da177e4SLinus Torvalds 
23091da177e4SLinus Torvalds 	}
23101da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
23111da177e4SLinus Torvalds 	WR_HARPOON(port + hp_xferstat, 0);
23121da177e4SLinus Torvalds 	WR_HARPOON(port + hp_fiforead, 0);
23131da177e4SLinus Torvalds 	WR_HARPOON(port + hp_fifowrite, 0);
23145c1b85e2SAlexey Dobriyan 	return message;
23151da177e4SLinus Torvalds }
23161da177e4SLinus Torvalds 
23171da177e4SLinus Torvalds /*---------------------------------------------------------------------
23181da177e4SLinus Torvalds  *
231947b5d69cSJames Bottomley   * Function: FPT_ssel
23201da177e4SLinus Torvalds  *
23211da177e4SLinus Torvalds  * Description: Load up automation and select target device.
23221da177e4SLinus Torvalds  *
23231da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
23241da177e4SLinus Torvalds 
2325d63a4cccSAlexey Dobriyan static void FPT_ssel(unsigned long port, unsigned char p_card)
23261da177e4SLinus Torvalds {
23271da177e4SLinus Torvalds 
2328db038cf8SAlexey Dobriyan 	unsigned char auto_loaded, i, target, *theCCB;
23291da177e4SLinus Torvalds 
2330d63a4cccSAlexey Dobriyan 	unsigned long cdb_reg;
233113e6851aSAlexey Dobriyan 	struct sccb_card *CurrCard;
233269eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
2333f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
2334db038cf8SAlexey Dobriyan 	unsigned char lastTag, lun;
23351da177e4SLinus Torvalds 
233647b5d69cSJames Bottomley  	CurrCard = &FPT_BL_Card[p_card];
23371da177e4SLinus Torvalds 	currSCCB = CurrCard->currentSCCB;
23381da177e4SLinus Torvalds 	target = currSCCB->TargID;
233947b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][target];
23401da177e4SLinus Torvalds 	lastTag = CurrCard->tagQ_Lst;
23411da177e4SLinus Torvalds 
23421da177e4SLinus Torvalds 	ARAM_ACCESS(port);
23431da177e4SLinus Torvalds 
23441da177e4SLinus Torvalds 	if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
23451da177e4SLinus Torvalds 		currSCCB->ControlByte &= ~F_USE_CMD_Q;
23461da177e4SLinus Torvalds 
23471da177e4SLinus Torvalds 	if (((CurrCard->globalFlags & F_CONLUN_IO) &&
23481da177e4SLinus Torvalds 	     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
23491da177e4SLinus Torvalds 
23501da177e4SLinus Torvalds 		lun = currSCCB->Lun;
23511da177e4SLinus Torvalds 	else
23521da177e4SLinus Torvalds 		lun = 0;
23531da177e4SLinus Torvalds 
23545c04a7b8SAlexey Dobriyan 	if (CurrCard->globalFlags & F_TAG_STARTED) {
23555c04a7b8SAlexey Dobriyan 		if (!(currSCCB->ControlByte & F_USE_CMD_Q)) {
235647b5d69cSJames Bottomley  			if ((currTar_Info->TarLUN_CA == 0)
23571da177e4SLinus Torvalds 			    && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
23585c04a7b8SAlexey Dobriyan 				== TAG_Q_TRYING)) {
23591da177e4SLinus Torvalds 
23605c04a7b8SAlexey Dobriyan 				if (currTar_Info->TarTagQ_Cnt != 0) {
236147b5d69cSJames Bottomley  					currTar_Info->TarLUNBusy[lun] = 1;
236247b5d69cSJames Bottomley  					FPT_queueSelectFail(CurrCard, p_card);
23631da177e4SLinus Torvalds 					SGRAM_ACCESS(port);
23641da177e4SLinus Torvalds 					return;
23651da177e4SLinus Torvalds 				}
23661da177e4SLinus Torvalds 
23671da177e4SLinus Torvalds 				else {
236847b5d69cSJames Bottomley  					currTar_Info->TarLUNBusy[lun] = 1;
23691da177e4SLinus Torvalds 				}
23701da177e4SLinus Torvalds 
23715c04a7b8SAlexey Dobriyan 			}
23725c04a7b8SAlexey Dobriyan 			/*End non-tagged */
23731da177e4SLinus Torvalds 			else {
237447b5d69cSJames Bottomley  				currTar_Info->TarLUNBusy[lun] = 1;
23751da177e4SLinus Torvalds 			}
23761da177e4SLinus Torvalds 
23775c04a7b8SAlexey Dobriyan 		}
23785c04a7b8SAlexey Dobriyan 		/*!Use cmd Q Tagged */
23791da177e4SLinus Torvalds 		else {
23805c04a7b8SAlexey Dobriyan 			if (currTar_Info->TarLUN_CA == 1) {
238147b5d69cSJames Bottomley  				FPT_queueSelectFail(CurrCard, p_card);
23821da177e4SLinus Torvalds 				SGRAM_ACCESS(port);
23831da177e4SLinus Torvalds 				return;
23841da177e4SLinus Torvalds 			}
23851da177e4SLinus Torvalds 
238647b5d69cSJames Bottomley  			currTar_Info->TarLUNBusy[lun] = 1;
23871da177e4SLinus Torvalds 
23881da177e4SLinus Torvalds 		}		/*else use cmd Q tagged */
23891da177e4SLinus Torvalds 
23905c04a7b8SAlexey Dobriyan 	}
23915c04a7b8SAlexey Dobriyan 	/*if glob tagged started */
23921da177e4SLinus Torvalds 	else {
239347b5d69cSJames Bottomley  		currTar_Info->TarLUNBusy[lun] = 1;
23941da177e4SLinus Torvalds 	}
23951da177e4SLinus Torvalds 
23961da177e4SLinus Torvalds 	if ((((CurrCard->globalFlags & F_CONLUN_IO) &&
23971da177e4SLinus Torvalds 	      ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
23985c04a7b8SAlexey Dobriyan 	     || (!(currSCCB->ControlByte & F_USE_CMD_Q)))) {
23995c04a7b8SAlexey Dobriyan 		if (CurrCard->discQCount >= QUEUE_DEPTH) {
240047b5d69cSJames Bottomley  			currTar_Info->TarLUNBusy[lun] = 1;
240147b5d69cSJames Bottomley  			FPT_queueSelectFail(CurrCard, p_card);
24021da177e4SLinus Torvalds 			SGRAM_ACCESS(port);
24031da177e4SLinus Torvalds 			return;
24041da177e4SLinus Torvalds 		}
24055c04a7b8SAlexey Dobriyan 		for (i = 1; i < QUEUE_DEPTH; i++) {
24065c04a7b8SAlexey Dobriyan 			if (++lastTag >= QUEUE_DEPTH)
24075c04a7b8SAlexey Dobriyan 				lastTag = 1;
24085c04a7b8SAlexey Dobriyan 			if (CurrCard->discQ_Tbl[lastTag] == NULL) {
24091da177e4SLinus Torvalds 				CurrCard->tagQ_Lst = lastTag;
24101da177e4SLinus Torvalds 				currTar_Info->LunDiscQ_Idx[lun] = lastTag;
24111da177e4SLinus Torvalds 				CurrCard->discQ_Tbl[lastTag] = currSCCB;
24121da177e4SLinus Torvalds 				CurrCard->discQCount++;
24131da177e4SLinus Torvalds 				break;
24141da177e4SLinus Torvalds 			}
24151da177e4SLinus Torvalds 		}
24165c04a7b8SAlexey Dobriyan 		if (i == QUEUE_DEPTH) {
241747b5d69cSJames Bottomley  			currTar_Info->TarLUNBusy[lun] = 1;
241847b5d69cSJames Bottomley  			FPT_queueSelectFail(CurrCard, p_card);
24191da177e4SLinus Torvalds 			SGRAM_ACCESS(port);
24201da177e4SLinus Torvalds 			return;
24211da177e4SLinus Torvalds 		}
24221da177e4SLinus Torvalds 	}
24231da177e4SLinus Torvalds 
242447b5d69cSJames Bottomley  	auto_loaded = 0;
24251da177e4SLinus Torvalds 
24261da177e4SLinus Torvalds 	WR_HARPOON(port + hp_select_id, target);
24271da177e4SLinus Torvalds 	WR_HARPOON(port + hp_gp_reg_3, target);	/* Use by new automation logic */
24281da177e4SLinus Torvalds 
24291da177e4SLinus Torvalds 	if (currSCCB->OperationCode == RESET_COMMAND) {
24301da177e4SLinus Torvalds 		WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
24315c04a7b8SAlexey Dobriyan 						   (currSCCB->
24325c04a7b8SAlexey Dobriyan 						    Sccb_idmsg & ~DISC_PRIV)));
24331da177e4SLinus Torvalds 
24341da177e4SLinus Torvalds 		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + NP);
24351da177e4SLinus Torvalds 
24361da177e4SLinus Torvalds 		currSCCB->Sccb_scsimsg = SMDEV_RESET;
24371da177e4SLinus Torvalds 
24381da177e4SLinus Torvalds 		WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
243947b5d69cSJames Bottomley  		auto_loaded = 1;
24401da177e4SLinus Torvalds 		currSCCB->Sccb_scsistat = SELECT_BDR_ST;
24411da177e4SLinus Torvalds 
24425c04a7b8SAlexey Dobriyan 		if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
24431da177e4SLinus Torvalds 			currTar_Info->TarSyncCtrl = 0;
24441da177e4SLinus Torvalds 			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
24451da177e4SLinus Torvalds 		}
24461da177e4SLinus Torvalds 
24475c04a7b8SAlexey Dobriyan 		if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
24481da177e4SLinus Torvalds 			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
24491da177e4SLinus Torvalds 		}
24501da177e4SLinus Torvalds 
245147b5d69cSJames Bottomley  		FPT_sssyncv(port, target, NARROW_SCSI, currTar_Info);
245247b5d69cSJames Bottomley  		FPT_SccbMgrTableInitTarget(p_card, target);
24531da177e4SLinus Torvalds 
24541da177e4SLinus Torvalds 	}
24551da177e4SLinus Torvalds 
24565c04a7b8SAlexey Dobriyan 	else if (currSCCB->Sccb_scsistat == ABORT_ST) {
24571da177e4SLinus Torvalds 		WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
24585c04a7b8SAlexey Dobriyan 						   (currSCCB->
24595c04a7b8SAlexey Dobriyan 						    Sccb_idmsg & ~DISC_PRIV)));
24601da177e4SLinus Torvalds 
24611da177e4SLinus Torvalds 		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
24621da177e4SLinus Torvalds 
24631da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT +
24645c04a7b8SAlexey Dobriyan 						     (((unsigned
24655c04a7b8SAlexey Dobriyan 							char)(currSCCB->
24665c04a7b8SAlexey Dobriyan 							      ControlByte &
24675c04a7b8SAlexey Dobriyan 							      TAG_TYPE_MASK)
24685c04a7b8SAlexey Dobriyan 						       >> 6) | (unsigned char)
24695c04a7b8SAlexey Dobriyan 						      0x20)));
24701da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 2),
24711da177e4SLinus Torvalds 			    (MPM_OP + AMSG_OUT + currSCCB->Sccb_tag));
24721da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 4), (BRH_OP + ALWAYS + NP));
24731da177e4SLinus Torvalds 
24741da177e4SLinus Torvalds 		WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
247547b5d69cSJames Bottomley  		auto_loaded = 1;
24761da177e4SLinus Torvalds 
24771da177e4SLinus Torvalds 	}
24781da177e4SLinus Torvalds 
24791da177e4SLinus Torvalds 	else if (!(currTar_Info->TarStatus & WIDE_NEGOCIATED)) {
248047b5d69cSJames Bottomley  		auto_loaded = FPT_siwidn(port, p_card);
24811da177e4SLinus Torvalds 		currSCCB->Sccb_scsistat = SELECT_WN_ST;
24821da177e4SLinus Torvalds 	}
24831da177e4SLinus Torvalds 
24841da177e4SLinus Torvalds 	else if (!((currTar_Info->TarStatus & TAR_SYNC_MASK)
24851da177e4SLinus Torvalds 		   == SYNC_SUPPORTED)) {
248647b5d69cSJames Bottomley  		auto_loaded = FPT_sisyncn(port, p_card, 0);
24871da177e4SLinus Torvalds 		currSCCB->Sccb_scsistat = SELECT_SN_ST;
24881da177e4SLinus Torvalds 	}
24891da177e4SLinus Torvalds 
24905c04a7b8SAlexey Dobriyan 	if (!auto_loaded) {
24911da177e4SLinus Torvalds 
24925c04a7b8SAlexey Dobriyan 		if (currSCCB->ControlByte & F_USE_CMD_Q) {
24931da177e4SLinus Torvalds 
24941da177e4SLinus Torvalds 			CurrCard->globalFlags |= F_TAG_STARTED;
24951da177e4SLinus Torvalds 
24961da177e4SLinus Torvalds 			if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
24975c04a7b8SAlexey Dobriyan 			    == TAG_Q_REJECT) {
24981da177e4SLinus Torvalds 				currSCCB->ControlByte &= ~F_USE_CMD_Q;
24991da177e4SLinus Torvalds 
25001da177e4SLinus Torvalds 				/* Fix up the start instruction with a jump to
25011da177e4SLinus Torvalds 				   Non-Tag-CMD handling */
25025c04a7b8SAlexey Dobriyan 				WRW_HARPOON((port + ID_MSG_STRT),
25035c04a7b8SAlexey Dobriyan 					    BRH_OP + ALWAYS + NTCMD);
25041da177e4SLinus Torvalds 
25051da177e4SLinus Torvalds 				WRW_HARPOON((port + NON_TAG_ID_MSG),
25065c04a7b8SAlexey Dobriyan 					    (MPM_OP + AMSG_OUT +
25075c04a7b8SAlexey Dobriyan 					     currSCCB->Sccb_idmsg));
25081da177e4SLinus Torvalds 
25095c04a7b8SAlexey Dobriyan 				WR_HARPOON(port + hp_autostart_3,
25105c04a7b8SAlexey Dobriyan 					   (SELECT + SELCHK_STRT));
25111da177e4SLinus Torvalds 
2512*25985edcSLucas De Marchi 				/* Setup our STATE so we know what happened when
25131da177e4SLinus Torvalds 				   the wheels fall off. */
25141da177e4SLinus Torvalds 				currSCCB->Sccb_scsistat = SELECT_ST;
25151da177e4SLinus Torvalds 
251647b5d69cSJames Bottomley  				currTar_Info->TarLUNBusy[lun] = 1;
25171da177e4SLinus Torvalds 			}
25181da177e4SLinus Torvalds 
25195c04a7b8SAlexey Dobriyan 			else {
25205c04a7b8SAlexey Dobriyan 				WRW_HARPOON((port + ID_MSG_STRT),
25215c04a7b8SAlexey Dobriyan 					    (MPM_OP + AMSG_OUT +
25225c04a7b8SAlexey Dobriyan 					     currSCCB->Sccb_idmsg));
25231da177e4SLinus Torvalds 
25245c04a7b8SAlexey Dobriyan 				WRW_HARPOON((port + ID_MSG_STRT + 2),
25255c04a7b8SAlexey Dobriyan 					    (MPM_OP + AMSG_OUT +
25265c04a7b8SAlexey Dobriyan 					     (((unsigned char)(currSCCB->
25275c04a7b8SAlexey Dobriyan 							       ControlByte &
25285c04a7b8SAlexey Dobriyan 							       TAG_TYPE_MASK)
2529db038cf8SAlexey Dobriyan 					       >> 6) | (unsigned char)0x20)));
25301da177e4SLinus Torvalds 
25315c04a7b8SAlexey Dobriyan 				for (i = 1; i < QUEUE_DEPTH; i++) {
25325c04a7b8SAlexey Dobriyan 					if (++lastTag >= QUEUE_DEPTH)
25335c04a7b8SAlexey Dobriyan 						lastTag = 1;
25345c04a7b8SAlexey Dobriyan 					if (CurrCard->discQ_Tbl[lastTag] ==
25355c04a7b8SAlexey Dobriyan 					    NULL) {
25365c04a7b8SAlexey Dobriyan 						WRW_HARPOON((port +
25375c04a7b8SAlexey Dobriyan 							     ID_MSG_STRT + 6),
25385c04a7b8SAlexey Dobriyan 							    (MPM_OP + AMSG_OUT +
25395c04a7b8SAlexey Dobriyan 							     lastTag));
25401da177e4SLinus Torvalds 						CurrCard->tagQ_Lst = lastTag;
25411da177e4SLinus Torvalds 						currSCCB->Sccb_tag = lastTag;
25425c04a7b8SAlexey Dobriyan 						CurrCard->discQ_Tbl[lastTag] =
25435c04a7b8SAlexey Dobriyan 						    currSCCB;
25441da177e4SLinus Torvalds 						CurrCard->discQCount++;
25451da177e4SLinus Torvalds 						break;
25461da177e4SLinus Torvalds 					}
25471da177e4SLinus Torvalds 				}
25481da177e4SLinus Torvalds 
25495c04a7b8SAlexey Dobriyan 				if (i == QUEUE_DEPTH) {
255047b5d69cSJames Bottomley  					currTar_Info->TarLUNBusy[lun] = 1;
255147b5d69cSJames Bottomley  					FPT_queueSelectFail(CurrCard, p_card);
25521da177e4SLinus Torvalds 					SGRAM_ACCESS(port);
25531da177e4SLinus Torvalds 					return;
25541da177e4SLinus Torvalds 				}
25551da177e4SLinus Torvalds 
25561da177e4SLinus Torvalds 				currSCCB->Sccb_scsistat = SELECT_Q_ST;
25571da177e4SLinus Torvalds 
25585c04a7b8SAlexey Dobriyan 				WR_HARPOON(port + hp_autostart_3,
25595c04a7b8SAlexey Dobriyan 					   (SELECT + SELCHK_STRT));
25601da177e4SLinus Torvalds 			}
25611da177e4SLinus Torvalds 		}
25621da177e4SLinus Torvalds 
25635c04a7b8SAlexey Dobriyan 		else {
25641da177e4SLinus Torvalds 
25655c04a7b8SAlexey Dobriyan 			WRW_HARPOON((port + ID_MSG_STRT),
25665c04a7b8SAlexey Dobriyan 				    BRH_OP + ALWAYS + NTCMD);
25671da177e4SLinus Torvalds 
25681da177e4SLinus Torvalds 			WRW_HARPOON((port + NON_TAG_ID_MSG),
25691da177e4SLinus Torvalds 				    (MPM_OP + AMSG_OUT + currSCCB->Sccb_idmsg));
25701da177e4SLinus Torvalds 
25711da177e4SLinus Torvalds 			currSCCB->Sccb_scsistat = SELECT_ST;
25721da177e4SLinus Torvalds 
25735c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_autostart_3,
25745c04a7b8SAlexey Dobriyan 				   (SELECT + SELCHK_STRT));
25751da177e4SLinus Torvalds 		}
25761da177e4SLinus Torvalds 
2577db038cf8SAlexey Dobriyan 		theCCB = (unsigned char *)&currSCCB->Cdb[0];
25781da177e4SLinus Torvalds 
25791da177e4SLinus Torvalds 		cdb_reg = port + CMD_STRT;
25801da177e4SLinus Torvalds 
25815c04a7b8SAlexey Dobriyan 		for (i = 0; i < currSCCB->CdbLength; i++) {
25821da177e4SLinus Torvalds 			WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + *theCCB));
25831da177e4SLinus Torvalds 			cdb_reg += 2;
25841da177e4SLinus Torvalds 			theCCB++;
25851da177e4SLinus Torvalds 		}
25861da177e4SLinus Torvalds 
25871da177e4SLinus Torvalds 		if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
25881da177e4SLinus Torvalds 			WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
25891da177e4SLinus Torvalds 
25905c04a7b8SAlexey Dobriyan 	}
25915c04a7b8SAlexey Dobriyan 	/* auto_loaded */
2592c823feebSAlexey Dobriyan 	WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
25931da177e4SLinus Torvalds 	WR_HARPOON(port + hp_xferstat, 0x00);
25941da177e4SLinus Torvalds 
25951da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), (PROG_HLT | TIMEOUT | SEL | BUS_FREE));
25961da177e4SLinus Torvalds 
25971da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT));
25981da177e4SLinus Torvalds 
25995c04a7b8SAlexey Dobriyan 	if (!(currSCCB->Sccb_MGRFlags & F_DEV_SELECTED)) {
26005c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_scsictrl_0,
26015c04a7b8SAlexey Dobriyan 			   (SEL_TAR | ENA_ATN | ENA_RESEL | ENA_SCAM_SEL));
26025c04a7b8SAlexey Dobriyan 	} else {
26031da177e4SLinus Torvalds 
2604db038cf8SAlexey Dobriyan /*      auto_loaded =  (RD_HARPOON(port+hp_autostart_3) & (unsigned char)0x1F);
26051da177e4SLinus Torvalds       auto_loaded |= AUTO_IMMED; */
26061da177e4SLinus Torvalds 		auto_loaded = AUTO_IMMED;
26071da177e4SLinus Torvalds 
26081da177e4SLinus Torvalds 		DISABLE_AUTO(port);
26091da177e4SLinus Torvalds 
26101da177e4SLinus Torvalds 		WR_HARPOON(port + hp_autostart_3, auto_loaded);
26111da177e4SLinus Torvalds 	}
26121da177e4SLinus Torvalds 
26131da177e4SLinus Torvalds 	SGRAM_ACCESS(port);
26141da177e4SLinus Torvalds }
26151da177e4SLinus Torvalds 
26161da177e4SLinus Torvalds /*---------------------------------------------------------------------
26171da177e4SLinus Torvalds  *
261847b5d69cSJames Bottomley   * Function: FPT_sres
26191da177e4SLinus Torvalds  *
26201da177e4SLinus Torvalds  * Description: Hookup the correct CCB and handle the incoming messages.
26211da177e4SLinus Torvalds  *
26221da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
26231da177e4SLinus Torvalds 
26245c04a7b8SAlexey Dobriyan static void FPT_sres(unsigned long port, unsigned char p_card,
26255c04a7b8SAlexey Dobriyan 		     struct sccb_card *pCurrCard)
26261da177e4SLinus Torvalds {
26271da177e4SLinus Torvalds 
2628db038cf8SAlexey Dobriyan 	unsigned char our_target, message, lun = 0, tag, msgRetryCount;
26291da177e4SLinus Torvalds 
2630f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
263169eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
26321da177e4SLinus Torvalds 
26335c04a7b8SAlexey Dobriyan 	if (pCurrCard->currentSCCB != NULL) {
26345c04a7b8SAlexey Dobriyan 		currTar_Info =
26355c04a7b8SAlexey Dobriyan 		    &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
26361da177e4SLinus Torvalds 		DISABLE_AUTO(port);
26371da177e4SLinus Torvalds 
26381da177e4SLinus Torvalds 		WR_HARPOON((port + hp_scsictrl_0), (ENA_RESEL | ENA_SCAM_SEL));
26391da177e4SLinus Torvalds 
26401da177e4SLinus Torvalds 		currSCCB = pCurrCard->currentSCCB;
26415c04a7b8SAlexey Dobriyan 		if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
26421da177e4SLinus Torvalds 			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
26431da177e4SLinus Torvalds 			currSCCB->Sccb_scsistat = BUS_FREE_ST;
26441da177e4SLinus Torvalds 		}
26455c04a7b8SAlexey Dobriyan 		if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
26461da177e4SLinus Torvalds 			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
26471da177e4SLinus Torvalds 			currSCCB->Sccb_scsistat = BUS_FREE_ST;
26481da177e4SLinus Torvalds 		}
26491da177e4SLinus Torvalds 		if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
26505c04a7b8SAlexey Dobriyan 		     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
26515c04a7b8SAlexey Dobriyan 		      TAG_Q_TRYING))) {
265247b5d69cSJames Bottomley  			currTar_Info->TarLUNBusy[currSCCB->Lun] = 0;
26535c04a7b8SAlexey Dobriyan 			if (currSCCB->Sccb_scsistat != ABORT_ST) {
26541da177e4SLinus Torvalds 				pCurrCard->discQCount--;
26555c04a7b8SAlexey Dobriyan 				pCurrCard->discQ_Tbl[currTar_Info->
26565c04a7b8SAlexey Dobriyan 						     LunDiscQ_Idx[currSCCB->
26575c04a7b8SAlexey Dobriyan 								  Lun]]
26581da177e4SLinus Torvalds 				    = NULL;
26591da177e4SLinus Torvalds 			}
26605c04a7b8SAlexey Dobriyan 		} else {
266147b5d69cSJames Bottomley  			currTar_Info->TarLUNBusy[0] = 0;
26625c04a7b8SAlexey Dobriyan 			if (currSCCB->Sccb_tag) {
26635c04a7b8SAlexey Dobriyan 				if (currSCCB->Sccb_scsistat != ABORT_ST) {
26641da177e4SLinus Torvalds 					pCurrCard->discQCount--;
26655c04a7b8SAlexey Dobriyan 					pCurrCard->discQ_Tbl[currSCCB->
26665c04a7b8SAlexey Dobriyan 							     Sccb_tag] = NULL;
26671da177e4SLinus Torvalds 				}
26685c04a7b8SAlexey Dobriyan 			} else {
26695c04a7b8SAlexey Dobriyan 				if (currSCCB->Sccb_scsistat != ABORT_ST) {
26701da177e4SLinus Torvalds 					pCurrCard->discQCount--;
26715c04a7b8SAlexey Dobriyan 					pCurrCard->discQ_Tbl[currTar_Info->
26725c04a7b8SAlexey Dobriyan 							     LunDiscQ_Idx[0]] =
26735c04a7b8SAlexey Dobriyan 					    NULL;
26741da177e4SLinus Torvalds 				}
26751da177e4SLinus Torvalds 			}
26761da177e4SLinus Torvalds 		}
26771da177e4SLinus Torvalds 
267847b5d69cSJames Bottomley  		FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
26791da177e4SLinus Torvalds 	}
26801da177e4SLinus Torvalds 
2681c823feebSAlexey Dobriyan 	WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
26821da177e4SLinus Torvalds 
2683db038cf8SAlexey Dobriyan 	our_target = (unsigned char)(RD_HARPOON(port + hp_select_id) >> 4);
268447b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
26851da177e4SLinus Torvalds 
26861da177e4SLinus Torvalds 	msgRetryCount = 0;
26875c04a7b8SAlexey Dobriyan 	do {
26881da177e4SLinus Torvalds 
268947b5d69cSJames Bottomley  		currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
26901da177e4SLinus Torvalds 		tag = 0;
26911da177e4SLinus Torvalds 
26925c04a7b8SAlexey Dobriyan 		while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
26935c04a7b8SAlexey Dobriyan 			if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
26941da177e4SLinus Torvalds 
26951da177e4SLinus Torvalds 				WRW_HARPOON((port + hp_intstat), PHASE);
26961da177e4SLinus Torvalds 				return;
26971da177e4SLinus Torvalds 			}
26981da177e4SLinus Torvalds 		}
26991da177e4SLinus Torvalds 
27001da177e4SLinus Torvalds 		WRW_HARPOON((port + hp_intstat), PHASE);
27015c04a7b8SAlexey Dobriyan 		if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH) {
27021da177e4SLinus Torvalds 
270347b5d69cSJames Bottomley  			message = FPT_sfm(port, pCurrCard->currentSCCB);
27045c04a7b8SAlexey Dobriyan 			if (message) {
27051da177e4SLinus Torvalds 
27065c04a7b8SAlexey Dobriyan 				if (message <= (0x80 | LUN_MASK)) {
2707db038cf8SAlexey Dobriyan 					lun = message & (unsigned char)LUN_MASK;
27081da177e4SLinus Torvalds 
27095c04a7b8SAlexey Dobriyan 					if ((currTar_Info->
27105c04a7b8SAlexey Dobriyan 					     TarStatus & TAR_TAG_Q_MASK) ==
27115c04a7b8SAlexey Dobriyan 					    TAG_Q_TRYING) {
27125c04a7b8SAlexey Dobriyan 						if (currTar_Info->TarTagQ_Cnt !=
27135c04a7b8SAlexey Dobriyan 						    0) {
27141da177e4SLinus Torvalds 
27155c04a7b8SAlexey Dobriyan 							if (!
27165c04a7b8SAlexey Dobriyan 							    (currTar_Info->
27175c04a7b8SAlexey Dobriyan 							     TarLUN_CA)) {
27181da177e4SLinus Torvalds 								ACCEPT_MSG(port);	/*Release the ACK for ID msg. */
27191da177e4SLinus Torvalds 
27205c04a7b8SAlexey Dobriyan 								message =
27215c04a7b8SAlexey Dobriyan 								    FPT_sfm
27225c04a7b8SAlexey Dobriyan 								    (port,
27235c04a7b8SAlexey Dobriyan 								     pCurrCard->
27245c04a7b8SAlexey Dobriyan 								     currentSCCB);
27255c04a7b8SAlexey Dobriyan 								if (message) {
27265c04a7b8SAlexey Dobriyan 									ACCEPT_MSG
27275c04a7b8SAlexey Dobriyan 									    (port);
27281da177e4SLinus Torvalds 								}
27291da177e4SLinus Torvalds 
27301da177e4SLinus Torvalds 								else
27315c04a7b8SAlexey Dobriyan 									message
27325c04a7b8SAlexey Dobriyan 									    = 0;
27331da177e4SLinus Torvalds 
27345c04a7b8SAlexey Dobriyan 								if (message !=
27355c04a7b8SAlexey Dobriyan 								    0) {
27365c04a7b8SAlexey Dobriyan 									tag =
27375c04a7b8SAlexey Dobriyan 									    FPT_sfm
27385c04a7b8SAlexey Dobriyan 									    (port,
27395c04a7b8SAlexey Dobriyan 									     pCurrCard->
27405c04a7b8SAlexey Dobriyan 									     currentSCCB);
27411da177e4SLinus Torvalds 
27425c04a7b8SAlexey Dobriyan 									if (!
27435c04a7b8SAlexey Dobriyan 									    (tag))
27445c04a7b8SAlexey Dobriyan 										message
27455c04a7b8SAlexey Dobriyan 										    =
27465c04a7b8SAlexey Dobriyan 										    0;
27471da177e4SLinus Torvalds 								}
27481da177e4SLinus Torvalds 
27495c04a7b8SAlexey Dobriyan 							}
27505c04a7b8SAlexey Dobriyan 							/*C.A. exists! */
27515c04a7b8SAlexey Dobriyan 						}
27525c04a7b8SAlexey Dobriyan 						/*End Q cnt != 0 */
27535c04a7b8SAlexey Dobriyan 					}
27545c04a7b8SAlexey Dobriyan 					/*End Tag cmds supported! */
27555c04a7b8SAlexey Dobriyan 				}
27565c04a7b8SAlexey Dobriyan 				/*End valid ID message.  */
27575c04a7b8SAlexey Dobriyan 				else {
27581da177e4SLinus Torvalds 
27591da177e4SLinus Torvalds 					ACCEPT_MSG_ATN(port);
27601da177e4SLinus Torvalds 				}
27611da177e4SLinus Torvalds 
27625c04a7b8SAlexey Dobriyan 			}
27635c04a7b8SAlexey Dobriyan 			/* End good id message. */
27645c04a7b8SAlexey Dobriyan 			else {
27651da177e4SLinus Torvalds 
276647b5d69cSJames Bottomley  				message = 0;
27671da177e4SLinus Torvalds 			}
27685c04a7b8SAlexey Dobriyan 		} else {
27691da177e4SLinus Torvalds 			ACCEPT_MSG_ATN(port);
27701da177e4SLinus Torvalds 
27715c04a7b8SAlexey Dobriyan 			while (!
27725c04a7b8SAlexey Dobriyan 			       (RDW_HARPOON((port + hp_intstat)) &
27735c04a7b8SAlexey Dobriyan 				(PHASE | RESET))
27745c04a7b8SAlexey Dobriyan 			       && !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
27755c04a7b8SAlexey Dobriyan 			       && (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
27761da177e4SLinus Torvalds 
27771da177e4SLinus Torvalds 			return;
27781da177e4SLinus Torvalds 		}
27791da177e4SLinus Torvalds 
27805c04a7b8SAlexey Dobriyan 		if (message == 0) {
27811da177e4SLinus Torvalds 			msgRetryCount++;
27825c04a7b8SAlexey Dobriyan 			if (msgRetryCount == 1) {
278347b5d69cSJames Bottomley  				FPT_SendMsg(port, SMPARITY);
27845c04a7b8SAlexey Dobriyan 			} else {
278547b5d69cSJames Bottomley  				FPT_SendMsg(port, SMDEV_RESET);
27861da177e4SLinus Torvalds 
27875c04a7b8SAlexey Dobriyan 				FPT_sssyncv(port, our_target, NARROW_SCSI,
27885c04a7b8SAlexey Dobriyan 					    currTar_Info);
27891da177e4SLinus Torvalds 
27905c04a7b8SAlexey Dobriyan 				if (FPT_sccbMgrTbl[p_card][our_target].
27915c04a7b8SAlexey Dobriyan 				    TarEEValue & EE_SYNC_MASK) {
27921da177e4SLinus Torvalds 
27935c04a7b8SAlexey Dobriyan 					FPT_sccbMgrTbl[p_card][our_target].
27945c04a7b8SAlexey Dobriyan 					    TarStatus &= ~TAR_SYNC_MASK;
27951da177e4SLinus Torvalds 
27961da177e4SLinus Torvalds 				}
27971da177e4SLinus Torvalds 
27985c04a7b8SAlexey Dobriyan 				if (FPT_sccbMgrTbl[p_card][our_target].
27995c04a7b8SAlexey Dobriyan 				    TarEEValue & EE_WIDE_SCSI) {
28001da177e4SLinus Torvalds 
28015c04a7b8SAlexey Dobriyan 					FPT_sccbMgrTbl[p_card][our_target].
28025c04a7b8SAlexey Dobriyan 					    TarStatus &= ~TAR_WIDE_MASK;
28031da177e4SLinus Torvalds 				}
28041da177e4SLinus Torvalds 
28055c04a7b8SAlexey Dobriyan 				FPT_queueFlushTargSccb(p_card, our_target,
28065c04a7b8SAlexey Dobriyan 						       SCCB_COMPLETE);
280747b5d69cSJames Bottomley  				FPT_SccbMgrTableInitTarget(p_card, our_target);
28081da177e4SLinus Torvalds 				return;
28091da177e4SLinus Torvalds 			}
28101da177e4SLinus Torvalds 		}
281147b5d69cSJames Bottomley  	} while (message == 0);
28121da177e4SLinus Torvalds 
28131da177e4SLinus Torvalds 	if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
28145c04a7b8SAlexey Dobriyan 	     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
281547b5d69cSJames Bottomley  		currTar_Info->TarLUNBusy[lun] = 1;
28165c04a7b8SAlexey Dobriyan 		pCurrCard->currentSCCB =
28175c04a7b8SAlexey Dobriyan 		    pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[lun]];
28185c04a7b8SAlexey Dobriyan 		if (pCurrCard->currentSCCB != NULL) {
28191da177e4SLinus Torvalds 			ACCEPT_MSG(port);
28205c04a7b8SAlexey Dobriyan 		} else {
28211da177e4SLinus Torvalds 			ACCEPT_MSG_ATN(port);
28221da177e4SLinus Torvalds 		}
28235c04a7b8SAlexey Dobriyan 	} else {
282447b5d69cSJames Bottomley  		currTar_Info->TarLUNBusy[0] = 1;
28251da177e4SLinus Torvalds 
28265c04a7b8SAlexey Dobriyan 		if (tag) {
28275c04a7b8SAlexey Dobriyan 			if (pCurrCard->discQ_Tbl[tag] != NULL) {
28285c04a7b8SAlexey Dobriyan 				pCurrCard->currentSCCB =
28295c04a7b8SAlexey Dobriyan 				    pCurrCard->discQ_Tbl[tag];
28301da177e4SLinus Torvalds 				currTar_Info->TarTagQ_Cnt--;
28311da177e4SLinus Torvalds 				ACCEPT_MSG(port);
28325c04a7b8SAlexey Dobriyan 			} else {
28331da177e4SLinus Torvalds 				ACCEPT_MSG_ATN(port);
28341da177e4SLinus Torvalds 			}
28355c04a7b8SAlexey Dobriyan 		} else {
28365c04a7b8SAlexey Dobriyan 			pCurrCard->currentSCCB =
28375c04a7b8SAlexey Dobriyan 			    pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]];
28385c04a7b8SAlexey Dobriyan 			if (pCurrCard->currentSCCB != NULL) {
28391da177e4SLinus Torvalds 				ACCEPT_MSG(port);
28405c04a7b8SAlexey Dobriyan 			} else {
28411da177e4SLinus Torvalds 				ACCEPT_MSG_ATN(port);
28421da177e4SLinus Torvalds 			}
28431da177e4SLinus Torvalds 		}
28441da177e4SLinus Torvalds 	}
28451da177e4SLinus Torvalds 
28465c04a7b8SAlexey Dobriyan 	if (pCurrCard->currentSCCB != NULL) {
28475c04a7b8SAlexey Dobriyan 		if (pCurrCard->currentSCCB->Sccb_scsistat == ABORT_ST) {
28481da177e4SLinus Torvalds 			/* During Abort Tag command, the target could have got re-selected
28491da177e4SLinus Torvalds 			   and completed the command. Check the select Q and remove the CCB
28501da177e4SLinus Torvalds 			   if it is in the Select Q */
285147b5d69cSJames Bottomley  			FPT_queueFindSccb(pCurrCard->currentSCCB, p_card);
28521da177e4SLinus Torvalds 		}
28531da177e4SLinus Torvalds 	}
28541da177e4SLinus Torvalds 
28551da177e4SLinus Torvalds 	while (!(RDW_HARPOON((port + hp_intstat)) & (PHASE | RESET)) &&
28561da177e4SLinus Torvalds 	       !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ) &&
28571da177e4SLinus Torvalds 	       (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
28581da177e4SLinus Torvalds }
28591da177e4SLinus Torvalds 
2860d63a4cccSAlexey Dobriyan static void FPT_SendMsg(unsigned long port, unsigned char message)
28611da177e4SLinus Torvalds {
28625c04a7b8SAlexey Dobriyan 	while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
28635c04a7b8SAlexey Dobriyan 		if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
28641da177e4SLinus Torvalds 
28651da177e4SLinus Torvalds 			WRW_HARPOON((port + hp_intstat), PHASE);
28661da177e4SLinus Torvalds 			return;
28671da177e4SLinus Torvalds 		}
28681da177e4SLinus Torvalds 	}
28691da177e4SLinus Torvalds 
28701da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), PHASE);
28715c04a7b8SAlexey Dobriyan 	if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGO_PH) {
28725c04a7b8SAlexey Dobriyan 		WRW_HARPOON((port + hp_intstat),
28735c04a7b8SAlexey Dobriyan 			    (BUS_FREE | PHASE | XFER_CNT_0));
28741da177e4SLinus Torvalds 
28751da177e4SLinus Torvalds 		WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
28761da177e4SLinus Torvalds 
28771da177e4SLinus Torvalds 		WR_HARPOON(port + hp_scsidata_0, message);
28781da177e4SLinus Torvalds 
28791da177e4SLinus Torvalds 		WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
28801da177e4SLinus Torvalds 
28811da177e4SLinus Torvalds 		ACCEPT_MSG(port);
28821da177e4SLinus Torvalds 
28831da177e4SLinus Torvalds 		WR_HARPOON(port + hp_portctrl_0, 0x00);
28841da177e4SLinus Torvalds 
28851da177e4SLinus Torvalds 		if ((message == SMABORT) || (message == SMDEV_RESET) ||
28865c04a7b8SAlexey Dobriyan 		    (message == SMABORT_TAG)) {
28875c04a7b8SAlexey Dobriyan 			while (!
28885c04a7b8SAlexey Dobriyan 			       (RDW_HARPOON((port + hp_intstat)) &
28895c04a7b8SAlexey Dobriyan 				(BUS_FREE | PHASE))) {
28905c04a7b8SAlexey Dobriyan 			}
28911da177e4SLinus Torvalds 
28925c04a7b8SAlexey Dobriyan 			if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
28931da177e4SLinus Torvalds 				WRW_HARPOON((port + hp_intstat), BUS_FREE);
28941da177e4SLinus Torvalds 			}
28951da177e4SLinus Torvalds 		}
28961da177e4SLinus Torvalds 	}
28971da177e4SLinus Torvalds }
28981da177e4SLinus Torvalds 
28991da177e4SLinus Torvalds /*---------------------------------------------------------------------
29001da177e4SLinus Torvalds  *
290147b5d69cSJames Bottomley   * Function: FPT_sdecm
29021da177e4SLinus Torvalds  *
2903*25985edcSLucas De Marchi  * Description: Determine the proper response to the message from the
29041da177e4SLinus Torvalds  *              target device.
29051da177e4SLinus Torvalds  *
29061da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
29075c04a7b8SAlexey Dobriyan static void FPT_sdecm(unsigned char message, unsigned long port,
29085c04a7b8SAlexey Dobriyan 		      unsigned char p_card)
29091da177e4SLinus Torvalds {
291069eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
291113e6851aSAlexey Dobriyan 	struct sccb_card *CurrCard;
2912f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
29131da177e4SLinus Torvalds 
291447b5d69cSJames Bottomley  	CurrCard = &FPT_BL_Card[p_card];
29151da177e4SLinus Torvalds 	currSCCB = CurrCard->currentSCCB;
29161da177e4SLinus Torvalds 
291747b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
29181da177e4SLinus Torvalds 
29195c04a7b8SAlexey Dobriyan 	if (message == SMREST_DATA_PTR) {
29205c04a7b8SAlexey Dobriyan 		if (!(currSCCB->Sccb_XferState & F_NO_DATA_YET)) {
29211da177e4SLinus Torvalds 			currSCCB->Sccb_ATC = currSCCB->Sccb_savedATC;
29221da177e4SLinus Torvalds 
292347b5d69cSJames Bottomley  			FPT_hostDataXferRestart(currSCCB);
29241da177e4SLinus Torvalds 		}
29251da177e4SLinus Torvalds 
29261da177e4SLinus Torvalds 		ACCEPT_MSG(port);
29275c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
29285c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
29291da177e4SLinus Torvalds 	}
29301da177e4SLinus Torvalds 
29315c04a7b8SAlexey Dobriyan 	else if (message == SMCMD_COMP) {
29321da177e4SLinus Torvalds 
29335c04a7b8SAlexey Dobriyan 		if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
29345c04a7b8SAlexey Dobriyan 			currTar_Info->TarStatus &=
29355c04a7b8SAlexey Dobriyan 			    ~(unsigned char)TAR_TAG_Q_MASK;
2936db038cf8SAlexey Dobriyan 			currTar_Info->TarStatus |= (unsigned char)TAG_Q_REJECT;
29371da177e4SLinus Torvalds 		}
29381da177e4SLinus Torvalds 
29391da177e4SLinus Torvalds 		ACCEPT_MSG(port);
29401da177e4SLinus Torvalds 
29411da177e4SLinus Torvalds 	}
29421da177e4SLinus Torvalds 
29431da177e4SLinus Torvalds 	else if ((message == SMNO_OP) || (message >= SMIDENT)
29445c04a7b8SAlexey Dobriyan 		 || (message == SMINIT_RECOVERY) || (message == SMREL_RECOVERY)) {
29451da177e4SLinus Torvalds 
29461da177e4SLinus Torvalds 		ACCEPT_MSG(port);
29475c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
29485c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
29491da177e4SLinus Torvalds 	}
29501da177e4SLinus Torvalds 
29515c04a7b8SAlexey Dobriyan 	else if (message == SMREJECT) {
29521da177e4SLinus Torvalds 
29531da177e4SLinus Torvalds 		if ((currSCCB->Sccb_scsistat == SELECT_SN_ST) ||
29541da177e4SLinus Torvalds 		    (currSCCB->Sccb_scsistat == SELECT_WN_ST) ||
29555c04a7b8SAlexey Dobriyan 		    ((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)
29565c04a7b8SAlexey Dobriyan 		    || ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) ==
29575c04a7b8SAlexey Dobriyan 			TAG_Q_TRYING))
29581da177e4SLinus Torvalds 		{
29591da177e4SLinus Torvalds 			WRW_HARPOON((port + hp_intstat), BUS_FREE);
29601da177e4SLinus Torvalds 
29611da177e4SLinus Torvalds 			ACCEPT_MSG(port);
29621da177e4SLinus Torvalds 
29631da177e4SLinus Torvalds 			while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
29645c04a7b8SAlexey Dobriyan 			       (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
29651da177e4SLinus Torvalds 			{
29661da177e4SLinus Torvalds 			}
29671da177e4SLinus Torvalds 
29685c04a7b8SAlexey Dobriyan 			if (currSCCB->Lun == 0x00) {
29695c04a7b8SAlexey Dobriyan 				if ((currSCCB->Sccb_scsistat == SELECT_SN_ST)) {
29701da177e4SLinus Torvalds 
29715c04a7b8SAlexey Dobriyan 					currTar_Info->TarStatus |=
29725c04a7b8SAlexey Dobriyan 					    (unsigned char)SYNC_SUPPORTED;
29731da177e4SLinus Torvalds 
29745c04a7b8SAlexey Dobriyan 					currTar_Info->TarEEValue &=
29755c04a7b8SAlexey Dobriyan 					    ~EE_SYNC_MASK;
29765c04a7b8SAlexey Dobriyan 				}
29771da177e4SLinus Torvalds 
29785c04a7b8SAlexey Dobriyan 				else if ((currSCCB->Sccb_scsistat ==
29795c04a7b8SAlexey Dobriyan 					  SELECT_WN_ST)) {
29805c04a7b8SAlexey Dobriyan 
29815c04a7b8SAlexey Dobriyan 					currTar_Info->TarStatus =
29825c04a7b8SAlexey Dobriyan 					    (currTar_Info->
29835c04a7b8SAlexey Dobriyan 					     TarStatus & ~WIDE_ENABLED) |
29845c04a7b8SAlexey Dobriyan 					    WIDE_NEGOCIATED;
29855c04a7b8SAlexey Dobriyan 
29865c04a7b8SAlexey Dobriyan 					currTar_Info->TarEEValue &=
29875c04a7b8SAlexey Dobriyan 					    ~EE_WIDE_SCSI;
29881da177e4SLinus Torvalds 
29891da177e4SLinus Torvalds 				}
29901da177e4SLinus Torvalds 
29915c04a7b8SAlexey Dobriyan 				else if ((currTar_Info->
29925c04a7b8SAlexey Dobriyan 					  TarStatus & TAR_TAG_Q_MASK) ==
29935c04a7b8SAlexey Dobriyan 					 TAG_Q_TRYING) {
29945c04a7b8SAlexey Dobriyan 					currTar_Info->TarStatus =
29955c04a7b8SAlexey Dobriyan 					    (currTar_Info->
29965c04a7b8SAlexey Dobriyan 					     TarStatus & ~(unsigned char)
29975c04a7b8SAlexey Dobriyan 					     TAR_TAG_Q_MASK) | TAG_Q_REJECT;
29981da177e4SLinus Torvalds 
29991da177e4SLinus Torvalds 					currSCCB->ControlByte &= ~F_USE_CMD_Q;
30001da177e4SLinus Torvalds 					CurrCard->discQCount--;
30015c04a7b8SAlexey Dobriyan 					CurrCard->discQ_Tbl[currSCCB->
30025c04a7b8SAlexey Dobriyan 							    Sccb_tag] = NULL;
30031da177e4SLinus Torvalds 					currSCCB->Sccb_tag = 0x00;
30041da177e4SLinus Torvalds 
30051da177e4SLinus Torvalds 				}
30061da177e4SLinus Torvalds 			}
30071da177e4SLinus Torvalds 
30085c04a7b8SAlexey Dobriyan 			if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
30091da177e4SLinus Torvalds 
30105c04a7b8SAlexey Dobriyan 				if (currSCCB->Lun == 0x00) {
30115c04a7b8SAlexey Dobriyan 					WRW_HARPOON((port + hp_intstat),
30125c04a7b8SAlexey Dobriyan 						    BUS_FREE);
30131da177e4SLinus Torvalds 					CurrCard->globalFlags |= F_NEW_SCCB_CMD;
30141da177e4SLinus Torvalds 				}
30151da177e4SLinus Torvalds 			}
30161da177e4SLinus Torvalds 
30175c04a7b8SAlexey Dobriyan 			else {
30181da177e4SLinus Torvalds 
30191da177e4SLinus Torvalds 				if ((CurrCard->globalFlags & F_CONLUN_IO) &&
30205c04a7b8SAlexey Dobriyan 				    ((currTar_Info->
30215c04a7b8SAlexey Dobriyan 				      TarStatus & TAR_TAG_Q_MASK) !=
30225c04a7b8SAlexey Dobriyan 				     TAG_Q_TRYING))
30235c04a7b8SAlexey Dobriyan 					currTar_Info->TarLUNBusy[currSCCB->
30245c04a7b8SAlexey Dobriyan 								 Lun] = 1;
30251da177e4SLinus Torvalds 				else
302647b5d69cSJames Bottomley  					currTar_Info->TarLUNBusy[0] = 1;
30271da177e4SLinus Torvalds 
30285c04a7b8SAlexey Dobriyan 				currSCCB->ControlByte &=
30295c04a7b8SAlexey Dobriyan 				    ~(unsigned char)F_USE_CMD_Q;
30301da177e4SLinus Torvalds 
30315c04a7b8SAlexey Dobriyan 				WR_HARPOON(port + hp_autostart_1,
30325c04a7b8SAlexey Dobriyan 					   (AUTO_IMMED + DISCONNECT_START));
30331da177e4SLinus Torvalds 
30341da177e4SLinus Torvalds 			}
30351da177e4SLinus Torvalds 		}
30361da177e4SLinus Torvalds 
30375c04a7b8SAlexey Dobriyan 		else {
30381da177e4SLinus Torvalds 			ACCEPT_MSG(port);
30391da177e4SLinus Torvalds 
30401da177e4SLinus Torvalds 			while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
30415c04a7b8SAlexey Dobriyan 			       (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
30421da177e4SLinus Torvalds 			{
30435c04a7b8SAlexey Dobriyan 			}
30445c04a7b8SAlexey Dobriyan 
30455c04a7b8SAlexey Dobriyan 			if (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)) {
30465c04a7b8SAlexey Dobriyan 				WR_HARPOON(port + hp_autostart_1,
30475c04a7b8SAlexey Dobriyan 					   (AUTO_IMMED + DISCONNECT_START));
30481da177e4SLinus Torvalds 			}
30491da177e4SLinus Torvalds 		}
30501da177e4SLinus Torvalds 	}
30511da177e4SLinus Torvalds 
30525c04a7b8SAlexey Dobriyan 	else if (message == SMEXT) {
30531da177e4SLinus Torvalds 
30541da177e4SLinus Torvalds 		ACCEPT_MSG(port);
305547b5d69cSJames Bottomley  		FPT_shandem(port, p_card, currSCCB);
30561da177e4SLinus Torvalds 	}
30571da177e4SLinus Torvalds 
30585c04a7b8SAlexey Dobriyan 	else if (message == SMIGNORWR) {
30591da177e4SLinus Torvalds 
30601da177e4SLinus Torvalds 		ACCEPT_MSG(port);	/* ACK the RESIDUE MSG */
30611da177e4SLinus Torvalds 
306247b5d69cSJames Bottomley  		message = FPT_sfm(port, currSCCB);
30631da177e4SLinus Torvalds 
30641da177e4SLinus Torvalds 		if (currSCCB->Sccb_scsimsg != SMPARITY)
30651da177e4SLinus Torvalds 			ACCEPT_MSG(port);
30665c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
30675c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
30681da177e4SLinus Torvalds 	}
30691da177e4SLinus Torvalds 
30705c04a7b8SAlexey Dobriyan 	else {
30711da177e4SLinus Torvalds 
30721da177e4SLinus Torvalds 		currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
30731da177e4SLinus Torvalds 		currSCCB->Sccb_scsimsg = SMREJECT;
30741da177e4SLinus Torvalds 
30751da177e4SLinus Torvalds 		ACCEPT_MSG_ATN(port);
30765c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
30775c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
30781da177e4SLinus Torvalds 	}
30791da177e4SLinus Torvalds }
30801da177e4SLinus Torvalds 
30811da177e4SLinus Torvalds /*---------------------------------------------------------------------
30821da177e4SLinus Torvalds  *
308347b5d69cSJames Bottomley   * Function: FPT_shandem
30841da177e4SLinus Torvalds  *
30851da177e4SLinus Torvalds  * Description: Decide what to do with the extended message.
30861da177e4SLinus Torvalds  *
30871da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
30885c04a7b8SAlexey Dobriyan static void FPT_shandem(unsigned long port, unsigned char p_card,
30895c04a7b8SAlexey Dobriyan 			struct sccb *pCurrSCCB)
30901da177e4SLinus Torvalds {
3091db038cf8SAlexey Dobriyan 	unsigned char length, message;
30921da177e4SLinus Torvalds 
309347b5d69cSJames Bottomley  	length = FPT_sfm(port, pCurrSCCB);
30945c04a7b8SAlexey Dobriyan 	if (length) {
30951da177e4SLinus Torvalds 
30961da177e4SLinus Torvalds 		ACCEPT_MSG(port);
309747b5d69cSJames Bottomley  		message = FPT_sfm(port, pCurrSCCB);
30985c04a7b8SAlexey Dobriyan 		if (message) {
30991da177e4SLinus Torvalds 
31005c04a7b8SAlexey Dobriyan 			if (message == SMSYNC) {
31011da177e4SLinus Torvalds 
31025c04a7b8SAlexey Dobriyan 				if (length == 0x03) {
31031da177e4SLinus Torvalds 
31041da177e4SLinus Torvalds 					ACCEPT_MSG(port);
310547b5d69cSJames Bottomley  					FPT_stsyncn(port, p_card);
31065c04a7b8SAlexey Dobriyan 				} else {
31071da177e4SLinus Torvalds 
31081da177e4SLinus Torvalds 					pCurrSCCB->Sccb_scsimsg = SMREJECT;
31091da177e4SLinus Torvalds 					ACCEPT_MSG_ATN(port);
31101da177e4SLinus Torvalds 				}
31115c04a7b8SAlexey Dobriyan 			} else if (message == SMWDTR) {
31121da177e4SLinus Torvalds 
31135c04a7b8SAlexey Dobriyan 				if (length == 0x02) {
31141da177e4SLinus Torvalds 
31151da177e4SLinus Torvalds 					ACCEPT_MSG(port);
311647b5d69cSJames Bottomley  					FPT_stwidn(port, p_card);
31175c04a7b8SAlexey Dobriyan 				} else {
31181da177e4SLinus Torvalds 
31191da177e4SLinus Torvalds 					pCurrSCCB->Sccb_scsimsg = SMREJECT;
31201da177e4SLinus Torvalds 					ACCEPT_MSG_ATN(port);
31211da177e4SLinus Torvalds 
31225c04a7b8SAlexey Dobriyan 					WR_HARPOON(port + hp_autostart_1,
31235c04a7b8SAlexey Dobriyan 						   (AUTO_IMMED +
31245c04a7b8SAlexey Dobriyan 						    DISCONNECT_START));
31251da177e4SLinus Torvalds 				}
31265c04a7b8SAlexey Dobriyan 			} else {
31271da177e4SLinus Torvalds 
31281da177e4SLinus Torvalds 				pCurrSCCB->Sccb_scsimsg = SMREJECT;
31291da177e4SLinus Torvalds 				ACCEPT_MSG_ATN(port);
31301da177e4SLinus Torvalds 
31315c04a7b8SAlexey Dobriyan 				WR_HARPOON(port + hp_autostart_1,
31325c04a7b8SAlexey Dobriyan 					   (AUTO_IMMED + DISCONNECT_START));
31331da177e4SLinus Torvalds 			}
31345c04a7b8SAlexey Dobriyan 		} else {
31351da177e4SLinus Torvalds 			if (pCurrSCCB->Sccb_scsimsg != SMPARITY)
31361da177e4SLinus Torvalds 				ACCEPT_MSG(port);
31375c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_autostart_1,
31385c04a7b8SAlexey Dobriyan 				   (AUTO_IMMED + DISCONNECT_START));
31391da177e4SLinus Torvalds 		}
31405c04a7b8SAlexey Dobriyan 	} else {
31411da177e4SLinus Torvalds 		if (pCurrSCCB->Sccb_scsimsg == SMPARITY)
31425c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_autostart_1,
31435c04a7b8SAlexey Dobriyan 				   (AUTO_IMMED + DISCONNECT_START));
31441da177e4SLinus Torvalds 	}
31451da177e4SLinus Torvalds }
31461da177e4SLinus Torvalds 
31471da177e4SLinus Torvalds /*---------------------------------------------------------------------
31481da177e4SLinus Torvalds  *
314947b5d69cSJames Bottomley   * Function: FPT_sisyncn
31501da177e4SLinus Torvalds  *
31511da177e4SLinus Torvalds  * Description: Read in a message byte from the SCSI bus, and check
31521da177e4SLinus Torvalds  *              for a parity error.
31531da177e4SLinus Torvalds  *
31541da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
31551da177e4SLinus Torvalds 
31565c04a7b8SAlexey Dobriyan static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card,
31575c04a7b8SAlexey Dobriyan 				 unsigned char syncFlag)
31581da177e4SLinus Torvalds {
315969eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
3160f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
31611da177e4SLinus Torvalds 
316247b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
316347b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
31641da177e4SLinus Torvalds 
31651da177e4SLinus Torvalds 	if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)) {
31661da177e4SLinus Torvalds 
31671da177e4SLinus Torvalds 		WRW_HARPOON((port + ID_MSG_STRT),
31685c04a7b8SAlexey Dobriyan 			    (MPM_OP + AMSG_OUT +
31695c04a7b8SAlexey Dobriyan 			     (currSCCB->
31705c04a7b8SAlexey Dobriyan 			      Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
31711da177e4SLinus Torvalds 
31721da177e4SLinus Torvalds 		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
31731da177e4SLinus Torvalds 
31745c04a7b8SAlexey Dobriyan 		WRW_HARPOON((port + SYNC_MSGS + 0),
31755c04a7b8SAlexey Dobriyan 			    (MPM_OP + AMSG_OUT + SMEXT));
31761da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
31775c04a7b8SAlexey Dobriyan 		WRW_HARPOON((port + SYNC_MSGS + 4),
31785c04a7b8SAlexey Dobriyan 			    (MPM_OP + AMSG_OUT + SMSYNC));
31791da177e4SLinus Torvalds 
31801da177e4SLinus Torvalds 		if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
31811da177e4SLinus Torvalds 
31825c04a7b8SAlexey Dobriyan 			WRW_HARPOON((port + SYNC_MSGS + 6),
31835c04a7b8SAlexey Dobriyan 				    (MPM_OP + AMSG_OUT + 12));
31841da177e4SLinus Torvalds 
31855c04a7b8SAlexey Dobriyan 		else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
31865c04a7b8SAlexey Dobriyan 			 EE_SYNC_10MB)
31871da177e4SLinus Torvalds 
31885c04a7b8SAlexey Dobriyan 			WRW_HARPOON((port + SYNC_MSGS + 6),
31895c04a7b8SAlexey Dobriyan 				    (MPM_OP + AMSG_OUT + 25));
31901da177e4SLinus Torvalds 
31915c04a7b8SAlexey Dobriyan 		else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
31925c04a7b8SAlexey Dobriyan 			 EE_SYNC_5MB)
31931da177e4SLinus Torvalds 
31945c04a7b8SAlexey Dobriyan 			WRW_HARPOON((port + SYNC_MSGS + 6),
31955c04a7b8SAlexey Dobriyan 				    (MPM_OP + AMSG_OUT + 50));
31961da177e4SLinus Torvalds 
31971da177e4SLinus Torvalds 		else
31985c04a7b8SAlexey Dobriyan 			WRW_HARPOON((port + SYNC_MSGS + 6),
31995c04a7b8SAlexey Dobriyan 				    (MPM_OP + AMSG_OUT + 00));
32001da177e4SLinus Torvalds 
32011da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
32025c04a7b8SAlexey Dobriyan 		WRW_HARPOON((port + SYNC_MSGS + 10),
32035c04a7b8SAlexey Dobriyan 			    (MPM_OP + AMSG_OUT + DEFAULT_OFFSET));
32041da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
32051da177e4SLinus Torvalds 
32065c04a7b8SAlexey Dobriyan 		if (syncFlag == 0) {
32075c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_autostart_3,
32085c04a7b8SAlexey Dobriyan 				   (SELECT + SELCHK_STRT));
32095c04a7b8SAlexey Dobriyan 			currTar_Info->TarStatus =
32105c04a7b8SAlexey Dobriyan 			    ((currTar_Info->
32115c04a7b8SAlexey Dobriyan 			      TarStatus & ~(unsigned char)TAR_SYNC_MASK) |
32125c04a7b8SAlexey Dobriyan 			     (unsigned char)SYNC_TRYING);
32135c04a7b8SAlexey Dobriyan 		} else {
32145c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_autostart_3,
32155c04a7b8SAlexey Dobriyan 				   (AUTO_IMMED + CMD_ONLY_STRT));
32161da177e4SLinus Torvalds 		}
32171da177e4SLinus Torvalds 
32185c1b85e2SAlexey Dobriyan 		return 1;
32191da177e4SLinus Torvalds 	}
32201da177e4SLinus Torvalds 
32211da177e4SLinus Torvalds 	else {
32221da177e4SLinus Torvalds 
3223db038cf8SAlexey Dobriyan 		currTar_Info->TarStatus |= (unsigned char)SYNC_SUPPORTED;
32241da177e4SLinus Torvalds 		currTar_Info->TarEEValue &= ~EE_SYNC_MASK;
32255c1b85e2SAlexey Dobriyan 		return 0;
32261da177e4SLinus Torvalds 	}
32271da177e4SLinus Torvalds }
32281da177e4SLinus Torvalds 
32291da177e4SLinus Torvalds /*---------------------------------------------------------------------
32301da177e4SLinus Torvalds  *
323147b5d69cSJames Bottomley   * Function: FPT_stsyncn
32321da177e4SLinus Torvalds  *
32331da177e4SLinus Torvalds  * Description: The has sent us a Sync Nego message so handle it as
32341da177e4SLinus Torvalds  *              necessary.
32351da177e4SLinus Torvalds  *
32361da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
3237d63a4cccSAlexey Dobriyan static void FPT_stsyncn(unsigned long port, unsigned char p_card)
32381da177e4SLinus Torvalds {
3239db038cf8SAlexey Dobriyan 	unsigned char sync_msg, offset, sync_reg, our_sync_msg;
324069eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
3241f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
32421da177e4SLinus Torvalds 
324347b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
324447b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
32451da177e4SLinus Torvalds 
324647b5d69cSJames Bottomley  	sync_msg = FPT_sfm(port, currSCCB);
32471da177e4SLinus Torvalds 
32485c04a7b8SAlexey Dobriyan 	if ((sync_msg == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
32495c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
32505c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
32511da177e4SLinus Torvalds 		return;
32521da177e4SLinus Torvalds 	}
32531da177e4SLinus Torvalds 
32541da177e4SLinus Torvalds 	ACCEPT_MSG(port);
32551da177e4SLinus Torvalds 
325647b5d69cSJames Bottomley  	offset = FPT_sfm(port, currSCCB);
32571da177e4SLinus Torvalds 
32585c04a7b8SAlexey Dobriyan 	if ((offset == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
32595c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
32605c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
32611da177e4SLinus Torvalds 		return;
32621da177e4SLinus Torvalds 	}
32631da177e4SLinus Torvalds 
32641da177e4SLinus Torvalds 	if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
32651da177e4SLinus Torvalds 
32661da177e4SLinus Torvalds 		our_sync_msg = 12;	/* Setup our Message to 20mb/s */
32671da177e4SLinus Torvalds 
32681da177e4SLinus Torvalds 	else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_10MB)
32691da177e4SLinus Torvalds 
32701da177e4SLinus Torvalds 		our_sync_msg = 25;	/* Setup our Message to 10mb/s */
32711da177e4SLinus Torvalds 
32721da177e4SLinus Torvalds 	else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_5MB)
32731da177e4SLinus Torvalds 
32741da177e4SLinus Torvalds 		our_sync_msg = 50;	/* Setup our Message to 5mb/s */
32751da177e4SLinus Torvalds 	else
32761da177e4SLinus Torvalds 
32771da177e4SLinus Torvalds 		our_sync_msg = 0;	/* Message = Async */
32781da177e4SLinus Torvalds 
32791da177e4SLinus Torvalds 	if (sync_msg < our_sync_msg) {
32801da177e4SLinus Torvalds 		sync_msg = our_sync_msg;	/*if faster, then set to max. */
32811da177e4SLinus Torvalds 	}
32821da177e4SLinus Torvalds 
32831da177e4SLinus Torvalds 	if (offset == ASYNC)
32841da177e4SLinus Torvalds 		sync_msg = ASYNC;
32851da177e4SLinus Torvalds 
32861da177e4SLinus Torvalds 	if (offset > MAX_OFFSET)
32871da177e4SLinus Torvalds 		offset = MAX_OFFSET;
32881da177e4SLinus Torvalds 
32891da177e4SLinus Torvalds 	sync_reg = 0x00;
32901da177e4SLinus Torvalds 
32911da177e4SLinus Torvalds 	if (sync_msg > 12)
32921da177e4SLinus Torvalds 
32931da177e4SLinus Torvalds 		sync_reg = 0x20;	/* Use 10MB/s */
32941da177e4SLinus Torvalds 
32951da177e4SLinus Torvalds 	if (sync_msg > 25)
32961da177e4SLinus Torvalds 
32971da177e4SLinus Torvalds 		sync_reg = 0x40;	/* Use 6.6MB/s */
32981da177e4SLinus Torvalds 
32991da177e4SLinus Torvalds 	if (sync_msg > 38)
33001da177e4SLinus Torvalds 
33011da177e4SLinus Torvalds 		sync_reg = 0x60;	/* Use 5MB/s */
33021da177e4SLinus Torvalds 
33031da177e4SLinus Torvalds 	if (sync_msg > 50)
33041da177e4SLinus Torvalds 
33051da177e4SLinus Torvalds 		sync_reg = 0x80;	/* Use 4MB/s */
33061da177e4SLinus Torvalds 
33071da177e4SLinus Torvalds 	if (sync_msg > 62)
33081da177e4SLinus Torvalds 
33091da177e4SLinus Torvalds 		sync_reg = 0xA0;	/* Use 3.33MB/s */
33101da177e4SLinus Torvalds 
33111da177e4SLinus Torvalds 	if (sync_msg > 75)
33121da177e4SLinus Torvalds 
33131da177e4SLinus Torvalds 		sync_reg = 0xC0;	/* Use 2.85MB/s */
33141da177e4SLinus Torvalds 
33151da177e4SLinus Torvalds 	if (sync_msg > 87)
33161da177e4SLinus Torvalds 
33171da177e4SLinus Torvalds 		sync_reg = 0xE0;	/* Use 2.5MB/s */
33181da177e4SLinus Torvalds 
33191da177e4SLinus Torvalds 	if (sync_msg > 100) {
33201da177e4SLinus Torvalds 
33211da177e4SLinus Torvalds 		sync_reg = 0x00;	/* Use ASYNC */
33221da177e4SLinus Torvalds 		offset = 0x00;
33231da177e4SLinus Torvalds 	}
33241da177e4SLinus Torvalds 
33251da177e4SLinus Torvalds 	if (currTar_Info->TarStatus & WIDE_ENABLED)
33261da177e4SLinus Torvalds 
33271da177e4SLinus Torvalds 		sync_reg |= offset;
33281da177e4SLinus Torvalds 
33291da177e4SLinus Torvalds 	else
33301da177e4SLinus Torvalds 
33311da177e4SLinus Torvalds 		sync_reg |= (offset | NARROW_SCSI);
33321da177e4SLinus Torvalds 
333347b5d69cSJames Bottomley  	FPT_sssyncv(port, currSCCB->TargID, sync_reg, currTar_Info);
33341da177e4SLinus Torvalds 
33351da177e4SLinus Torvalds 	if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
33361da177e4SLinus Torvalds 
33371da177e4SLinus Torvalds 		ACCEPT_MSG(port);
33381da177e4SLinus Torvalds 
33391da177e4SLinus Torvalds 		currTar_Info->TarStatus = ((currTar_Info->TarStatus &
33405c04a7b8SAlexey Dobriyan 					    ~(unsigned char)TAR_SYNC_MASK) |
33415c04a7b8SAlexey Dobriyan 					   (unsigned char)SYNC_SUPPORTED);
33421da177e4SLinus Torvalds 
33435c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
33445c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
33451da177e4SLinus Torvalds 	}
33461da177e4SLinus Torvalds 
33471da177e4SLinus Torvalds 	else {
33481da177e4SLinus Torvalds 
33491da177e4SLinus Torvalds 		ACCEPT_MSG_ATN(port);
33501da177e4SLinus Torvalds 
335147b5d69cSJames Bottomley  		FPT_sisyncr(port, sync_msg, offset);
33521da177e4SLinus Torvalds 
33531da177e4SLinus Torvalds 		currTar_Info->TarStatus = ((currTar_Info->TarStatus &
33545c04a7b8SAlexey Dobriyan 					    ~(unsigned char)TAR_SYNC_MASK) |
33555c04a7b8SAlexey Dobriyan 					   (unsigned char)SYNC_SUPPORTED);
33561da177e4SLinus Torvalds 	}
33571da177e4SLinus Torvalds }
33581da177e4SLinus Torvalds 
33591da177e4SLinus Torvalds /*---------------------------------------------------------------------
33601da177e4SLinus Torvalds  *
336147b5d69cSJames Bottomley   * Function: FPT_sisyncr
33621da177e4SLinus Torvalds  *
33631da177e4SLinus Torvalds  * Description: Answer the targets sync message.
33641da177e4SLinus Torvalds  *
33651da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
33665c04a7b8SAlexey Dobriyan static void FPT_sisyncr(unsigned long port, unsigned char sync_pulse,
33675c04a7b8SAlexey Dobriyan 			unsigned char offset)
33681da177e4SLinus Torvalds {
33691da177e4SLinus Torvalds 	ARAM_ACCESS(port);
33701da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT));
33711da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
33721da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMSYNC));
33731da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 6), (MPM_OP + AMSG_OUT + sync_pulse));
33741da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
33751da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 10), (MPM_OP + AMSG_OUT + offset));
33761da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
33771da177e4SLinus Torvalds 	SGRAM_ACCESS(port);
33781da177e4SLinus Torvalds 
33791da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
33801da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
33811da177e4SLinus Torvalds 
33821da177e4SLinus Torvalds 	WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
33831da177e4SLinus Torvalds 
33845c04a7b8SAlexey Dobriyan 	while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
33851da177e4SLinus Torvalds 	}
33865c04a7b8SAlexey Dobriyan }
33871da177e4SLinus Torvalds 
33881da177e4SLinus Torvalds /*---------------------------------------------------------------------
33891da177e4SLinus Torvalds  *
339047b5d69cSJames Bottomley   * Function: FPT_siwidn
33911da177e4SLinus Torvalds  *
33921da177e4SLinus Torvalds  * Description: Read in a message byte from the SCSI bus, and check
33931da177e4SLinus Torvalds  *              for a parity error.
33941da177e4SLinus Torvalds  *
33951da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
33961da177e4SLinus Torvalds 
3397d63a4cccSAlexey Dobriyan static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card)
33981da177e4SLinus Torvalds {
339969eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
3400f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
34011da177e4SLinus Torvalds 
340247b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
340347b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
34041da177e4SLinus Torvalds 
34051da177e4SLinus Torvalds 	if (!((currTar_Info->TarStatus & TAR_WIDE_MASK) == WIDE_NEGOCIATED)) {
34061da177e4SLinus Torvalds 
34071da177e4SLinus Torvalds 		WRW_HARPOON((port + ID_MSG_STRT),
34085c04a7b8SAlexey Dobriyan 			    (MPM_OP + AMSG_OUT +
34095c04a7b8SAlexey Dobriyan 			     (currSCCB->
34105c04a7b8SAlexey Dobriyan 			      Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
34111da177e4SLinus Torvalds 
34121da177e4SLinus Torvalds 		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
34131da177e4SLinus Torvalds 
34145c04a7b8SAlexey Dobriyan 		WRW_HARPOON((port + SYNC_MSGS + 0),
34155c04a7b8SAlexey Dobriyan 			    (MPM_OP + AMSG_OUT + SMEXT));
34161da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
34175c04a7b8SAlexey Dobriyan 		WRW_HARPOON((port + SYNC_MSGS + 4),
34185c04a7b8SAlexey Dobriyan 			    (MPM_OP + AMSG_OUT + SMWDTR));
34191da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
34205c04a7b8SAlexey Dobriyan 		WRW_HARPOON((port + SYNC_MSGS + 8),
34215c04a7b8SAlexey Dobriyan 			    (MPM_OP + AMSG_OUT + SM16BIT));
34221da177e4SLinus Torvalds 		WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
34231da177e4SLinus Torvalds 
34241da177e4SLinus Torvalds 		WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
34251da177e4SLinus Torvalds 
34261da177e4SLinus Torvalds 		currTar_Info->TarStatus = ((currTar_Info->TarStatus &
34275c04a7b8SAlexey Dobriyan 					    ~(unsigned char)TAR_WIDE_MASK) |
34285c04a7b8SAlexey Dobriyan 					   (unsigned char)WIDE_ENABLED);
34291da177e4SLinus Torvalds 
34305c1b85e2SAlexey Dobriyan 		return 1;
34311da177e4SLinus Torvalds 	}
34321da177e4SLinus Torvalds 
34331da177e4SLinus Torvalds 	else {
34341da177e4SLinus Torvalds 
34351da177e4SLinus Torvalds 		currTar_Info->TarStatus = ((currTar_Info->TarStatus &
34365c04a7b8SAlexey Dobriyan 					    ~(unsigned char)TAR_WIDE_MASK) |
34375c04a7b8SAlexey Dobriyan 					   WIDE_NEGOCIATED);
34381da177e4SLinus Torvalds 
34391da177e4SLinus Torvalds 		currTar_Info->TarEEValue &= ~EE_WIDE_SCSI;
34405c1b85e2SAlexey Dobriyan 		return 0;
34411da177e4SLinus Torvalds 	}
34421da177e4SLinus Torvalds }
34431da177e4SLinus Torvalds 
34441da177e4SLinus Torvalds /*---------------------------------------------------------------------
34451da177e4SLinus Torvalds  *
344647b5d69cSJames Bottomley   * Function: FPT_stwidn
34471da177e4SLinus Torvalds  *
34481da177e4SLinus Torvalds  * Description: The has sent us a Wide Nego message so handle it as
34491da177e4SLinus Torvalds  *              necessary.
34501da177e4SLinus Torvalds  *
34511da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
3452d63a4cccSAlexey Dobriyan static void FPT_stwidn(unsigned long port, unsigned char p_card)
34531da177e4SLinus Torvalds {
3454db038cf8SAlexey Dobriyan 	unsigned char width;
345569eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
3456f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
34571da177e4SLinus Torvalds 
345847b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
345947b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
34601da177e4SLinus Torvalds 
346147b5d69cSJames Bottomley  	width = FPT_sfm(port, currSCCB);
34621da177e4SLinus Torvalds 
34635c04a7b8SAlexey Dobriyan 	if ((width == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
34645c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
34655c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
34661da177e4SLinus Torvalds 		return;
34671da177e4SLinus Torvalds 	}
34681da177e4SLinus Torvalds 
34691da177e4SLinus Torvalds 	if (!(currTar_Info->TarEEValue & EE_WIDE_SCSI))
34701da177e4SLinus Torvalds 		width = 0;
34711da177e4SLinus Torvalds 
34721da177e4SLinus Torvalds 	if (width) {
34731da177e4SLinus Torvalds 		currTar_Info->TarStatus |= WIDE_ENABLED;
34741da177e4SLinus Torvalds 		width = 0;
34755c04a7b8SAlexey Dobriyan 	} else {
34761da177e4SLinus Torvalds 		width = NARROW_SCSI;
34771da177e4SLinus Torvalds 		currTar_Info->TarStatus &= ~WIDE_ENABLED;
34781da177e4SLinus Torvalds 	}
34791da177e4SLinus Torvalds 
348047b5d69cSJames Bottomley  	FPT_sssyncv(port, currSCCB->TargID, width, currTar_Info);
34811da177e4SLinus Torvalds 
34825c04a7b8SAlexey Dobriyan 	if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
34831da177e4SLinus Torvalds 
34841da177e4SLinus Torvalds 		currTar_Info->TarStatus |= WIDE_NEGOCIATED;
34851da177e4SLinus Torvalds 
34865c04a7b8SAlexey Dobriyan 		if (!
34875c04a7b8SAlexey Dobriyan 		    ((currTar_Info->TarStatus & TAR_SYNC_MASK) ==
34885c04a7b8SAlexey Dobriyan 		     SYNC_SUPPORTED)) {
34891da177e4SLinus Torvalds 			ACCEPT_MSG_ATN(port);
34901da177e4SLinus Torvalds 			ARAM_ACCESS(port);
349147b5d69cSJames Bottomley  			FPT_sisyncn(port, p_card, 1);
34921da177e4SLinus Torvalds 			currSCCB->Sccb_scsistat = SELECT_SN_ST;
34931da177e4SLinus Torvalds 			SGRAM_ACCESS(port);
34945c04a7b8SAlexey Dobriyan 		} else {
34951da177e4SLinus Torvalds 			ACCEPT_MSG(port);
34965c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_autostart_1,
34975c04a7b8SAlexey Dobriyan 				   (AUTO_IMMED + DISCONNECT_START));
34981da177e4SLinus Torvalds 		}
34991da177e4SLinus Torvalds 	}
35001da177e4SLinus Torvalds 
35011da177e4SLinus Torvalds 	else {
35021da177e4SLinus Torvalds 
35031da177e4SLinus Torvalds 		ACCEPT_MSG_ATN(port);
35041da177e4SLinus Torvalds 
35051da177e4SLinus Torvalds 		if (currTar_Info->TarEEValue & EE_WIDE_SCSI)
35061da177e4SLinus Torvalds 			width = SM16BIT;
35071da177e4SLinus Torvalds 		else
35081da177e4SLinus Torvalds 			width = SM8BIT;
35091da177e4SLinus Torvalds 
351047b5d69cSJames Bottomley  		FPT_siwidr(port, width);
35111da177e4SLinus Torvalds 
35121da177e4SLinus Torvalds 		currTar_Info->TarStatus |= (WIDE_NEGOCIATED | WIDE_ENABLED);
35131da177e4SLinus Torvalds 	}
35141da177e4SLinus Torvalds }
35151da177e4SLinus Torvalds 
35161da177e4SLinus Torvalds /*---------------------------------------------------------------------
35171da177e4SLinus Torvalds  *
351847b5d69cSJames Bottomley   * Function: FPT_siwidr
35191da177e4SLinus Torvalds  *
35201da177e4SLinus Torvalds  * Description: Answer the targets Wide nego message.
35211da177e4SLinus Torvalds  *
35221da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
3523d63a4cccSAlexey Dobriyan static void FPT_siwidr(unsigned long port, unsigned char width)
35241da177e4SLinus Torvalds {
35251da177e4SLinus Torvalds 	ARAM_ACCESS(port);
35261da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT));
35271da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
35281da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMWDTR));
35291da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
35301da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 8), (MPM_OP + AMSG_OUT + width));
35311da177e4SLinus Torvalds 	WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
35321da177e4SLinus Torvalds 	SGRAM_ACCESS(port);
35331da177e4SLinus Torvalds 
35341da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
35351da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
35361da177e4SLinus Torvalds 
35371da177e4SLinus Torvalds 	WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
35381da177e4SLinus Torvalds 
35395c04a7b8SAlexey Dobriyan 	while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
35401da177e4SLinus Torvalds 	}
35415c04a7b8SAlexey Dobriyan }
35421da177e4SLinus Torvalds 
35431da177e4SLinus Torvalds /*---------------------------------------------------------------------
35441da177e4SLinus Torvalds  *
354547b5d69cSJames Bottomley   * Function: FPT_sssyncv
35461da177e4SLinus Torvalds  *
35471da177e4SLinus Torvalds  * Description: Write the desired value to the Sync Register for the
35481da177e4SLinus Torvalds  *              ID specified.
35491da177e4SLinus Torvalds  *
35501da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
35515c04a7b8SAlexey Dobriyan static void FPT_sssyncv(unsigned long p_port, unsigned char p_id,
35525c04a7b8SAlexey Dobriyan 			unsigned char p_sync_value,
3553f31dc0cdSAlexey Dobriyan 			struct sccb_mgr_tar_info *currTar_Info)
35541da177e4SLinus Torvalds {
3555db038cf8SAlexey Dobriyan 	unsigned char index;
35561da177e4SLinus Torvalds 
35571da177e4SLinus Torvalds 	index = p_id;
35581da177e4SLinus Torvalds 
35591da177e4SLinus Torvalds 	switch (index) {
35601da177e4SLinus Torvalds 
35611da177e4SLinus Torvalds 	case 0:
35621da177e4SLinus Torvalds 		index = 12;	/* hp_synctarg_0 */
35631da177e4SLinus Torvalds 		break;
35641da177e4SLinus Torvalds 	case 1:
35651da177e4SLinus Torvalds 		index = 13;	/* hp_synctarg_1 */
35661da177e4SLinus Torvalds 		break;
35671da177e4SLinus Torvalds 	case 2:
35681da177e4SLinus Torvalds 		index = 14;	/* hp_synctarg_2 */
35691da177e4SLinus Torvalds 		break;
35701da177e4SLinus Torvalds 	case 3:
35711da177e4SLinus Torvalds 		index = 15;	/* hp_synctarg_3 */
35721da177e4SLinus Torvalds 		break;
35731da177e4SLinus Torvalds 	case 4:
35741da177e4SLinus Torvalds 		index = 8;	/* hp_synctarg_4 */
35751da177e4SLinus Torvalds 		break;
35761da177e4SLinus Torvalds 	case 5:
35771da177e4SLinus Torvalds 		index = 9;	/* hp_synctarg_5 */
35781da177e4SLinus Torvalds 		break;
35791da177e4SLinus Torvalds 	case 6:
35801da177e4SLinus Torvalds 		index = 10;	/* hp_synctarg_6 */
35811da177e4SLinus Torvalds 		break;
35821da177e4SLinus Torvalds 	case 7:
35831da177e4SLinus Torvalds 		index = 11;	/* hp_synctarg_7 */
35841da177e4SLinus Torvalds 		break;
35851da177e4SLinus Torvalds 	case 8:
35861da177e4SLinus Torvalds 		index = 4;	/* hp_synctarg_8 */
35871da177e4SLinus Torvalds 		break;
35881da177e4SLinus Torvalds 	case 9:
35891da177e4SLinus Torvalds 		index = 5;	/* hp_synctarg_9 */
35901da177e4SLinus Torvalds 		break;
35911da177e4SLinus Torvalds 	case 10:
35921da177e4SLinus Torvalds 		index = 6;	/* hp_synctarg_10 */
35931da177e4SLinus Torvalds 		break;
35941da177e4SLinus Torvalds 	case 11:
35951da177e4SLinus Torvalds 		index = 7;	/* hp_synctarg_11 */
35961da177e4SLinus Torvalds 		break;
35971da177e4SLinus Torvalds 	case 12:
35981da177e4SLinus Torvalds 		index = 0;	/* hp_synctarg_12 */
35991da177e4SLinus Torvalds 		break;
36001da177e4SLinus Torvalds 	case 13:
36011da177e4SLinus Torvalds 		index = 1;	/* hp_synctarg_13 */
36021da177e4SLinus Torvalds 		break;
36031da177e4SLinus Torvalds 	case 14:
36041da177e4SLinus Torvalds 		index = 2;	/* hp_synctarg_14 */
36051da177e4SLinus Torvalds 		break;
36061da177e4SLinus Torvalds 	case 15:
36071da177e4SLinus Torvalds 		index = 3;	/* hp_synctarg_15 */
36081da177e4SLinus Torvalds 
36091da177e4SLinus Torvalds 	}
36101da177e4SLinus Torvalds 
36111da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_synctarg_base + index, p_sync_value);
36121da177e4SLinus Torvalds 
36131da177e4SLinus Torvalds 	currTar_Info->TarSyncCtrl = p_sync_value;
36141da177e4SLinus Torvalds }
36151da177e4SLinus Torvalds 
36161da177e4SLinus Torvalds /*---------------------------------------------------------------------
36171da177e4SLinus Torvalds  *
361847b5d69cSJames Bottomley   * Function: FPT_sresb
36191da177e4SLinus Torvalds  *
36201da177e4SLinus Torvalds  * Description: Reset the desired card's SCSI bus.
36211da177e4SLinus Torvalds  *
36221da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
3623d63a4cccSAlexey Dobriyan static void FPT_sresb(unsigned long port, unsigned char p_card)
36241da177e4SLinus Torvalds {
3625db038cf8SAlexey Dobriyan 	unsigned char scsiID, i;
36261da177e4SLinus Torvalds 
3627f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
36281da177e4SLinus Torvalds 
36291da177e4SLinus Torvalds 	WR_HARPOON(port + hp_page_ctrl,
36301da177e4SLinus Torvalds 		   (RD_HARPOON(port + hp_page_ctrl) | G_INT_DISABLE));
36311da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
36321da177e4SLinus Torvalds 
36331da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsictrl_0, SCSI_RST);
36341da177e4SLinus Torvalds 
36351da177e4SLinus Torvalds 	scsiID = RD_HARPOON(port + hp_seltimeout);
36361da177e4SLinus Torvalds 	WR_HARPOON(port + hp_seltimeout, TO_5ms);
36371da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), TIMEOUT);
36381da177e4SLinus Torvalds 
36391da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT | START_TO));
36401da177e4SLinus Torvalds 
36415c04a7b8SAlexey Dobriyan 	while (!(RDW_HARPOON((port + hp_intstat)) & TIMEOUT)) {
36425c04a7b8SAlexey Dobriyan 	}
36431da177e4SLinus Torvalds 
36441da177e4SLinus Torvalds 	WR_HARPOON(port + hp_seltimeout, scsiID);
36451da177e4SLinus Torvalds 
36461da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
36471da177e4SLinus Torvalds 
364847b5d69cSJames Bottomley  	FPT_Wait(port, TO_5ms);
36491da177e4SLinus Torvalds 
36501da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
36511da177e4SLinus Torvalds 
36521da177e4SLinus Torvalds 	WR_HARPOON(port + hp_int_mask, (RD_HARPOON(port + hp_int_mask) | 0x00));
36531da177e4SLinus Torvalds 
36545c04a7b8SAlexey Dobriyan 	for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
365547b5d69cSJames Bottomley  		currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
36561da177e4SLinus Torvalds 
36575c04a7b8SAlexey Dobriyan 		if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
36581da177e4SLinus Torvalds 			currTar_Info->TarSyncCtrl = 0;
36591da177e4SLinus Torvalds 			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
36601da177e4SLinus Torvalds 		}
36611da177e4SLinus Torvalds 
36625c04a7b8SAlexey Dobriyan 		if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
36631da177e4SLinus Torvalds 			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
36641da177e4SLinus Torvalds 		}
36651da177e4SLinus Torvalds 
366647b5d69cSJames Bottomley  		FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
36671da177e4SLinus Torvalds 
366847b5d69cSJames Bottomley  		FPT_SccbMgrTableInitTarget(p_card, scsiID);
36691da177e4SLinus Torvalds 	}
36701da177e4SLinus Torvalds 
367147b5d69cSJames Bottomley  	FPT_BL_Card[p_card].scanIndex = 0x00;
367247b5d69cSJames Bottomley  	FPT_BL_Card[p_card].currentSCCB = NULL;
367347b5d69cSJames Bottomley  	FPT_BL_Card[p_card].globalFlags &= ~(F_TAG_STARTED | F_HOST_XFER_ACT
36741da177e4SLinus Torvalds 					     | F_NEW_SCCB_CMD);
367547b5d69cSJames Bottomley  	FPT_BL_Card[p_card].cmdCounter = 0x00;
367647b5d69cSJames Bottomley  	FPT_BL_Card[p_card].discQCount = 0x00;
367747b5d69cSJames Bottomley  	FPT_BL_Card[p_card].tagQ_Lst = 0x01;
36781da177e4SLinus Torvalds 
36791da177e4SLinus Torvalds 	for (i = 0; i < QUEUE_DEPTH; i++)
368047b5d69cSJames Bottomley  		FPT_BL_Card[p_card].discQ_Tbl[i] = NULL;
36811da177e4SLinus Torvalds 
36821da177e4SLinus Torvalds 	WR_HARPOON(port + hp_page_ctrl,
36831da177e4SLinus Torvalds 		   (RD_HARPOON(port + hp_page_ctrl) & ~G_INT_DISABLE));
36841da177e4SLinus Torvalds 
36851da177e4SLinus Torvalds }
36861da177e4SLinus Torvalds 
36871da177e4SLinus Torvalds /*---------------------------------------------------------------------
36881da177e4SLinus Torvalds  *
368947b5d69cSJames Bottomley   * Function: FPT_ssenss
36901da177e4SLinus Torvalds  *
36911da177e4SLinus Torvalds  * Description: Setup for the Auto Sense command.
36921da177e4SLinus Torvalds  *
36931da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
369413e6851aSAlexey Dobriyan static void FPT_ssenss(struct sccb_card *pCurrCard)
36951da177e4SLinus Torvalds {
3696db038cf8SAlexey Dobriyan 	unsigned char i;
369769eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
36981da177e4SLinus Torvalds 
36991da177e4SLinus Torvalds 	currSCCB = pCurrCard->currentSCCB;
37001da177e4SLinus Torvalds 
37011da177e4SLinus Torvalds 	currSCCB->Save_CdbLen = currSCCB->CdbLength;
37021da177e4SLinus Torvalds 
37031da177e4SLinus Torvalds 	for (i = 0; i < 6; i++) {
37041da177e4SLinus Torvalds 
37051da177e4SLinus Torvalds 		currSCCB->Save_Cdb[i] = currSCCB->Cdb[i];
37061da177e4SLinus Torvalds 	}
37071da177e4SLinus Torvalds 
37081da177e4SLinus Torvalds 	currSCCB->CdbLength = SIX_BYTE_CMD;
37091da177e4SLinus Torvalds 	currSCCB->Cdb[0] = SCSI_REQUEST_SENSE;
3710db038cf8SAlexey Dobriyan 	currSCCB->Cdb[1] = currSCCB->Cdb[1] & (unsigned char)0xE0;	/*Keep LUN. */
37111da177e4SLinus Torvalds 	currSCCB->Cdb[2] = 0x00;
37121da177e4SLinus Torvalds 	currSCCB->Cdb[3] = 0x00;
37131da177e4SLinus Torvalds 	currSCCB->Cdb[4] = currSCCB->RequestSenseLength;
37141da177e4SLinus Torvalds 	currSCCB->Cdb[5] = 0x00;
37151da177e4SLinus Torvalds 
37161da177e4SLinus Torvalds 	currSCCB->Sccb_XferCnt = (unsigned long)currSCCB->RequestSenseLength;
37171da177e4SLinus Torvalds 
37181da177e4SLinus Torvalds 	currSCCB->Sccb_ATC = 0x00;
37191da177e4SLinus Torvalds 
37201da177e4SLinus Torvalds 	currSCCB->Sccb_XferState |= F_AUTO_SENSE;
37211da177e4SLinus Torvalds 
37221da177e4SLinus Torvalds 	currSCCB->Sccb_XferState &= ~F_SG_XFER;
37231da177e4SLinus Torvalds 
3724db038cf8SAlexey Dobriyan 	currSCCB->Sccb_idmsg = currSCCB->Sccb_idmsg & ~(unsigned char)DISC_PRIV;
37251da177e4SLinus Torvalds 
37261da177e4SLinus Torvalds 	currSCCB->ControlByte = 0x00;
37271da177e4SLinus Torvalds 
37281da177e4SLinus Torvalds 	currSCCB->Sccb_MGRFlags &= F_STATUSLOADED;
37291da177e4SLinus Torvalds }
37301da177e4SLinus Torvalds 
37311da177e4SLinus Torvalds /*---------------------------------------------------------------------
37321da177e4SLinus Torvalds  *
373347b5d69cSJames Bottomley   * Function: FPT_sxfrp
37341da177e4SLinus Torvalds  *
37351da177e4SLinus Torvalds  * Description: Transfer data into the bit bucket until the device
37361da177e4SLinus Torvalds  *              decides to switch phase.
37371da177e4SLinus Torvalds  *
37381da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
37391da177e4SLinus Torvalds 
3740d63a4cccSAlexey Dobriyan static void FPT_sxfrp(unsigned long p_port, unsigned char p_card)
37411da177e4SLinus Torvalds {
3742db038cf8SAlexey Dobriyan 	unsigned char curr_phz;
37431da177e4SLinus Torvalds 
37441da177e4SLinus Torvalds 	DISABLE_AUTO(p_port);
37451da177e4SLinus Torvalds 
374647b5d69cSJames Bottomley  	if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
37471da177e4SLinus Torvalds 
37485c04a7b8SAlexey Dobriyan 		FPT_hostDataXferAbort(p_port, p_card,
37495c04a7b8SAlexey Dobriyan 				      FPT_BL_Card[p_card].currentSCCB);
37501da177e4SLinus Torvalds 
37511da177e4SLinus Torvalds 	}
37521da177e4SLinus Torvalds 
37531da177e4SLinus Torvalds 	/* If the Automation handled the end of the transfer then do not
37541da177e4SLinus Torvalds 	   match the phase or we will get out of sync with the ISR.       */
37551da177e4SLinus Torvalds 
37565c04a7b8SAlexey Dobriyan 	if (RDW_HARPOON((p_port + hp_intstat)) &
37575c04a7b8SAlexey Dobriyan 	    (BUS_FREE | XFER_CNT_0 | AUTO_INT))
37581da177e4SLinus Torvalds 		return;
37591da177e4SLinus Torvalds 
37601da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_xfercnt_0, 0x00);
37611da177e4SLinus Torvalds 
3762db038cf8SAlexey Dobriyan 	curr_phz = RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ;
37631da177e4SLinus Torvalds 
37641da177e4SLinus Torvalds 	WRW_HARPOON((p_port + hp_intstat), XFER_CNT_0);
37651da177e4SLinus Torvalds 
37661da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsisig, curr_phz);
37671da177e4SLinus Torvalds 
37681da177e4SLinus Torvalds 	while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET)) &&
37695c04a7b8SAlexey Dobriyan 	       (curr_phz ==
37705c04a7b8SAlexey Dobriyan 		(RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ)))
37711da177e4SLinus Torvalds 	{
37725c04a7b8SAlexey Dobriyan 		if (curr_phz & (unsigned char)SCSI_IOBIT) {
37735c04a7b8SAlexey Dobriyan 			WR_HARPOON(p_port + hp_portctrl_0,
37745c04a7b8SAlexey Dobriyan 				   (SCSI_PORT | HOST_PORT | SCSI_INBIT));
37751da177e4SLinus Torvalds 
37765c04a7b8SAlexey Dobriyan 			if (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
37771da177e4SLinus Torvalds 				RD_HARPOON(p_port + hp_fifodata_0);
37781da177e4SLinus Torvalds 			}
37795c04a7b8SAlexey Dobriyan 		} else {
37805c04a7b8SAlexey Dobriyan 			WR_HARPOON(p_port + hp_portctrl_0,
37815c04a7b8SAlexey Dobriyan 				   (SCSI_PORT | HOST_PORT | HOST_WRT));
37825c04a7b8SAlexey Dobriyan 			if (RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY) {
37831da177e4SLinus Torvalds 				WR_HARPOON(p_port + hp_fifodata_0, 0xFA);
37841da177e4SLinus Torvalds 			}
37851da177e4SLinus Torvalds 		}
37861da177e4SLinus Torvalds 	}			/* End of While loop for padding data I/O phase */
37871da177e4SLinus Torvalds 
37885c04a7b8SAlexey Dobriyan 	while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
37891da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ)
37901da177e4SLinus Torvalds 			break;
37911da177e4SLinus Torvalds 	}
37921da177e4SLinus Torvalds 
37935c04a7b8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_portctrl_0,
37945c04a7b8SAlexey Dobriyan 		   (SCSI_PORT | HOST_PORT | SCSI_INBIT));
37955c04a7b8SAlexey Dobriyan 	while (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
37961da177e4SLinus Torvalds 		RD_HARPOON(p_port + hp_fifodata_0);
37971da177e4SLinus Torvalds 	}
37981da177e4SLinus Torvalds 
37995c04a7b8SAlexey Dobriyan 	if (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
38005c04a7b8SAlexey Dobriyan 		WR_HARPOON(p_port + hp_autostart_0,
38015c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + DISCONNECT_START));
38025c04a7b8SAlexey Dobriyan 		while (!(RDW_HARPOON((p_port + hp_intstat)) & AUTO_INT)) {
38031da177e4SLinus Torvalds 		}
38041da177e4SLinus Torvalds 
38055c04a7b8SAlexey Dobriyan 		if (RDW_HARPOON((p_port + hp_intstat)) &
38065c04a7b8SAlexey Dobriyan 		    (ICMD_COMP | ITAR_DISC))
38075c04a7b8SAlexey Dobriyan 			while (!
38085c04a7b8SAlexey Dobriyan 			       (RDW_HARPOON((p_port + hp_intstat)) &
38095c04a7b8SAlexey Dobriyan 				(BUS_FREE | RSEL))) ;
38105c04a7b8SAlexey Dobriyan 	}
38115c04a7b8SAlexey Dobriyan }
38121da177e4SLinus Torvalds 
38131da177e4SLinus Torvalds /*---------------------------------------------------------------------
38141da177e4SLinus Torvalds  *
381547b5d69cSJames Bottomley   * Function: FPT_schkdd
38161da177e4SLinus Torvalds  *
38171da177e4SLinus Torvalds  * Description: Make sure data has been flushed from both FIFOs and abort
38181da177e4SLinus Torvalds  *              the operations if necessary.
38191da177e4SLinus Torvalds  *
38201da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
38211da177e4SLinus Torvalds 
3822d63a4cccSAlexey Dobriyan static void FPT_schkdd(unsigned long port, unsigned char p_card)
38231da177e4SLinus Torvalds {
3824c823feebSAlexey Dobriyan 	unsigned short TimeOutLoop;
3825db038cf8SAlexey Dobriyan 	unsigned char sPhase;
38261da177e4SLinus Torvalds 
382769eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
38281da177e4SLinus Torvalds 
382947b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
38301da177e4SLinus Torvalds 
38311da177e4SLinus Torvalds 	if ((currSCCB->Sccb_scsistat != DATA_OUT_ST) &&
38321da177e4SLinus Torvalds 	    (currSCCB->Sccb_scsistat != DATA_IN_ST)) {
38331da177e4SLinus Torvalds 		return;
38341da177e4SLinus Torvalds 	}
38351da177e4SLinus Torvalds 
38365c04a7b8SAlexey Dobriyan 	if (currSCCB->Sccb_XferState & F_ODD_BALL_CNT) {
38371da177e4SLinus Torvalds 
38381da177e4SLinus Torvalds 		currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - 1);
38391da177e4SLinus Torvalds 
38401da177e4SLinus Torvalds 		currSCCB->Sccb_XferCnt = 1;
38411da177e4SLinus Torvalds 
38421da177e4SLinus Torvalds 		currSCCB->Sccb_XferState &= ~F_ODD_BALL_CNT;
3843c823feebSAlexey Dobriyan 		WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
38441da177e4SLinus Torvalds 		WR_HARPOON(port + hp_xferstat, 0x00);
38451da177e4SLinus Torvalds 	}
38461da177e4SLinus Torvalds 
38475c04a7b8SAlexey Dobriyan 	else {
38481da177e4SLinus Torvalds 
38491da177e4SLinus Torvalds 		currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
38501da177e4SLinus Torvalds 
38511da177e4SLinus Torvalds 		currSCCB->Sccb_XferCnt = 0;
38521da177e4SLinus Torvalds 	}
38531da177e4SLinus Torvalds 
38541da177e4SLinus Torvalds 	if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
38551da177e4SLinus Torvalds 	    (currSCCB->HostStatus == SCCB_COMPLETE)) {
38561da177e4SLinus Torvalds 
38571da177e4SLinus Torvalds 		currSCCB->HostStatus = SCCB_PARITY_ERR;
38581da177e4SLinus Torvalds 		WRW_HARPOON((port + hp_intstat), PARITY);
38591da177e4SLinus Torvalds 	}
38601da177e4SLinus Torvalds 
386147b5d69cSJames Bottomley  	FPT_hostDataXferAbort(port, p_card, currSCCB);
38621da177e4SLinus Torvalds 
38635c04a7b8SAlexey Dobriyan 	while (RD_HARPOON(port + hp_scsisig) & SCSI_ACK) {
38645c04a7b8SAlexey Dobriyan 	}
38651da177e4SLinus Torvalds 
38661da177e4SLinus Torvalds 	TimeOutLoop = 0;
38671da177e4SLinus Torvalds 
38685c04a7b8SAlexey Dobriyan 	while (RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY) {
38691da177e4SLinus Torvalds 		if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
38701da177e4SLinus Torvalds 			return;
38711da177e4SLinus Torvalds 		}
3872db038cf8SAlexey Dobriyan 		if (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) {
38731da177e4SLinus Torvalds 			break;
38741da177e4SLinus Torvalds 		}
38751da177e4SLinus Torvalds 		if (RDW_HARPOON((port + hp_intstat)) & RESET) {
38761da177e4SLinus Torvalds 			return;
38771da177e4SLinus Torvalds 		}
38785c04a7b8SAlexey Dobriyan 		if ((RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
38795c04a7b8SAlexey Dobriyan 		    || (TimeOutLoop++ > 0x3000))
38801da177e4SLinus Torvalds 			break;
38811da177e4SLinus Torvalds 	}
38821da177e4SLinus Torvalds 
38831da177e4SLinus Torvalds 	sPhase = RD_HARPOON(port + hp_scsisig) & (SCSI_BSY | S_SCSI_PHZ);
38841da177e4SLinus Torvalds 	if ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) ||
3885db038cf8SAlexey Dobriyan 	    (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) ||
38861da177e4SLinus Torvalds 	    (sPhase == (SCSI_BSY | S_DATAO_PH)) ||
38875c04a7b8SAlexey Dobriyan 	    (sPhase == (SCSI_BSY | S_DATAI_PH))) {
38881da177e4SLinus Torvalds 
38891da177e4SLinus Torvalds 		WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
38901da177e4SLinus Torvalds 
38915c04a7b8SAlexey Dobriyan 		if (!(currSCCB->Sccb_XferState & F_ALL_XFERRED)) {
38921da177e4SLinus Torvalds 			if (currSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
389347b5d69cSJames Bottomley  				FPT_phaseDataIn(port, p_card);
38941da177e4SLinus Torvalds 			}
38951da177e4SLinus Torvalds 
38961da177e4SLinus Torvalds 			else {
389747b5d69cSJames Bottomley  				FPT_phaseDataOut(port, p_card);
38981da177e4SLinus Torvalds 			}
38995c04a7b8SAlexey Dobriyan 		} else {
390047b5d69cSJames Bottomley  			FPT_sxfrp(port, p_card);
39011da177e4SLinus Torvalds 			if (!(RDW_HARPOON((port + hp_intstat)) &
39025c04a7b8SAlexey Dobriyan 			      (BUS_FREE | ICMD_COMP | ITAR_DISC | RESET))) {
39031da177e4SLinus Torvalds 				WRW_HARPOON((port + hp_intstat), AUTO_INT);
390447b5d69cSJames Bottomley  				FPT_phaseDecode(port, p_card);
39051da177e4SLinus Torvalds 			}
39061da177e4SLinus Torvalds 		}
39071da177e4SLinus Torvalds 
39081da177e4SLinus Torvalds 	}
39091da177e4SLinus Torvalds 
39101da177e4SLinus Torvalds 	else {
39111da177e4SLinus Torvalds 		WR_HARPOON(port + hp_portctrl_0, 0x00);
39121da177e4SLinus Torvalds 	}
39131da177e4SLinus Torvalds }
39141da177e4SLinus Torvalds 
39151da177e4SLinus Torvalds /*---------------------------------------------------------------------
39161da177e4SLinus Torvalds  *
391747b5d69cSJames Bottomley   * Function: FPT_sinits
39181da177e4SLinus Torvalds  *
39191da177e4SLinus Torvalds  * Description: Setup SCCB manager fields in this SCCB.
39201da177e4SLinus Torvalds  *
39211da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
39221da177e4SLinus Torvalds 
392369eb2ea4SAlexey Dobriyan static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card)
39241da177e4SLinus Torvalds {
3925f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
39261da177e4SLinus Torvalds 
39275d7ebb9cSDan Carpenter 	if ((p_sccb->TargID >= MAX_SCSI_TAR) || (p_sccb->Lun >= MAX_LUN)) {
39281da177e4SLinus Torvalds 		return;
39291da177e4SLinus Torvalds 	}
393047b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
39311da177e4SLinus Torvalds 
39321da177e4SLinus Torvalds 	p_sccb->Sccb_XferState = 0x00;
39331da177e4SLinus Torvalds 	p_sccb->Sccb_XferCnt = p_sccb->DataLength;
39341da177e4SLinus Torvalds 
39351da177e4SLinus Torvalds 	if ((p_sccb->OperationCode == SCATTER_GATHER_COMMAND) ||
39361da177e4SLinus Torvalds 	    (p_sccb->OperationCode == RESIDUAL_SG_COMMAND)) {
39371da177e4SLinus Torvalds 
39381da177e4SLinus Torvalds 		p_sccb->Sccb_SGoffset = 0;
39391da177e4SLinus Torvalds 		p_sccb->Sccb_XferState = F_SG_XFER;
39401da177e4SLinus Torvalds 		p_sccb->Sccb_XferCnt = 0x00;
39411da177e4SLinus Torvalds 	}
39421da177e4SLinus Torvalds 
39431da177e4SLinus Torvalds 	if (p_sccb->DataLength == 0x00)
39441da177e4SLinus Torvalds 
39451da177e4SLinus Torvalds 		p_sccb->Sccb_XferState |= F_ALL_XFERRED;
39461da177e4SLinus Torvalds 
39475c04a7b8SAlexey Dobriyan 	if (p_sccb->ControlByte & F_USE_CMD_Q) {
39481da177e4SLinus Torvalds 		if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
39491da177e4SLinus Torvalds 			p_sccb->ControlByte &= ~F_USE_CMD_Q;
39501da177e4SLinus Torvalds 
39511da177e4SLinus Torvalds 		else
39521da177e4SLinus Torvalds 			currTar_Info->TarStatus |= TAG_Q_TRYING;
39531da177e4SLinus Torvalds 	}
39541da177e4SLinus Torvalds 
39551da177e4SLinus Torvalds /*      For !single SCSI device in system  & device allow Disconnect
39561da177e4SLinus Torvalds 	or command is tag_q type then send Cmd with Disconnect Enable
39571da177e4SLinus Torvalds 	else send Cmd with Disconnect Disable */
39581da177e4SLinus Torvalds 
39591da177e4SLinus Torvalds /*
396047b5d69cSJames Bottomley     if (((!(FPT_BL_Card[p_card].globalFlags & F_SINGLE_DEVICE)) &&
39611da177e4SLinus Torvalds       (currTar_Info->TarStatus & TAR_ALLOW_DISC)) ||
39621da177e4SLinus Torvalds       (currTar_Info->TarStatus & TAG_Q_TRYING)) {
39631da177e4SLinus Torvalds */
39641da177e4SLinus Torvalds 	if ((currTar_Info->TarStatus & TAR_ALLOW_DISC) ||
39651da177e4SLinus Torvalds 	    (currTar_Info->TarStatus & TAG_Q_TRYING)) {
39665c04a7b8SAlexey Dobriyan 		p_sccb->Sccb_idmsg =
39675c04a7b8SAlexey Dobriyan 		    (unsigned char)(SMIDENT | DISC_PRIV) | p_sccb->Lun;
39681da177e4SLinus Torvalds 	}
39691da177e4SLinus Torvalds 
39701da177e4SLinus Torvalds 	else {
39711da177e4SLinus Torvalds 
3972db038cf8SAlexey Dobriyan 		p_sccb->Sccb_idmsg = (unsigned char)SMIDENT | p_sccb->Lun;
39731da177e4SLinus Torvalds 	}
39741da177e4SLinus Torvalds 
39751da177e4SLinus Torvalds 	p_sccb->HostStatus = 0x00;
39761da177e4SLinus Torvalds 	p_sccb->TargetStatus = 0x00;
39771da177e4SLinus Torvalds 	p_sccb->Sccb_tag = 0x00;
39781da177e4SLinus Torvalds 	p_sccb->Sccb_MGRFlags = 0x00;
39791da177e4SLinus Torvalds 	p_sccb->Sccb_sgseg = 0x00;
39801da177e4SLinus Torvalds 	p_sccb->Sccb_ATC = 0x00;
39811da177e4SLinus Torvalds 	p_sccb->Sccb_savedATC = 0x00;
39821da177e4SLinus Torvalds /*
39831da177e4SLinus Torvalds    p_sccb->SccbVirtDataPtr    = 0x00;
39841da177e4SLinus Torvalds    p_sccb->Sccb_forwardlink   = NULL;
39851da177e4SLinus Torvalds    p_sccb->Sccb_backlink      = NULL;
39861da177e4SLinus Torvalds  */
39871da177e4SLinus Torvalds 	p_sccb->Sccb_scsistat = BUS_FREE_ST;
39881da177e4SLinus Torvalds 	p_sccb->SccbStatus = SCCB_IN_PROCESS;
39891da177e4SLinus Torvalds 	p_sccb->Sccb_scsimsg = SMNO_OP;
39901da177e4SLinus Torvalds 
39911da177e4SLinus Torvalds }
39921da177e4SLinus Torvalds 
39931da177e4SLinus Torvalds /*---------------------------------------------------------------------
39941da177e4SLinus Torvalds  *
39951da177e4SLinus Torvalds  * Function: Phase Decode
39961da177e4SLinus Torvalds  *
39971da177e4SLinus Torvalds  * Description: Determine the phase and call the appropriate function.
39981da177e4SLinus Torvalds  *
39991da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
40001da177e4SLinus Torvalds 
4001d63a4cccSAlexey Dobriyan static void FPT_phaseDecode(unsigned long p_port, unsigned char p_card)
40021da177e4SLinus Torvalds {
40031da177e4SLinus Torvalds 	unsigned char phase_ref;
4004d63a4cccSAlexey Dobriyan 	void (*phase) (unsigned long, unsigned char);
40051da177e4SLinus Torvalds 
40061da177e4SLinus Torvalds 	DISABLE_AUTO(p_port);
40071da177e4SLinus Torvalds 
40085c04a7b8SAlexey Dobriyan 	phase_ref =
40095c04a7b8SAlexey Dobriyan 	    (unsigned char)(RD_HARPOON(p_port + hp_scsisig) & S_SCSI_PHZ);
40101da177e4SLinus Torvalds 
401147b5d69cSJames Bottomley  	phase = FPT_s_PhaseTbl[phase_ref];
40121da177e4SLinus Torvalds 
40131da177e4SLinus Torvalds 	(*phase) (p_port, p_card);	/* Call the correct phase func */
40141da177e4SLinus Torvalds }
40151da177e4SLinus Torvalds 
40161da177e4SLinus Torvalds /*---------------------------------------------------------------------
40171da177e4SLinus Torvalds  *
40181da177e4SLinus Torvalds  * Function: Data Out Phase
40191da177e4SLinus Torvalds  *
40201da177e4SLinus Torvalds  * Description: Start up both the BusMaster and Xbow.
40211da177e4SLinus Torvalds  *
40221da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
40231da177e4SLinus Torvalds 
4024d63a4cccSAlexey Dobriyan static void FPT_phaseDataOut(unsigned long port, unsigned char p_card)
40251da177e4SLinus Torvalds {
40261da177e4SLinus Torvalds 
402769eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
40281da177e4SLinus Torvalds 
402947b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
40305c04a7b8SAlexey Dobriyan 	if (currSCCB == NULL) {
40311da177e4SLinus Torvalds 		return;		/* Exit if No SCCB record */
40321da177e4SLinus Torvalds 	}
40331da177e4SLinus Torvalds 
40341da177e4SLinus Torvalds 	currSCCB->Sccb_scsistat = DATA_OUT_ST;
40351da177e4SLinus Torvalds 	currSCCB->Sccb_XferState &= ~(F_HOST_XFER_DIR | F_NO_DATA_YET);
40361da177e4SLinus Torvalds 
40371da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
40381da177e4SLinus Torvalds 
40391da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
40401da177e4SLinus Torvalds 
40411da177e4SLinus Torvalds 	WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
40421da177e4SLinus Torvalds 
404347b5d69cSJames Bottomley  	FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
40441da177e4SLinus Torvalds 
40451da177e4SLinus Torvalds 	if (currSCCB->Sccb_XferCnt == 0) {
40461da177e4SLinus Torvalds 
40471da177e4SLinus Torvalds 		if ((currSCCB->ControlByte & SCCB_DATA_XFER_OUT) &&
40481da177e4SLinus Torvalds 		    (currSCCB->HostStatus == SCCB_COMPLETE))
40491da177e4SLinus Torvalds 			currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
40501da177e4SLinus Torvalds 
405147b5d69cSJames Bottomley  		FPT_sxfrp(port, p_card);
40521da177e4SLinus Torvalds 		if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
405347b5d69cSJames Bottomley  			FPT_phaseDecode(port, p_card);
40541da177e4SLinus Torvalds 	}
40551da177e4SLinus Torvalds }
40561da177e4SLinus Torvalds 
40571da177e4SLinus Torvalds /*---------------------------------------------------------------------
40581da177e4SLinus Torvalds  *
40591da177e4SLinus Torvalds  * Function: Data In Phase
40601da177e4SLinus Torvalds  *
40611da177e4SLinus Torvalds  * Description: Startup the BusMaster and the XBOW.
40621da177e4SLinus Torvalds  *
40631da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
40641da177e4SLinus Torvalds 
4065d63a4cccSAlexey Dobriyan static void FPT_phaseDataIn(unsigned long port, unsigned char p_card)
40661da177e4SLinus Torvalds {
40671da177e4SLinus Torvalds 
406869eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
40691da177e4SLinus Torvalds 
407047b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
40711da177e4SLinus Torvalds 
40725c04a7b8SAlexey Dobriyan 	if (currSCCB == NULL) {
40731da177e4SLinus Torvalds 		return;		/* Exit if No SCCB record */
40741da177e4SLinus Torvalds 	}
40751da177e4SLinus Torvalds 
40761da177e4SLinus Torvalds 	currSCCB->Sccb_scsistat = DATA_IN_ST;
40771da177e4SLinus Torvalds 	currSCCB->Sccb_XferState |= F_HOST_XFER_DIR;
40781da177e4SLinus Torvalds 	currSCCB->Sccb_XferState &= ~F_NO_DATA_YET;
40791da177e4SLinus Torvalds 
40801da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
40811da177e4SLinus Torvalds 
40821da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
40831da177e4SLinus Torvalds 
40841da177e4SLinus Torvalds 	WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
40851da177e4SLinus Torvalds 
408647b5d69cSJames Bottomley  	FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
40871da177e4SLinus Torvalds 
40881da177e4SLinus Torvalds 	if (currSCCB->Sccb_XferCnt == 0) {
40891da177e4SLinus Torvalds 
40901da177e4SLinus Torvalds 		if ((currSCCB->ControlByte & SCCB_DATA_XFER_IN) &&
40911da177e4SLinus Torvalds 		    (currSCCB->HostStatus == SCCB_COMPLETE))
40921da177e4SLinus Torvalds 			currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
40931da177e4SLinus Torvalds 
409447b5d69cSJames Bottomley  		FPT_sxfrp(port, p_card);
40951da177e4SLinus Torvalds 		if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
409647b5d69cSJames Bottomley  			FPT_phaseDecode(port, p_card);
40971da177e4SLinus Torvalds 
40981da177e4SLinus Torvalds 	}
40991da177e4SLinus Torvalds }
41001da177e4SLinus Torvalds 
41011da177e4SLinus Torvalds /*---------------------------------------------------------------------
41021da177e4SLinus Torvalds  *
41031da177e4SLinus Torvalds  * Function: Command Phase
41041da177e4SLinus Torvalds  *
41051da177e4SLinus Torvalds  * Description: Load the CDB into the automation and start it up.
41061da177e4SLinus Torvalds  *
41071da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
41081da177e4SLinus Torvalds 
4109d63a4cccSAlexey Dobriyan static void FPT_phaseCommand(unsigned long p_port, unsigned char p_card)
41101da177e4SLinus Torvalds {
411169eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
4112d63a4cccSAlexey Dobriyan 	unsigned long cdb_reg;
4113db038cf8SAlexey Dobriyan 	unsigned char i;
41141da177e4SLinus Torvalds 
411547b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
41161da177e4SLinus Torvalds 
41171da177e4SLinus Torvalds 	if (currSCCB->OperationCode == RESET_COMMAND) {
41181da177e4SLinus Torvalds 
41191da177e4SLinus Torvalds 		currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
41201da177e4SLinus Torvalds 		currSCCB->CdbLength = SIX_BYTE_CMD;
41211da177e4SLinus Torvalds 	}
41221da177e4SLinus Torvalds 
41231da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsisig, 0x00);
41241da177e4SLinus Torvalds 
41251da177e4SLinus Torvalds 	ARAM_ACCESS(p_port);
41261da177e4SLinus Torvalds 
41271da177e4SLinus Torvalds 	cdb_reg = p_port + CMD_STRT;
41281da177e4SLinus Torvalds 
41291da177e4SLinus Torvalds 	for (i = 0; i < currSCCB->CdbLength; i++) {
41301da177e4SLinus Torvalds 
41311da177e4SLinus Torvalds 		if (currSCCB->OperationCode == RESET_COMMAND)
41321da177e4SLinus Torvalds 
41331da177e4SLinus Torvalds 			WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + 0x00));
41341da177e4SLinus Torvalds 
41351da177e4SLinus Torvalds 		else
41365c04a7b8SAlexey Dobriyan 			WRW_HARPOON(cdb_reg,
41375c04a7b8SAlexey Dobriyan 				    (MPM_OP + ACOMMAND + currSCCB->Cdb[i]));
41381da177e4SLinus Torvalds 		cdb_reg += 2;
41391da177e4SLinus Torvalds 	}
41401da177e4SLinus Torvalds 
41411da177e4SLinus Torvalds 	if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
41421da177e4SLinus Torvalds 		WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
41431da177e4SLinus Torvalds 
41441da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_portctrl_0, (SCSI_PORT));
41451da177e4SLinus Torvalds 
41461da177e4SLinus Torvalds 	currSCCB->Sccb_scsistat = COMMAND_ST;
41471da177e4SLinus Torvalds 
41481da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_autostart_3, (AUTO_IMMED | CMD_ONLY_STRT));
41491da177e4SLinus Torvalds 	SGRAM_ACCESS(p_port);
41501da177e4SLinus Torvalds }
41511da177e4SLinus Torvalds 
41521da177e4SLinus Torvalds /*---------------------------------------------------------------------
41531da177e4SLinus Torvalds  *
41541da177e4SLinus Torvalds  * Function: Status phase
41551da177e4SLinus Torvalds  *
41561da177e4SLinus Torvalds  * Description: Bring in the status and command complete message bytes
41571da177e4SLinus Torvalds  *
41581da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
41591da177e4SLinus Torvalds 
4160d63a4cccSAlexey Dobriyan static void FPT_phaseStatus(unsigned long port, unsigned char p_card)
41611da177e4SLinus Torvalds {
41621da177e4SLinus Torvalds 	/* Start-up the automation to finish off this command and let the
41631da177e4SLinus Torvalds 	   isr handle the interrupt for command complete when it comes in.
41641da177e4SLinus Torvalds 	   We could wait here for the interrupt to be generated?
41651da177e4SLinus Torvalds 	 */
41661da177e4SLinus Torvalds 
41671da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsisig, 0x00);
41681da177e4SLinus Torvalds 
41691da177e4SLinus Torvalds 	WR_HARPOON(port + hp_autostart_0, (AUTO_IMMED + END_DATA_START));
41701da177e4SLinus Torvalds }
41711da177e4SLinus Torvalds 
41721da177e4SLinus Torvalds /*---------------------------------------------------------------------
41731da177e4SLinus Torvalds  *
41741da177e4SLinus Torvalds  * Function: Phase Message Out
41751da177e4SLinus Torvalds  *
41761da177e4SLinus Torvalds  * Description: Send out our message (if we have one) and handle whatever
41771da177e4SLinus Torvalds  *              else is involed.
41781da177e4SLinus Torvalds  *
41791da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
41801da177e4SLinus Torvalds 
4181d63a4cccSAlexey Dobriyan static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card)
41821da177e4SLinus Torvalds {
4183db038cf8SAlexey Dobriyan 	unsigned char message, scsiID;
418469eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
4185f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
41861da177e4SLinus Torvalds 
418747b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
41881da177e4SLinus Torvalds 
41891da177e4SLinus Torvalds 	if (currSCCB != NULL) {
41901da177e4SLinus Torvalds 
41911da177e4SLinus Torvalds 		message = currSCCB->Sccb_scsimsg;
41921da177e4SLinus Torvalds 		scsiID = currSCCB->TargID;
41931da177e4SLinus Torvalds 
41945c04a7b8SAlexey Dobriyan 		if (message == SMDEV_RESET) {
41951da177e4SLinus Torvalds 
419647b5d69cSJames Bottomley  			currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
41971da177e4SLinus Torvalds 			currTar_Info->TarSyncCtrl = 0;
419847b5d69cSJames Bottomley  			FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
41991da177e4SLinus Torvalds 
42005c04a7b8SAlexey Dobriyan 			if (FPT_sccbMgrTbl[p_card][scsiID].
42015c04a7b8SAlexey Dobriyan 			    TarEEValue & EE_SYNC_MASK) {
42021da177e4SLinus Torvalds 
42035c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
42045c04a7b8SAlexey Dobriyan 				    ~TAR_SYNC_MASK;
42051da177e4SLinus Torvalds 
42061da177e4SLinus Torvalds 			}
42071da177e4SLinus Torvalds 
42085c04a7b8SAlexey Dobriyan 			if (FPT_sccbMgrTbl[p_card][scsiID].
42095c04a7b8SAlexey Dobriyan 			    TarEEValue & EE_WIDE_SCSI) {
42101da177e4SLinus Torvalds 
42115c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
42125c04a7b8SAlexey Dobriyan 				    ~TAR_WIDE_MASK;
42131da177e4SLinus Torvalds 			}
42141da177e4SLinus Torvalds 
421547b5d69cSJames Bottomley  			FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
421647b5d69cSJames Bottomley  			FPT_SccbMgrTableInitTarget(p_card, scsiID);
42175c04a7b8SAlexey Dobriyan 		} else if (currSCCB->Sccb_scsistat == ABORT_ST) {
42181da177e4SLinus Torvalds 			currSCCB->HostStatus = SCCB_COMPLETE;
42195c04a7b8SAlexey Dobriyan 			if (FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] !=
42205c04a7b8SAlexey Dobriyan 			    NULL) {
42215c04a7b8SAlexey Dobriyan 				FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
42225c04a7b8SAlexey Dobriyan 							      Sccb_tag] = NULL;
422347b5d69cSJames Bottomley  				FPT_sccbMgrTbl[p_card][scsiID].TarTagQ_Cnt--;
42241da177e4SLinus Torvalds 			}
42251da177e4SLinus Torvalds 
42261da177e4SLinus Torvalds 		}
42271da177e4SLinus Torvalds 
42285c04a7b8SAlexey Dobriyan 		else if (currSCCB->Sccb_scsistat < COMMAND_ST) {
42291da177e4SLinus Torvalds 
42305c04a7b8SAlexey Dobriyan 			if (message == SMNO_OP) {
42311da177e4SLinus Torvalds 				currSCCB->Sccb_MGRFlags |= F_DEV_SELECTED;
42321da177e4SLinus Torvalds 
423347b5d69cSJames Bottomley  				FPT_ssel(port, p_card);
42341da177e4SLinus Torvalds 				return;
42351da177e4SLinus Torvalds 			}
42365c04a7b8SAlexey Dobriyan 		} else {
42371da177e4SLinus Torvalds 
42381da177e4SLinus Torvalds 			if (message == SMABORT)
42391da177e4SLinus Torvalds 
424047b5d69cSJames Bottomley  				FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
42411da177e4SLinus Torvalds 		}
42421da177e4SLinus Torvalds 
42435c04a7b8SAlexey Dobriyan 	} else {
42441da177e4SLinus Torvalds 		message = SMABORT;
42451da177e4SLinus Torvalds 	}
42461da177e4SLinus Torvalds 
42471da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), (BUS_FREE | PHASE | XFER_CNT_0));
42481da177e4SLinus Torvalds 
42491da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
42501da177e4SLinus Torvalds 
42511da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsidata_0, message);
42521da177e4SLinus Torvalds 
42531da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
42541da177e4SLinus Torvalds 
42551da177e4SLinus Torvalds 	ACCEPT_MSG(port);
42561da177e4SLinus Torvalds 
42571da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, 0x00);
42581da177e4SLinus Torvalds 
42591da177e4SLinus Torvalds 	if ((message == SMABORT) || (message == SMDEV_RESET) ||
42605c04a7b8SAlexey Dobriyan 	    (message == SMABORT_TAG)) {
42611da177e4SLinus Torvalds 
42625c04a7b8SAlexey Dobriyan 		while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | PHASE))) {
42635c04a7b8SAlexey Dobriyan 		}
42641da177e4SLinus Torvalds 
42655c04a7b8SAlexey Dobriyan 		if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
42661da177e4SLinus Torvalds 			WRW_HARPOON((port + hp_intstat), BUS_FREE);
42671da177e4SLinus Torvalds 
42685c04a7b8SAlexey Dobriyan 			if (currSCCB != NULL) {
42691da177e4SLinus Torvalds 
42705c04a7b8SAlexey Dobriyan 				if ((FPT_BL_Card[p_card].
42715c04a7b8SAlexey Dobriyan 				     globalFlags & F_CONLUN_IO)
42725c04a7b8SAlexey Dobriyan 				    &&
42735c04a7b8SAlexey Dobriyan 				    ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
42745c04a7b8SAlexey Dobriyan 				      TarStatus & TAR_TAG_Q_MASK) !=
42755c04a7b8SAlexey Dobriyan 				     TAG_Q_TRYING))
42765c04a7b8SAlexey Dobriyan 					FPT_sccbMgrTbl[p_card][currSCCB->
42775c04a7b8SAlexey Dobriyan 							       TargID].
42785c04a7b8SAlexey Dobriyan 					    TarLUNBusy[currSCCB->Lun] = 0;
42791da177e4SLinus Torvalds 				else
42805c04a7b8SAlexey Dobriyan 					FPT_sccbMgrTbl[p_card][currSCCB->
42815c04a7b8SAlexey Dobriyan 							       TargID].
42825c04a7b8SAlexey Dobriyan 					    TarLUNBusy[0] = 0;
42831da177e4SLinus Torvalds 
42845c04a7b8SAlexey Dobriyan 				FPT_queueCmdComplete(&FPT_BL_Card[p_card],
42855c04a7b8SAlexey Dobriyan 						     currSCCB, p_card);
42861da177e4SLinus Torvalds 			}
42871da177e4SLinus Torvalds 
42885c04a7b8SAlexey Dobriyan 			else {
42895c04a7b8SAlexey Dobriyan 				FPT_BL_Card[p_card].globalFlags |=
42905c04a7b8SAlexey Dobriyan 				    F_NEW_SCCB_CMD;
42911da177e4SLinus Torvalds 			}
42921da177e4SLinus Torvalds 		}
42931da177e4SLinus Torvalds 
42945c04a7b8SAlexey Dobriyan 		else {
42951da177e4SLinus Torvalds 
429647b5d69cSJames Bottomley  			FPT_sxfrp(port, p_card);
42971da177e4SLinus Torvalds 		}
42981da177e4SLinus Torvalds 	}
42991da177e4SLinus Torvalds 
43005c04a7b8SAlexey Dobriyan 	else {
43011da177e4SLinus Torvalds 
43025c04a7b8SAlexey Dobriyan 		if (message == SMPARITY) {
43031da177e4SLinus Torvalds 			currSCCB->Sccb_scsimsg = SMNO_OP;
43045c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_autostart_1,
43055c04a7b8SAlexey Dobriyan 				   (AUTO_IMMED + DISCONNECT_START));
43065c04a7b8SAlexey Dobriyan 		} else {
430747b5d69cSJames Bottomley  			FPT_sxfrp(port, p_card);
43081da177e4SLinus Torvalds 		}
43091da177e4SLinus Torvalds 	}
43101da177e4SLinus Torvalds }
43111da177e4SLinus Torvalds 
43121da177e4SLinus Torvalds /*---------------------------------------------------------------------
43131da177e4SLinus Torvalds  *
43141da177e4SLinus Torvalds  * Function: Message In phase
43151da177e4SLinus Torvalds  *
43161da177e4SLinus Torvalds  * Description: Bring in the message and determine what to do with it.
43171da177e4SLinus Torvalds  *
43181da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
43191da177e4SLinus Torvalds 
4320d63a4cccSAlexey Dobriyan static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card)
43211da177e4SLinus Torvalds {
4322db038cf8SAlexey Dobriyan 	unsigned char message;
432369eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
43241da177e4SLinus Torvalds 
432547b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
43261da177e4SLinus Torvalds 
43275c04a7b8SAlexey Dobriyan 	if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
43281da177e4SLinus Torvalds 
432947b5d69cSJames Bottomley  		FPT_phaseChkFifo(port, p_card);
43301da177e4SLinus Torvalds 	}
43311da177e4SLinus Torvalds 
43321da177e4SLinus Torvalds 	message = RD_HARPOON(port + hp_scsidata_0);
43335c04a7b8SAlexey Dobriyan 	if ((message == SMDISC) || (message == SMSAVE_DATA_PTR)) {
43341da177e4SLinus Torvalds 
43355c04a7b8SAlexey Dobriyan 		WR_HARPOON(port + hp_autostart_1,
43365c04a7b8SAlexey Dobriyan 			   (AUTO_IMMED + END_DATA_START));
43371da177e4SLinus Torvalds 
43381da177e4SLinus Torvalds 	}
43391da177e4SLinus Torvalds 
43405c04a7b8SAlexey Dobriyan 	else {
43411da177e4SLinus Torvalds 
434247b5d69cSJames Bottomley  		message = FPT_sfm(port, currSCCB);
43435c04a7b8SAlexey Dobriyan 		if (message) {
43441da177e4SLinus Torvalds 
434547b5d69cSJames Bottomley  			FPT_sdecm(message, port, p_card);
43461da177e4SLinus Torvalds 
43475c04a7b8SAlexey Dobriyan 		} else {
43481da177e4SLinus Torvalds 			if (currSCCB->Sccb_scsimsg != SMPARITY)
43491da177e4SLinus Torvalds 				ACCEPT_MSG(port);
43505c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_autostart_1,
43515c04a7b8SAlexey Dobriyan 				   (AUTO_IMMED + DISCONNECT_START));
43521da177e4SLinus Torvalds 		}
43531da177e4SLinus Torvalds 	}
43541da177e4SLinus Torvalds 
43551da177e4SLinus Torvalds }
43561da177e4SLinus Torvalds 
43571da177e4SLinus Torvalds /*---------------------------------------------------------------------
43581da177e4SLinus Torvalds  *
43591da177e4SLinus Torvalds  * Function: Illegal phase
43601da177e4SLinus Torvalds  *
43611da177e4SLinus Torvalds  * Description: Target switched to some illegal phase, so all we can do
43621da177e4SLinus Torvalds  *              is report an error back to the host (if that is possible)
43631da177e4SLinus Torvalds  *              and send an ABORT message to the misbehaving target.
43641da177e4SLinus Torvalds  *
43651da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
43661da177e4SLinus Torvalds 
4367d63a4cccSAlexey Dobriyan static void FPT_phaseIllegal(unsigned long port, unsigned char p_card)
43681da177e4SLinus Torvalds {
436969eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
43701da177e4SLinus Torvalds 
437147b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
43721da177e4SLinus Torvalds 
43731da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsisig, RD_HARPOON(port + hp_scsisig));
43741da177e4SLinus Torvalds 	if (currSCCB != NULL) {
43751da177e4SLinus Torvalds 
43761da177e4SLinus Torvalds 		currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
43771da177e4SLinus Torvalds 		currSCCB->Sccb_scsistat = ABORT_ST;
43781da177e4SLinus Torvalds 		currSCCB->Sccb_scsimsg = SMABORT;
43791da177e4SLinus Torvalds 	}
43801da177e4SLinus Torvalds 
43811da177e4SLinus Torvalds 	ACCEPT_MSG_ATN(port);
43821da177e4SLinus Torvalds }
43831da177e4SLinus Torvalds 
43841da177e4SLinus Torvalds /*---------------------------------------------------------------------
43851da177e4SLinus Torvalds  *
43861da177e4SLinus Torvalds  * Function: Phase Check FIFO
43871da177e4SLinus Torvalds  *
43881da177e4SLinus Torvalds  * Description: Make sure data has been flushed from both FIFOs and abort
43891da177e4SLinus Torvalds  *              the operations if necessary.
43901da177e4SLinus Torvalds  *
43911da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
43921da177e4SLinus Torvalds 
4393d63a4cccSAlexey Dobriyan static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card)
43941da177e4SLinus Torvalds {
4395d63a4cccSAlexey Dobriyan 	unsigned long xfercnt;
439669eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
43971da177e4SLinus Torvalds 
439847b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
43991da177e4SLinus Torvalds 
44005c04a7b8SAlexey Dobriyan 	if (currSCCB->Sccb_scsistat == DATA_IN_ST) {
44011da177e4SLinus Torvalds 
44021da177e4SLinus Torvalds 		while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) &&
44035c04a7b8SAlexey Dobriyan 		       (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)) {
44045c04a7b8SAlexey Dobriyan 		}
44051da177e4SLinus Torvalds 
44065c04a7b8SAlexey Dobriyan 		if (!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) {
44071da177e4SLinus Torvalds 			currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
44081da177e4SLinus Torvalds 
44091da177e4SLinus Torvalds 			currSCCB->Sccb_XferCnt = 0;
44101da177e4SLinus Torvalds 
44111da177e4SLinus Torvalds 			if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
44125c04a7b8SAlexey Dobriyan 			    (currSCCB->HostStatus == SCCB_COMPLETE)) {
44131da177e4SLinus Torvalds 				currSCCB->HostStatus = SCCB_PARITY_ERR;
44141da177e4SLinus Torvalds 				WRW_HARPOON((port + hp_intstat), PARITY);
44151da177e4SLinus Torvalds 			}
44161da177e4SLinus Torvalds 
441747b5d69cSJames Bottomley  			FPT_hostDataXferAbort(port, p_card, currSCCB);
44181da177e4SLinus Torvalds 
441947b5d69cSJames Bottomley  			FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
44201da177e4SLinus Torvalds 
44215c04a7b8SAlexey Dobriyan 			while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY))
44225c04a7b8SAlexey Dobriyan 			       && (RD_HARPOON(port + hp_ext_status) &
44235c04a7b8SAlexey Dobriyan 				   BM_CMD_BUSY)) {
44245c04a7b8SAlexey Dobriyan 			}
44251da177e4SLinus Torvalds 
44261da177e4SLinus Torvalds 		}
44275c04a7b8SAlexey Dobriyan 	}
44281da177e4SLinus Torvalds 
44295c04a7b8SAlexey Dobriyan 	/*End Data In specific code. */
44301da177e4SLinus Torvalds 	GET_XFER_CNT(port, xfercnt);
44311da177e4SLinus Torvalds 
44321da177e4SLinus Torvalds 	WR_HARPOON(port + hp_xfercnt_0, 0x00);
44331da177e4SLinus Torvalds 
44341da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_0, 0x00);
44351da177e4SLinus Torvalds 
44361da177e4SLinus Torvalds 	currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - xfercnt);
44371da177e4SLinus Torvalds 
44381da177e4SLinus Torvalds 	currSCCB->Sccb_XferCnt = xfercnt;
44391da177e4SLinus Torvalds 
44401da177e4SLinus Torvalds 	if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
44411da177e4SLinus Torvalds 	    (currSCCB->HostStatus == SCCB_COMPLETE)) {
44421da177e4SLinus Torvalds 
44431da177e4SLinus Torvalds 		currSCCB->HostStatus = SCCB_PARITY_ERR;
44441da177e4SLinus Torvalds 		WRW_HARPOON((port + hp_intstat), PARITY);
44451da177e4SLinus Torvalds 	}
44461da177e4SLinus Torvalds 
444747b5d69cSJames Bottomley  	FPT_hostDataXferAbort(port, p_card, currSCCB);
44481da177e4SLinus Torvalds 
44491da177e4SLinus Torvalds 	WR_HARPOON(port + hp_fifowrite, 0x00);
44501da177e4SLinus Torvalds 	WR_HARPOON(port + hp_fiforead, 0x00);
44511da177e4SLinus Torvalds 	WR_HARPOON(port + hp_xferstat, 0x00);
44521da177e4SLinus Torvalds 
44531da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
44541da177e4SLinus Torvalds }
44551da177e4SLinus Torvalds 
44561da177e4SLinus Torvalds /*---------------------------------------------------------------------
44571da177e4SLinus Torvalds  *
44581da177e4SLinus Torvalds  * Function: Phase Bus Free
44591da177e4SLinus Torvalds  *
44601da177e4SLinus Torvalds  * Description: We just went bus free so figure out if it was
44611da177e4SLinus Torvalds  *              because of command complete or from a disconnect.
44621da177e4SLinus Torvalds  *
44631da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
4464d63a4cccSAlexey Dobriyan static void FPT_phaseBusFree(unsigned long port, unsigned char p_card)
44651da177e4SLinus Torvalds {
446669eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
44671da177e4SLinus Torvalds 
446847b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
44691da177e4SLinus Torvalds 
44705c04a7b8SAlexey Dobriyan 	if (currSCCB != NULL) {
44711da177e4SLinus Torvalds 
44721da177e4SLinus Torvalds 		DISABLE_AUTO(port);
44731da177e4SLinus Torvalds 
44745c04a7b8SAlexey Dobriyan 		if (currSCCB->OperationCode == RESET_COMMAND) {
44751da177e4SLinus Torvalds 
447647b5d69cSJames Bottomley  			if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
44775c04a7b8SAlexey Dobriyan 			    ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
44785c04a7b8SAlexey Dobriyan 			      TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
44795c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
44805c04a7b8SAlexey Dobriyan 				    TarLUNBusy[currSCCB->Lun] = 0;
44811da177e4SLinus Torvalds 			else
44825c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
44835c04a7b8SAlexey Dobriyan 				    TarLUNBusy[0] = 0;
44841da177e4SLinus Torvalds 
44855c04a7b8SAlexey Dobriyan 			FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
44865c04a7b8SAlexey Dobriyan 					     p_card);
44871da177e4SLinus Torvalds 
448847b5d69cSJames Bottomley  			FPT_queueSearchSelect(&FPT_BL_Card[p_card], p_card);
44891da177e4SLinus Torvalds 
44901da177e4SLinus Torvalds 		}
44911da177e4SLinus Torvalds 
44925c04a7b8SAlexey Dobriyan 		else if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
449347b5d69cSJames Bottomley  			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4494db038cf8SAlexey Dobriyan 			    (unsigned char)SYNC_SUPPORTED;
44955c04a7b8SAlexey Dobriyan 			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
44965c04a7b8SAlexey Dobriyan 			    ~EE_SYNC_MASK;
44971da177e4SLinus Torvalds 		}
44981da177e4SLinus Torvalds 
44995c04a7b8SAlexey Dobriyan 		else if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
450047b5d69cSJames Bottomley  			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
450147b5d69cSJames Bottomley  			    (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
45021da177e4SLinus Torvalds 			     TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
45031da177e4SLinus Torvalds 
45045c04a7b8SAlexey Dobriyan 			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
45055c04a7b8SAlexey Dobriyan 			    ~EE_WIDE_SCSI;
45061da177e4SLinus Torvalds 		}
45071da177e4SLinus Torvalds 
45085c04a7b8SAlexey Dobriyan 		else if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
45091da177e4SLinus Torvalds 			/* Make sure this is not a phony BUS_FREE.  If we were
45101da177e4SLinus Torvalds 			   reselected or if BUSY is NOT on then this is a
45111da177e4SLinus Torvalds 			   valid BUS FREE.  SRR Wednesday, 5/10/1995.     */
45121da177e4SLinus Torvalds 
45131da177e4SLinus Torvalds 			if ((!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ||
45145c04a7b8SAlexey Dobriyan 			    (RDW_HARPOON((port + hp_intstat)) & RSEL)) {
45155c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
45165c04a7b8SAlexey Dobriyan 				    TarStatus &= ~TAR_TAG_Q_MASK;
45175c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
45185c04a7b8SAlexey Dobriyan 				    TarStatus |= TAG_Q_REJECT;
45191da177e4SLinus Torvalds 			}
45201da177e4SLinus Torvalds 
45215c04a7b8SAlexey Dobriyan 			else {
45221da177e4SLinus Torvalds 				return;
45231da177e4SLinus Torvalds 			}
45241da177e4SLinus Torvalds 		}
45251da177e4SLinus Torvalds 
45265c04a7b8SAlexey Dobriyan 		else {
45271da177e4SLinus Torvalds 
45281da177e4SLinus Torvalds 			currSCCB->Sccb_scsistat = BUS_FREE_ST;
45291da177e4SLinus Torvalds 
45305c04a7b8SAlexey Dobriyan 			if (!currSCCB->HostStatus) {
45311da177e4SLinus Torvalds 				currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
45321da177e4SLinus Torvalds 			}
45331da177e4SLinus Torvalds 
453447b5d69cSJames Bottomley  			if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
45355c04a7b8SAlexey Dobriyan 			    ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
45365c04a7b8SAlexey Dobriyan 			      TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
45375c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
45385c04a7b8SAlexey Dobriyan 				    TarLUNBusy[currSCCB->Lun] = 0;
45391da177e4SLinus Torvalds 			else
45405c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
45415c04a7b8SAlexey Dobriyan 				    TarLUNBusy[0] = 0;
45421da177e4SLinus Torvalds 
45435c04a7b8SAlexey Dobriyan 			FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
45445c04a7b8SAlexey Dobriyan 					     p_card);
45451da177e4SLinus Torvalds 			return;
45461da177e4SLinus Torvalds 		}
45471da177e4SLinus Torvalds 
454847b5d69cSJames Bottomley  		FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
45491da177e4SLinus Torvalds 
45501da177e4SLinus Torvalds 	}			/*end if !=null */
45511da177e4SLinus Torvalds }
45521da177e4SLinus Torvalds 
45531da177e4SLinus Torvalds /*---------------------------------------------------------------------
45541da177e4SLinus Torvalds  *
45551da177e4SLinus Torvalds  * Function: Auto Load Default Map
45561da177e4SLinus Torvalds  *
45571da177e4SLinus Torvalds  * Description: Load the Automation RAM with the defualt map values.
45581da177e4SLinus Torvalds  *
45591da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
4560d63a4cccSAlexey Dobriyan static void FPT_autoLoadDefaultMap(unsigned long p_port)
45611da177e4SLinus Torvalds {
4562d63a4cccSAlexey Dobriyan 	unsigned long map_addr;
45631da177e4SLinus Torvalds 
45641da177e4SLinus Torvalds 	ARAM_ACCESS(p_port);
45651da177e4SLinus Torvalds 	map_addr = p_port + hp_aramBase;
45661da177e4SLinus Torvalds 
45671da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0xC0));	/*ID MESSAGE */
45681da177e4SLinus Torvalds 	map_addr += 2;
45691da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x20));	/*SIMPLE TAG QUEUEING MSG */
45701da177e4SLinus Torvalds 	map_addr += 2;
45711da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, RAT_OP);	/*RESET ATTENTION */
45721da177e4SLinus Torvalds 	map_addr += 2;
45731da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x00));	/*TAG ID MSG */
45741da177e4SLinus Torvalds 	map_addr += 2;
45751da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 0 */
45761da177e4SLinus Torvalds 	map_addr += 2;
45771da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 1 */
45781da177e4SLinus Torvalds 	map_addr += 2;
45791da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 2 */
45801da177e4SLinus Torvalds 	map_addr += 2;
45811da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 3 */
45821da177e4SLinus Torvalds 	map_addr += 2;
45831da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 4 */
45841da177e4SLinus Torvalds 	map_addr += 2;
45851da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 5 */
45861da177e4SLinus Torvalds 	map_addr += 2;
45871da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 6 */
45881da177e4SLinus Torvalds 	map_addr += 2;
45891da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 7 */
45901da177e4SLinus Torvalds 	map_addr += 2;
45911da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 8 */
45921da177e4SLinus Torvalds 	map_addr += 2;
45931da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 9 */
45941da177e4SLinus Torvalds 	map_addr += 2;
45951da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 10 */
45961da177e4SLinus Torvalds 	map_addr += 2;
45971da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 11 */
45981da177e4SLinus Torvalds 	map_addr += 2;
45991da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CPE_OP + ADATA_OUT + DINT));	/*JUMP IF DATA OUT */
46001da177e4SLinus Torvalds 	map_addr += 2;
46011da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (TCB_OP + FIFO_0 + DI));	/*JUMP IF NO DATA IN FIFO */
46021da177e4SLinus Torvalds 	map_addr += 2;		/*This means AYNC DATA IN */
46031da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (SSI_OP + SSI_IDO_STRT));	/*STOP AND INTERRUPT */
46041da177e4SLinus Torvalds 	map_addr += 2;
46051da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CPE_OP + ADATA_IN + DINT));	/*JUMP IF NOT DATA IN PHZ */
46061da177e4SLinus Torvalds 	map_addr += 2;
46071da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST));	/*IF NOT MSG IN CHECK 4 DATA IN */
46081da177e4SLinus Torvalds 	map_addr += 2;
46091da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x02));	/*SAVE DATA PTR MSG? */
46101da177e4SLinus Torvalds 	map_addr += 2;
46111da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + DC));	/*GO CHECK FOR DISCONNECT MSG */
46121da177e4SLinus Torvalds 	map_addr += 2;
46131da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR1));	/*SAVE DATA PTRS MSG */
46141da177e4SLinus Torvalds 	map_addr += 2;
46151da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST));	/*IF NOT MSG IN CHECK DATA IN */
46161da177e4SLinus Torvalds 	map_addr += 2;
46171da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x04));	/*DISCONNECT MSG? */
46181da177e4SLinus Torvalds 	map_addr += 2;
46191da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + UNKNWN));	/*UKNKNOWN MSG */
46201da177e4SLinus Torvalds 	map_addr += 2;
46211da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET));	/*XFER DISCONNECT MSG */
46221da177e4SLinus Torvalds 	map_addr += 2;
46231da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (SSI_OP + SSI_ITAR_DISC));	/*STOP AND INTERRUPT */
46241da177e4SLinus Torvalds 	map_addr += 2;
46251da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CPN_OP + ASTATUS + UNKNWN));	/*JUMP IF NOT STATUS PHZ. */
46261da177e4SLinus Torvalds 	map_addr += 2;
46271da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR0));	/*GET STATUS BYTE */
46281da177e4SLinus Torvalds 	map_addr += 2;
46291da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + CC));	/*ERROR IF NOT MSG IN PHZ */
46301da177e4SLinus Torvalds 	map_addr += 2;
46311da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x00));	/*CHECK FOR CMD COMPLETE MSG. */
46321da177e4SLinus Torvalds 	map_addr += 2;
46331da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + CC));	/*ERROR IF NOT CMD COMPLETE MSG. */
46341da177e4SLinus Torvalds 	map_addr += 2;
46351da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET));	/*GET CMD COMPLETE MSG */
46361da177e4SLinus Torvalds 	map_addr += 2;
46371da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (SSI_OP + SSI_ICMD_COMP));	/*END OF COMMAND */
46381da177e4SLinus Torvalds 	map_addr += 2;
46391da177e4SLinus Torvalds 
46401da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (SSI_OP + SSI_IUNKWN));	/*RECEIVED UNKNOWN MSG BYTE */
46411da177e4SLinus Torvalds 	map_addr += 2;
46421da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC));	/*NO COMMAND COMPLETE AFTER STATUS */
46431da177e4SLinus Torvalds 	map_addr += 2;
46441da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (SSI_OP + SSI_ITICKLE));	/*BIOS Tickled the Mgr */
46451da177e4SLinus Torvalds 	map_addr += 2;
46461da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (SSI_OP + SSI_IRFAIL));	/*EXPECTED ID/TAG MESSAGES AND */
46471da177e4SLinus Torvalds 	map_addr += 2;		/* DIDN'T GET ONE */
46481da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (CRR_OP + AR3 + S_IDREG));	/* comp SCSI SEL ID & AR3 */
46491da177e4SLinus Torvalds 	map_addr += 2;
46501da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (BRH_OP + EQUAL + 0x00));	/*SEL ID OK then Conti. */
46511da177e4SLinus Torvalds 	map_addr += 2;
46521da177e4SLinus Torvalds 	WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC));	/*NO COMMAND COMPLETE AFTER STATUS */
46531da177e4SLinus Torvalds 
46541da177e4SLinus Torvalds 	SGRAM_ACCESS(p_port);
46551da177e4SLinus Torvalds }
46561da177e4SLinus Torvalds 
46571da177e4SLinus Torvalds /*---------------------------------------------------------------------
46581da177e4SLinus Torvalds  *
46591da177e4SLinus Torvalds  * Function: Auto Command Complete
46601da177e4SLinus Torvalds  *
46611da177e4SLinus Torvalds  * Description: Post command back to host and find another command
46621da177e4SLinus Torvalds  *              to execute.
46631da177e4SLinus Torvalds  *
46641da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
46651da177e4SLinus Torvalds 
4666d63a4cccSAlexey Dobriyan static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card)
46671da177e4SLinus Torvalds {
466869eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
4669db038cf8SAlexey Dobriyan 	unsigned char status_byte;
46701da177e4SLinus Torvalds 
467147b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
46721da177e4SLinus Torvalds 
46731da177e4SLinus Torvalds 	status_byte = RD_HARPOON(p_port + hp_gp_reg_0);
46741da177e4SLinus Torvalds 
467547b5d69cSJames Bottomley  	FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA = 0;
46761da177e4SLinus Torvalds 
46771da177e4SLinus Torvalds 	if (status_byte != SSGOOD) {
46781da177e4SLinus Torvalds 
46791da177e4SLinus Torvalds 		if (status_byte == SSQ_FULL) {
46801da177e4SLinus Torvalds 
468147b5d69cSJames Bottomley  			if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
46825c04a7b8SAlexey Dobriyan 			     ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
46835c04a7b8SAlexey Dobriyan 			       TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
46845c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
46855c04a7b8SAlexey Dobriyan 				    TarLUNBusy[currSCCB->Lun] = 1;
468647b5d69cSJames Bottomley  				if (FPT_BL_Card[p_card].discQCount != 0)
468747b5d69cSJames Bottomley  					FPT_BL_Card[p_card].discQCount--;
46885c04a7b8SAlexey Dobriyan 				FPT_BL_Card[p_card].
46895c04a7b8SAlexey Dobriyan 				    discQ_Tbl[FPT_sccbMgrTbl[p_card]
46905c04a7b8SAlexey Dobriyan 					      [currSCCB->TargID].
46915c04a7b8SAlexey Dobriyan 					      LunDiscQ_Idx[currSCCB->Lun]] =
46925c04a7b8SAlexey Dobriyan 				    NULL;
46935c04a7b8SAlexey Dobriyan 			} else {
46945c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
46955c04a7b8SAlexey Dobriyan 				    TarLUNBusy[0] = 1;
46965c04a7b8SAlexey Dobriyan 				if (currSCCB->Sccb_tag) {
469747b5d69cSJames Bottomley  					if (FPT_BL_Card[p_card].discQCount != 0)
46985c04a7b8SAlexey Dobriyan 						FPT_BL_Card[p_card].
46995c04a7b8SAlexey Dobriyan 						    discQCount--;
47005c04a7b8SAlexey Dobriyan 					FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
47015c04a7b8SAlexey Dobriyan 								      Sccb_tag]
47025c04a7b8SAlexey Dobriyan 					    = NULL;
47035c04a7b8SAlexey Dobriyan 				} else {
470447b5d69cSJames Bottomley  					if (FPT_BL_Card[p_card].discQCount != 0)
47055c04a7b8SAlexey Dobriyan 						FPT_BL_Card[p_card].
47065c04a7b8SAlexey Dobriyan 						    discQCount--;
47075c04a7b8SAlexey Dobriyan 					FPT_BL_Card[p_card].
47085c04a7b8SAlexey Dobriyan 					    discQ_Tbl[FPT_sccbMgrTbl[p_card]
47095c04a7b8SAlexey Dobriyan 						      [currSCCB->TargID].
47105c04a7b8SAlexey Dobriyan 						      LunDiscQ_Idx[0]] = NULL;
47111da177e4SLinus Torvalds 				}
47121da177e4SLinus Torvalds 			}
47131da177e4SLinus Torvalds 
47141da177e4SLinus Torvalds 			currSCCB->Sccb_MGRFlags |= F_STATUSLOADED;
47151da177e4SLinus Torvalds 
471647b5d69cSJames Bottomley  			FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
47171da177e4SLinus Torvalds 
47181da177e4SLinus Torvalds 			return;
47191da177e4SLinus Torvalds 		}
47201da177e4SLinus Torvalds 
47215c04a7b8SAlexey Dobriyan 		if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
472247b5d69cSJames Bottomley  			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4723db038cf8SAlexey Dobriyan 			    (unsigned char)SYNC_SUPPORTED;
47241da177e4SLinus Torvalds 
47255c04a7b8SAlexey Dobriyan 			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
47265c04a7b8SAlexey Dobriyan 			    ~EE_SYNC_MASK;
472747b5d69cSJames Bottomley  			FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
47281da177e4SLinus Torvalds 
472947b5d69cSJames Bottomley  			if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
47305c04a7b8SAlexey Dobriyan 			     ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
47315c04a7b8SAlexey Dobriyan 			       TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
47325c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
47335c04a7b8SAlexey Dobriyan 				    TarLUNBusy[currSCCB->Lun] = 1;
473447b5d69cSJames Bottomley  				if (FPT_BL_Card[p_card].discQCount != 0)
473547b5d69cSJames Bottomley  					FPT_BL_Card[p_card].discQCount--;
47365c04a7b8SAlexey Dobriyan 				FPT_BL_Card[p_card].
47375c04a7b8SAlexey Dobriyan 				    discQ_Tbl[FPT_sccbMgrTbl[p_card]
47385c04a7b8SAlexey Dobriyan 					      [currSCCB->TargID].
47395c04a7b8SAlexey Dobriyan 					      LunDiscQ_Idx[currSCCB->Lun]] =
47405c04a7b8SAlexey Dobriyan 				    NULL;
47415c04a7b8SAlexey Dobriyan 			} else {
47425c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
47435c04a7b8SAlexey Dobriyan 				    TarLUNBusy[0] = 1;
47445c04a7b8SAlexey Dobriyan 				if (currSCCB->Sccb_tag) {
474547b5d69cSJames Bottomley  					if (FPT_BL_Card[p_card].discQCount != 0)
47465c04a7b8SAlexey Dobriyan 						FPT_BL_Card[p_card].
47475c04a7b8SAlexey Dobriyan 						    discQCount--;
47485c04a7b8SAlexey Dobriyan 					FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
47495c04a7b8SAlexey Dobriyan 								      Sccb_tag]
47505c04a7b8SAlexey Dobriyan 					    = NULL;
47515c04a7b8SAlexey Dobriyan 				} else {
475247b5d69cSJames Bottomley  					if (FPT_BL_Card[p_card].discQCount != 0)
47535c04a7b8SAlexey Dobriyan 						FPT_BL_Card[p_card].
47545c04a7b8SAlexey Dobriyan 						    discQCount--;
47555c04a7b8SAlexey Dobriyan 					FPT_BL_Card[p_card].
47565c04a7b8SAlexey Dobriyan 					    discQ_Tbl[FPT_sccbMgrTbl[p_card]
47575c04a7b8SAlexey Dobriyan 						      [currSCCB->TargID].
47585c04a7b8SAlexey Dobriyan 						      LunDiscQ_Idx[0]] = NULL;
47591da177e4SLinus Torvalds 				}
47601da177e4SLinus Torvalds 			}
47611da177e4SLinus Torvalds 			return;
47621da177e4SLinus Torvalds 
47631da177e4SLinus Torvalds 		}
47641da177e4SLinus Torvalds 
47655c04a7b8SAlexey Dobriyan 		if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
47661da177e4SLinus Torvalds 
476747b5d69cSJames Bottomley  			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
476847b5d69cSJames Bottomley  			    (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
47691da177e4SLinus Torvalds 			     TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
47701da177e4SLinus Torvalds 
47715c04a7b8SAlexey Dobriyan 			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
47725c04a7b8SAlexey Dobriyan 			    ~EE_WIDE_SCSI;
477347b5d69cSJames Bottomley  			FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
47741da177e4SLinus Torvalds 
477547b5d69cSJames Bottomley  			if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
47765c04a7b8SAlexey Dobriyan 			     ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
47775c04a7b8SAlexey Dobriyan 			       TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
47785c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
47795c04a7b8SAlexey Dobriyan 				    TarLUNBusy[currSCCB->Lun] = 1;
478047b5d69cSJames Bottomley  				if (FPT_BL_Card[p_card].discQCount != 0)
478147b5d69cSJames Bottomley  					FPT_BL_Card[p_card].discQCount--;
47825c04a7b8SAlexey Dobriyan 				FPT_BL_Card[p_card].
47835c04a7b8SAlexey Dobriyan 				    discQ_Tbl[FPT_sccbMgrTbl[p_card]
47845c04a7b8SAlexey Dobriyan 					      [currSCCB->TargID].
47855c04a7b8SAlexey Dobriyan 					      LunDiscQ_Idx[currSCCB->Lun]] =
47865c04a7b8SAlexey Dobriyan 				    NULL;
47875c04a7b8SAlexey Dobriyan 			} else {
47885c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
47895c04a7b8SAlexey Dobriyan 				    TarLUNBusy[0] = 1;
47905c04a7b8SAlexey Dobriyan 				if (currSCCB->Sccb_tag) {
479147b5d69cSJames Bottomley  					if (FPT_BL_Card[p_card].discQCount != 0)
47925c04a7b8SAlexey Dobriyan 						FPT_BL_Card[p_card].
47935c04a7b8SAlexey Dobriyan 						    discQCount--;
47945c04a7b8SAlexey Dobriyan 					FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
47955c04a7b8SAlexey Dobriyan 								      Sccb_tag]
47965c04a7b8SAlexey Dobriyan 					    = NULL;
47975c04a7b8SAlexey Dobriyan 				} else {
479847b5d69cSJames Bottomley  					if (FPT_BL_Card[p_card].discQCount != 0)
47995c04a7b8SAlexey Dobriyan 						FPT_BL_Card[p_card].
48005c04a7b8SAlexey Dobriyan 						    discQCount--;
48015c04a7b8SAlexey Dobriyan 					FPT_BL_Card[p_card].
48025c04a7b8SAlexey Dobriyan 					    discQ_Tbl[FPT_sccbMgrTbl[p_card]
48035c04a7b8SAlexey Dobriyan 						      [currSCCB->TargID].
48045c04a7b8SAlexey Dobriyan 						      LunDiscQ_Idx[0]] = NULL;
48051da177e4SLinus Torvalds 				}
48061da177e4SLinus Torvalds 			}
48071da177e4SLinus Torvalds 			return;
48081da177e4SLinus Torvalds 
48091da177e4SLinus Torvalds 		}
48101da177e4SLinus Torvalds 
48115c04a7b8SAlexey Dobriyan 		if (status_byte == SSCHECK) {
48125c04a7b8SAlexey Dobriyan 			if (FPT_BL_Card[p_card].globalFlags & F_DO_RENEGO) {
48135c04a7b8SAlexey Dobriyan 				if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
48145c04a7b8SAlexey Dobriyan 				    TarEEValue & EE_SYNC_MASK) {
48155c04a7b8SAlexey Dobriyan 					FPT_sccbMgrTbl[p_card][currSCCB->
48165c04a7b8SAlexey Dobriyan 							       TargID].
48175c04a7b8SAlexey Dobriyan 					    TarStatus &= ~TAR_SYNC_MASK;
48181da177e4SLinus Torvalds 				}
48195c04a7b8SAlexey Dobriyan 				if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
48205c04a7b8SAlexey Dobriyan 				    TarEEValue & EE_WIDE_SCSI) {
48215c04a7b8SAlexey Dobriyan 					FPT_sccbMgrTbl[p_card][currSCCB->
48225c04a7b8SAlexey Dobriyan 							       TargID].
48235c04a7b8SAlexey Dobriyan 					    TarStatus &= ~TAR_WIDE_MASK;
48241da177e4SLinus Torvalds 				}
48251da177e4SLinus Torvalds 			}
48261da177e4SLinus Torvalds 		}
48271da177e4SLinus Torvalds 
48281da177e4SLinus Torvalds 		if (!(currSCCB->Sccb_XferState & F_AUTO_SENSE)) {
48291da177e4SLinus Torvalds 
48301da177e4SLinus Torvalds 			currSCCB->SccbStatus = SCCB_ERROR;
48311da177e4SLinus Torvalds 			currSCCB->TargetStatus = status_byte;
48321da177e4SLinus Torvalds 
48331da177e4SLinus Torvalds 			if (status_byte == SSCHECK) {
48341da177e4SLinus Torvalds 
48355c04a7b8SAlexey Dobriyan 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
48365c04a7b8SAlexey Dobriyan 				    TarLUN_CA = 1;
48371da177e4SLinus Torvalds 
48385c04a7b8SAlexey Dobriyan 				if (currSCCB->RequestSenseLength !=
48395c04a7b8SAlexey Dobriyan 				    NO_AUTO_REQUEST_SENSE) {
48401da177e4SLinus Torvalds 
48411da177e4SLinus Torvalds 					if (currSCCB->RequestSenseLength == 0)
48425c04a7b8SAlexey Dobriyan 						currSCCB->RequestSenseLength =
48435c04a7b8SAlexey Dobriyan 						    14;
48441da177e4SLinus Torvalds 
484547b5d69cSJames Bottomley  					FPT_ssenss(&FPT_BL_Card[p_card]);
48465c04a7b8SAlexey Dobriyan 					FPT_BL_Card[p_card].globalFlags |=
48475c04a7b8SAlexey Dobriyan 					    F_NEW_SCCB_CMD;
48481da177e4SLinus Torvalds 
48495c04a7b8SAlexey Dobriyan 					if (((FPT_BL_Card[p_card].
48505c04a7b8SAlexey Dobriyan 					      globalFlags & F_CONLUN_IO)
48515c04a7b8SAlexey Dobriyan 					     &&
48525c04a7b8SAlexey Dobriyan 					     ((FPT_sccbMgrTbl[p_card]
48535c04a7b8SAlexey Dobriyan 					       [currSCCB->TargID].
48545c04a7b8SAlexey Dobriyan 					       TarStatus & TAR_TAG_Q_MASK) !=
48555c04a7b8SAlexey Dobriyan 					      TAG_Q_TRYING))) {
48565c04a7b8SAlexey Dobriyan 						FPT_sccbMgrTbl[p_card]
48575c04a7b8SAlexey Dobriyan 						    [currSCCB->TargID].
48585c04a7b8SAlexey Dobriyan 						    TarLUNBusy[currSCCB->Lun] =
48595c04a7b8SAlexey Dobriyan 						    1;
48605c04a7b8SAlexey Dobriyan 						if (FPT_BL_Card[p_card].
48615c04a7b8SAlexey Dobriyan 						    discQCount != 0)
48625c04a7b8SAlexey Dobriyan 							FPT_BL_Card[p_card].
48635c04a7b8SAlexey Dobriyan 							    discQCount--;
48645c04a7b8SAlexey Dobriyan 						FPT_BL_Card[p_card].
48655c04a7b8SAlexey Dobriyan 						    discQ_Tbl[FPT_sccbMgrTbl
48665c04a7b8SAlexey Dobriyan 							      [p_card]
48675c04a7b8SAlexey Dobriyan 							      [currSCCB->
48685c04a7b8SAlexey Dobriyan 							       TargID].
48695c04a7b8SAlexey Dobriyan 							      LunDiscQ_Idx
48705c04a7b8SAlexey Dobriyan 							      [currSCCB->Lun]] =
48715c04a7b8SAlexey Dobriyan 						    NULL;
48725c04a7b8SAlexey Dobriyan 					} else {
48735c04a7b8SAlexey Dobriyan 						FPT_sccbMgrTbl[p_card]
48745c04a7b8SAlexey Dobriyan 						    [currSCCB->TargID].
48755c04a7b8SAlexey Dobriyan 						    TarLUNBusy[0] = 1;
48765c04a7b8SAlexey Dobriyan 						if (currSCCB->Sccb_tag) {
48775c04a7b8SAlexey Dobriyan 							if (FPT_BL_Card[p_card].
48785c04a7b8SAlexey Dobriyan 							    discQCount != 0)
48795c04a7b8SAlexey Dobriyan 								FPT_BL_Card
48805c04a7b8SAlexey Dobriyan 								    [p_card].
48815c04a7b8SAlexey Dobriyan 								    discQCount--;
48825c04a7b8SAlexey Dobriyan 							FPT_BL_Card[p_card].
48835c04a7b8SAlexey Dobriyan 							    discQ_Tbl[currSCCB->
48845c04a7b8SAlexey Dobriyan 								      Sccb_tag]
48855c04a7b8SAlexey Dobriyan 							    = NULL;
48865c04a7b8SAlexey Dobriyan 						} else {
48875c04a7b8SAlexey Dobriyan 							if (FPT_BL_Card[p_card].
48885c04a7b8SAlexey Dobriyan 							    discQCount != 0)
48895c04a7b8SAlexey Dobriyan 								FPT_BL_Card
48905c04a7b8SAlexey Dobriyan 								    [p_card].
48915c04a7b8SAlexey Dobriyan 								    discQCount--;
48925c04a7b8SAlexey Dobriyan 							FPT_BL_Card[p_card].
48935c04a7b8SAlexey Dobriyan 							    discQ_Tbl
48945c04a7b8SAlexey Dobriyan 							    [FPT_sccbMgrTbl
48955c04a7b8SAlexey Dobriyan 							     [p_card][currSCCB->
48965c04a7b8SAlexey Dobriyan 								      TargID].
48975c04a7b8SAlexey Dobriyan 							     LunDiscQ_Idx[0]] =
48985c04a7b8SAlexey Dobriyan 							    NULL;
48991da177e4SLinus Torvalds 						}
49001da177e4SLinus Torvalds 					}
49011da177e4SLinus Torvalds 					return;
49021da177e4SLinus Torvalds 				}
49031da177e4SLinus Torvalds 			}
490447b5d69cSJames Bottomley  		}
490547b5d69cSJames Bottomley  	}
490647b5d69cSJames Bottomley  
490747b5d69cSJames Bottomley  	if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
49085c04a7b8SAlexey Dobriyan 	    ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
49095c04a7b8SAlexey Dobriyan 	      TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
49105c04a7b8SAlexey Dobriyan 		FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->
49115c04a7b8SAlexey Dobriyan 								    Lun] = 0;
49121da177e4SLinus Torvalds 	else
491347b5d69cSJames Bottomley  		FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0;
491447b5d69cSJames Bottomley  
491547b5d69cSJames Bottomley  	FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, p_card);
49161da177e4SLinus Torvalds }
49171da177e4SLinus Torvalds 
49181da177e4SLinus Torvalds #define SHORT_WAIT   0x0000000F
49191da177e4SLinus Torvalds #define LONG_WAIT    0x0000FFFFL
49201da177e4SLinus Torvalds 
49211da177e4SLinus Torvalds /*---------------------------------------------------------------------
49221da177e4SLinus Torvalds  *
49231da177e4SLinus Torvalds  * Function: Data Transfer Processor
49241da177e4SLinus Torvalds  *
49251da177e4SLinus Torvalds  * Description: This routine performs two tasks.
49261da177e4SLinus Torvalds  *              (1) Start data transfer by calling HOST_DATA_XFER_START
49271da177e4SLinus Torvalds  *              function.  Once data transfer is started, (2) Depends
49281da177e4SLinus Torvalds  *              on the type of data transfer mode Scatter/Gather mode
49291da177e4SLinus Torvalds  *              or NON Scatter/Gather mode.  In NON Scatter/Gather mode,
49301da177e4SLinus Torvalds  *              this routine checks Sccb_MGRFlag (F_HOST_XFER_ACT bit) for
49311da177e4SLinus Torvalds  *              data transfer done.  In Scatter/Gather mode, this routine
49321da177e4SLinus Torvalds  *              checks bus master command complete and dual rank busy
49331da177e4SLinus Torvalds  *              bit to keep chaining SC transfer command.  Similarly,
49341da177e4SLinus Torvalds  *              in Scatter/Gather mode, it checks Sccb_MGRFlag
49351da177e4SLinus Torvalds  *              (F_HOST_XFER_ACT bit) for data transfer done.
49361da177e4SLinus Torvalds  *
49371da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
49381da177e4SLinus Torvalds 
49395c04a7b8SAlexey Dobriyan static void FPT_dataXferProcessor(unsigned long port,
49405c04a7b8SAlexey Dobriyan 				  struct sccb_card *pCurrCard)
49411da177e4SLinus Torvalds {
494269eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
49431da177e4SLinus Torvalds 
49441da177e4SLinus Torvalds 	currSCCB = pCurrCard->currentSCCB;
49451da177e4SLinus Torvalds 
49465c04a7b8SAlexey Dobriyan 	if (currSCCB->Sccb_XferState & F_SG_XFER) {
49471da177e4SLinus Torvalds 		if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
49481da177e4SLinus Torvalds 		{
4949db038cf8SAlexey Dobriyan 			currSCCB->Sccb_sgseg += (unsigned char)SG_BUF_CNT;
49501da177e4SLinus Torvalds 			currSCCB->Sccb_SGoffset = 0x00;
49511da177e4SLinus Torvalds 		}
49521da177e4SLinus Torvalds 		pCurrCard->globalFlags |= F_HOST_XFER_ACT;
49531da177e4SLinus Torvalds 
495447b5d69cSJames Bottomley  		FPT_busMstrSGDataXferStart(port, currSCCB);
49551da177e4SLinus Torvalds 	}
49561da177e4SLinus Torvalds 
49575c04a7b8SAlexey Dobriyan 	else {
49585c04a7b8SAlexey Dobriyan 		if (!(pCurrCard->globalFlags & F_HOST_XFER_ACT)) {
49591da177e4SLinus Torvalds 			pCurrCard->globalFlags |= F_HOST_XFER_ACT;
49601da177e4SLinus Torvalds 
496147b5d69cSJames Bottomley  			FPT_busMstrDataXferStart(port, currSCCB);
49621da177e4SLinus Torvalds 		}
49631da177e4SLinus Torvalds 	}
49641da177e4SLinus Torvalds }
49651da177e4SLinus Torvalds 
49661da177e4SLinus Torvalds /*---------------------------------------------------------------------
49671da177e4SLinus Torvalds  *
49681da177e4SLinus Torvalds  * Function: BusMaster Scatter Gather Data Transfer Start
49691da177e4SLinus Torvalds  *
49701da177e4SLinus Torvalds  * Description:
49711da177e4SLinus Torvalds  *
49721da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
49735c04a7b8SAlexey Dobriyan static void FPT_busMstrSGDataXferStart(unsigned long p_port,
49745c04a7b8SAlexey Dobriyan 				       struct sccb *pcurrSCCB)
49751da177e4SLinus Torvalds {
4976d63a4cccSAlexey Dobriyan 	unsigned long count, addr, tmpSGCnt;
4977ce793215SAlexey Dobriyan 	unsigned int sg_index;
4978db038cf8SAlexey Dobriyan 	unsigned char sg_count, i;
4979d63a4cccSAlexey Dobriyan 	unsigned long reg_offset;
49801da177e4SLinus Torvalds 
49811da177e4SLinus Torvalds 	if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
49821da177e4SLinus Torvalds 
4983d63a4cccSAlexey Dobriyan 		count = ((unsigned long)HOST_RD_CMD) << 24;
49841da177e4SLinus Torvalds 	}
49851da177e4SLinus Torvalds 
49861da177e4SLinus Torvalds 	else {
4987d63a4cccSAlexey Dobriyan 		count = ((unsigned long)HOST_WRT_CMD) << 24;
49881da177e4SLinus Torvalds 	}
49891da177e4SLinus Torvalds 
49901da177e4SLinus Torvalds 	sg_count = 0;
49911da177e4SLinus Torvalds 	tmpSGCnt = 0;
49921da177e4SLinus Torvalds 	sg_index = pcurrSCCB->Sccb_sgseg;
49931da177e4SLinus Torvalds 	reg_offset = hp_aramBase;
49941da177e4SLinus Torvalds 
49955c04a7b8SAlexey Dobriyan 	i = (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
49965c04a7b8SAlexey Dobriyan 			    ~(SGRAM_ARAM | SCATTER_EN));
49971da177e4SLinus Torvalds 
49981da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_page_ctrl, i);
49991da177e4SLinus Torvalds 
5000db038cf8SAlexey Dobriyan 	while ((sg_count < (unsigned char)SG_BUF_CNT) &&
50015c04a7b8SAlexey Dobriyan 	       ((unsigned long)(sg_index * (unsigned int)SG_ELEMENT_SIZE) <
50025c04a7b8SAlexey Dobriyan 		pcurrSCCB->DataLength)) {
50031da177e4SLinus Torvalds 
5004d63a4cccSAlexey Dobriyan 		tmpSGCnt += *(((unsigned long *)pcurrSCCB->DataPointer) +
50051da177e4SLinus Torvalds 			      (sg_index * 2));
50061da177e4SLinus Torvalds 
5007d63a4cccSAlexey Dobriyan 		count |= *(((unsigned long *)pcurrSCCB->DataPointer) +
50081da177e4SLinus Torvalds 			   (sg_index * 2));
50091da177e4SLinus Torvalds 
5010d63a4cccSAlexey Dobriyan 		addr = *(((unsigned long *)pcurrSCCB->DataPointer) +
50111da177e4SLinus Torvalds 			 ((sg_index * 2) + 1));
50121da177e4SLinus Torvalds 
50131da177e4SLinus Torvalds 		if ((!sg_count) && (pcurrSCCB->Sccb_SGoffset)) {
50141da177e4SLinus Torvalds 
50155c04a7b8SAlexey Dobriyan 			addr +=
50165c04a7b8SAlexey Dobriyan 			    ((count & 0x00FFFFFFL) - pcurrSCCB->Sccb_SGoffset);
50175c04a7b8SAlexey Dobriyan 			count =
50185c04a7b8SAlexey Dobriyan 			    (count & 0xFF000000L) | pcurrSCCB->Sccb_SGoffset;
50191da177e4SLinus Torvalds 
50201da177e4SLinus Torvalds 			tmpSGCnt = count & 0x00FFFFFFL;
50211da177e4SLinus Torvalds 		}
50221da177e4SLinus Torvalds 
50231da177e4SLinus Torvalds 		WR_HARP32(p_port, reg_offset, addr);
50241da177e4SLinus Torvalds 		reg_offset += 4;
50251da177e4SLinus Torvalds 
50261da177e4SLinus Torvalds 		WR_HARP32(p_port, reg_offset, count);
50271da177e4SLinus Torvalds 		reg_offset += 4;
50281da177e4SLinus Torvalds 
50291da177e4SLinus Torvalds 		count &= 0xFF000000L;
50301da177e4SLinus Torvalds 		sg_index++;
50311da177e4SLinus Torvalds 		sg_count++;
50321da177e4SLinus Torvalds 
50331da177e4SLinus Torvalds 	}			/*End While */
50341da177e4SLinus Torvalds 
50351da177e4SLinus Torvalds 	pcurrSCCB->Sccb_XferCnt = tmpSGCnt;
50361da177e4SLinus Torvalds 
50371da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_sg_addr, (sg_count << 4));
50381da177e4SLinus Torvalds 
50391da177e4SLinus Torvalds 	if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
50401da177e4SLinus Torvalds 
50411da177e4SLinus Torvalds 		WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
50421da177e4SLinus Torvalds 
50435c04a7b8SAlexey Dobriyan 		WR_HARPOON(p_port + hp_portctrl_0,
50445c04a7b8SAlexey Dobriyan 			   (DMA_PORT | SCSI_PORT | SCSI_INBIT));
50451da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
50461da177e4SLinus Torvalds 	}
50471da177e4SLinus Torvalds 
50481da177e4SLinus Torvalds 	else {
50491da177e4SLinus Torvalds 
50501da177e4SLinus Torvalds 		if ((!(RD_HARPOON(p_port + hp_synctarg_0) & NARROW_SCSI)) &&
50515c04a7b8SAlexey Dobriyan 		    (tmpSGCnt & 0x000000001)) {
50521da177e4SLinus Torvalds 
50531da177e4SLinus Torvalds 			pcurrSCCB->Sccb_XferState |= F_ODD_BALL_CNT;
50541da177e4SLinus Torvalds 			tmpSGCnt--;
50551da177e4SLinus Torvalds 		}
50561da177e4SLinus Torvalds 
50571da177e4SLinus Torvalds 		WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
50581da177e4SLinus Torvalds 
50595c04a7b8SAlexey Dobriyan 		WR_HARPOON(p_port + hp_portctrl_0,
50605c04a7b8SAlexey Dobriyan 			   (SCSI_PORT | DMA_PORT | DMA_RD));
50611da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
50621da177e4SLinus Torvalds 	}
50631da177e4SLinus Torvalds 
5064db038cf8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_page_ctrl, (unsigned char)(i | SCATTER_EN));
50651da177e4SLinus Torvalds 
50661da177e4SLinus Torvalds }
50671da177e4SLinus Torvalds 
50681da177e4SLinus Torvalds /*---------------------------------------------------------------------
50691da177e4SLinus Torvalds  *
50701da177e4SLinus Torvalds  * Function: BusMaster Data Transfer Start
50711da177e4SLinus Torvalds  *
50721da177e4SLinus Torvalds  * Description:
50731da177e4SLinus Torvalds  *
50741da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
50755c04a7b8SAlexey Dobriyan static void FPT_busMstrDataXferStart(unsigned long p_port,
50765c04a7b8SAlexey Dobriyan 				     struct sccb *pcurrSCCB)
50771da177e4SLinus Torvalds {
5078d63a4cccSAlexey Dobriyan 	unsigned long addr, count;
50791da177e4SLinus Torvalds 
50801da177e4SLinus Torvalds 	if (!(pcurrSCCB->Sccb_XferState & F_AUTO_SENSE)) {
50811da177e4SLinus Torvalds 
50821da177e4SLinus Torvalds 		count = pcurrSCCB->Sccb_XferCnt;
50831da177e4SLinus Torvalds 
50845c04a7b8SAlexey Dobriyan 		addr =
50855c04a7b8SAlexey Dobriyan 		    (unsigned long)pcurrSCCB->DataPointer + pcurrSCCB->Sccb_ATC;
50861da177e4SLinus Torvalds 	}
50871da177e4SLinus Torvalds 
50881da177e4SLinus Torvalds 	else {
50891da177e4SLinus Torvalds 		addr = pcurrSCCB->SensePointer;
50901da177e4SLinus Torvalds 		count = pcurrSCCB->RequestSenseLength;
50911da177e4SLinus Torvalds 
50921da177e4SLinus Torvalds 	}
50931da177e4SLinus Torvalds 
50941da177e4SLinus Torvalds 	HP_SETUP_ADDR_CNT(p_port, addr, count);
50951da177e4SLinus Torvalds 
50961da177e4SLinus Torvalds 	if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
50971da177e4SLinus Torvalds 
50985c04a7b8SAlexey Dobriyan 		WR_HARPOON(p_port + hp_portctrl_0,
50995c04a7b8SAlexey Dobriyan 			   (DMA_PORT | SCSI_PORT | SCSI_INBIT));
51001da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
51011da177e4SLinus Torvalds 
51021da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_xfer_cmd,
51031da177e4SLinus Torvalds 			   (XFER_DMA_HOST | XFER_HOST_AUTO | XFER_DMA_8BIT));
51041da177e4SLinus Torvalds 	}
51051da177e4SLinus Torvalds 
51061da177e4SLinus Torvalds 	else {
51071da177e4SLinus Torvalds 
51085c04a7b8SAlexey Dobriyan 		WR_HARPOON(p_port + hp_portctrl_0,
51095c04a7b8SAlexey Dobriyan 			   (SCSI_PORT | DMA_PORT | DMA_RD));
51101da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
51111da177e4SLinus Torvalds 
51121da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_xfer_cmd,
51131da177e4SLinus Torvalds 			   (XFER_HOST_DMA | XFER_HOST_AUTO | XFER_DMA_8BIT));
51141da177e4SLinus Torvalds 
51151da177e4SLinus Torvalds 	}
51161da177e4SLinus Torvalds }
51171da177e4SLinus Torvalds 
51181da177e4SLinus Torvalds /*---------------------------------------------------------------------
51191da177e4SLinus Torvalds  *
51201da177e4SLinus Torvalds  * Function: BusMaster Timeout Handler
51211da177e4SLinus Torvalds  *
51221da177e4SLinus Torvalds  * Description: This function is called after a bus master command busy time
51231da177e4SLinus Torvalds  *               out is detected.  This routines issue halt state machine
51241da177e4SLinus Torvalds  *               with a software time out for command busy.  If command busy
51251da177e4SLinus Torvalds  *               is still asserted at the end of the time out, it issues
51261da177e4SLinus Torvalds  *               hard abort with another software time out.  It hard abort
51271da177e4SLinus Torvalds  *               command busy is also time out, it'll just give up.
51281da177e4SLinus Torvalds  *
51291da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
5130d63a4cccSAlexey Dobriyan static unsigned char FPT_busMstrTimeOut(unsigned long p_port)
51311da177e4SLinus Torvalds {
5132d63a4cccSAlexey Dobriyan 	unsigned long timeout;
51331da177e4SLinus Torvalds 
51341da177e4SLinus Torvalds 	timeout = LONG_WAIT;
51351da177e4SLinus Torvalds 
51361da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_sys_ctrl, HALT_MACH);
51371da177e4SLinus Torvalds 
51385c04a7b8SAlexey Dobriyan 	while ((!(RD_HARPOON(p_port + hp_ext_status) & CMD_ABORTED))
51395c04a7b8SAlexey Dobriyan 	       && timeout--) {
51405c04a7b8SAlexey Dobriyan 	}
51411da177e4SLinus Torvalds 
51421da177e4SLinus Torvalds 	if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
51431da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_sys_ctrl, HARD_ABORT);
51441da177e4SLinus Torvalds 
51451da177e4SLinus Torvalds 		timeout = LONG_WAIT;
51465c04a7b8SAlexey Dobriyan 		while ((RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY)
51475c04a7b8SAlexey Dobriyan 		       && timeout--) {
51485c04a7b8SAlexey Dobriyan 		}
51491da177e4SLinus Torvalds 	}
51501da177e4SLinus Torvalds 
51511da177e4SLinus Torvalds 	RD_HARPOON(p_port + hp_int_status);	/*Clear command complete */
51521da177e4SLinus Torvalds 
51531da177e4SLinus Torvalds 	if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
51545c1b85e2SAlexey Dobriyan 		return 1;
51551da177e4SLinus Torvalds 	}
51561da177e4SLinus Torvalds 
51571da177e4SLinus Torvalds 	else {
51585c1b85e2SAlexey Dobriyan 		return 0;
51591da177e4SLinus Torvalds 	}
51601da177e4SLinus Torvalds }
51611da177e4SLinus Torvalds 
51621da177e4SLinus Torvalds /*---------------------------------------------------------------------
51631da177e4SLinus Torvalds  *
51641da177e4SLinus Torvalds  * Function: Host Data Transfer Abort
51651da177e4SLinus Torvalds  *
51661da177e4SLinus Torvalds  * Description: Abort any in progress transfer.
51671da177e4SLinus Torvalds  *
51681da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
51695c04a7b8SAlexey Dobriyan static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card,
51705c04a7b8SAlexey Dobriyan 				  struct sccb *pCurrSCCB)
51711da177e4SLinus Torvalds {
51721da177e4SLinus Torvalds 
5173d63a4cccSAlexey Dobriyan 	unsigned long timeout;
5174d63a4cccSAlexey Dobriyan 	unsigned long remain_cnt;
5175ce793215SAlexey Dobriyan 	unsigned int sg_ptr;
51761da177e4SLinus Torvalds 
517747b5d69cSJames Bottomley  	FPT_BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT;
51781da177e4SLinus Torvalds 
51791da177e4SLinus Torvalds 	if (pCurrSCCB->Sccb_XferState & F_AUTO_SENSE) {
51801da177e4SLinus Torvalds 
51811da177e4SLinus Torvalds 		if (!(RD_HARPOON(port + hp_int_status) & INT_CMD_COMPL)) {
51821da177e4SLinus Torvalds 
51835c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_bm_ctrl,
51845c04a7b8SAlexey Dobriyan 				   (RD_HARPOON(port + hp_bm_ctrl) |
51855c04a7b8SAlexey Dobriyan 				    FLUSH_XFER_CNTR));
51861da177e4SLinus Torvalds 			timeout = LONG_WAIT;
51871da177e4SLinus Torvalds 
51885c04a7b8SAlexey Dobriyan 			while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
51895c04a7b8SAlexey Dobriyan 			       && timeout--) {
51905c04a7b8SAlexey Dobriyan 			}
51911da177e4SLinus Torvalds 
51925c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_bm_ctrl,
51935c04a7b8SAlexey Dobriyan 				   (RD_HARPOON(port + hp_bm_ctrl) &
51945c04a7b8SAlexey Dobriyan 				    ~FLUSH_XFER_CNTR));
51951da177e4SLinus Torvalds 
51961da177e4SLinus Torvalds 			if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
51971da177e4SLinus Torvalds 
519847b5d69cSJames Bottomley  				if (FPT_busMstrTimeOut(port)) {
51991da177e4SLinus Torvalds 
52001da177e4SLinus Torvalds 					if (pCurrSCCB->HostStatus == 0x00)
52011da177e4SLinus Torvalds 
52025c04a7b8SAlexey Dobriyan 						pCurrSCCB->HostStatus =
52035c04a7b8SAlexey Dobriyan 						    SCCB_BM_ERR;
52041da177e4SLinus Torvalds 
52051da177e4SLinus Torvalds 				}
52061da177e4SLinus Torvalds 
52075c04a7b8SAlexey Dobriyan 				if (RD_HARPOON(port + hp_int_status) &
52085c04a7b8SAlexey Dobriyan 				    INT_EXT_STATUS)
52091da177e4SLinus Torvalds 
52105c04a7b8SAlexey Dobriyan 					if (RD_HARPOON(port + hp_ext_status) &
52115c04a7b8SAlexey Dobriyan 					    BAD_EXT_STATUS)
52121da177e4SLinus Torvalds 
52135c04a7b8SAlexey Dobriyan 						if (pCurrSCCB->HostStatus ==
52145c04a7b8SAlexey Dobriyan 						    0x00)
52151da177e4SLinus Torvalds 						{
52165c04a7b8SAlexey Dobriyan 							pCurrSCCB->HostStatus =
52175c04a7b8SAlexey Dobriyan 							    SCCB_BM_ERR;
52181da177e4SLinus Torvalds 						}
52191da177e4SLinus Torvalds 			}
52201da177e4SLinus Torvalds 		}
52211da177e4SLinus Torvalds 	}
52221da177e4SLinus Torvalds 
52231da177e4SLinus Torvalds 	else if (pCurrSCCB->Sccb_XferCnt) {
52241da177e4SLinus Torvalds 
52251da177e4SLinus Torvalds 		if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
52261da177e4SLinus Torvalds 
52275c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_page_ctrl,
52285c04a7b8SAlexey Dobriyan 				   (RD_HARPOON(port + hp_page_ctrl) &
52291da177e4SLinus Torvalds 				    ~SCATTER_EN));
52301da177e4SLinus Torvalds 
52311da177e4SLinus Torvalds 			WR_HARPOON(port + hp_sg_addr, 0x00);
52321da177e4SLinus Torvalds 
52331da177e4SLinus Torvalds 			sg_ptr = pCurrSCCB->Sccb_sgseg + SG_BUF_CNT;
52341da177e4SLinus Torvalds 
52355c04a7b8SAlexey Dobriyan 			if (sg_ptr >
52365c04a7b8SAlexey Dobriyan 			    (unsigned int)(pCurrSCCB->DataLength /
52375c04a7b8SAlexey Dobriyan 					   SG_ELEMENT_SIZE)) {
52381da177e4SLinus Torvalds 
52395c04a7b8SAlexey Dobriyan 				sg_ptr =
52405c04a7b8SAlexey Dobriyan 				    (unsigned int)(pCurrSCCB->DataLength /
52415c04a7b8SAlexey Dobriyan 						   SG_ELEMENT_SIZE);
52421da177e4SLinus Torvalds 			}
52431da177e4SLinus Torvalds 
52441da177e4SLinus Torvalds 			remain_cnt = pCurrSCCB->Sccb_XferCnt;
52451da177e4SLinus Torvalds 
52461da177e4SLinus Torvalds 			while (remain_cnt < 0x01000000L) {
52471da177e4SLinus Torvalds 
52481da177e4SLinus Torvalds 				sg_ptr--;
52491da177e4SLinus Torvalds 
52505c04a7b8SAlexey Dobriyan 				if (remain_cnt >
52515c04a7b8SAlexey Dobriyan 				    (unsigned
52525c04a7b8SAlexey Dobriyan 				     long)(*(((unsigned long *)pCurrSCCB->
52531da177e4SLinus Torvalds 					      DataPointer) + (sg_ptr * 2)))) {
52541da177e4SLinus Torvalds 
52555c04a7b8SAlexey Dobriyan 					remain_cnt -=
52565c04a7b8SAlexey Dobriyan 					    (unsigned
52575c04a7b8SAlexey Dobriyan 					     long)(*(((unsigned long *)
52585c04a7b8SAlexey Dobriyan 						      pCurrSCCB->DataPointer) +
52595c04a7b8SAlexey Dobriyan 						     (sg_ptr * 2)));
52601da177e4SLinus Torvalds 				}
52611da177e4SLinus Torvalds 
52621da177e4SLinus Torvalds 				else {
52631da177e4SLinus Torvalds 
52641da177e4SLinus Torvalds 					break;
52651da177e4SLinus Torvalds 				}
52661da177e4SLinus Torvalds 			}
52671da177e4SLinus Torvalds 
52681da177e4SLinus Torvalds 			if (remain_cnt < 0x01000000L) {
52691da177e4SLinus Torvalds 
52701da177e4SLinus Torvalds 				pCurrSCCB->Sccb_SGoffset = remain_cnt;
52711da177e4SLinus Torvalds 
5272c823feebSAlexey Dobriyan 				pCurrSCCB->Sccb_sgseg = (unsigned short)sg_ptr;
52731da177e4SLinus Torvalds 
52745c04a7b8SAlexey Dobriyan 				if ((unsigned long)(sg_ptr * SG_ELEMENT_SIZE) ==
52755c04a7b8SAlexey Dobriyan 				    pCurrSCCB->DataLength && (remain_cnt == 0))
52761da177e4SLinus Torvalds 
52775c04a7b8SAlexey Dobriyan 					pCurrSCCB->Sccb_XferState |=
52785c04a7b8SAlexey Dobriyan 					    F_ALL_XFERRED;
52791da177e4SLinus Torvalds 			}
52801da177e4SLinus Torvalds 
52811da177e4SLinus Torvalds 			else {
52821da177e4SLinus Torvalds 
52831da177e4SLinus Torvalds 				if (pCurrSCCB->HostStatus == 0x00) {
52841da177e4SLinus Torvalds 
52855c04a7b8SAlexey Dobriyan 					pCurrSCCB->HostStatus =
52865c04a7b8SAlexey Dobriyan 					    SCCB_GROSS_FW_ERR;
52871da177e4SLinus Torvalds 				}
52881da177e4SLinus Torvalds 			}
52891da177e4SLinus Torvalds 		}
52901da177e4SLinus Torvalds 
52911da177e4SLinus Torvalds 		if (!(pCurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)) {
52921da177e4SLinus Torvalds 
52931da177e4SLinus Torvalds 			if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
52941da177e4SLinus Torvalds 
529547b5d69cSJames Bottomley  				FPT_busMstrTimeOut(port);
52961da177e4SLinus Torvalds 			}
52971da177e4SLinus Torvalds 
52981da177e4SLinus Torvalds 			else {
52991da177e4SLinus Torvalds 
53005c04a7b8SAlexey Dobriyan 				if (RD_HARPOON(port + hp_int_status) &
53015c04a7b8SAlexey Dobriyan 				    INT_EXT_STATUS) {
53021da177e4SLinus Torvalds 
53035c04a7b8SAlexey Dobriyan 					if (RD_HARPOON(port + hp_ext_status) &
53045c04a7b8SAlexey Dobriyan 					    BAD_EXT_STATUS) {
53051da177e4SLinus Torvalds 
53065c04a7b8SAlexey Dobriyan 						if (pCurrSCCB->HostStatus ==
53075c04a7b8SAlexey Dobriyan 						    0x00) {
53081da177e4SLinus Torvalds 
53095c04a7b8SAlexey Dobriyan 							pCurrSCCB->HostStatus =
53105c04a7b8SAlexey Dobriyan 							    SCCB_BM_ERR;
53111da177e4SLinus Torvalds 						}
53121da177e4SLinus Torvalds 					}
53131da177e4SLinus Torvalds 				}
53141da177e4SLinus Torvalds 
53151da177e4SLinus Torvalds 			}
53161da177e4SLinus Torvalds 		}
53171da177e4SLinus Torvalds 
53181da177e4SLinus Torvalds 		else {
53191da177e4SLinus Torvalds 
53201da177e4SLinus Torvalds 			if ((RD_HARPOON(port + hp_fifo_cnt)) >= BM_THRESHOLD) {
53211da177e4SLinus Torvalds 
53221da177e4SLinus Torvalds 				timeout = SHORT_WAIT;
53231da177e4SLinus Torvalds 
53245c04a7b8SAlexey Dobriyan 				while ((RD_HARPOON(port + hp_ext_status) &
53255c04a7b8SAlexey Dobriyan 					BM_CMD_BUSY)
53265c04a7b8SAlexey Dobriyan 				       && ((RD_HARPOON(port + hp_fifo_cnt)) >=
53275c04a7b8SAlexey Dobriyan 					   BM_THRESHOLD) && timeout--) {
53285c04a7b8SAlexey Dobriyan 				}
53291da177e4SLinus Torvalds 			}
53301da177e4SLinus Torvalds 
53311da177e4SLinus Torvalds 			if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
53321da177e4SLinus Torvalds 
53335c04a7b8SAlexey Dobriyan 				WR_HARPOON(port + hp_bm_ctrl,
53345c04a7b8SAlexey Dobriyan 					   (RD_HARPOON(port + hp_bm_ctrl) |
53351da177e4SLinus Torvalds 					    FLUSH_XFER_CNTR));
53361da177e4SLinus Torvalds 
53371da177e4SLinus Torvalds 				timeout = LONG_WAIT;
53381da177e4SLinus Torvalds 
53395c04a7b8SAlexey Dobriyan 				while ((RD_HARPOON(port + hp_ext_status) &
53405c04a7b8SAlexey Dobriyan 					BM_CMD_BUSY) && timeout--) {
53415c04a7b8SAlexey Dobriyan 				}
53421da177e4SLinus Torvalds 
53435c04a7b8SAlexey Dobriyan 				WR_HARPOON(port + hp_bm_ctrl,
53445c04a7b8SAlexey Dobriyan 					   (RD_HARPOON(port + hp_bm_ctrl) &
53451da177e4SLinus Torvalds 					    ~FLUSH_XFER_CNTR));
53461da177e4SLinus Torvalds 
53475c04a7b8SAlexey Dobriyan 				if (RD_HARPOON(port + hp_ext_status) &
53485c04a7b8SAlexey Dobriyan 				    BM_CMD_BUSY) {
53491da177e4SLinus Torvalds 
53501da177e4SLinus Torvalds 					if (pCurrSCCB->HostStatus == 0x00) {
53511da177e4SLinus Torvalds 
53525c04a7b8SAlexey Dobriyan 						pCurrSCCB->HostStatus =
53535c04a7b8SAlexey Dobriyan 						    SCCB_BM_ERR;
53541da177e4SLinus Torvalds 					}
53551da177e4SLinus Torvalds 
535647b5d69cSJames Bottomley  					FPT_busMstrTimeOut(port);
53571da177e4SLinus Torvalds 				}
53581da177e4SLinus Torvalds 			}
53591da177e4SLinus Torvalds 
53601da177e4SLinus Torvalds 			if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
53611da177e4SLinus Torvalds 
53625c04a7b8SAlexey Dobriyan 				if (RD_HARPOON(port + hp_ext_status) &
53635c04a7b8SAlexey Dobriyan 				    BAD_EXT_STATUS) {
53641da177e4SLinus Torvalds 
53651da177e4SLinus Torvalds 					if (pCurrSCCB->HostStatus == 0x00) {
53661da177e4SLinus Torvalds 
53675c04a7b8SAlexey Dobriyan 						pCurrSCCB->HostStatus =
53685c04a7b8SAlexey Dobriyan 						    SCCB_BM_ERR;
53691da177e4SLinus Torvalds 					}
53701da177e4SLinus Torvalds 				}
53711da177e4SLinus Torvalds 			}
53721da177e4SLinus Torvalds 		}
53731da177e4SLinus Torvalds 
53741da177e4SLinus Torvalds 	}
53751da177e4SLinus Torvalds 
53761da177e4SLinus Torvalds 	else {
53771da177e4SLinus Torvalds 
53781da177e4SLinus Torvalds 		if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
53791da177e4SLinus Torvalds 
53801da177e4SLinus Torvalds 			timeout = LONG_WAIT;
53811da177e4SLinus Torvalds 
53825c04a7b8SAlexey Dobriyan 			while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
53835c04a7b8SAlexey Dobriyan 			       && timeout--) {
53845c04a7b8SAlexey Dobriyan 			}
53851da177e4SLinus Torvalds 
53861da177e4SLinus Torvalds 			if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
53871da177e4SLinus Torvalds 
53881da177e4SLinus Torvalds 				if (pCurrSCCB->HostStatus == 0x00) {
53891da177e4SLinus Torvalds 
53901da177e4SLinus Torvalds 					pCurrSCCB->HostStatus = SCCB_BM_ERR;
53911da177e4SLinus Torvalds 				}
53921da177e4SLinus Torvalds 
539347b5d69cSJames Bottomley  				FPT_busMstrTimeOut(port);
53941da177e4SLinus Torvalds 			}
53951da177e4SLinus Torvalds 		}
53961da177e4SLinus Torvalds 
53971da177e4SLinus Torvalds 		if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
53981da177e4SLinus Torvalds 
53991da177e4SLinus Torvalds 			if (RD_HARPOON(port + hp_ext_status) & BAD_EXT_STATUS) {
54001da177e4SLinus Torvalds 
54011da177e4SLinus Torvalds 				if (pCurrSCCB->HostStatus == 0x00) {
54021da177e4SLinus Torvalds 
54031da177e4SLinus Torvalds 					pCurrSCCB->HostStatus = SCCB_BM_ERR;
54041da177e4SLinus Torvalds 				}
54051da177e4SLinus Torvalds 			}
54061da177e4SLinus Torvalds 
54071da177e4SLinus Torvalds 		}
54081da177e4SLinus Torvalds 
54091da177e4SLinus Torvalds 		if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
54101da177e4SLinus Torvalds 
54115c04a7b8SAlexey Dobriyan 			WR_HARPOON(port + hp_page_ctrl,
54125c04a7b8SAlexey Dobriyan 				   (RD_HARPOON(port + hp_page_ctrl) &
54131da177e4SLinus Torvalds 				    ~SCATTER_EN));
54141da177e4SLinus Torvalds 
54151da177e4SLinus Torvalds 			WR_HARPOON(port + hp_sg_addr, 0x00);
54161da177e4SLinus Torvalds 
54171da177e4SLinus Torvalds 			pCurrSCCB->Sccb_sgseg += SG_BUF_CNT;
54181da177e4SLinus Torvalds 
54191da177e4SLinus Torvalds 			pCurrSCCB->Sccb_SGoffset = 0x00;
54201da177e4SLinus Torvalds 
54215c04a7b8SAlexey Dobriyan 			if ((unsigned long)(pCurrSCCB->Sccb_sgseg *
54225c04a7b8SAlexey Dobriyan 					    SG_ELEMENT_SIZE) >=
54231da177e4SLinus Torvalds 			    pCurrSCCB->DataLength) {
54241da177e4SLinus Torvalds 
54251da177e4SLinus Torvalds 				pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
54261da177e4SLinus Torvalds 
54275c04a7b8SAlexey Dobriyan 				pCurrSCCB->Sccb_sgseg =
54285c04a7b8SAlexey Dobriyan 				    (unsigned short)(pCurrSCCB->DataLength /
54295c04a7b8SAlexey Dobriyan 						     SG_ELEMENT_SIZE);
54301da177e4SLinus Torvalds 
54311da177e4SLinus Torvalds 			}
54321da177e4SLinus Torvalds 		}
54331da177e4SLinus Torvalds 
54341da177e4SLinus Torvalds 		else {
54351da177e4SLinus Torvalds 
54361da177e4SLinus Torvalds 			if (!(pCurrSCCB->Sccb_XferState & F_AUTO_SENSE))
54371da177e4SLinus Torvalds 
54381da177e4SLinus Torvalds 				pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
54391da177e4SLinus Torvalds 		}
54401da177e4SLinus Torvalds 	}
54411da177e4SLinus Torvalds 
54421da177e4SLinus Torvalds 	WR_HARPOON(port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
54431da177e4SLinus Torvalds }
54441da177e4SLinus Torvalds 
54451da177e4SLinus Torvalds /*---------------------------------------------------------------------
54461da177e4SLinus Torvalds  *
54471da177e4SLinus Torvalds  * Function: Host Data Transfer Restart
54481da177e4SLinus Torvalds  *
54491da177e4SLinus Torvalds  * Description: Reset the available count due to a restore data
54501da177e4SLinus Torvalds  *              pointers message.
54511da177e4SLinus Torvalds  *
54521da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
545369eb2ea4SAlexey Dobriyan static void FPT_hostDataXferRestart(struct sccb *currSCCB)
54541da177e4SLinus Torvalds {
5455d63a4cccSAlexey Dobriyan 	unsigned long data_count;
5456ce793215SAlexey Dobriyan 	unsigned int sg_index;
5457d63a4cccSAlexey Dobriyan 	unsigned long *sg_ptr;
54581da177e4SLinus Torvalds 
54591da177e4SLinus Torvalds 	if (currSCCB->Sccb_XferState & F_SG_XFER) {
54601da177e4SLinus Torvalds 
54611da177e4SLinus Torvalds 		currSCCB->Sccb_XferCnt = 0;
54621da177e4SLinus Torvalds 
54631da177e4SLinus Torvalds 		sg_index = 0xffff;	/*Index by long words into sg list. */
54641da177e4SLinus Torvalds 		data_count = 0;	/*Running count of SG xfer counts. */
54651da177e4SLinus Torvalds 
5466d63a4cccSAlexey Dobriyan 		sg_ptr = (unsigned long *)currSCCB->DataPointer;
54671da177e4SLinus Torvalds 
54681da177e4SLinus Torvalds 		while (data_count < currSCCB->Sccb_ATC) {
54691da177e4SLinus Torvalds 
54701da177e4SLinus Torvalds 			sg_index++;
54711da177e4SLinus Torvalds 			data_count += *(sg_ptr + (sg_index * 2));
54721da177e4SLinus Torvalds 		}
54731da177e4SLinus Torvalds 
54741da177e4SLinus Torvalds 		if (data_count == currSCCB->Sccb_ATC) {
54751da177e4SLinus Torvalds 
54761da177e4SLinus Torvalds 			currSCCB->Sccb_SGoffset = 0;
54771da177e4SLinus Torvalds 			sg_index++;
54781da177e4SLinus Torvalds 		}
54791da177e4SLinus Torvalds 
54801da177e4SLinus Torvalds 		else {
54815c04a7b8SAlexey Dobriyan 			currSCCB->Sccb_SGoffset =
54825c04a7b8SAlexey Dobriyan 			    data_count - currSCCB->Sccb_ATC;
54831da177e4SLinus Torvalds 		}
54841da177e4SLinus Torvalds 
5485c823feebSAlexey Dobriyan 		currSCCB->Sccb_sgseg = (unsigned short)sg_index;
54861da177e4SLinus Torvalds 	}
54871da177e4SLinus Torvalds 
54881da177e4SLinus Torvalds 	else {
54895c04a7b8SAlexey Dobriyan 		currSCCB->Sccb_XferCnt =
54905c04a7b8SAlexey Dobriyan 		    currSCCB->DataLength - currSCCB->Sccb_ATC;
54911da177e4SLinus Torvalds 	}
54921da177e4SLinus Torvalds }
54931da177e4SLinus Torvalds 
54941da177e4SLinus Torvalds /*---------------------------------------------------------------------
54951da177e4SLinus Torvalds  *
549647b5d69cSJames Bottomley   * Function: FPT_scini
54971da177e4SLinus Torvalds  *
54981da177e4SLinus Torvalds  * Description: Setup all data structures necessary for SCAM selection.
54991da177e4SLinus Torvalds  *
55001da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
55011da177e4SLinus Torvalds 
55025c04a7b8SAlexey Dobriyan static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
55035c04a7b8SAlexey Dobriyan 		      unsigned char p_power_up)
55041da177e4SLinus Torvalds {
55051da177e4SLinus Torvalds 
5506db038cf8SAlexey Dobriyan 	unsigned char loser, assigned_id;
5507d63a4cccSAlexey Dobriyan 	unsigned long p_port;
55081da177e4SLinus Torvalds 
5509db038cf8SAlexey Dobriyan 	unsigned char i, k, ScamFlg;
551013e6851aSAlexey Dobriyan 	struct sccb_card *currCard;
551168d0c1aeSAlexey Dobriyan 	struct nvram_info *pCurrNvRam;
55121da177e4SLinus Torvalds 
551347b5d69cSJames Bottomley  	currCard = &FPT_BL_Card[p_card];
55141da177e4SLinus Torvalds 	p_port = currCard->ioPort;
55151da177e4SLinus Torvalds 	pCurrNvRam = currCard->pNvRamInfo;
55161da177e4SLinus Torvalds 
55171da177e4SLinus Torvalds 	if (pCurrNvRam) {
55181da177e4SLinus Torvalds 		ScamFlg = pCurrNvRam->niScamConf;
55191da177e4SLinus Torvalds 		i = pCurrNvRam->niSysConf;
55205c04a7b8SAlexey Dobriyan 	} else {
55215c04a7b8SAlexey Dobriyan 		ScamFlg =
55225c04a7b8SAlexey Dobriyan 		    (unsigned char)FPT_utilEERead(p_port, SCAM_CONFIG / 2);
55235c04a7b8SAlexey Dobriyan 		i = (unsigned
55245c04a7b8SAlexey Dobriyan 		     char)(FPT_utilEERead(p_port, (SYSTEM_CONFIG / 2)));
55251da177e4SLinus Torvalds 	}
55261da177e4SLinus Torvalds 	if (!(i & 0x02))	/* check if reset bus in AutoSCSI parameter set */
55271da177e4SLinus Torvalds 		return;
55281da177e4SLinus Torvalds 
552947b5d69cSJames Bottomley  	FPT_inisci(p_card, p_port, p_our_id);
55301da177e4SLinus Torvalds 
55311da177e4SLinus Torvalds 	/* Force to wait 1 sec after SCSI bus reset. Some SCAM device FW
55321da177e4SLinus Torvalds 	   too slow to return to SCAM selection */
55331da177e4SLinus Torvalds 
55341da177e4SLinus Torvalds 	/* if (p_power_up)
553547b5d69cSJames Bottomley  	   FPT_Wait1Second(p_port);
55361da177e4SLinus Torvalds 	   else
553747b5d69cSJames Bottomley  	   FPT_Wait(p_port, TO_250ms); */
55381da177e4SLinus Torvalds 
553947b5d69cSJames Bottomley  	FPT_Wait1Second(p_port);
55401da177e4SLinus Torvalds 
55415c04a7b8SAlexey Dobriyan 	if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2)) {
55425c04a7b8SAlexey Dobriyan 		while (!(FPT_scarb(p_port, INIT_SELTD))) {
55435c04a7b8SAlexey Dobriyan 		}
55441da177e4SLinus Torvalds 
554547b5d69cSJames Bottomley  		FPT_scsel(p_port);
55461da177e4SLinus Torvalds 
55471da177e4SLinus Torvalds 		do {
554847b5d69cSJames Bottomley  			FPT_scxferc(p_port, SYNC_PTRN);
554947b5d69cSJames Bottomley  			FPT_scxferc(p_port, DOM_MSTR);
55505c04a7b8SAlexey Dobriyan 			loser =
55515c04a7b8SAlexey Dobriyan 			    FPT_scsendi(p_port,
55525c04a7b8SAlexey Dobriyan 					&FPT_scamInfo[p_our_id].id_string[0]);
55531da177e4SLinus Torvalds 		} while (loser == 0xFF);
55541da177e4SLinus Torvalds 
555547b5d69cSJames Bottomley  		FPT_scbusf(p_port);
55561da177e4SLinus Torvalds 
55575c04a7b8SAlexey Dobriyan 		if ((p_power_up) && (!loser)) {
555847b5d69cSJames Bottomley  			FPT_sresb(p_port, p_card);
555947b5d69cSJames Bottomley  			FPT_Wait(p_port, TO_250ms);
55601da177e4SLinus Torvalds 
55615c04a7b8SAlexey Dobriyan 			while (!(FPT_scarb(p_port, INIT_SELTD))) {
55625c04a7b8SAlexey Dobriyan 			}
55631da177e4SLinus Torvalds 
556447b5d69cSJames Bottomley  			FPT_scsel(p_port);
55651da177e4SLinus Torvalds 
55661da177e4SLinus Torvalds 			do {
556747b5d69cSJames Bottomley  				FPT_scxferc(p_port, SYNC_PTRN);
556847b5d69cSJames Bottomley  				FPT_scxferc(p_port, DOM_MSTR);
55695c04a7b8SAlexey Dobriyan 				loser =
55705c04a7b8SAlexey Dobriyan 				    FPT_scsendi(p_port,
55715c04a7b8SAlexey Dobriyan 						&FPT_scamInfo[p_our_id].
55721da177e4SLinus Torvalds 						id_string[0]);
55731da177e4SLinus Torvalds 			} while (loser == 0xFF);
55741da177e4SLinus Torvalds 
557547b5d69cSJames Bottomley  			FPT_scbusf(p_port);
55761da177e4SLinus Torvalds 		}
55771da177e4SLinus Torvalds 	}
55781da177e4SLinus Torvalds 
55795c04a7b8SAlexey Dobriyan 	else {
558047b5d69cSJames Bottomley  		loser = 0;
55811da177e4SLinus Torvalds 	}
55821da177e4SLinus Torvalds 
55835c04a7b8SAlexey Dobriyan 	if (!loser) {
55841da177e4SLinus Torvalds 
558547b5d69cSJames Bottomley  		FPT_scamInfo[p_our_id].state = ID_ASSIGNED;
55861da177e4SLinus Torvalds 
55875c04a7b8SAlexey Dobriyan 		if (ScamFlg & SCAM_ENABLED) {
55881da177e4SLinus Torvalds 
55895c04a7b8SAlexey Dobriyan 			for (i = 0; i < MAX_SCSI_TAR; i++) {
559047b5d69cSJames Bottomley  				if ((FPT_scamInfo[i].state == ID_UNASSIGNED) ||
55915c04a7b8SAlexey Dobriyan 				    (FPT_scamInfo[i].state == ID_UNUSED)) {
55925c04a7b8SAlexey Dobriyan 					if (FPT_scsell(p_port, i)) {
559347b5d69cSJames Bottomley  						FPT_scamInfo[i].state = LEGACY;
55945c04a7b8SAlexey Dobriyan 						if ((FPT_scamInfo[i].
55955c04a7b8SAlexey Dobriyan 						     id_string[0] != 0xFF)
55965c04a7b8SAlexey Dobriyan 						    || (FPT_scamInfo[i].
55975c04a7b8SAlexey Dobriyan 							id_string[1] != 0xFA)) {
55981da177e4SLinus Torvalds 
55995c04a7b8SAlexey Dobriyan 							FPT_scamInfo[i].
56005c04a7b8SAlexey Dobriyan 							    id_string[0] = 0xFF;
56015c04a7b8SAlexey Dobriyan 							FPT_scamInfo[i].
56025c04a7b8SAlexey Dobriyan 							    id_string[1] = 0xFA;
56031da177e4SLinus Torvalds 							if (pCurrNvRam == NULL)
56045c04a7b8SAlexey Dobriyan 								currCard->
56055c04a7b8SAlexey Dobriyan 								    globalFlags
56065c04a7b8SAlexey Dobriyan 								    |=
56075c04a7b8SAlexey Dobriyan 								    F_UPDATE_EEPROM;
56081da177e4SLinus Torvalds 						}
56091da177e4SLinus Torvalds 					}
56101da177e4SLinus Torvalds 				}
56111da177e4SLinus Torvalds 			}
56121da177e4SLinus Torvalds 
561347b5d69cSJames Bottomley  			FPT_sresb(p_port, p_card);
561447b5d69cSJames Bottomley  			FPT_Wait1Second(p_port);
56155c04a7b8SAlexey Dobriyan 			while (!(FPT_scarb(p_port, INIT_SELTD))) {
56165c04a7b8SAlexey Dobriyan 			}
561747b5d69cSJames Bottomley  			FPT_scsel(p_port);
561847b5d69cSJames Bottomley  			FPT_scasid(p_card, p_port);
56191da177e4SLinus Torvalds 		}
56201da177e4SLinus Torvalds 
56211da177e4SLinus Torvalds 	}
56221da177e4SLinus Torvalds 
56235c04a7b8SAlexey Dobriyan 	else if ((loser) && (ScamFlg & SCAM_ENABLED)) {
562447b5d69cSJames Bottomley  		FPT_scamInfo[p_our_id].id_string[0] = SLV_TYPE_CODE0;
562547b5d69cSJames Bottomley  		assigned_id = 0;
562647b5d69cSJames Bottomley  		FPT_scwtsel(p_port);
56271da177e4SLinus Torvalds 
56281da177e4SLinus Torvalds 		do {
56295c04a7b8SAlexey Dobriyan 			while (FPT_scxferc(p_port, 0x00) != SYNC_PTRN) {
56305c04a7b8SAlexey Dobriyan 			}
56311da177e4SLinus Torvalds 
563247b5d69cSJames Bottomley  			i = FPT_scxferc(p_port, 0x00);
56335c04a7b8SAlexey Dobriyan 			if (i == ASSIGN_ID) {
56345c04a7b8SAlexey Dobriyan 				if (!
56355c04a7b8SAlexey Dobriyan 				    (FPT_scsendi
56365c04a7b8SAlexey Dobriyan 				     (p_port,
56375c04a7b8SAlexey Dobriyan 				      &FPT_scamInfo[p_our_id].id_string[0]))) {
563847b5d69cSJames Bottomley  					i = FPT_scxferc(p_port, 0x00);
56395c04a7b8SAlexey Dobriyan 					if (FPT_scvalq(i)) {
564047b5d69cSJames Bottomley  						k = FPT_scxferc(p_port, 0x00);
56411da177e4SLinus Torvalds 
56425c04a7b8SAlexey Dobriyan 						if (FPT_scvalq(k)) {
56431da177e4SLinus Torvalds 							currCard->ourId =
56445c04a7b8SAlexey Dobriyan 							    ((unsigned char)(i
56455c04a7b8SAlexey Dobriyan 									     <<
56465c04a7b8SAlexey Dobriyan 									     3)
56475c04a7b8SAlexey Dobriyan 							     +
56485c04a7b8SAlexey Dobriyan 							     (k &
56495c04a7b8SAlexey Dobriyan 							      (unsigned char)7))
56505c04a7b8SAlexey Dobriyan 							    & (unsigned char)
56515c04a7b8SAlexey Dobriyan 							    0x3F;
56525c04a7b8SAlexey Dobriyan 							FPT_inisci(p_card,
56535c04a7b8SAlexey Dobriyan 								   p_port,
56545c04a7b8SAlexey Dobriyan 								   p_our_id);
56555c04a7b8SAlexey Dobriyan 							FPT_scamInfo[currCard->
56565c04a7b8SAlexey Dobriyan 								     ourId].
56575c04a7b8SAlexey Dobriyan 							    state = ID_ASSIGNED;
56585c04a7b8SAlexey Dobriyan 							FPT_scamInfo[currCard->
56595c04a7b8SAlexey Dobriyan 								     ourId].
56605c04a7b8SAlexey Dobriyan 							    id_string[0]
56611da177e4SLinus Torvalds 							    = SLV_TYPE_CODE0;
566247b5d69cSJames Bottomley  							assigned_id = 1;
56631da177e4SLinus Torvalds 						}
56641da177e4SLinus Torvalds 					}
56651da177e4SLinus Torvalds 				}
56661da177e4SLinus Torvalds 			}
56671da177e4SLinus Torvalds 
56685c04a7b8SAlexey Dobriyan 			else if (i == SET_P_FLAG) {
566947b5d69cSJames Bottomley  				if (!(FPT_scsendi(p_port,
56705c04a7b8SAlexey Dobriyan 						  &FPT_scamInfo[p_our_id].
56715c04a7b8SAlexey Dobriyan 						  id_string[0])))
56725c04a7b8SAlexey Dobriyan 					FPT_scamInfo[p_our_id].id_string[0] |=
56735c04a7b8SAlexey Dobriyan 					    0x80;
56741da177e4SLinus Torvalds 			}
56751da177e4SLinus Torvalds 		} while (!assigned_id);
56761da177e4SLinus Torvalds 
56775c04a7b8SAlexey Dobriyan 		while (FPT_scxferc(p_port, 0x00) != CFG_CMPLT) {
56785c04a7b8SAlexey Dobriyan 		}
56791da177e4SLinus Torvalds 	}
56801da177e4SLinus Torvalds 
56815c04a7b8SAlexey Dobriyan 	if (ScamFlg & SCAM_ENABLED) {
568247b5d69cSJames Bottomley  		FPT_scbusf(p_port);
56835c04a7b8SAlexey Dobriyan 		if (currCard->globalFlags & F_UPDATE_EEPROM) {
568447b5d69cSJames Bottomley  			FPT_scsavdi(p_card, p_port);
56851da177e4SLinus Torvalds 			currCard->globalFlags &= ~F_UPDATE_EEPROM;
56861da177e4SLinus Torvalds 		}
56871da177e4SLinus Torvalds 	}
56881da177e4SLinus Torvalds 
56891da177e4SLinus Torvalds /*
56901da177e4SLinus Torvalds    for (i=0,k=0; i < MAX_SCSI_TAR; i++)
56911da177e4SLinus Torvalds       {
569247b5d69cSJames Bottomley        if ((FPT_scamInfo[i].state == ID_ASSIGNED) ||
569347b5d69cSJames Bottomley           (FPT_scamInfo[i].state == LEGACY))
56941da177e4SLinus Torvalds          k++;
56951da177e4SLinus Torvalds       }
56961da177e4SLinus Torvalds 
56971da177e4SLinus Torvalds    if (k==2)
56981da177e4SLinus Torvalds       currCard->globalFlags |= F_SINGLE_DEVICE;
56991da177e4SLinus Torvalds    else
57001da177e4SLinus Torvalds       currCard->globalFlags &= ~F_SINGLE_DEVICE;
57011da177e4SLinus Torvalds */
57021da177e4SLinus Torvalds }
57031da177e4SLinus Torvalds 
57041da177e4SLinus Torvalds /*---------------------------------------------------------------------
57051da177e4SLinus Torvalds  *
570647b5d69cSJames Bottomley   * Function: FPT_scarb
57071da177e4SLinus Torvalds  *
57081da177e4SLinus Torvalds  * Description: Gain control of the bus and wait SCAM select time (250ms)
57091da177e4SLinus Torvalds  *
57101da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
57111da177e4SLinus Torvalds 
5712d63a4cccSAlexey Dobriyan static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type)
57131da177e4SLinus Torvalds {
57145c04a7b8SAlexey Dobriyan 	if (p_sel_type == INIT_SELTD) {
57151da177e4SLinus Torvalds 
57165c04a7b8SAlexey Dobriyan 		while (RD_HARPOON(p_port + hp_scsisig) & (SCSI_SEL | SCSI_BSY)) {
57175c04a7b8SAlexey Dobriyan 		}
57181da177e4SLinus Torvalds 
57191da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL)
57205c1b85e2SAlexey Dobriyan 			return 0;
57211da177e4SLinus Torvalds 
57221da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_scsidata_0) != 00)
57235c1b85e2SAlexey Dobriyan 			return 0;
57241da177e4SLinus Torvalds 
57255c04a7b8SAlexey Dobriyan 		WR_HARPOON(p_port + hp_scsisig,
57265c04a7b8SAlexey Dobriyan 			   (RD_HARPOON(p_port + hp_scsisig) | SCSI_BSY));
57271da177e4SLinus Torvalds 
57281da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL) {
57291da177e4SLinus Torvalds 
57305c04a7b8SAlexey Dobriyan 			WR_HARPOON(p_port + hp_scsisig,
57315c04a7b8SAlexey Dobriyan 				   (RD_HARPOON(p_port + hp_scsisig) &
57321da177e4SLinus Torvalds 				    ~SCSI_BSY));
57335c1b85e2SAlexey Dobriyan 			return 0;
57341da177e4SLinus Torvalds 		}
57351da177e4SLinus Torvalds 
57365c04a7b8SAlexey Dobriyan 		WR_HARPOON(p_port + hp_scsisig,
57375c04a7b8SAlexey Dobriyan 			   (RD_HARPOON(p_port + hp_scsisig) | SCSI_SEL));
57381da177e4SLinus Torvalds 
57391da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_scsidata_0) != 00) {
57401da177e4SLinus Torvalds 
57415c04a7b8SAlexey Dobriyan 			WR_HARPOON(p_port + hp_scsisig,
57425c04a7b8SAlexey Dobriyan 				   (RD_HARPOON(p_port + hp_scsisig) &
57431da177e4SLinus Torvalds 				    ~(SCSI_BSY | SCSI_SEL)));
57445c1b85e2SAlexey Dobriyan 			return 0;
57451da177e4SLinus Torvalds 		}
57461da177e4SLinus Torvalds 	}
57471da177e4SLinus Torvalds 
57481da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
57491da177e4SLinus Torvalds 					   & ~ACTdeassert));
57501da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsireset, SCAM_EN);
57511da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_0, 0x00);
57521da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_1, 0x00);
57531da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_portctrl_0, SCSI_BUS_EN);
57541da177e4SLinus Torvalds 
57555c04a7b8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_scsisig,
57565c04a7b8SAlexey Dobriyan 		   (RD_HARPOON(p_port + hp_scsisig) | SCSI_MSG));
57571da177e4SLinus Torvalds 
57581da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsisig, (RD_HARPOON(p_port + hp_scsisig)
57591da177e4SLinus Torvalds 					 & ~SCSI_BSY));
57601da177e4SLinus Torvalds 
576147b5d69cSJames Bottomley  	FPT_Wait(p_port, TO_250ms);
57621da177e4SLinus Torvalds 
57635c1b85e2SAlexey Dobriyan 	return 1;
57641da177e4SLinus Torvalds }
57651da177e4SLinus Torvalds 
57661da177e4SLinus Torvalds /*---------------------------------------------------------------------
57671da177e4SLinus Torvalds  *
576847b5d69cSJames Bottomley   * Function: FPT_scbusf
57691da177e4SLinus Torvalds  *
57701da177e4SLinus Torvalds  * Description: Release the SCSI bus and disable SCAM selection.
57711da177e4SLinus Torvalds  *
57721da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
57731da177e4SLinus Torvalds 
5774d63a4cccSAlexey Dobriyan static void FPT_scbusf(unsigned long p_port)
57751da177e4SLinus Torvalds {
57761da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_page_ctrl,
57771da177e4SLinus Torvalds 		   (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
57781da177e4SLinus Torvalds 
57791da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_0, 0x00);
57801da177e4SLinus Torvalds 
57811da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_portctrl_0, (RD_HARPOON(p_port + hp_portctrl_0)
57821da177e4SLinus Torvalds 					    & ~SCSI_BUS_EN));
57831da177e4SLinus Torvalds 
57841da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsisig, 0x00);
57851da177e4SLinus Torvalds 
57861da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsireset, (RD_HARPOON(p_port + hp_scsireset)
57871da177e4SLinus Torvalds 					   & ~SCAM_EN));
57881da177e4SLinus Torvalds 
57891da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
57901da177e4SLinus Torvalds 					   | ACTdeassert));
57911da177e4SLinus Torvalds 
57921da177e4SLinus Torvalds 	WRW_HARPOON((p_port + hp_intstat), (BUS_FREE | AUTO_INT | SCAM_SEL));
57931da177e4SLinus Torvalds 
57941da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_page_ctrl,
57951da177e4SLinus Torvalds 		   (RD_HARPOON(p_port + hp_page_ctrl) & ~G_INT_DISABLE));
57961da177e4SLinus Torvalds }
57971da177e4SLinus Torvalds 
57981da177e4SLinus Torvalds /*---------------------------------------------------------------------
57991da177e4SLinus Torvalds  *
580047b5d69cSJames Bottomley   * Function: FPT_scasid
58011da177e4SLinus Torvalds  *
58021da177e4SLinus Torvalds  * Description: Assign an ID to all the SCAM devices.
58031da177e4SLinus Torvalds  *
58041da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
58051da177e4SLinus Torvalds 
5806d63a4cccSAlexey Dobriyan static void FPT_scasid(unsigned char p_card, unsigned long p_port)
58071da177e4SLinus Torvalds {
5808db038cf8SAlexey Dobriyan 	unsigned char temp_id_string[ID_STRING_LENGTH];
58091da177e4SLinus Torvalds 
5810db038cf8SAlexey Dobriyan 	unsigned char i, k, scam_id;
5811db038cf8SAlexey Dobriyan 	unsigned char crcBytes[3];
581268d0c1aeSAlexey Dobriyan 	struct nvram_info *pCurrNvRam;
5813fd1e29edSAlexey Dobriyan 	unsigned short *pCrcBytes;
58141da177e4SLinus Torvalds 
581547b5d69cSJames Bottomley  	pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
58161da177e4SLinus Torvalds 
581747b5d69cSJames Bottomley  	i = 0;
58181da177e4SLinus Torvalds 
58195c04a7b8SAlexey Dobriyan 	while (!i) {
58201da177e4SLinus Torvalds 
58215c04a7b8SAlexey Dobriyan 		for (k = 0; k < ID_STRING_LENGTH; k++) {
5822db038cf8SAlexey Dobriyan 			temp_id_string[k] = (unsigned char)0x00;
58231da177e4SLinus Torvalds 		}
58241da177e4SLinus Torvalds 
582547b5d69cSJames Bottomley  		FPT_scxferc(p_port, SYNC_PTRN);
582647b5d69cSJames Bottomley  		FPT_scxferc(p_port, ASSIGN_ID);
58271da177e4SLinus Torvalds 
58285c04a7b8SAlexey Dobriyan 		if (!(FPT_sciso(p_port, &temp_id_string[0]))) {
58291da177e4SLinus Torvalds 			if (pCurrNvRam) {
5830fd1e29edSAlexey Dobriyan 				pCrcBytes = (unsigned short *)&crcBytes[0];
583147b5d69cSJames Bottomley  				*pCrcBytes = FPT_CalcCrc16(&temp_id_string[0]);
583247b5d69cSJames Bottomley  				crcBytes[2] = FPT_CalcLrc(&temp_id_string[0]);
58331da177e4SLinus Torvalds 				temp_id_string[1] = crcBytes[2];
58341da177e4SLinus Torvalds 				temp_id_string[2] = crcBytes[0];
58351da177e4SLinus Torvalds 				temp_id_string[3] = crcBytes[1];
58361da177e4SLinus Torvalds 				for (k = 4; k < ID_STRING_LENGTH; k++)
5837db038cf8SAlexey Dobriyan 					temp_id_string[k] = (unsigned char)0x00;
58381da177e4SLinus Torvalds 			}
583947b5d69cSJames Bottomley  			i = FPT_scmachid(p_card, temp_id_string);
58401da177e4SLinus Torvalds 
58415c04a7b8SAlexey Dobriyan 			if (i == CLR_PRIORITY) {
584247b5d69cSJames Bottomley  				FPT_scxferc(p_port, MISC_CODE);
584347b5d69cSJames Bottomley  				FPT_scxferc(p_port, CLR_P_FLAG);
584447b5d69cSJames Bottomley  				i = 0;	/*Not the last ID yet. */
58451da177e4SLinus Torvalds 			}
58461da177e4SLinus Torvalds 
58475c04a7b8SAlexey Dobriyan 			else if (i != NO_ID_AVAIL) {
58481da177e4SLinus Torvalds 				if (i < 8)
584947b5d69cSJames Bottomley  					FPT_scxferc(p_port, ID_0_7);
58501da177e4SLinus Torvalds 				else
585147b5d69cSJames Bottomley  					FPT_scxferc(p_port, ID_8_F);
58521da177e4SLinus Torvalds 
5853db038cf8SAlexey Dobriyan 				scam_id = (i & (unsigned char)0x07);
58541da177e4SLinus Torvalds 
58551da177e4SLinus Torvalds 				for (k = 1; k < 0x08; k <<= 1)
58561da177e4SLinus Torvalds 					if (!(k & i))
58571da177e4SLinus Torvalds 						scam_id += 0x08;	/*Count number of zeros in DB0-3. */
58581da177e4SLinus Torvalds 
585947b5d69cSJames Bottomley  				FPT_scxferc(p_port, scam_id);
58601da177e4SLinus Torvalds 
586147b5d69cSJames Bottomley  				i = 0;	/*Not the last ID yet. */
58621da177e4SLinus Torvalds 			}
58631da177e4SLinus Torvalds 		}
58641da177e4SLinus Torvalds 
58655c04a7b8SAlexey Dobriyan 		else {
586647b5d69cSJames Bottomley  			i = 1;
58671da177e4SLinus Torvalds 		}
58681da177e4SLinus Torvalds 
58691da177e4SLinus Torvalds 	}			/*End while */
58701da177e4SLinus Torvalds 
587147b5d69cSJames Bottomley  	FPT_scxferc(p_port, SYNC_PTRN);
587247b5d69cSJames Bottomley  	FPT_scxferc(p_port, CFG_CMPLT);
58731da177e4SLinus Torvalds }
58741da177e4SLinus Torvalds 
58751da177e4SLinus Torvalds /*---------------------------------------------------------------------
58761da177e4SLinus Torvalds  *
587747b5d69cSJames Bottomley   * Function: FPT_scsel
58781da177e4SLinus Torvalds  *
58791da177e4SLinus Torvalds  * Description: Select all the SCAM devices.
58801da177e4SLinus Torvalds  *
58811da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
58821da177e4SLinus Torvalds 
5883d63a4cccSAlexey Dobriyan static void FPT_scsel(unsigned long p_port)
58841da177e4SLinus Torvalds {
58851da177e4SLinus Torvalds 
58861da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsisig, SCSI_SEL);
588747b5d69cSJames Bottomley  	FPT_scwiros(p_port, SCSI_MSG);
58881da177e4SLinus Torvalds 
58891da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsisig, (SCSI_SEL | SCSI_BSY));
58901da177e4SLinus Torvalds 
58915c04a7b8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_scsisig,
58925c04a7b8SAlexey Dobriyan 		   (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
58935c04a7b8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_scsidata_0,
58945c04a7b8SAlexey Dobriyan 		   (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) |
5895db038cf8SAlexey Dobriyan 				   (unsigned char)(BIT(7) + BIT(6))));
58961da177e4SLinus Torvalds 
58971da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsisig, (SCSI_BSY | SCSI_IOBIT | SCSI_CD));
589847b5d69cSJames Bottomley  	FPT_scwiros(p_port, SCSI_SEL);
58991da177e4SLinus Torvalds 
59005c04a7b8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_scsidata_0,
59015c04a7b8SAlexey Dobriyan 		   (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) &
5902db038cf8SAlexey Dobriyan 				   ~(unsigned char)BIT(6)));
590347b5d69cSJames Bottomley  	FPT_scwirod(p_port, BIT(6));
59041da177e4SLinus Torvalds 
59055c04a7b8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_scsisig,
59065c04a7b8SAlexey Dobriyan 		   (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
59071da177e4SLinus Torvalds }
59081da177e4SLinus Torvalds 
59091da177e4SLinus Torvalds /*---------------------------------------------------------------------
59101da177e4SLinus Torvalds  *
591147b5d69cSJames Bottomley   * Function: FPT_scxferc
59121da177e4SLinus Torvalds  *
59131da177e4SLinus Torvalds  * Description: Handshake the p_data (DB4-0) across the bus.
59141da177e4SLinus Torvalds  *
59151da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
59161da177e4SLinus Torvalds 
5917d63a4cccSAlexey Dobriyan static unsigned char FPT_scxferc(unsigned long p_port, unsigned char p_data)
59181da177e4SLinus Torvalds {
5919db038cf8SAlexey Dobriyan 	unsigned char curr_data, ret_data;
59201da177e4SLinus Torvalds 
59211da177e4SLinus Torvalds 	curr_data = p_data | BIT(7) | BIT(5);	/*Start with DB7 & DB5 asserted. */
59221da177e4SLinus Torvalds 
59231da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
59241da177e4SLinus Torvalds 
59251da177e4SLinus Torvalds 	curr_data &= ~BIT(7);
59261da177e4SLinus Torvalds 
59271da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
59281da177e4SLinus Torvalds 
592947b5d69cSJames Bottomley  	FPT_scwirod(p_port, BIT(7));	/*Wait for DB7 to be released. */
59301da177e4SLinus Torvalds 	while (!(RD_HARPOON(p_port + hp_scsidata_0) & BIT(5))) ;
59311da177e4SLinus Torvalds 
5932db038cf8SAlexey Dobriyan 	ret_data = (RD_HARPOON(p_port + hp_scsidata_0) & (unsigned char)0x1F);
59331da177e4SLinus Torvalds 
59341da177e4SLinus Torvalds 	curr_data |= BIT(6);
59351da177e4SLinus Torvalds 
59361da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
59371da177e4SLinus Torvalds 
59381da177e4SLinus Torvalds 	curr_data &= ~BIT(5);
59391da177e4SLinus Torvalds 
59401da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
59411da177e4SLinus Torvalds 
594247b5d69cSJames Bottomley  	FPT_scwirod(p_port, BIT(5));	/*Wait for DB5 to be released. */
59431da177e4SLinus Torvalds 
59441da177e4SLinus Torvalds 	curr_data &= ~(BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));	/*Release data bits */
59451da177e4SLinus Torvalds 	curr_data |= BIT(7);
59461da177e4SLinus Torvalds 
59471da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
59481da177e4SLinus Torvalds 
59491da177e4SLinus Torvalds 	curr_data &= ~BIT(6);
59501da177e4SLinus Torvalds 
59511da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
59521da177e4SLinus Torvalds 
595347b5d69cSJames Bottomley  	FPT_scwirod(p_port, BIT(6));	/*Wait for DB6 to be released. */
59541da177e4SLinus Torvalds 
59555c1b85e2SAlexey Dobriyan 	return ret_data;
59561da177e4SLinus Torvalds }
59571da177e4SLinus Torvalds 
59581da177e4SLinus Torvalds /*---------------------------------------------------------------------
59591da177e4SLinus Torvalds  *
596047b5d69cSJames Bottomley   * Function: FPT_scsendi
59611da177e4SLinus Torvalds  *
59621da177e4SLinus Torvalds  * Description: Transfer our Identification string to determine if we
59631da177e4SLinus Torvalds  *              will be the dominant master.
59641da177e4SLinus Torvalds  *
59651da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
59661da177e4SLinus Torvalds 
59675c04a7b8SAlexey Dobriyan static unsigned char FPT_scsendi(unsigned long p_port,
59685c04a7b8SAlexey Dobriyan 				 unsigned char p_id_string[])
59691da177e4SLinus Torvalds {
5970db038cf8SAlexey Dobriyan 	unsigned char ret_data, byte_cnt, bit_cnt, defer;
59711da177e4SLinus Torvalds 
597247b5d69cSJames Bottomley  	defer = 0;
59731da177e4SLinus Torvalds 
59741da177e4SLinus Torvalds 	for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
59751da177e4SLinus Torvalds 
59761da177e4SLinus Torvalds 		for (bit_cnt = 0x80; bit_cnt != 0; bit_cnt >>= 1) {
59771da177e4SLinus Torvalds 
59781da177e4SLinus Torvalds 			if (defer)
597947b5d69cSJames Bottomley  				ret_data = FPT_scxferc(p_port, 00);
59801da177e4SLinus Torvalds 
59811da177e4SLinus Torvalds 			else if (p_id_string[byte_cnt] & bit_cnt)
59821da177e4SLinus Torvalds 
598347b5d69cSJames Bottomley  				ret_data = FPT_scxferc(p_port, 02);
59841da177e4SLinus Torvalds 
59851da177e4SLinus Torvalds 			else {
59861da177e4SLinus Torvalds 
598747b5d69cSJames Bottomley  				ret_data = FPT_scxferc(p_port, 01);
59881da177e4SLinus Torvalds 				if (ret_data & 02)
598947b5d69cSJames Bottomley  					defer = 1;
59901da177e4SLinus Torvalds 			}
59911da177e4SLinus Torvalds 
59921da177e4SLinus Torvalds 			if ((ret_data & 0x1C) == 0x10)
59935c1b85e2SAlexey Dobriyan 				return 0x00;	/*End of isolation stage, we won! */
59941da177e4SLinus Torvalds 
59951da177e4SLinus Torvalds 			if (ret_data & 0x1C)
59965c1b85e2SAlexey Dobriyan 				return 0xFF;
59971da177e4SLinus Torvalds 
59981da177e4SLinus Torvalds 			if ((defer) && (!(ret_data & 0x1F)))
59995c1b85e2SAlexey Dobriyan 				return 0x01;	/*End of isolation stage, we lost. */
60001da177e4SLinus Torvalds 
60011da177e4SLinus Torvalds 		}		/*bit loop */
60021da177e4SLinus Torvalds 
60031da177e4SLinus Torvalds 	}			/*byte loop */
60041da177e4SLinus Torvalds 
60051da177e4SLinus Torvalds 	if (defer)
60065c1b85e2SAlexey Dobriyan 		return 0x01;	/*We lost */
60071da177e4SLinus Torvalds 	else
60085c1b85e2SAlexey Dobriyan 		return 0;	/*We WON! Yeeessss! */
60091da177e4SLinus Torvalds }
60101da177e4SLinus Torvalds 
60111da177e4SLinus Torvalds /*---------------------------------------------------------------------
60121da177e4SLinus Torvalds  *
601347b5d69cSJames Bottomley   * Function: FPT_sciso
60141da177e4SLinus Torvalds  *
60151da177e4SLinus Torvalds  * Description: Transfer the Identification string.
60161da177e4SLinus Torvalds  *
60171da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
60181da177e4SLinus Torvalds 
60195c04a7b8SAlexey Dobriyan static unsigned char FPT_sciso(unsigned long p_port,
60205c04a7b8SAlexey Dobriyan 			       unsigned char p_id_string[])
60211da177e4SLinus Torvalds {
6022db038cf8SAlexey Dobriyan 	unsigned char ret_data, the_data, byte_cnt, bit_cnt;
60231da177e4SLinus Torvalds 
60241da177e4SLinus Torvalds 	the_data = 0;
60251da177e4SLinus Torvalds 
60261da177e4SLinus Torvalds 	for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
60271da177e4SLinus Torvalds 
60281da177e4SLinus Torvalds 		for (bit_cnt = 0; bit_cnt < 8; bit_cnt++) {
60291da177e4SLinus Torvalds 
603047b5d69cSJames Bottomley  			ret_data = FPT_scxferc(p_port, 0);
60311da177e4SLinus Torvalds 
60321da177e4SLinus Torvalds 			if (ret_data & 0xFC)
60335c1b85e2SAlexey Dobriyan 				return 0xFF;
60341da177e4SLinus Torvalds 
60351da177e4SLinus Torvalds 			else {
60361da177e4SLinus Torvalds 
60371da177e4SLinus Torvalds 				the_data <<= 1;
60381da177e4SLinus Torvalds 				if (ret_data & BIT(1)) {
60391da177e4SLinus Torvalds 					the_data |= 1;
60401da177e4SLinus Torvalds 				}
60411da177e4SLinus Torvalds 			}
60421da177e4SLinus Torvalds 
60435c04a7b8SAlexey Dobriyan 			if ((ret_data & 0x1F) == 0) {
60441da177e4SLinus Torvalds /*
60451da177e4SLinus Torvalds 				if(bit_cnt != 0 || bit_cnt != 8)
60461da177e4SLinus Torvalds 				{
60471da177e4SLinus Torvalds 					byte_cnt = 0;
60481da177e4SLinus Torvalds 					bit_cnt = 0;
604947b5d69cSJames Bottomley  					FPT_scxferc(p_port, SYNC_PTRN);
605047b5d69cSJames Bottomley  					FPT_scxferc(p_port, ASSIGN_ID);
60511da177e4SLinus Torvalds 					continue;
60521da177e4SLinus Torvalds 				}
60531da177e4SLinus Torvalds */
60541da177e4SLinus Torvalds 				if (byte_cnt)
60555c1b85e2SAlexey Dobriyan 					return 0x00;
60561da177e4SLinus Torvalds 				else
60575c1b85e2SAlexey Dobriyan 					return 0xFF;
60581da177e4SLinus Torvalds 			}
60591da177e4SLinus Torvalds 
60601da177e4SLinus Torvalds 		}		/*bit loop */
60611da177e4SLinus Torvalds 
60621da177e4SLinus Torvalds 		p_id_string[byte_cnt] = the_data;
60631da177e4SLinus Torvalds 
60641da177e4SLinus Torvalds 	}			/*byte loop */
60651da177e4SLinus Torvalds 
60665c1b85e2SAlexey Dobriyan 	return 0;
60671da177e4SLinus Torvalds }
60681da177e4SLinus Torvalds 
60691da177e4SLinus Torvalds /*---------------------------------------------------------------------
60701da177e4SLinus Torvalds  *
607147b5d69cSJames Bottomley   * Function: FPT_scwirod
60721da177e4SLinus Torvalds  *
60731da177e4SLinus Torvalds  * Description: Sample the SCSI data bus making sure the signal has been
60741da177e4SLinus Torvalds  *              deasserted for the correct number of consecutive samples.
60751da177e4SLinus Torvalds  *
60761da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
60771da177e4SLinus Torvalds 
6078d63a4cccSAlexey Dobriyan static void FPT_scwirod(unsigned long p_port, unsigned char p_data_bit)
60791da177e4SLinus Torvalds {
6080db038cf8SAlexey Dobriyan 	unsigned char i;
60811da177e4SLinus Torvalds 
60821da177e4SLinus Torvalds 	i = 0;
60831da177e4SLinus Torvalds 	while (i < MAX_SCSI_TAR) {
60841da177e4SLinus Torvalds 
60851da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_scsidata_0) & p_data_bit)
60861da177e4SLinus Torvalds 
60871da177e4SLinus Torvalds 			i = 0;
60881da177e4SLinus Torvalds 
60891da177e4SLinus Torvalds 		else
60901da177e4SLinus Torvalds 
60911da177e4SLinus Torvalds 			i++;
60921da177e4SLinus Torvalds 
60931da177e4SLinus Torvalds 	}
60941da177e4SLinus Torvalds }
60951da177e4SLinus Torvalds 
60961da177e4SLinus Torvalds /*---------------------------------------------------------------------
60971da177e4SLinus Torvalds  *
609847b5d69cSJames Bottomley   * Function: FPT_scwiros
60991da177e4SLinus Torvalds  *
61001da177e4SLinus Torvalds  * Description: Sample the SCSI Signal lines making sure the signal has been
61011da177e4SLinus Torvalds  *              deasserted for the correct number of consecutive samples.
61021da177e4SLinus Torvalds  *
61031da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
61041da177e4SLinus Torvalds 
6105d63a4cccSAlexey Dobriyan static void FPT_scwiros(unsigned long p_port, unsigned char p_data_bit)
61061da177e4SLinus Torvalds {
6107db038cf8SAlexey Dobriyan 	unsigned char i;
61081da177e4SLinus Torvalds 
61091da177e4SLinus Torvalds 	i = 0;
61101da177e4SLinus Torvalds 	while (i < MAX_SCSI_TAR) {
61111da177e4SLinus Torvalds 
61121da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_scsisig) & p_data_bit)
61131da177e4SLinus Torvalds 
61141da177e4SLinus Torvalds 			i = 0;
61151da177e4SLinus Torvalds 
61161da177e4SLinus Torvalds 		else
61171da177e4SLinus Torvalds 
61181da177e4SLinus Torvalds 			i++;
61191da177e4SLinus Torvalds 
61201da177e4SLinus Torvalds 	}
61211da177e4SLinus Torvalds }
61221da177e4SLinus Torvalds 
61231da177e4SLinus Torvalds /*---------------------------------------------------------------------
61241da177e4SLinus Torvalds  *
612547b5d69cSJames Bottomley   * Function: FPT_scvalq
61261da177e4SLinus Torvalds  *
61271da177e4SLinus Torvalds  * Description: Make sure we received a valid data byte.
61281da177e4SLinus Torvalds  *
61291da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
61301da177e4SLinus Torvalds 
6131db038cf8SAlexey Dobriyan static unsigned char FPT_scvalq(unsigned char p_quintet)
61321da177e4SLinus Torvalds {
6133db038cf8SAlexey Dobriyan 	unsigned char count;
61341da177e4SLinus Torvalds 
61351da177e4SLinus Torvalds 	for (count = 1; count < 0x08; count <<= 1) {
61361da177e4SLinus Torvalds 		if (!(p_quintet & count))
61371da177e4SLinus Torvalds 			p_quintet -= 0x80;
61381da177e4SLinus Torvalds 	}
61391da177e4SLinus Torvalds 
61401da177e4SLinus Torvalds 	if (p_quintet & 0x18)
61415c1b85e2SAlexey Dobriyan 		return 0;
61421da177e4SLinus Torvalds 
61431da177e4SLinus Torvalds 	else
61445c1b85e2SAlexey Dobriyan 		return 1;
61451da177e4SLinus Torvalds }
61461da177e4SLinus Torvalds 
61471da177e4SLinus Torvalds /*---------------------------------------------------------------------
61481da177e4SLinus Torvalds  *
614947b5d69cSJames Bottomley   * Function: FPT_scsell
61501da177e4SLinus Torvalds  *
61511da177e4SLinus Torvalds  * Description: Select the specified device ID using a selection timeout
61521da177e4SLinus Torvalds  *              less than 4ms.  If somebody responds then it is a legacy
61531da177e4SLinus Torvalds  *              drive and this ID must be marked as such.
61541da177e4SLinus Torvalds  *
61551da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
61561da177e4SLinus Torvalds 
6157d63a4cccSAlexey Dobriyan static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id)
61581da177e4SLinus Torvalds {
6159d63a4cccSAlexey Dobriyan 	unsigned long i;
61601da177e4SLinus Torvalds 
61611da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_page_ctrl,
61621da177e4SLinus Torvalds 		   (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
61631da177e4SLinus Torvalds 
61641da177e4SLinus Torvalds 	ARAM_ACCESS(p_port);
61651da177e4SLinus Torvalds 
61665c04a7b8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_addstat,
61675c04a7b8SAlexey Dobriyan 		   (RD_HARPOON(p_port + hp_addstat) | SCAM_TIMER));
61681da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_seltimeout, TO_4ms);
61691da177e4SLinus Torvalds 
61701da177e4SLinus Torvalds 	for (i = p_port + CMD_STRT; i < p_port + CMD_STRT + 12; i += 2) {
61711da177e4SLinus Torvalds 		WRW_HARPOON(i, (MPM_OP + ACOMMAND));
61721da177e4SLinus Torvalds 	}
61731da177e4SLinus Torvalds 	WRW_HARPOON(i, (BRH_OP + ALWAYS + NP));
61741da177e4SLinus Torvalds 
61751da177e4SLinus Torvalds 	WRW_HARPOON((p_port + hp_intstat),
61761da177e4SLinus Torvalds 		    (RESET | TIMEOUT | SEL | BUS_FREE | AUTO_INT));
61771da177e4SLinus Torvalds 
61781da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_select_id, targ_id);
61791da177e4SLinus Torvalds 
61801da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_portctrl_0, SCSI_PORT);
61811da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_autostart_3, (SELECT | CMD_ONLY_STRT));
61821da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_scsictrl_0, (SEL_TAR | ENA_RESEL));
61831da177e4SLinus Torvalds 
61841da177e4SLinus Torvalds 	while (!(RDW_HARPOON((p_port + hp_intstat)) &
61855c04a7b8SAlexey Dobriyan 		 (RESET | PROG_HLT | TIMEOUT | AUTO_INT))) {
61865c04a7b8SAlexey Dobriyan 	}
61871da177e4SLinus Torvalds 
61881da177e4SLinus Torvalds 	if (RDW_HARPOON((p_port + hp_intstat)) & RESET)
618947b5d69cSJames Bottomley  		FPT_Wait(p_port, TO_250ms);
61901da177e4SLinus Torvalds 
61911da177e4SLinus Torvalds 	DISABLE_AUTO(p_port);
61921da177e4SLinus Torvalds 
61935c04a7b8SAlexey Dobriyan 	WR_HARPOON(p_port + hp_addstat,
61945c04a7b8SAlexey Dobriyan 		   (RD_HARPOON(p_port + hp_addstat) & ~SCAM_TIMER));
61951da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_seltimeout, TO_290ms);
61961da177e4SLinus Torvalds 
61971da177e4SLinus Torvalds 	SGRAM_ACCESS(p_port);
61981da177e4SLinus Torvalds 
61991da177e4SLinus Torvalds 	if (RDW_HARPOON((p_port + hp_intstat)) & (RESET | TIMEOUT)) {
62001da177e4SLinus Torvalds 
62011da177e4SLinus Torvalds 		WRW_HARPOON((p_port + hp_intstat),
62021da177e4SLinus Torvalds 			    (RESET | TIMEOUT | SEL | BUS_FREE | PHASE));
62031da177e4SLinus Torvalds 
62041da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_page_ctrl,
62055c04a7b8SAlexey Dobriyan 			   (RD_HARPOON(p_port + hp_page_ctrl) &
62065c04a7b8SAlexey Dobriyan 			    ~G_INT_DISABLE));
62071da177e4SLinus Torvalds 
62085c1b85e2SAlexey Dobriyan 		return 0;	/*No legacy device */
62091da177e4SLinus Torvalds 	}
62101da177e4SLinus Torvalds 
62111da177e4SLinus Torvalds 	else {
62121da177e4SLinus Torvalds 
62131da177e4SLinus Torvalds 		while (!(RDW_HARPOON((p_port + hp_intstat)) & BUS_FREE)) {
62145c04a7b8SAlexey Dobriyan 			if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ) {
62155c04a7b8SAlexey Dobriyan 				WR_HARPOON(p_port + hp_scsisig,
62165c04a7b8SAlexey Dobriyan 					   (SCSI_ACK + S_ILL_PH));
62171da177e4SLinus Torvalds 				ACCEPT_MSG(p_port);
62181da177e4SLinus Torvalds 			}
62191da177e4SLinus Torvalds 		}
62201da177e4SLinus Torvalds 
62211da177e4SLinus Torvalds 		WRW_HARPOON((p_port + hp_intstat), CLR_ALL_INT_1);
62221da177e4SLinus Torvalds 
62231da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_page_ctrl,
62245c04a7b8SAlexey Dobriyan 			   (RD_HARPOON(p_port + hp_page_ctrl) &
62255c04a7b8SAlexey Dobriyan 			    ~G_INT_DISABLE));
62261da177e4SLinus Torvalds 
62275c1b85e2SAlexey Dobriyan 		return 1;	/*Found one of them oldies! */
62281da177e4SLinus Torvalds 	}
62291da177e4SLinus Torvalds }
62301da177e4SLinus Torvalds 
62311da177e4SLinus Torvalds /*---------------------------------------------------------------------
62321da177e4SLinus Torvalds  *
623347b5d69cSJames Bottomley   * Function: FPT_scwtsel
62341da177e4SLinus Torvalds  *
62351da177e4SLinus Torvalds  * Description: Wait to be selected by another SCAM initiator.
62361da177e4SLinus Torvalds  *
62371da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
62381da177e4SLinus Torvalds 
6239d63a4cccSAlexey Dobriyan static void FPT_scwtsel(unsigned long p_port)
62401da177e4SLinus Torvalds {
62415c04a7b8SAlexey Dobriyan 	while (!(RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL)) {
62421da177e4SLinus Torvalds 	}
62435c04a7b8SAlexey Dobriyan }
62441da177e4SLinus Torvalds 
62451da177e4SLinus Torvalds /*---------------------------------------------------------------------
62461da177e4SLinus Torvalds  *
624747b5d69cSJames Bottomley   * Function: FPT_inisci
62481da177e4SLinus Torvalds  *
62491da177e4SLinus Torvalds  * Description: Setup the data Structure with the info from the EEPROM.
62501da177e4SLinus Torvalds  *
62511da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
62521da177e4SLinus Torvalds 
62535c04a7b8SAlexey Dobriyan static void FPT_inisci(unsigned char p_card, unsigned long p_port,
62545c04a7b8SAlexey Dobriyan 		       unsigned char p_our_id)
62551da177e4SLinus Torvalds {
6256db038cf8SAlexey Dobriyan 	unsigned char i, k, max_id;
6257c823feebSAlexey Dobriyan 	unsigned short ee_data;
625868d0c1aeSAlexey Dobriyan 	struct nvram_info *pCurrNvRam;
62591da177e4SLinus Torvalds 
626047b5d69cSJames Bottomley  	pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
62611da177e4SLinus Torvalds 
62621da177e4SLinus Torvalds 	if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
62631da177e4SLinus Torvalds 		max_id = 0x08;
62641da177e4SLinus Torvalds 
62651da177e4SLinus Torvalds 	else
62661da177e4SLinus Torvalds 		max_id = 0x10;
62671da177e4SLinus Torvalds 
62681da177e4SLinus Torvalds 	if (pCurrNvRam) {
62691da177e4SLinus Torvalds 		for (i = 0; i < max_id; i++) {
62701da177e4SLinus Torvalds 
62711da177e4SLinus Torvalds 			for (k = 0; k < 4; k++)
62725c04a7b8SAlexey Dobriyan 				FPT_scamInfo[i].id_string[k] =
62735c04a7b8SAlexey Dobriyan 				    pCurrNvRam->niScamTbl[i][k];
62741da177e4SLinus Torvalds 			for (k = 4; k < ID_STRING_LENGTH; k++)
62755c04a7b8SAlexey Dobriyan 				FPT_scamInfo[i].id_string[k] =
62765c04a7b8SAlexey Dobriyan 				    (unsigned char)0x00;
62771da177e4SLinus Torvalds 
627847b5d69cSJames Bottomley  			if (FPT_scamInfo[i].id_string[0] == 0x00)
627947b5d69cSJames Bottomley  				FPT_scamInfo[i].state = ID_UNUSED;	/*Default to unused ID. */
62801da177e4SLinus Torvalds 			else
628147b5d69cSJames Bottomley  				FPT_scamInfo[i].state = ID_UNASSIGNED;	/*Default to unassigned ID. */
62821da177e4SLinus Torvalds 
62831da177e4SLinus Torvalds 		}
62841da177e4SLinus Torvalds 	} else {
62855c04a7b8SAlexey Dobriyan 		for (i = 0; i < max_id; i++) {
62865c04a7b8SAlexey Dobriyan 			for (k = 0; k < ID_STRING_LENGTH; k += 2) {
62875c04a7b8SAlexey Dobriyan 				ee_data =
62885c04a7b8SAlexey Dobriyan 				    FPT_utilEERead(p_port,
62895c04a7b8SAlexey Dobriyan 						   (unsigned
62905c04a7b8SAlexey Dobriyan 						    short)((EE_SCAMBASE / 2) +
62915c04a7b8SAlexey Dobriyan 							   (unsigned short)(i *
62925c04a7b8SAlexey Dobriyan 									    ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
62935c04a7b8SAlexey Dobriyan 				FPT_scamInfo[i].id_string[k] =
62945c04a7b8SAlexey Dobriyan 				    (unsigned char)ee_data;
62951da177e4SLinus Torvalds 				ee_data >>= 8;
62965c04a7b8SAlexey Dobriyan 				FPT_scamInfo[i].id_string[k + 1] =
62975c04a7b8SAlexey Dobriyan 				    (unsigned char)ee_data;
62981da177e4SLinus Torvalds 			}
62991da177e4SLinus Torvalds 
630047b5d69cSJames Bottomley  			if ((FPT_scamInfo[i].id_string[0] == 0x00) ||
630147b5d69cSJames Bottomley  			    (FPT_scamInfo[i].id_string[0] == 0xFF))
63021da177e4SLinus Torvalds 
630347b5d69cSJames Bottomley  				FPT_scamInfo[i].state = ID_UNUSED;	/*Default to unused ID. */
63041da177e4SLinus Torvalds 
63051da177e4SLinus Torvalds 			else
630647b5d69cSJames Bottomley  				FPT_scamInfo[i].state = ID_UNASSIGNED;	/*Default to unassigned ID. */
63071da177e4SLinus Torvalds 
63081da177e4SLinus Torvalds 		}
63091da177e4SLinus Torvalds 	}
63101da177e4SLinus Torvalds 	for (k = 0; k < ID_STRING_LENGTH; k++)
631147b5d69cSJames Bottomley  		FPT_scamInfo[p_our_id].id_string[k] = FPT_scamHAString[k];
63121da177e4SLinus Torvalds 
63131da177e4SLinus Torvalds }
63141da177e4SLinus Torvalds 
63151da177e4SLinus Torvalds /*---------------------------------------------------------------------
63161da177e4SLinus Torvalds  *
631747b5d69cSJames Bottomley   * Function: FPT_scmachid
63181da177e4SLinus Torvalds  *
63191da177e4SLinus Torvalds  * Description: Match the Device ID string with our values stored in
63201da177e4SLinus Torvalds  *              the EEPROM.
63211da177e4SLinus Torvalds  *
63221da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
63231da177e4SLinus Torvalds 
63245c04a7b8SAlexey Dobriyan static unsigned char FPT_scmachid(unsigned char p_card,
63255c04a7b8SAlexey Dobriyan 				  unsigned char p_id_string[])
63261da177e4SLinus Torvalds {
63271da177e4SLinus Torvalds 
6328db038cf8SAlexey Dobriyan 	unsigned char i, k, match;
63291da177e4SLinus Torvalds 
63301da177e4SLinus Torvalds 	for (i = 0; i < MAX_SCSI_TAR; i++) {
63311da177e4SLinus Torvalds 
633247b5d69cSJames Bottomley  		match = 1;
63331da177e4SLinus Torvalds 
63345c04a7b8SAlexey Dobriyan 		for (k = 0; k < ID_STRING_LENGTH; k++) {
633547b5d69cSJames Bottomley  			if (p_id_string[k] != FPT_scamInfo[i].id_string[k])
633647b5d69cSJames Bottomley  				match = 0;
63371da177e4SLinus Torvalds 		}
63381da177e4SLinus Torvalds 
63395c04a7b8SAlexey Dobriyan 		if (match) {
634047b5d69cSJames Bottomley  			FPT_scamInfo[i].state = ID_ASSIGNED;
63415c1b85e2SAlexey Dobriyan 			return i;
63421da177e4SLinus Torvalds 		}
63431da177e4SLinus Torvalds 
63441da177e4SLinus Torvalds 	}
63451da177e4SLinus Torvalds 
63461da177e4SLinus Torvalds 	if (p_id_string[0] & BIT(5))
63471da177e4SLinus Torvalds 		i = 8;
63481da177e4SLinus Torvalds 	else
63491da177e4SLinus Torvalds 		i = MAX_SCSI_TAR;
63501da177e4SLinus Torvalds 
63515c04a7b8SAlexey Dobriyan 	if (((p_id_string[0] & 0x06) == 0x02)
63525c04a7b8SAlexey Dobriyan 	    || ((p_id_string[0] & 0x06) == 0x04))
6353db038cf8SAlexey Dobriyan 		match = p_id_string[1] & (unsigned char)0x1F;
63541da177e4SLinus Torvalds 	else
63551da177e4SLinus Torvalds 		match = 7;
63561da177e4SLinus Torvalds 
63575c04a7b8SAlexey Dobriyan 	while (i > 0) {
63581da177e4SLinus Torvalds 		i--;
63591da177e4SLinus Torvalds 
63605c04a7b8SAlexey Dobriyan 		if (FPT_scamInfo[match].state == ID_UNUSED) {
63615c04a7b8SAlexey Dobriyan 			for (k = 0; k < ID_STRING_LENGTH; k++) {
63625c04a7b8SAlexey Dobriyan 				FPT_scamInfo[match].id_string[k] =
63635c04a7b8SAlexey Dobriyan 				    p_id_string[k];
63641da177e4SLinus Torvalds 			}
63651da177e4SLinus Torvalds 
636647b5d69cSJames Bottomley  			FPT_scamInfo[match].state = ID_ASSIGNED;
63671da177e4SLinus Torvalds 
636847b5d69cSJames Bottomley  			if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
63695c04a7b8SAlexey Dobriyan 				FPT_BL_Card[p_card].globalFlags |=
63705c04a7b8SAlexey Dobriyan 				    F_UPDATE_EEPROM;
63715c1b85e2SAlexey Dobriyan 			return match;
63721da177e4SLinus Torvalds 
63731da177e4SLinus Torvalds 		}
63741da177e4SLinus Torvalds 
63751da177e4SLinus Torvalds 		match--;
63761da177e4SLinus Torvalds 
63775c04a7b8SAlexey Dobriyan 		if (match == 0xFF) {
63781da177e4SLinus Torvalds 			if (p_id_string[0] & BIT(5))
63791da177e4SLinus Torvalds 				match = 7;
63801da177e4SLinus Torvalds 			else
63811da177e4SLinus Torvalds 				match = MAX_SCSI_TAR - 1;
63821da177e4SLinus Torvalds 		}
63831da177e4SLinus Torvalds 	}
63841da177e4SLinus Torvalds 
63855c04a7b8SAlexey Dobriyan 	if (p_id_string[0] & BIT(7)) {
63865c1b85e2SAlexey Dobriyan 		return CLR_PRIORITY;
63871da177e4SLinus Torvalds 	}
63881da177e4SLinus Torvalds 
63891da177e4SLinus Torvalds 	if (p_id_string[0] & BIT(5))
63901da177e4SLinus Torvalds 		i = 8;
63911da177e4SLinus Torvalds 	else
63921da177e4SLinus Torvalds 		i = MAX_SCSI_TAR;
63931da177e4SLinus Torvalds 
63945c04a7b8SAlexey Dobriyan 	if (((p_id_string[0] & 0x06) == 0x02)
63955c04a7b8SAlexey Dobriyan 	    || ((p_id_string[0] & 0x06) == 0x04))
6396db038cf8SAlexey Dobriyan 		match = p_id_string[1] & (unsigned char)0x1F;
63971da177e4SLinus Torvalds 	else
63981da177e4SLinus Torvalds 		match = 7;
63991da177e4SLinus Torvalds 
64005c04a7b8SAlexey Dobriyan 	while (i > 0) {
64011da177e4SLinus Torvalds 
64021da177e4SLinus Torvalds 		i--;
64031da177e4SLinus Torvalds 
64045c04a7b8SAlexey Dobriyan 		if (FPT_scamInfo[match].state == ID_UNASSIGNED) {
64055c04a7b8SAlexey Dobriyan 			for (k = 0; k < ID_STRING_LENGTH; k++) {
64065c04a7b8SAlexey Dobriyan 				FPT_scamInfo[match].id_string[k] =
64075c04a7b8SAlexey Dobriyan 				    p_id_string[k];
64081da177e4SLinus Torvalds 			}
64091da177e4SLinus Torvalds 
641047b5d69cSJames Bottomley  			FPT_scamInfo[match].id_string[0] |= BIT(7);
641147b5d69cSJames Bottomley  			FPT_scamInfo[match].state = ID_ASSIGNED;
641247b5d69cSJames Bottomley  			if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
64135c04a7b8SAlexey Dobriyan 				FPT_BL_Card[p_card].globalFlags |=
64145c04a7b8SAlexey Dobriyan 				    F_UPDATE_EEPROM;
64155c1b85e2SAlexey Dobriyan 			return match;
64161da177e4SLinus Torvalds 
64171da177e4SLinus Torvalds 		}
64181da177e4SLinus Torvalds 
64191da177e4SLinus Torvalds 		match--;
64201da177e4SLinus Torvalds 
64215c04a7b8SAlexey Dobriyan 		if (match == 0xFF) {
64221da177e4SLinus Torvalds 			if (p_id_string[0] & BIT(5))
64231da177e4SLinus Torvalds 				match = 7;
64241da177e4SLinus Torvalds 			else
64251da177e4SLinus Torvalds 				match = MAX_SCSI_TAR - 1;
64261da177e4SLinus Torvalds 		}
64271da177e4SLinus Torvalds 	}
64281da177e4SLinus Torvalds 
64295c1b85e2SAlexey Dobriyan 	return NO_ID_AVAIL;
64301da177e4SLinus Torvalds }
64311da177e4SLinus Torvalds 
64321da177e4SLinus Torvalds /*---------------------------------------------------------------------
64331da177e4SLinus Torvalds  *
643447b5d69cSJames Bottomley   * Function: FPT_scsavdi
64351da177e4SLinus Torvalds  *
64361da177e4SLinus Torvalds  * Description: Save off the device SCAM ID strings.
64371da177e4SLinus Torvalds  *
64381da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
64391da177e4SLinus Torvalds 
6440d63a4cccSAlexey Dobriyan static void FPT_scsavdi(unsigned char p_card, unsigned long p_port)
64411da177e4SLinus Torvalds {
6442db038cf8SAlexey Dobriyan 	unsigned char i, k, max_id;
6443c823feebSAlexey Dobriyan 	unsigned short ee_data, sum_data;
64441da177e4SLinus Torvalds 
64451da177e4SLinus Torvalds 	sum_data = 0x0000;
64461da177e4SLinus Torvalds 
64475c04a7b8SAlexey Dobriyan 	for (i = 1; i < EE_SCAMBASE / 2; i++) {
644847b5d69cSJames Bottomley  		sum_data += FPT_utilEERead(p_port, i);
64491da177e4SLinus Torvalds 	}
64501da177e4SLinus Torvalds 
645147b5d69cSJames Bottomley  	FPT_utilEEWriteOnOff(p_port, 1);	/* Enable write access to the EEPROM */
64521da177e4SLinus Torvalds 
64531da177e4SLinus Torvalds 	if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
64541da177e4SLinus Torvalds 		max_id = 0x08;
64551da177e4SLinus Torvalds 
64561da177e4SLinus Torvalds 	else
64571da177e4SLinus Torvalds 		max_id = 0x10;
64581da177e4SLinus Torvalds 
64595c04a7b8SAlexey Dobriyan 	for (i = 0; i < max_id; i++) {
64601da177e4SLinus Torvalds 
64615c04a7b8SAlexey Dobriyan 		for (k = 0; k < ID_STRING_LENGTH; k += 2) {
646247b5d69cSJames Bottomley  			ee_data = FPT_scamInfo[i].id_string[k + 1];
64631da177e4SLinus Torvalds 			ee_data <<= 8;
646447b5d69cSJames Bottomley  			ee_data |= FPT_scamInfo[i].id_string[k];
64651da177e4SLinus Torvalds 			sum_data += ee_data;
64665c04a7b8SAlexey Dobriyan 			FPT_utilEEWrite(p_port, ee_data,
64675c04a7b8SAlexey Dobriyan 					(unsigned short)((EE_SCAMBASE / 2) +
64685c04a7b8SAlexey Dobriyan 							 (unsigned short)(i *
64695c04a7b8SAlexey Dobriyan 									  ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
64701da177e4SLinus Torvalds 		}
64711da177e4SLinus Torvalds 	}
64721da177e4SLinus Torvalds 
647347b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, sum_data, EEPROM_CHECK_SUM / 2);
647447b5d69cSJames Bottomley  	FPT_utilEEWriteOnOff(p_port, 0);	/* Turn off write access */
64751da177e4SLinus Torvalds }
64761da177e4SLinus Torvalds 
64771da177e4SLinus Torvalds /*---------------------------------------------------------------------
64781da177e4SLinus Torvalds  *
647947b5d69cSJames Bottomley   * Function: FPT_XbowInit
64801da177e4SLinus Torvalds  *
64811da177e4SLinus Torvalds  * Description: Setup the Xbow for normal operation.
64821da177e4SLinus Torvalds  *
64831da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
64841da177e4SLinus Torvalds 
6485d63a4cccSAlexey Dobriyan static void FPT_XbowInit(unsigned long port, unsigned char ScamFlg)
64861da177e4SLinus Torvalds {
6487db038cf8SAlexey Dobriyan 	unsigned char i;
64881da177e4SLinus Torvalds 
64891da177e4SLinus Torvalds 	i = RD_HARPOON(port + hp_page_ctrl);
6490db038cf8SAlexey Dobriyan 	WR_HARPOON(port + hp_page_ctrl, (unsigned char)(i | G_INT_DISABLE));
64911da177e4SLinus Torvalds 
64921da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsireset, 0x00);
64931da177e4SLinus Torvalds 	WR_HARPOON(port + hp_portctrl_1, HOST_MODE8);
64941da177e4SLinus Torvalds 
64955c04a7b8SAlexey Dobriyan 	WR_HARPOON(port + hp_scsireset, (DMA_RESET | HPSCSI_RESET | PROG_RESET |
64961da177e4SLinus Torvalds 					 FIFO_CLR));
64971da177e4SLinus Torvalds 
64981da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsireset, SCSI_INI);
64991da177e4SLinus Torvalds 
65001da177e4SLinus Torvalds 	WR_HARPOON(port + hp_clkctrl_0, CLKCTRL_DEFAULT);
65011da177e4SLinus Torvalds 
65021da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsisig, 0x00);	/*  Clear any signals we might */
65031da177e4SLinus Torvalds 	WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
65041da177e4SLinus Torvalds 
65051da177e4SLinus Torvalds 	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
65061da177e4SLinus Torvalds 
650747b5d69cSJames Bottomley  	FPT_default_intena = RESET | RSEL | PROG_HLT | TIMEOUT |
65081da177e4SLinus Torvalds 	    BUS_FREE | XFER_CNT_0 | AUTO_INT;
65091da177e4SLinus Torvalds 
65101da177e4SLinus Torvalds 	if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2))
651147b5d69cSJames Bottomley  		FPT_default_intena |= SCAM_SEL;
65121da177e4SLinus Torvalds 
651347b5d69cSJames Bottomley  	WRW_HARPOON((port + hp_intena), FPT_default_intena);
65141da177e4SLinus Torvalds 
65151da177e4SLinus Torvalds 	WR_HARPOON(port + hp_seltimeout, TO_290ms);
65161da177e4SLinus Torvalds 
65171da177e4SLinus Torvalds 	/* Turn on SCSI_MODE8 for narrow cards to fix the
65181da177e4SLinus Torvalds 	   strapping issue with the DUAL CHANNEL card */
65191da177e4SLinus Torvalds 	if (RD_HARPOON(port + hp_page_ctrl) & NARROW_SCSI_CARD)
65201da177e4SLinus Torvalds 		WR_HARPOON(port + hp_addstat, SCSI_MODE8);
65211da177e4SLinus Torvalds 
65221da177e4SLinus Torvalds 	WR_HARPOON(port + hp_page_ctrl, i);
65231da177e4SLinus Torvalds 
65241da177e4SLinus Torvalds }
65251da177e4SLinus Torvalds 
65261da177e4SLinus Torvalds /*---------------------------------------------------------------------
65271da177e4SLinus Torvalds  *
652847b5d69cSJames Bottomley   * Function: FPT_BusMasterInit
65291da177e4SLinus Torvalds  *
65301da177e4SLinus Torvalds  * Description: Initialize the BusMaster for normal operations.
65311da177e4SLinus Torvalds  *
65321da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
65331da177e4SLinus Torvalds 
6534d63a4cccSAlexey Dobriyan static void FPT_BusMasterInit(unsigned long p_port)
65351da177e4SLinus Torvalds {
65361da177e4SLinus Torvalds 
65371da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_sys_ctrl, DRVR_RST);
65381da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
65391da177e4SLinus Torvalds 
65401da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_host_blk_cnt, XFER_BLK64);
65411da177e4SLinus Torvalds 
65421da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_bm_ctrl, (BMCTRL_DEFAULT));
65431da177e4SLinus Torvalds 
65441da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, (SCSI_TERM_ENA_H));
65451da177e4SLinus Torvalds 
65461da177e4SLinus Torvalds 	RD_HARPOON(p_port + hp_int_status);	/*Clear interrupts. */
65471da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
65481da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_page_ctrl, (RD_HARPOON(p_port + hp_page_ctrl) &
65491da177e4SLinus Torvalds 					   ~SCATTER_EN));
65501da177e4SLinus Torvalds }
65511da177e4SLinus Torvalds 
65521da177e4SLinus Torvalds /*---------------------------------------------------------------------
65531da177e4SLinus Torvalds  *
655447b5d69cSJames Bottomley   * Function: FPT_DiagEEPROM
65551da177e4SLinus Torvalds  *
65561da177e4SLinus Torvalds  * Description: Verfiy checksum and 'Key' and initialize the EEPROM if
65571da177e4SLinus Torvalds  *              necessary.
65581da177e4SLinus Torvalds  *
65591da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
65601da177e4SLinus Torvalds 
6561d63a4cccSAlexey Dobriyan static void FPT_DiagEEPROM(unsigned long p_port)
65621da177e4SLinus Torvalds {
6563c823feebSAlexey Dobriyan 	unsigned short index, temp, max_wd_cnt;
65641da177e4SLinus Torvalds 
65651da177e4SLinus Torvalds 	if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
65661da177e4SLinus Torvalds 		max_wd_cnt = EEPROM_WD_CNT;
65671da177e4SLinus Torvalds 	else
65681da177e4SLinus Torvalds 		max_wd_cnt = EEPROM_WD_CNT * 2;
65691da177e4SLinus Torvalds 
657047b5d69cSJames Bottomley  	temp = FPT_utilEERead(p_port, FW_SIGNATURE / 2);
65711da177e4SLinus Torvalds 
65721da177e4SLinus Torvalds 	if (temp == 0x4641) {
65731da177e4SLinus Torvalds 
65741da177e4SLinus Torvalds 		for (index = 2; index < max_wd_cnt; index++) {
65751da177e4SLinus Torvalds 
657647b5d69cSJames Bottomley  			temp += FPT_utilEERead(p_port, index);
65771da177e4SLinus Torvalds 
65781da177e4SLinus Torvalds 		}
65791da177e4SLinus Torvalds 
658047b5d69cSJames Bottomley  		if (temp == FPT_utilEERead(p_port, EEPROM_CHECK_SUM / 2)) {
65811da177e4SLinus Torvalds 
65821da177e4SLinus Torvalds 			return;	/*EEPROM is Okay so return now! */
65831da177e4SLinus Torvalds 		}
65841da177e4SLinus Torvalds 	}
65851da177e4SLinus Torvalds 
6586db038cf8SAlexey Dobriyan 	FPT_utilEEWriteOnOff(p_port, (unsigned char)1);
65871da177e4SLinus Torvalds 
65881da177e4SLinus Torvalds 	for (index = 0; index < max_wd_cnt; index++) {
65891da177e4SLinus Torvalds 
659047b5d69cSJames Bottomley  		FPT_utilEEWrite(p_port, 0x0000, index);
65911da177e4SLinus Torvalds 	}
65921da177e4SLinus Torvalds 
65931da177e4SLinus Torvalds 	temp = 0;
65941da177e4SLinus Torvalds 
659547b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4641, FW_SIGNATURE / 2);
65961da177e4SLinus Torvalds 	temp += 0x4641;
659747b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x3920, MODEL_NUMB_0 / 2);
65981da177e4SLinus Torvalds 	temp += 0x3920;
659947b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x3033, MODEL_NUMB_2 / 2);
66001da177e4SLinus Torvalds 	temp += 0x3033;
660147b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x2020, MODEL_NUMB_4 / 2);
66021da177e4SLinus Torvalds 	temp += 0x2020;
660347b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x70D3, SYSTEM_CONFIG / 2);
66041da177e4SLinus Torvalds 	temp += 0x70D3;
660547b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x0010, BIOS_CONFIG / 2);
66061da177e4SLinus Torvalds 	temp += 0x0010;
660747b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x0003, SCAM_CONFIG / 2);
66081da177e4SLinus Torvalds 	temp += 0x0003;
660947b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x0007, ADAPTER_SCSI_ID / 2);
66101da177e4SLinus Torvalds 	temp += 0x0007;
66111da177e4SLinus Torvalds 
661247b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x0000, IGNORE_B_SCAN / 2);
66131da177e4SLinus Torvalds 	temp += 0x0000;
661447b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x0000, SEND_START_ENA / 2);
66151da177e4SLinus Torvalds 	temp += 0x0000;
661647b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x0000, DEVICE_ENABLE / 2);
66171da177e4SLinus Torvalds 	temp += 0x0000;
66181da177e4SLinus Torvalds 
661947b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL01 / 2);
66201da177e4SLinus Torvalds 	temp += 0x4242;
662147b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL23 / 2);
66221da177e4SLinus Torvalds 	temp += 0x4242;
662347b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL45 / 2);
66241da177e4SLinus Torvalds 	temp += 0x4242;
662547b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL67 / 2);
66261da177e4SLinus Torvalds 	temp += 0x4242;
662747b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL89 / 2);
66281da177e4SLinus Torvalds 	temp += 0x4242;
662947b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLab / 2);
66301da177e4SLinus Torvalds 	temp += 0x4242;
663147b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLcd / 2);
66321da177e4SLinus Torvalds 	temp += 0x4242;
663347b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLef / 2);
66341da177e4SLinus Torvalds 	temp += 0x4242;
66351da177e4SLinus Torvalds 
663647b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x6C46, 64 / 2);	/*PRODUCT ID */
66371da177e4SLinus Torvalds 	temp += 0x6C46;
663847b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x7361, 66 / 2);	/* FlashPoint LT   */
66391da177e4SLinus Torvalds 	temp += 0x7361;
664047b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x5068, 68 / 2);
66411da177e4SLinus Torvalds 	temp += 0x5068;
664247b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x696F, 70 / 2);
66431da177e4SLinus Torvalds 	temp += 0x696F;
664447b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x746E, 72 / 2);
66451da177e4SLinus Torvalds 	temp += 0x746E;
664647b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4C20, 74 / 2);
66471da177e4SLinus Torvalds 	temp += 0x4C20;
664847b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x2054, 76 / 2);
66491da177e4SLinus Torvalds 	temp += 0x2054;
665047b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x2020, 78 / 2);
66511da177e4SLinus Torvalds 	temp += 0x2020;
66521da177e4SLinus Torvalds 
66531da177e4SLinus Torvalds 	index = ((EE_SCAMBASE / 2) + (7 * 16));
665447b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, (0x0700 + TYPE_CODE0), index);
66551da177e4SLinus Torvalds 	temp += (0x0700 + TYPE_CODE0);
66561da177e4SLinus Torvalds 	index++;
665747b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x5542, index);	/*Vendor ID code */
66581da177e4SLinus Torvalds 	temp += 0x5542;		/* BUSLOGIC      */
66591da177e4SLinus Torvalds 	index++;
666047b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4C53, index);
66611da177e4SLinus Torvalds 	temp += 0x4C53;
66621da177e4SLinus Torvalds 	index++;
666347b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x474F, index);
66641da177e4SLinus Torvalds 	temp += 0x474F;
66651da177e4SLinus Torvalds 	index++;
666647b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4349, index);
66671da177e4SLinus Torvalds 	temp += 0x4349;
66681da177e4SLinus Torvalds 	index++;
666947b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x5442, index);	/*Vendor unique code */
66701da177e4SLinus Torvalds 	temp += 0x5442;		/* BT- 930           */
66711da177e4SLinus Torvalds 	index++;
667247b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x202D, index);
66731da177e4SLinus Torvalds 	temp += 0x202D;
66741da177e4SLinus Torvalds 	index++;
667547b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x3339, index);
66761da177e4SLinus Torvalds 	temp += 0x3339;
66771da177e4SLinus Torvalds 	index++;		/*Serial #          */
667847b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x2030, index);	/* 01234567         */
66791da177e4SLinus Torvalds 	temp += 0x2030;
66801da177e4SLinus Torvalds 	index++;
668147b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x5453, index);
66821da177e4SLinus Torvalds 	temp += 0x5453;
66831da177e4SLinus Torvalds 	index++;
668447b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x5645, index);
66851da177e4SLinus Torvalds 	temp += 0x5645;
66861da177e4SLinus Torvalds 	index++;
668747b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x2045, index);
66881da177e4SLinus Torvalds 	temp += 0x2045;
66891da177e4SLinus Torvalds 	index++;
669047b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x202F, index);
66911da177e4SLinus Torvalds 	temp += 0x202F;
66921da177e4SLinus Torvalds 	index++;
669347b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x4F4A, index);
66941da177e4SLinus Torvalds 	temp += 0x4F4A;
66951da177e4SLinus Torvalds 	index++;
669647b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x204E, index);
66971da177e4SLinus Torvalds 	temp += 0x204E;
66981da177e4SLinus Torvalds 	index++;
669947b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, 0x3539, index);
67001da177e4SLinus Torvalds 	temp += 0x3539;
67011da177e4SLinus Torvalds 
670247b5d69cSJames Bottomley  	FPT_utilEEWrite(p_port, temp, EEPROM_CHECK_SUM / 2);
67031da177e4SLinus Torvalds 
6704db038cf8SAlexey Dobriyan 	FPT_utilEEWriteOnOff(p_port, (unsigned char)0);
67051da177e4SLinus Torvalds 
67061da177e4SLinus Torvalds }
67071da177e4SLinus Torvalds 
67081da177e4SLinus Torvalds /*---------------------------------------------------------------------
67091da177e4SLinus Torvalds  *
67101da177e4SLinus Torvalds  * Function: Queue Search Select
67111da177e4SLinus Torvalds  *
67121da177e4SLinus Torvalds  * Description: Try to find a new command to execute.
67131da177e4SLinus Torvalds  *
67141da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
67151da177e4SLinus Torvalds 
67165c04a7b8SAlexey Dobriyan static void FPT_queueSearchSelect(struct sccb_card *pCurrCard,
67175c04a7b8SAlexey Dobriyan 				  unsigned char p_card)
67181da177e4SLinus Torvalds {
6719db038cf8SAlexey Dobriyan 	unsigned char scan_ptr, lun;
6720f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
672169eb2ea4SAlexey Dobriyan 	struct sccb *pOldSccb;
67221da177e4SLinus Torvalds 
67231da177e4SLinus Torvalds 	scan_ptr = pCurrCard->scanIndex;
67245c04a7b8SAlexey Dobriyan 	do {
672547b5d69cSJames Bottomley  		currTar_Info = &FPT_sccbMgrTbl[p_card][scan_ptr];
67261da177e4SLinus Torvalds 		if ((pCurrCard->globalFlags & F_CONLUN_IO) &&
67275c04a7b8SAlexey Dobriyan 		    ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
67285c04a7b8SAlexey Dobriyan 		     TAG_Q_TRYING)) {
67295c04a7b8SAlexey Dobriyan 			if (currTar_Info->TarSelQ_Cnt != 0) {
67301da177e4SLinus Torvalds 
67311da177e4SLinus Torvalds 				scan_ptr++;
67321da177e4SLinus Torvalds 				if (scan_ptr == MAX_SCSI_TAR)
67331da177e4SLinus Torvalds 					scan_ptr = 0;
67341da177e4SLinus Torvalds 
67355c04a7b8SAlexey Dobriyan 				for (lun = 0; lun < MAX_LUN; lun++) {
67365c04a7b8SAlexey Dobriyan 					if (currTar_Info->TarLUNBusy[lun] == 0) {
67371da177e4SLinus Torvalds 
67385c04a7b8SAlexey Dobriyan 						pCurrCard->currentSCCB =
67395c04a7b8SAlexey Dobriyan 						    currTar_Info->TarSelQ_Head;
67401da177e4SLinus Torvalds 						pOldSccb = NULL;
67411da177e4SLinus Torvalds 
67425c04a7b8SAlexey Dobriyan 						while ((pCurrCard->
67435c04a7b8SAlexey Dobriyan 							currentSCCB != NULL)
67445c04a7b8SAlexey Dobriyan 						       && (lun !=
67455c04a7b8SAlexey Dobriyan 							   pCurrCard->
67465c04a7b8SAlexey Dobriyan 							   currentSCCB->Lun)) {
67475c04a7b8SAlexey Dobriyan 							pOldSccb =
67485c04a7b8SAlexey Dobriyan 							    pCurrCard->
67495c04a7b8SAlexey Dobriyan 							    currentSCCB;
67505c04a7b8SAlexey Dobriyan 							pCurrCard->currentSCCB =
67515c04a7b8SAlexey Dobriyan 							    (struct sccb
67525c04a7b8SAlexey Dobriyan 							     *)(pCurrCard->
67535c04a7b8SAlexey Dobriyan 								currentSCCB)->
67541da177e4SLinus Torvalds 							    Sccb_forwardlink;
67551da177e4SLinus Torvalds 						}
67565c04a7b8SAlexey Dobriyan 						if (pCurrCard->currentSCCB ==
67575c04a7b8SAlexey Dobriyan 						    NULL)
67581da177e4SLinus Torvalds 							continue;
67595c04a7b8SAlexey Dobriyan 						if (pOldSccb != NULL) {
67605c04a7b8SAlexey Dobriyan 							pOldSccb->
67615c04a7b8SAlexey Dobriyan 							    Sccb_forwardlink =
67625c04a7b8SAlexey Dobriyan 							    (struct sccb
67635c04a7b8SAlexey Dobriyan 							     *)(pCurrCard->
67645c04a7b8SAlexey Dobriyan 								currentSCCB)->
67651da177e4SLinus Torvalds 							    Sccb_forwardlink;
67665c04a7b8SAlexey Dobriyan 							pOldSccb->
67675c04a7b8SAlexey Dobriyan 							    Sccb_backlink =
67685c04a7b8SAlexey Dobriyan 							    (struct sccb
67695c04a7b8SAlexey Dobriyan 							     *)(pCurrCard->
67705c04a7b8SAlexey Dobriyan 								currentSCCB)->
67711da177e4SLinus Torvalds 							    Sccb_backlink;
67725c04a7b8SAlexey Dobriyan 							currTar_Info->
67735c04a7b8SAlexey Dobriyan 							    TarSelQ_Cnt--;
67745c04a7b8SAlexey Dobriyan 						} else {
67755c04a7b8SAlexey Dobriyan 							currTar_Info->
67765c04a7b8SAlexey Dobriyan 							    TarSelQ_Head =
67775c04a7b8SAlexey Dobriyan 							    (struct sccb
67785c04a7b8SAlexey Dobriyan 							     *)(pCurrCard->
67795c04a7b8SAlexey Dobriyan 								currentSCCB)->
67805c04a7b8SAlexey Dobriyan 							    Sccb_forwardlink;
67811da177e4SLinus Torvalds 
67825c04a7b8SAlexey Dobriyan 							if (currTar_Info->
67835c04a7b8SAlexey Dobriyan 							    TarSelQ_Head ==
67845c04a7b8SAlexey Dobriyan 							    NULL) {
67855c04a7b8SAlexey Dobriyan 								currTar_Info->
67865c04a7b8SAlexey Dobriyan 								    TarSelQ_Tail
67875c04a7b8SAlexey Dobriyan 								    = NULL;
67885c04a7b8SAlexey Dobriyan 								currTar_Info->
67895c04a7b8SAlexey Dobriyan 								    TarSelQ_Cnt
67905c04a7b8SAlexey Dobriyan 								    = 0;
67915c04a7b8SAlexey Dobriyan 							} else {
67925c04a7b8SAlexey Dobriyan 								currTar_Info->
67935c04a7b8SAlexey Dobriyan 								    TarSelQ_Cnt--;
67945c04a7b8SAlexey Dobriyan 								currTar_Info->
67955c04a7b8SAlexey Dobriyan 								    TarSelQ_Head->
67965c04a7b8SAlexey Dobriyan 								    Sccb_backlink
67975c04a7b8SAlexey Dobriyan 								    =
67985c04a7b8SAlexey Dobriyan 								    (struct sccb
67995c04a7b8SAlexey Dobriyan 								     *)NULL;
68001da177e4SLinus Torvalds 							}
68011da177e4SLinus Torvalds 						}
68021da177e4SLinus Torvalds 						pCurrCard->scanIndex = scan_ptr;
68031da177e4SLinus Torvalds 
68045c04a7b8SAlexey Dobriyan 						pCurrCard->globalFlags |=
68055c04a7b8SAlexey Dobriyan 						    F_NEW_SCCB_CMD;
68061da177e4SLinus Torvalds 
68071da177e4SLinus Torvalds 						break;
68081da177e4SLinus Torvalds 					}
68091da177e4SLinus Torvalds 				}
68101da177e4SLinus Torvalds 			}
68111da177e4SLinus Torvalds 
68125c04a7b8SAlexey Dobriyan 			else {
68131da177e4SLinus Torvalds 				scan_ptr++;
68141da177e4SLinus Torvalds 				if (scan_ptr == MAX_SCSI_TAR) {
68151da177e4SLinus Torvalds 					scan_ptr = 0;
68161da177e4SLinus Torvalds 				}
68171da177e4SLinus Torvalds 			}
68181da177e4SLinus Torvalds 
68195c04a7b8SAlexey Dobriyan 		} else {
68201da177e4SLinus Torvalds 			if ((currTar_Info->TarSelQ_Cnt != 0) &&
68215c04a7b8SAlexey Dobriyan 			    (currTar_Info->TarLUNBusy[0] == 0)) {
68221da177e4SLinus Torvalds 
68235c04a7b8SAlexey Dobriyan 				pCurrCard->currentSCCB =
68245c04a7b8SAlexey Dobriyan 				    currTar_Info->TarSelQ_Head;
68251da177e4SLinus Torvalds 
68265c04a7b8SAlexey Dobriyan 				currTar_Info->TarSelQ_Head =
68275c04a7b8SAlexey Dobriyan 				    (struct sccb *)(pCurrCard->currentSCCB)->
68285c04a7b8SAlexey Dobriyan 				    Sccb_forwardlink;
68291da177e4SLinus Torvalds 
68305c04a7b8SAlexey Dobriyan 				if (currTar_Info->TarSelQ_Head == NULL) {
68311da177e4SLinus Torvalds 					currTar_Info->TarSelQ_Tail = NULL;
68321da177e4SLinus Torvalds 					currTar_Info->TarSelQ_Cnt = 0;
68335c04a7b8SAlexey Dobriyan 				} else {
68341da177e4SLinus Torvalds 					currTar_Info->TarSelQ_Cnt--;
68355c04a7b8SAlexey Dobriyan 					currTar_Info->TarSelQ_Head->
68365c04a7b8SAlexey Dobriyan 					    Sccb_backlink = (struct sccb *)NULL;
68371da177e4SLinus Torvalds 				}
68381da177e4SLinus Torvalds 
68391da177e4SLinus Torvalds 				scan_ptr++;
68401da177e4SLinus Torvalds 				if (scan_ptr == MAX_SCSI_TAR)
68411da177e4SLinus Torvalds 					scan_ptr = 0;
68421da177e4SLinus Torvalds 
68431da177e4SLinus Torvalds 				pCurrCard->scanIndex = scan_ptr;
68441da177e4SLinus Torvalds 
68451da177e4SLinus Torvalds 				pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
68461da177e4SLinus Torvalds 
68471da177e4SLinus Torvalds 				break;
68481da177e4SLinus Torvalds 			}
68491da177e4SLinus Torvalds 
68505c04a7b8SAlexey Dobriyan 			else {
68511da177e4SLinus Torvalds 				scan_ptr++;
68525c04a7b8SAlexey Dobriyan 				if (scan_ptr == MAX_SCSI_TAR) {
68531da177e4SLinus Torvalds 					scan_ptr = 0;
68541da177e4SLinus Torvalds 				}
68551da177e4SLinus Torvalds 			}
68561da177e4SLinus Torvalds 		}
68571da177e4SLinus Torvalds 	} while (scan_ptr != pCurrCard->scanIndex);
68581da177e4SLinus Torvalds }
68591da177e4SLinus Torvalds 
68601da177e4SLinus Torvalds /*---------------------------------------------------------------------
68611da177e4SLinus Torvalds  *
68621da177e4SLinus Torvalds  * Function: Queue Select Fail
68631da177e4SLinus Torvalds  *
68641da177e4SLinus Torvalds  * Description: Add the current SCCB to the head of the Queue.
68651da177e4SLinus Torvalds  *
68661da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
68671da177e4SLinus Torvalds 
68685c04a7b8SAlexey Dobriyan static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
68695c04a7b8SAlexey Dobriyan 				unsigned char p_card)
68701da177e4SLinus Torvalds {
6871db038cf8SAlexey Dobriyan 	unsigned char thisTarg;
6872f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
68731da177e4SLinus Torvalds 
68745c04a7b8SAlexey Dobriyan 	if (pCurrCard->currentSCCB != NULL) {
68755c04a7b8SAlexey Dobriyan 		thisTarg =
68765c04a7b8SAlexey Dobriyan 		    (unsigned char)(((struct sccb *)(pCurrCard->currentSCCB))->
68775c04a7b8SAlexey Dobriyan 				    TargID);
687847b5d69cSJames Bottomley  		currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
68791da177e4SLinus Torvalds 
688069eb2ea4SAlexey Dobriyan 		pCurrCard->currentSCCB->Sccb_backlink = (struct sccb *)NULL;
68811da177e4SLinus Torvalds 
68825c04a7b8SAlexey Dobriyan 		pCurrCard->currentSCCB->Sccb_forwardlink =
68835c04a7b8SAlexey Dobriyan 		    currTar_Info->TarSelQ_Head;
68841da177e4SLinus Torvalds 
68855c04a7b8SAlexey Dobriyan 		if (currTar_Info->TarSelQ_Cnt == 0) {
68861da177e4SLinus Torvalds 			currTar_Info->TarSelQ_Tail = pCurrCard->currentSCCB;
68871da177e4SLinus Torvalds 		}
68881da177e4SLinus Torvalds 
68895c04a7b8SAlexey Dobriyan 		else {
68905c04a7b8SAlexey Dobriyan 			currTar_Info->TarSelQ_Head->Sccb_backlink =
68915c04a7b8SAlexey Dobriyan 			    pCurrCard->currentSCCB;
68921da177e4SLinus Torvalds 		}
68931da177e4SLinus Torvalds 
68941da177e4SLinus Torvalds 		currTar_Info->TarSelQ_Head = pCurrCard->currentSCCB;
68951da177e4SLinus Torvalds 
68961da177e4SLinus Torvalds 		pCurrCard->currentSCCB = NULL;
68971da177e4SLinus Torvalds 		currTar_Info->TarSelQ_Cnt++;
68981da177e4SLinus Torvalds 	}
68991da177e4SLinus Torvalds }
69005c04a7b8SAlexey Dobriyan 
69011da177e4SLinus Torvalds /*---------------------------------------------------------------------
69021da177e4SLinus Torvalds  *
69031da177e4SLinus Torvalds  * Function: Queue Command Complete
69041da177e4SLinus Torvalds  *
69051da177e4SLinus Torvalds  * Description: Call the callback function with the current SCCB.
69061da177e4SLinus Torvalds  *
69071da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
69081da177e4SLinus Torvalds 
69095c04a7b8SAlexey Dobriyan static void FPT_queueCmdComplete(struct sccb_card *pCurrCard,
69105c04a7b8SAlexey Dobriyan 				 struct sccb *p_sccb, unsigned char p_card)
69111da177e4SLinus Torvalds {
69121da177e4SLinus Torvalds 
6913db038cf8SAlexey Dobriyan 	unsigned char i, SCSIcmd;
69141da177e4SLinus Torvalds 	CALL_BK_FN callback;
6915f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
69161da177e4SLinus Torvalds 
69171da177e4SLinus Torvalds 	SCSIcmd = p_sccb->Cdb[0];
69181da177e4SLinus Torvalds 
69191da177e4SLinus Torvalds 	if (!(p_sccb->Sccb_XferState & F_ALL_XFERRED)) {
69201da177e4SLinus Torvalds 
69215c04a7b8SAlexey Dobriyan 		if ((p_sccb->
69225c04a7b8SAlexey Dobriyan 		     ControlByte & (SCCB_DATA_XFER_OUT | SCCB_DATA_XFER_IN))
69235c04a7b8SAlexey Dobriyan 		    && (p_sccb->HostStatus == SCCB_COMPLETE)
69245c04a7b8SAlexey Dobriyan 		    && (p_sccb->TargetStatus != SSCHECK))
69251da177e4SLinus Torvalds 
69261da177e4SLinus Torvalds 			if ((SCSIcmd == SCSI_READ) ||
69271da177e4SLinus Torvalds 			    (SCSIcmd == SCSI_WRITE) ||
69281da177e4SLinus Torvalds 			    (SCSIcmd == SCSI_READ_EXTENDED) ||
69291da177e4SLinus Torvalds 			    (SCSIcmd == SCSI_WRITE_EXTENDED) ||
69301da177e4SLinus Torvalds 			    (SCSIcmd == SCSI_WRITE_AND_VERIFY) ||
69311da177e4SLinus Torvalds 			    (SCSIcmd == SCSI_START_STOP_UNIT) ||
69321da177e4SLinus Torvalds 			    (pCurrCard->globalFlags & F_NO_FILTER)
69331da177e4SLinus Torvalds 			    )
69341da177e4SLinus Torvalds 				p_sccb->HostStatus = SCCB_DATA_UNDER_RUN;
69351da177e4SLinus Torvalds 	}
69361da177e4SLinus Torvalds 
69375c04a7b8SAlexey Dobriyan 	if (p_sccb->SccbStatus == SCCB_IN_PROCESS) {
69381da177e4SLinus Torvalds 		if (p_sccb->HostStatus || p_sccb->TargetStatus)
69391da177e4SLinus Torvalds 			p_sccb->SccbStatus = SCCB_ERROR;
69401da177e4SLinus Torvalds 		else
69411da177e4SLinus Torvalds 			p_sccb->SccbStatus = SCCB_SUCCESS;
69421da177e4SLinus Torvalds 	}
69431da177e4SLinus Torvalds 
69441da177e4SLinus Torvalds 	if (p_sccb->Sccb_XferState & F_AUTO_SENSE) {
69451da177e4SLinus Torvalds 
69461da177e4SLinus Torvalds 		p_sccb->CdbLength = p_sccb->Save_CdbLen;
69471da177e4SLinus Torvalds 		for (i = 0; i < 6; i++) {
69481da177e4SLinus Torvalds 			p_sccb->Cdb[i] = p_sccb->Save_Cdb[i];
69491da177e4SLinus Torvalds 		}
69501da177e4SLinus Torvalds 	}
69511da177e4SLinus Torvalds 
69521da177e4SLinus Torvalds 	if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) ||
69531da177e4SLinus Torvalds 	    (p_sccb->OperationCode == RESIDUAL_COMMAND)) {
69541da177e4SLinus Torvalds 
695547b5d69cSJames Bottomley  		FPT_utilUpdateResidual(p_sccb);
69561da177e4SLinus Torvalds 	}
69571da177e4SLinus Torvalds 
69581da177e4SLinus Torvalds 	pCurrCard->cmdCounter--;
69591da177e4SLinus Torvalds 	if (!pCurrCard->cmdCounter) {
69601da177e4SLinus Torvalds 
69611da177e4SLinus Torvalds 		if (pCurrCard->globalFlags & F_GREEN_PC) {
69625c04a7b8SAlexey Dobriyan 			WR_HARPOON(pCurrCard->ioPort + hp_clkctrl_0,
69635c04a7b8SAlexey Dobriyan 				   (PWR_DWN | CLKCTRL_DEFAULT));
69641da177e4SLinus Torvalds 			WR_HARPOON(pCurrCard->ioPort + hp_sys_ctrl, STOP_CLK);
69651da177e4SLinus Torvalds 		}
69661da177e4SLinus Torvalds 
69671da177e4SLinus Torvalds 		WR_HARPOON(pCurrCard->ioPort + hp_semaphore,
69685c04a7b8SAlexey Dobriyan 			   (RD_HARPOON(pCurrCard->ioPort + hp_semaphore) &
69695c04a7b8SAlexey Dobriyan 			    ~SCCB_MGR_ACTIVE));
69701da177e4SLinus Torvalds 
69711da177e4SLinus Torvalds 	}
69721da177e4SLinus Torvalds 
69735c04a7b8SAlexey Dobriyan 	if (pCurrCard->discQCount != 0) {
697447b5d69cSJames Bottomley  		currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
69751da177e4SLinus Torvalds 		if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
69765c04a7b8SAlexey Dobriyan 		     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
69775c04a7b8SAlexey Dobriyan 		      TAG_Q_TRYING))) {
69781da177e4SLinus Torvalds 			pCurrCard->discQCount--;
69795c04a7b8SAlexey Dobriyan 			pCurrCard->discQ_Tbl[currTar_Info->
69805c04a7b8SAlexey Dobriyan 					     LunDiscQ_Idx[p_sccb->Lun]] = NULL;
69815c04a7b8SAlexey Dobriyan 		} else {
69825c04a7b8SAlexey Dobriyan 			if (p_sccb->Sccb_tag) {
69831da177e4SLinus Torvalds 				pCurrCard->discQCount--;
69841da177e4SLinus Torvalds 				pCurrCard->discQ_Tbl[p_sccb->Sccb_tag] = NULL;
69855c04a7b8SAlexey Dobriyan 			} else {
69861da177e4SLinus Torvalds 				pCurrCard->discQCount--;
69875c04a7b8SAlexey Dobriyan 				pCurrCard->discQ_Tbl[currTar_Info->
69885c04a7b8SAlexey Dobriyan 						     LunDiscQ_Idx[0]] = NULL;
69891da177e4SLinus Torvalds 			}
69901da177e4SLinus Torvalds 		}
69911da177e4SLinus Torvalds 
69921da177e4SLinus Torvalds 	}
69931da177e4SLinus Torvalds 
69941da177e4SLinus Torvalds 	callback = (CALL_BK_FN) p_sccb->SccbCallback;
69951da177e4SLinus Torvalds 	callback(p_sccb);
69961da177e4SLinus Torvalds 	pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
69971da177e4SLinus Torvalds 	pCurrCard->currentSCCB = NULL;
69981da177e4SLinus Torvalds }
69991da177e4SLinus Torvalds 
70001da177e4SLinus Torvalds /*---------------------------------------------------------------------
70011da177e4SLinus Torvalds  *
70021da177e4SLinus Torvalds  * Function: Queue Disconnect
70031da177e4SLinus Torvalds  *
70041da177e4SLinus Torvalds  * Description: Add SCCB to our disconnect array.
70051da177e4SLinus Torvalds  *
70061da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
700769eb2ea4SAlexey Dobriyan static void FPT_queueDisconnect(struct sccb *p_sccb, unsigned char p_card)
70081da177e4SLinus Torvalds {
7009f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
70101da177e4SLinus Torvalds 
701147b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
70121da177e4SLinus Torvalds 
701347b5d69cSJames Bottomley  	if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
70145c04a7b8SAlexey Dobriyan 	     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
70155c04a7b8SAlexey Dobriyan 		FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
70165c04a7b8SAlexey Dobriyan 					      LunDiscQ_Idx[p_sccb->Lun]] =
70175c04a7b8SAlexey Dobriyan 		    p_sccb;
70185c04a7b8SAlexey Dobriyan 	} else {
70195c04a7b8SAlexey Dobriyan 		if (p_sccb->Sccb_tag) {
70205c04a7b8SAlexey Dobriyan 			FPT_BL_Card[p_card].discQ_Tbl[p_sccb->Sccb_tag] =
70215c04a7b8SAlexey Dobriyan 			    p_sccb;
70225c04a7b8SAlexey Dobriyan 			FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarLUNBusy[0] =
70235c04a7b8SAlexey Dobriyan 			    0;
702447b5d69cSJames Bottomley  			FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarTagQ_Cnt++;
70255c04a7b8SAlexey Dobriyan 		} else {
70265c04a7b8SAlexey Dobriyan 			FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
70275c04a7b8SAlexey Dobriyan 						      LunDiscQ_Idx[0]] = p_sccb;
70281da177e4SLinus Torvalds 		}
70291da177e4SLinus Torvalds 	}
703047b5d69cSJames Bottomley  	FPT_BL_Card[p_card].currentSCCB = NULL;
70311da177e4SLinus Torvalds }
70321da177e4SLinus Torvalds 
70331da177e4SLinus Torvalds /*---------------------------------------------------------------------
70341da177e4SLinus Torvalds  *
70351da177e4SLinus Torvalds  * Function: Queue Flush SCCB
70361da177e4SLinus Torvalds  *
70371da177e4SLinus Torvalds  * Description: Flush all SCCB's back to the host driver for this target.
70381da177e4SLinus Torvalds  *
70391da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
70401da177e4SLinus Torvalds 
7041db038cf8SAlexey Dobriyan static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code)
70421da177e4SLinus Torvalds {
7043db038cf8SAlexey Dobriyan 	unsigned char qtag, thisTarg;
704469eb2ea4SAlexey Dobriyan 	struct sccb *currSCCB;
7045f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
70461da177e4SLinus Torvalds 
704747b5d69cSJames Bottomley  	currSCCB = FPT_BL_Card[p_card].currentSCCB;
70485c04a7b8SAlexey Dobriyan 	if (currSCCB != NULL) {
7049db038cf8SAlexey Dobriyan 		thisTarg = (unsigned char)currSCCB->TargID;
705047b5d69cSJames Bottomley  		currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
70511da177e4SLinus Torvalds 
70521da177e4SLinus Torvalds 		for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
70531da177e4SLinus Torvalds 
705447b5d69cSJames Bottomley  			if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
70555c04a7b8SAlexey Dobriyan 			    (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
70565c04a7b8SAlexey Dobriyan 			     thisTarg)) {
70571da177e4SLinus Torvalds 
70585c04a7b8SAlexey Dobriyan 				FPT_BL_Card[p_card].discQ_Tbl[qtag]->
70595c04a7b8SAlexey Dobriyan 				    HostStatus = (unsigned char)error_code;
70601da177e4SLinus Torvalds 
70615c04a7b8SAlexey Dobriyan 				FPT_queueCmdComplete(&FPT_BL_Card[p_card],
70625c04a7b8SAlexey Dobriyan 						     FPT_BL_Card[p_card].
70635c04a7b8SAlexey Dobriyan 						     discQ_Tbl[qtag], p_card);
70641da177e4SLinus Torvalds 
706547b5d69cSJames Bottomley  				FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
70661da177e4SLinus Torvalds 				currTar_Info->TarTagQ_Cnt--;
70671da177e4SLinus Torvalds 
70681da177e4SLinus Torvalds 			}
70691da177e4SLinus Torvalds 		}
70701da177e4SLinus Torvalds 	}
70711da177e4SLinus Torvalds 
70721da177e4SLinus Torvalds }
70731da177e4SLinus Torvalds 
70741da177e4SLinus Torvalds /*---------------------------------------------------------------------
70751da177e4SLinus Torvalds  *
70761da177e4SLinus Torvalds  * Function: Queue Flush Target SCCB
70771da177e4SLinus Torvalds  *
70781da177e4SLinus Torvalds  * Description: Flush all SCCB's back to the host driver for this target.
70791da177e4SLinus Torvalds  *
70801da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
70811da177e4SLinus Torvalds 
7082db038cf8SAlexey Dobriyan static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
7083db038cf8SAlexey Dobriyan 				   unsigned char error_code)
70841da177e4SLinus Torvalds {
7085db038cf8SAlexey Dobriyan 	unsigned char qtag;
7086f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
70871da177e4SLinus Torvalds 
708847b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
70891da177e4SLinus Torvalds 
70901da177e4SLinus Torvalds 	for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
70911da177e4SLinus Torvalds 
709247b5d69cSJames Bottomley  		if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
70935c04a7b8SAlexey Dobriyan 		    (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg)) {
70941da177e4SLinus Torvalds 
70955c04a7b8SAlexey Dobriyan 			FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus =
70965c04a7b8SAlexey Dobriyan 			    (unsigned char)error_code;
70971da177e4SLinus Torvalds 
70985c04a7b8SAlexey Dobriyan 			FPT_queueCmdComplete(&FPT_BL_Card[p_card],
70995c04a7b8SAlexey Dobriyan 					     FPT_BL_Card[p_card].
71005c04a7b8SAlexey Dobriyan 					     discQ_Tbl[qtag], p_card);
71011da177e4SLinus Torvalds 
710247b5d69cSJames Bottomley  			FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
71031da177e4SLinus Torvalds 			currTar_Info->TarTagQ_Cnt--;
71041da177e4SLinus Torvalds 
71051da177e4SLinus Torvalds 		}
71061da177e4SLinus Torvalds 	}
71071da177e4SLinus Torvalds 
71081da177e4SLinus Torvalds }
71091da177e4SLinus Torvalds 
711069eb2ea4SAlexey Dobriyan static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char p_card)
71111da177e4SLinus Torvalds {
7112f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
711347b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
71141da177e4SLinus Torvalds 
71151da177e4SLinus Torvalds 	p_SCCB->Sccb_forwardlink = NULL;
71161da177e4SLinus Torvalds 
71171da177e4SLinus Torvalds 	p_SCCB->Sccb_backlink = currTar_Info->TarSelQ_Tail;
71181da177e4SLinus Torvalds 
71191da177e4SLinus Torvalds 	if (currTar_Info->TarSelQ_Cnt == 0) {
71201da177e4SLinus Torvalds 
71211da177e4SLinus Torvalds 		currTar_Info->TarSelQ_Head = p_SCCB;
71221da177e4SLinus Torvalds 	}
71231da177e4SLinus Torvalds 
71241da177e4SLinus Torvalds 	else {
71251da177e4SLinus Torvalds 
71261da177e4SLinus Torvalds 		currTar_Info->TarSelQ_Tail->Sccb_forwardlink = p_SCCB;
71271da177e4SLinus Torvalds 	}
71281da177e4SLinus Torvalds 
71291da177e4SLinus Torvalds 	currTar_Info->TarSelQ_Tail = p_SCCB;
71301da177e4SLinus Torvalds 	currTar_Info->TarSelQ_Cnt++;
71311da177e4SLinus Torvalds }
71321da177e4SLinus Torvalds 
71331da177e4SLinus Torvalds /*---------------------------------------------------------------------
71341da177e4SLinus Torvalds  *
71351da177e4SLinus Torvalds  * Function: Queue Find SCCB
71361da177e4SLinus Torvalds  *
71371da177e4SLinus Torvalds  * Description: Search the target select Queue for this SCCB, and
71381da177e4SLinus Torvalds  *              remove it if found.
71391da177e4SLinus Torvalds  *
71401da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
71411da177e4SLinus Torvalds 
71425c04a7b8SAlexey Dobriyan static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB,
71435c04a7b8SAlexey Dobriyan 				       unsigned char p_card)
71441da177e4SLinus Torvalds {
714569eb2ea4SAlexey Dobriyan 	struct sccb *q_ptr;
7146f31dc0cdSAlexey Dobriyan 	struct sccb_mgr_tar_info *currTar_Info;
71471da177e4SLinus Torvalds 
714847b5d69cSJames Bottomley  	currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
71491da177e4SLinus Torvalds 
71501da177e4SLinus Torvalds 	q_ptr = currTar_Info->TarSelQ_Head;
71511da177e4SLinus Torvalds 
71521da177e4SLinus Torvalds 	while (q_ptr != NULL) {
71531da177e4SLinus Torvalds 
71541da177e4SLinus Torvalds 		if (q_ptr == p_SCCB) {
71551da177e4SLinus Torvalds 
71561da177e4SLinus Torvalds 			if (currTar_Info->TarSelQ_Head == q_ptr) {
71571da177e4SLinus Torvalds 
71585c04a7b8SAlexey Dobriyan 				currTar_Info->TarSelQ_Head =
71595c04a7b8SAlexey Dobriyan 				    q_ptr->Sccb_forwardlink;
71601da177e4SLinus Torvalds 			}
71611da177e4SLinus Torvalds 
71621da177e4SLinus Torvalds 			if (currTar_Info->TarSelQ_Tail == q_ptr) {
71631da177e4SLinus Torvalds 
71645c04a7b8SAlexey Dobriyan 				currTar_Info->TarSelQ_Tail =
71655c04a7b8SAlexey Dobriyan 				    q_ptr->Sccb_backlink;
71661da177e4SLinus Torvalds 			}
71671da177e4SLinus Torvalds 
71681da177e4SLinus Torvalds 			if (q_ptr->Sccb_forwardlink != NULL) {
71695c04a7b8SAlexey Dobriyan 				q_ptr->Sccb_forwardlink->Sccb_backlink =
71705c04a7b8SAlexey Dobriyan 				    q_ptr->Sccb_backlink;
71711da177e4SLinus Torvalds 			}
71721da177e4SLinus Torvalds 
71731da177e4SLinus Torvalds 			if (q_ptr->Sccb_backlink != NULL) {
71745c04a7b8SAlexey Dobriyan 				q_ptr->Sccb_backlink->Sccb_forwardlink =
71755c04a7b8SAlexey Dobriyan 				    q_ptr->Sccb_forwardlink;
71761da177e4SLinus Torvalds 			}
71771da177e4SLinus Torvalds 
71781da177e4SLinus Torvalds 			currTar_Info->TarSelQ_Cnt--;
71791da177e4SLinus Torvalds 
71805c1b85e2SAlexey Dobriyan 			return 1;
71811da177e4SLinus Torvalds 		}
71821da177e4SLinus Torvalds 
71831da177e4SLinus Torvalds 		else {
71841da177e4SLinus Torvalds 			q_ptr = q_ptr->Sccb_forwardlink;
71851da177e4SLinus Torvalds 		}
71861da177e4SLinus Torvalds 	}
71871da177e4SLinus Torvalds 
71885c1b85e2SAlexey Dobriyan 	return 0;
71891da177e4SLinus Torvalds 
71901da177e4SLinus Torvalds }
71911da177e4SLinus Torvalds 
71921da177e4SLinus Torvalds /*---------------------------------------------------------------------
71931da177e4SLinus Torvalds  *
71941da177e4SLinus Torvalds  * Function: Utility Update Residual Count
71951da177e4SLinus Torvalds  *
71961da177e4SLinus Torvalds  * Description: Update the XferCnt to the remaining byte count.
71971da177e4SLinus Torvalds  *              If we transferred all the data then just write zero.
71981da177e4SLinus Torvalds  *              If Non-SG transfer then report Total Cnt - Actual Transfer
71991da177e4SLinus Torvalds  *              Cnt.  For SG transfers add the count fields of all
72001da177e4SLinus Torvalds  *              remaining SG elements, as well as any partial remaining
72011da177e4SLinus Torvalds  *              element.
72021da177e4SLinus Torvalds  *
72031da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
72041da177e4SLinus Torvalds 
720569eb2ea4SAlexey Dobriyan static void FPT_utilUpdateResidual(struct sccb *p_SCCB)
72061da177e4SLinus Torvalds {
7207d63a4cccSAlexey Dobriyan 	unsigned long partial_cnt;
7208ce793215SAlexey Dobriyan 	unsigned int sg_index;
7209d63a4cccSAlexey Dobriyan 	unsigned long *sg_ptr;
72101da177e4SLinus Torvalds 
72111da177e4SLinus Torvalds 	if (p_SCCB->Sccb_XferState & F_ALL_XFERRED) {
72121da177e4SLinus Torvalds 
72131da177e4SLinus Torvalds 		p_SCCB->DataLength = 0x0000;
72141da177e4SLinus Torvalds 	}
72151da177e4SLinus Torvalds 
72161da177e4SLinus Torvalds 	else if (p_SCCB->Sccb_XferState & F_SG_XFER) {
72171da177e4SLinus Torvalds 
72181da177e4SLinus Torvalds 		partial_cnt = 0x0000;
72191da177e4SLinus Torvalds 
72201da177e4SLinus Torvalds 		sg_index = p_SCCB->Sccb_sgseg;
72211da177e4SLinus Torvalds 
7222d63a4cccSAlexey Dobriyan 		sg_ptr = (unsigned long *)p_SCCB->DataPointer;
72231da177e4SLinus Torvalds 
72241da177e4SLinus Torvalds 		if (p_SCCB->Sccb_SGoffset) {
72251da177e4SLinus Torvalds 
72261da177e4SLinus Torvalds 			partial_cnt = p_SCCB->Sccb_SGoffset;
72271da177e4SLinus Torvalds 			sg_index++;
72281da177e4SLinus Torvalds 		}
72291da177e4SLinus Torvalds 
72305c04a7b8SAlexey Dobriyan 		while (((unsigned long)sg_index *
72315c04a7b8SAlexey Dobriyan 			(unsigned long)SG_ELEMENT_SIZE) < p_SCCB->DataLength) {
72321da177e4SLinus Torvalds 
72331da177e4SLinus Torvalds 			partial_cnt += *(sg_ptr + (sg_index * 2));
72341da177e4SLinus Torvalds 			sg_index++;
72351da177e4SLinus Torvalds 		}
72361da177e4SLinus Torvalds 
72371da177e4SLinus Torvalds 		p_SCCB->DataLength = partial_cnt;
72381da177e4SLinus Torvalds 	}
72391da177e4SLinus Torvalds 
72401da177e4SLinus Torvalds 	else {
72411da177e4SLinus Torvalds 
72421da177e4SLinus Torvalds 		p_SCCB->DataLength -= p_SCCB->Sccb_ATC;
72431da177e4SLinus Torvalds 	}
72441da177e4SLinus Torvalds }
72451da177e4SLinus Torvalds 
72461da177e4SLinus Torvalds /*---------------------------------------------------------------------
72471da177e4SLinus Torvalds  *
72481da177e4SLinus Torvalds  * Function: Wait 1 Second
72491da177e4SLinus Torvalds  *
72501da177e4SLinus Torvalds  * Description: Wait for 1 second.
72511da177e4SLinus Torvalds  *
72521da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
72531da177e4SLinus Torvalds 
7254d63a4cccSAlexey Dobriyan static void FPT_Wait1Second(unsigned long p_port)
72551da177e4SLinus Torvalds {
7256db038cf8SAlexey Dobriyan 	unsigned char i;
72571da177e4SLinus Torvalds 
72581da177e4SLinus Torvalds 	for (i = 0; i < 4; i++) {
72591da177e4SLinus Torvalds 
726047b5d69cSJames Bottomley  		FPT_Wait(p_port, TO_250ms);
72611da177e4SLinus Torvalds 
72621da177e4SLinus Torvalds 		if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
72631da177e4SLinus Torvalds 			break;
72641da177e4SLinus Torvalds 
72651da177e4SLinus Torvalds 		if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
72661da177e4SLinus Torvalds 			break;
72671da177e4SLinus Torvalds 	}
72681da177e4SLinus Torvalds }
72691da177e4SLinus Torvalds 
72701da177e4SLinus Torvalds /*---------------------------------------------------------------------
72711da177e4SLinus Torvalds  *
727247b5d69cSJames Bottomley   * Function: FPT_Wait
72731da177e4SLinus Torvalds  *
72741da177e4SLinus Torvalds  * Description: Wait the desired delay.
72751da177e4SLinus Torvalds  *
72761da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
72771da177e4SLinus Torvalds 
7278d63a4cccSAlexey Dobriyan static void FPT_Wait(unsigned long p_port, unsigned char p_delay)
72791da177e4SLinus Torvalds {
7280db038cf8SAlexey Dobriyan 	unsigned char old_timer;
7281db038cf8SAlexey Dobriyan 	unsigned char green_flag;
72821da177e4SLinus Torvalds 
72831da177e4SLinus Torvalds 	old_timer = RD_HARPOON(p_port + hp_seltimeout);
72841da177e4SLinus Torvalds 
72851da177e4SLinus Torvalds 	green_flag = RD_HARPOON(p_port + hp_clkctrl_0);
72861da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
72871da177e4SLinus Torvalds 
72881da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_seltimeout, p_delay);
72891da177e4SLinus Torvalds 	WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
729047b5d69cSJames Bottomley  	WRW_HARPOON((p_port + hp_intena), (FPT_default_intena & ~TIMEOUT));
72911da177e4SLinus Torvalds 
72921da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_portctrl_0,
72931da177e4SLinus Torvalds 		   (RD_HARPOON(p_port + hp_portctrl_0) | START_TO));
72941da177e4SLinus Torvalds 
72951da177e4SLinus Torvalds 	while (!(RDW_HARPOON((p_port + hp_intstat)) & TIMEOUT)) {
72961da177e4SLinus Torvalds 
72971da177e4SLinus Torvalds 		if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
72981da177e4SLinus Torvalds 			break;
72991da177e4SLinus Torvalds 
73001da177e4SLinus Torvalds 		if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
73011da177e4SLinus Torvalds 			break;
73021da177e4SLinus Torvalds 	}
73031da177e4SLinus Torvalds 
73041da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_portctrl_0,
73051da177e4SLinus Torvalds 		   (RD_HARPOON(p_port + hp_portctrl_0) & ~START_TO));
73061da177e4SLinus Torvalds 
73071da177e4SLinus Torvalds 	WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
730847b5d69cSJames Bottomley  	WRW_HARPOON((p_port + hp_intena), FPT_default_intena);
73091da177e4SLinus Torvalds 
73101da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_clkctrl_0, green_flag);
73111da177e4SLinus Torvalds 
73121da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_seltimeout, old_timer);
73131da177e4SLinus Torvalds }
73141da177e4SLinus Torvalds 
73151da177e4SLinus Torvalds /*---------------------------------------------------------------------
73161da177e4SLinus Torvalds  *
73171da177e4SLinus Torvalds  * Function: Enable/Disable Write to EEPROM
73181da177e4SLinus Torvalds  *
73191da177e4SLinus Torvalds  * Description: The EEPROM must first be enabled for writes
73201da177e4SLinus Torvalds  *              A total of 9 clocks are needed.
73211da177e4SLinus Torvalds  *
73221da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
73231da177e4SLinus Torvalds 
7324d63a4cccSAlexey Dobriyan static void FPT_utilEEWriteOnOff(unsigned long p_port, unsigned char p_mode)
73251da177e4SLinus Torvalds {
7326db038cf8SAlexey Dobriyan 	unsigned char ee_value;
73271da177e4SLinus Torvalds 
73285c04a7b8SAlexey Dobriyan 	ee_value =
73295c04a7b8SAlexey Dobriyan 	    (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
73305c04a7b8SAlexey Dobriyan 			    (EXT_ARB_ACK | SCSI_TERM_ENA_H));
73311da177e4SLinus Torvalds 
73321da177e4SLinus Torvalds 	if (p_mode)
73331da177e4SLinus Torvalds 
733447b5d69cSJames Bottomley  		FPT_utilEESendCmdAddr(p_port, EWEN, EWEN_ADDR);
73351da177e4SLinus Torvalds 
73361da177e4SLinus Torvalds 	else
73371da177e4SLinus Torvalds 
733847b5d69cSJames Bottomley  		FPT_utilEESendCmdAddr(p_port, EWDS, EWDS_ADDR);
73391da177e4SLinus Torvalds 
73401da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));	/*Turn off CS */
73411da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);	/*Turn off Master Select */
73421da177e4SLinus Torvalds }
73431da177e4SLinus Torvalds 
73441da177e4SLinus Torvalds /*---------------------------------------------------------------------
73451da177e4SLinus Torvalds  *
73461da177e4SLinus Torvalds  * Function: Write EEPROM
73471da177e4SLinus Torvalds  *
73481da177e4SLinus Torvalds  * Description: Write a word to the EEPROM at the specified
73491da177e4SLinus Torvalds  *              address.
73501da177e4SLinus Torvalds  *
73511da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
73521da177e4SLinus Torvalds 
73535c04a7b8SAlexey Dobriyan static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data,
73545c04a7b8SAlexey Dobriyan 			    unsigned short ee_addr)
73551da177e4SLinus Torvalds {
73561da177e4SLinus Torvalds 
7357db038cf8SAlexey Dobriyan 	unsigned char ee_value;
7358c823feebSAlexey Dobriyan 	unsigned short i;
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_WRITE, ee_addr);
73661da177e4SLinus Torvalds 
73671da177e4SLinus Torvalds 	ee_value |= (SEE_MS + SEE_CS);
73681da177e4SLinus Torvalds 
73691da177e4SLinus Torvalds 	for (i = 0x8000; i != 0; i >>= 1) {
73701da177e4SLinus Torvalds 
73711da177e4SLinus Torvalds 		if (i & ee_data)
73721da177e4SLinus Torvalds 			ee_value |= SEE_DO;
73731da177e4SLinus Torvalds 		else
73741da177e4SLinus Torvalds 			ee_value &= ~SEE_DO;
73751da177e4SLinus Torvalds 
73761da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
73771da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
73781da177e4SLinus Torvalds 		ee_value |= SEE_CLK;	/* Clock  data! */
73791da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
73801da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
73811da177e4SLinus Torvalds 		ee_value &= ~SEE_CLK;
73821da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
73831da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
73841da177e4SLinus Torvalds 	}
73851da177e4SLinus Torvalds 	ee_value &= (EXT_ARB_ACK | SCSI_TERM_ENA_H);
73861da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));
73871da177e4SLinus Torvalds 
738847b5d69cSJames Bottomley  	FPT_Wait(p_port, TO_10ms);
73891da177e4SLinus Torvalds 
73901da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS | SEE_CS));	/* Set CS to EEPROM */
73911da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));	/* Turn off CS */
73921da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);	/* Turn off Master Select */
73931da177e4SLinus Torvalds }
73941da177e4SLinus Torvalds 
73951da177e4SLinus Torvalds /*---------------------------------------------------------------------
73961da177e4SLinus Torvalds  *
73971da177e4SLinus Torvalds  * Function: Read EEPROM
73981da177e4SLinus Torvalds  *
73991da177e4SLinus Torvalds  * Description: Read a word from the EEPROM at the desired
74001da177e4SLinus Torvalds  *              address.
74011da177e4SLinus Torvalds  *
74021da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
74031da177e4SLinus Torvalds 
74045c04a7b8SAlexey Dobriyan static unsigned short FPT_utilEERead(unsigned long p_port,
74055c04a7b8SAlexey Dobriyan 				     unsigned short ee_addr)
74061da177e4SLinus Torvalds {
7407c823feebSAlexey Dobriyan 	unsigned short i, ee_data1, ee_data2;
74081da177e4SLinus Torvalds 
74091da177e4SLinus Torvalds 	i = 0;
741047b5d69cSJames Bottomley  	ee_data1 = FPT_utilEEReadOrg(p_port, ee_addr);
74115c04a7b8SAlexey Dobriyan 	do {
741247b5d69cSJames Bottomley  		ee_data2 = FPT_utilEEReadOrg(p_port, ee_addr);
74131da177e4SLinus Torvalds 
74141da177e4SLinus Torvalds 		if (ee_data1 == ee_data2)
74155c1b85e2SAlexey Dobriyan 			return ee_data1;
74161da177e4SLinus Torvalds 
74171da177e4SLinus Torvalds 		ee_data1 = ee_data2;
74181da177e4SLinus Torvalds 		i++;
74191da177e4SLinus Torvalds 
74201da177e4SLinus Torvalds 	} while (i < 4);
74211da177e4SLinus Torvalds 
74225c1b85e2SAlexey Dobriyan 	return ee_data1;
74231da177e4SLinus Torvalds }
74241da177e4SLinus Torvalds 
74251da177e4SLinus Torvalds /*---------------------------------------------------------------------
74261da177e4SLinus Torvalds  *
74271da177e4SLinus Torvalds  * Function: Read EEPROM Original
74281da177e4SLinus Torvalds  *
74291da177e4SLinus Torvalds  * Description: Read a word from the EEPROM at the desired
74301da177e4SLinus Torvalds  *              address.
74311da177e4SLinus Torvalds  *
74321da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
74331da177e4SLinus Torvalds 
74345c04a7b8SAlexey Dobriyan static unsigned short FPT_utilEEReadOrg(unsigned long p_port,
74355c04a7b8SAlexey Dobriyan 					unsigned short ee_addr)
74361da177e4SLinus Torvalds {
74371da177e4SLinus Torvalds 
7438db038cf8SAlexey Dobriyan 	unsigned char ee_value;
7439c823feebSAlexey Dobriyan 	unsigned short i, ee_data;
74401da177e4SLinus Torvalds 
74415c04a7b8SAlexey Dobriyan 	ee_value =
74425c04a7b8SAlexey Dobriyan 	    (unsigned
74435c04a7b8SAlexey Dobriyan 	     char)((RD_HARPOON(p_port + hp_ee_ctrl) &
74445c04a7b8SAlexey Dobriyan 		    (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
74451da177e4SLinus Torvalds 
744647b5d69cSJames Bottomley  	FPT_utilEESendCmdAddr(p_port, EE_READ, ee_addr);
74471da177e4SLinus Torvalds 
74481da177e4SLinus Torvalds 	ee_value |= (SEE_MS + SEE_CS);
74491da177e4SLinus Torvalds 	ee_data = 0;
74501da177e4SLinus Torvalds 
74511da177e4SLinus Torvalds 	for (i = 1; i <= 16; i++) {
74521da177e4SLinus Torvalds 
74531da177e4SLinus Torvalds 		ee_value |= SEE_CLK;	/* Clock  data! */
74541da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74551da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74561da177e4SLinus Torvalds 		ee_value &= ~SEE_CLK;
74571da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74581da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74591da177e4SLinus Torvalds 
74601da177e4SLinus Torvalds 		ee_data <<= 1;
74611da177e4SLinus Torvalds 
74621da177e4SLinus Torvalds 		if (RD_HARPOON(p_port + hp_ee_ctrl) & SEE_DI)
74631da177e4SLinus Torvalds 			ee_data |= 1;
74641da177e4SLinus Torvalds 	}
74651da177e4SLinus Torvalds 
74661da177e4SLinus Torvalds 	ee_value &= ~(SEE_MS + SEE_CS);
74671da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));	/*Turn off CS */
74681da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);	/*Turn off Master Select */
74691da177e4SLinus Torvalds 
74705c1b85e2SAlexey Dobriyan 	return ee_data;
74711da177e4SLinus Torvalds }
74721da177e4SLinus Torvalds 
74731da177e4SLinus Torvalds /*---------------------------------------------------------------------
74741da177e4SLinus Torvalds  *
74751da177e4SLinus Torvalds  * Function: Send EE command and Address to the EEPROM
74761da177e4SLinus Torvalds  *
74771da177e4SLinus Torvalds  * Description: Transfers the correct command and sends the address
74781da177e4SLinus Torvalds  *              to the eeprom.
74791da177e4SLinus Torvalds  *
74801da177e4SLinus Torvalds  *---------------------------------------------------------------------*/
74811da177e4SLinus Torvalds 
74825c04a7b8SAlexey Dobriyan static void FPT_utilEESendCmdAddr(unsigned long p_port, unsigned char ee_cmd,
74835c04a7b8SAlexey Dobriyan 				  unsigned short ee_addr)
74841da177e4SLinus Torvalds {
7485db038cf8SAlexey Dobriyan 	unsigned char ee_value;
7486db038cf8SAlexey Dobriyan 	unsigned char narrow_flg;
74871da177e4SLinus Torvalds 
7488c823feebSAlexey Dobriyan 	unsigned short i;
74891da177e4SLinus Torvalds 
74905c04a7b8SAlexey Dobriyan 	narrow_flg =
74915c04a7b8SAlexey Dobriyan 	    (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
74925c04a7b8SAlexey Dobriyan 			    NARROW_SCSI_CARD);
74931da177e4SLinus Torvalds 
74941da177e4SLinus Torvalds 	ee_value = SEE_MS;
74951da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74961da177e4SLinus Torvalds 
74971da177e4SLinus Torvalds 	ee_value |= SEE_CS;	/* Set CS to EEPROM */
74981da177e4SLinus Torvalds 	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
74991da177e4SLinus Torvalds 
75001da177e4SLinus Torvalds 	for (i = 0x04; i != 0; i >>= 1) {
75011da177e4SLinus Torvalds 
75021da177e4SLinus Torvalds 		if (i & ee_cmd)
75031da177e4SLinus Torvalds 			ee_value |= SEE_DO;
75041da177e4SLinus Torvalds 		else
75051da177e4SLinus Torvalds 			ee_value &= ~SEE_DO;
75061da177e4SLinus Torvalds 
75071da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
75081da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
75091da177e4SLinus Torvalds 		ee_value |= SEE_CLK;	/* Clock  data! */
75101da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
75111da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
75121da177e4SLinus Torvalds 		ee_value &= ~SEE_CLK;
75131da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
75141da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
75151da177e4SLinus Torvalds 	}
75161da177e4SLinus Torvalds 
75171da177e4SLinus Torvalds 	if (narrow_flg)
75181da177e4SLinus Torvalds 		i = 0x0080;
75191da177e4SLinus Torvalds 
75201da177e4SLinus Torvalds 	else
75211da177e4SLinus Torvalds 		i = 0x0200;
75221da177e4SLinus Torvalds 
75231da177e4SLinus Torvalds 	while (i != 0) {
75241da177e4SLinus Torvalds 
75251da177e4SLinus Torvalds 		if (i & ee_addr)
75261da177e4SLinus Torvalds 			ee_value |= SEE_DO;
75271da177e4SLinus Torvalds 		else
75281da177e4SLinus Torvalds 			ee_value &= ~SEE_DO;
75291da177e4SLinus Torvalds 
75301da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
75311da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
75321da177e4SLinus Torvalds 		ee_value |= SEE_CLK;	/* Clock  data! */
75331da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
75341da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
75351da177e4SLinus Torvalds 		ee_value &= ~SEE_CLK;
75361da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
75371da177e4SLinus Torvalds 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
75381da177e4SLinus Torvalds 
75391da177e4SLinus Torvalds 		i >>= 1;
75401da177e4SLinus Torvalds 	}
75411da177e4SLinus Torvalds }
75421da177e4SLinus Torvalds 
7543c823feebSAlexey Dobriyan static unsigned short FPT_CalcCrc16(unsigned char buffer[])
75441da177e4SLinus Torvalds {
7545c823feebSAlexey Dobriyan 	unsigned short crc = 0;
75461da177e4SLinus Torvalds 	int i, j;
7547c823feebSAlexey Dobriyan 	unsigned short ch;
75485c04a7b8SAlexey Dobriyan 	for (i = 0; i < ID_STRING_LENGTH; i++) {
7549c823feebSAlexey Dobriyan 		ch = (unsigned short)buffer[i];
75505c04a7b8SAlexey Dobriyan 		for (j = 0; j < 8; j++) {
75511da177e4SLinus Torvalds 			if ((crc ^ ch) & 1)
75521da177e4SLinus Torvalds 				crc = (crc >> 1) ^ CRCMASK;
75531da177e4SLinus Torvalds 			else
75541da177e4SLinus Torvalds 				crc >>= 1;
75551da177e4SLinus Torvalds 			ch >>= 1;
75561da177e4SLinus Torvalds 		}
75571da177e4SLinus Torvalds 	}
75585c1b85e2SAlexey Dobriyan 	return crc;
75591da177e4SLinus Torvalds }
75601da177e4SLinus Torvalds 
7561db038cf8SAlexey Dobriyan static unsigned char FPT_CalcLrc(unsigned char buffer[])
75621da177e4SLinus Torvalds {
75631da177e4SLinus Torvalds 	int i;
7564db038cf8SAlexey Dobriyan 	unsigned char lrc;
75651da177e4SLinus Torvalds 	lrc = 0;
75661da177e4SLinus Torvalds 	for (i = 0; i < ID_STRING_LENGTH; i++)
75671da177e4SLinus Torvalds 		lrc ^= buffer[i];
75685c1b85e2SAlexey Dobriyan 	return lrc;
75691da177e4SLinus Torvalds }
75701da177e4SLinus Torvalds 
75711da177e4SLinus Torvalds /*
75721da177e4SLinus Torvalds   The following inline definitions avoid type conflicts.
75731da177e4SLinus Torvalds */
75741da177e4SLinus Torvalds 
75751da177e4SLinus Torvalds static inline unsigned char
75761da177e4SLinus Torvalds FlashPoint__ProbeHostAdapter(struct FlashPoint_Info *FlashPointInfo)
75771da177e4SLinus Torvalds {
75785c04a7b8SAlexey Dobriyan 	return FlashPoint_ProbeHostAdapter((struct sccb_mgr_info *)
75795c04a7b8SAlexey Dobriyan 					   FlashPointInfo);
75801da177e4SLinus Torvalds }
75811da177e4SLinus Torvalds 
75821da177e4SLinus Torvalds static inline FlashPoint_CardHandle_T
75831da177e4SLinus Torvalds FlashPoint__HardwareResetHostAdapter(struct FlashPoint_Info *FlashPointInfo)
75841da177e4SLinus Torvalds {
75855c04a7b8SAlexey Dobriyan 	return FlashPoint_HardwareResetHostAdapter((struct sccb_mgr_info *)
75865c04a7b8SAlexey Dobriyan 						   FlashPointInfo);
75871da177e4SLinus Torvalds }
75881da177e4SLinus Torvalds 
75891da177e4SLinus Torvalds static inline void
75901da177e4SLinus Torvalds FlashPoint__ReleaseHostAdapter(FlashPoint_CardHandle_T CardHandle)
75911da177e4SLinus Torvalds {
75921da177e4SLinus Torvalds 	FlashPoint_ReleaseHostAdapter(CardHandle);
75931da177e4SLinus Torvalds }
75941da177e4SLinus Torvalds 
75951da177e4SLinus Torvalds static inline void
75965c04a7b8SAlexey Dobriyan FlashPoint__StartCCB(FlashPoint_CardHandle_T CardHandle,
75975c04a7b8SAlexey Dobriyan 		     struct BusLogic_CCB *CCB)
75981da177e4SLinus Torvalds {
759969eb2ea4SAlexey Dobriyan 	FlashPoint_StartCCB(CardHandle, (struct sccb *)CCB);
76001da177e4SLinus Torvalds }
76011da177e4SLinus Torvalds 
76021da177e4SLinus Torvalds static inline void
76035c04a7b8SAlexey Dobriyan FlashPoint__AbortCCB(FlashPoint_CardHandle_T CardHandle,
76045c04a7b8SAlexey Dobriyan 		     struct BusLogic_CCB *CCB)
76051da177e4SLinus Torvalds {
760669eb2ea4SAlexey Dobriyan 	FlashPoint_AbortCCB(CardHandle, (struct sccb *)CCB);
76071da177e4SLinus Torvalds }
76081da177e4SLinus Torvalds 
76092065e310SRichard Knutsson static inline bool
76101da177e4SLinus Torvalds FlashPoint__InterruptPending(FlashPoint_CardHandle_T CardHandle)
76111da177e4SLinus Torvalds {
76121da177e4SLinus Torvalds 	return FlashPoint_InterruptPending(CardHandle);
76131da177e4SLinus Torvalds }
76141da177e4SLinus Torvalds 
76151da177e4SLinus Torvalds static inline int
76161da177e4SLinus Torvalds FlashPoint__HandleInterrupt(FlashPoint_CardHandle_T CardHandle)
76171da177e4SLinus Torvalds {
76181da177e4SLinus Torvalds 	return FlashPoint_HandleInterrupt(CardHandle);
76191da177e4SLinus Torvalds }
76201da177e4SLinus Torvalds 
76211da177e4SLinus Torvalds #define FlashPoint_ProbeHostAdapter	    FlashPoint__ProbeHostAdapter
76221da177e4SLinus Torvalds #define FlashPoint_HardwareResetHostAdapter FlashPoint__HardwareResetHostAdapter
76231da177e4SLinus Torvalds #define FlashPoint_ReleaseHostAdapter	    FlashPoint__ReleaseHostAdapter
76241da177e4SLinus Torvalds #define FlashPoint_StartCCB		    FlashPoint__StartCCB
76251da177e4SLinus Torvalds #define FlashPoint_AbortCCB		    FlashPoint__AbortCCB
76261da177e4SLinus Torvalds #define FlashPoint_InterruptPending	    FlashPoint__InterruptPending
76271da177e4SLinus Torvalds #define FlashPoint_HandleInterrupt	    FlashPoint__HandleInterrupt
76281da177e4SLinus Torvalds 
762978b4b05dSMatthew Wilcox #else				/* !CONFIG_SCSI_FLASHPOINT */
76301da177e4SLinus Torvalds 
76311da177e4SLinus Torvalds /*
76321da177e4SLinus Torvalds   Define prototypes for the FlashPoint SCCB Manager Functions.
76331da177e4SLinus Torvalds */
76341da177e4SLinus Torvalds 
76351da177e4SLinus Torvalds extern unsigned char FlashPoint_ProbeHostAdapter(struct FlashPoint_Info *);
76361da177e4SLinus Torvalds extern FlashPoint_CardHandle_T
76371da177e4SLinus Torvalds FlashPoint_HardwareResetHostAdapter(struct FlashPoint_Info *);
76381da177e4SLinus Torvalds extern void FlashPoint_StartCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *);
76391da177e4SLinus Torvalds extern int FlashPoint_AbortCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *);
76402065e310SRichard Knutsson extern bool FlashPoint_InterruptPending(FlashPoint_CardHandle_T);
76411da177e4SLinus Torvalds extern int FlashPoint_HandleInterrupt(FlashPoint_CardHandle_T);
76421da177e4SLinus Torvalds extern void FlashPoint_ReleaseHostAdapter(FlashPoint_CardHandle_T);
76431da177e4SLinus Torvalds 
764478b4b05dSMatthew Wilcox #endif				/* CONFIG_SCSI_FLASHPOINT */
7645