blob: 867b864f50479033bd5e206de8bec23cd4a0a81a [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2
3 FlashPoint.c -- FlashPoint SCCB Manager for Linux
4
5 This file contains the FlashPoint SCCB Manager from BusLogic's FlashPoint
6 Driver Developer's Kit, with minor modifications by Leonard N. Zubkoff for
7 Linux compatibility. It was provided by BusLogic in the form of 16 separate
8 source files, which would have unnecessarily cluttered the scsi directory, so
9 the individual files have been combined into this single file.
10
11 Copyright 1995-1996 by Mylex Corporation. All Rights Reserved
12
13 This file is available under both the GNU General Public License
14 and a BSD-style copyright; see LICENSE.FlashPoint for details.
15
16*/
17
Linus Torvalds1da177e2005-04-16 15:20:36 -070018
Matthew Wilcox78b4b052008-03-13 06:55:08 -060019#ifdef CONFIG_SCSI_FLASHPOINT
Linus Torvalds1da177e2005-04-16 15:20:36 -070020
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#define MAX_CARDS 8
22#undef BUSTYPE_PCI
23
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#define CRCMASK 0xA001
25
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#define FAILURE 0xFFFFFFFFL
27
Alexey Dobriyan69eb2ea2006-03-08 00:14:29 -080028struct sccb;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -080029typedef void (*CALL_BK_FN) (struct sccb *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070030
Alexey Dobriyan7f101662006-03-08 00:14:30 -080031struct sccb_mgr_info {
Khalid Aziz391e2f22013-05-16 19:44:14 -060032 u32 si_baseaddr;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -080033 unsigned char si_present;
34 unsigned char si_intvect;
35 unsigned char si_id;
36 unsigned char si_lun;
Khalid Aziz391e2f22013-05-16 19:44:14 -060037 u16 si_fw_revision;
38 u16 si_per_targ_init_sync;
39 u16 si_per_targ_fast_nego;
40 u16 si_per_targ_ultra_nego;
41 u16 si_per_targ_no_disc;
42 u16 si_per_targ_wide_nego;
43 u16 si_flags;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -080044 unsigned char si_card_family;
45 unsigned char si_bustype;
46 unsigned char si_card_model[3];
47 unsigned char si_relative_cardnum;
48 unsigned char si_reserved[4];
Khalid Aziz391e2f22013-05-16 19:44:14 -060049 u32 si_OS_reserved;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -080050 unsigned char si_XlatInfo[4];
Khalid Aziz391e2f22013-05-16 19:44:14 -060051 u32 si_reserved2[5];
52 u32 si_secondary_range;
Alexey Dobriyan7f101662006-03-08 00:14:30 -080053};
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
James Bottomley 47b5d692005-04-24 02:38:05 -050055#define SCSI_PARITY_ENA 0x0001
56#define LOW_BYTE_TERM 0x0010
57#define HIGH_BYTE_TERM 0x0020
58#define BUSTYPE_PCI 0x3
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
60#define SUPPORT_16TAR_32LUN 0x0002
61#define SOFT_RESET 0x0004
62#define EXTENDED_TRANSLATION 0x0008
63#define POST_ALL_UNDERRRUNS 0x0040
64#define FLAG_SCAM_ENABLED 0x0080
65#define FLAG_SCAM_LEVEL2 0x0100
66
Linus Torvalds1da177e2005-04-16 15:20:36 -070067#define HARPOON_FAMILY 0x02
68
Alexey Dobriyan323579882006-01-15 02:12:54 +010069/* SCCB struct used for both SCCB and UCB manager compiles!
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 * The UCB Manager treats the SCCB as it's 'native hardware structure'
71 */
72
Khalid Aziz391e2f22013-05-16 19:44:14 -060073/*#pragma pack(1)*/
Alexey Dobriyan69eb2ea2006-03-08 00:14:29 -080074struct sccb {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -080075 unsigned char OperationCode;
76 unsigned char ControlByte;
77 unsigned char CdbLength;
78 unsigned char RequestSenseLength;
Khalid Aziz391e2f22013-05-16 19:44:14 -060079 u32 DataLength;
80 void *DataPointer;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -080081 unsigned char CcbRes[2];
82 unsigned char HostStatus;
83 unsigned char TargetStatus;
84 unsigned char TargID;
85 unsigned char Lun;
86 unsigned char Cdb[12];
87 unsigned char CcbRes1;
88 unsigned char Reserved1;
Khalid Aziz391e2f22013-05-16 19:44:14 -060089 u32 Reserved2;
90 u32 SensePointer;
Linus Torvalds1da177e2005-04-16 15:20:36 -070091
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -080092 CALL_BK_FN SccbCallback; /* VOID (*SccbCallback)(); */
Khalid Aziz391e2f22013-05-16 19:44:14 -060093 u32 SccbIOPort; /* Identifies board base port */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -080094 unsigned char SccbStatus;
95 unsigned char SCCBRes2;
Khalid Aziz391e2f22013-05-16 19:44:14 -060096 u16 SccbOSFlags;
Linus Torvalds1da177e2005-04-16 15:20:36 -070097
Khalid Aziz391e2f22013-05-16 19:44:14 -060098 u32 Sccb_XferCnt; /* actual transfer count */
99 u32 Sccb_ATC;
100 u32 SccbVirtDataPtr; /* virtual addr for OS/2 */
101 u32 Sccb_res1;
102 u16 Sccb_MGRFlags;
103 u16 Sccb_sgseg;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800104 unsigned char Sccb_scsimsg; /* identify msg for selection */
105 unsigned char Sccb_tag;
106 unsigned char Sccb_scsistat;
107 unsigned char Sccb_idmsg; /* image of last msg in */
108 struct sccb *Sccb_forwardlink;
109 struct sccb *Sccb_backlink;
Khalid Aziz391e2f22013-05-16 19:44:14 -0600110 u32 Sccb_savedATC;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800111 unsigned char Save_Cdb[6];
112 unsigned char Save_CdbLen;
113 unsigned char Sccb_XferState;
Khalid Aziz391e2f22013-05-16 19:44:14 -0600114 u32 Sccb_SGoffset;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800115};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116
117#pragma pack()
118
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119#define SCATTER_GATHER_COMMAND 0x02
120#define RESIDUAL_COMMAND 0x03
121#define RESIDUAL_SG_COMMAND 0x04
122#define RESET_COMMAND 0x81
123
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800124#define F_USE_CMD_Q 0x20 /*Inidcates TAGGED command. */
125#define TAG_TYPE_MASK 0xC0 /*Type of tag msg to send. */
126#define SCCB_DATA_XFER_OUT 0x10 /* Write */
127#define SCCB_DATA_XFER_IN 0x08 /* Read */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800129#define NO_AUTO_REQUEST_SENSE 0x01 /* No Request Sense Buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800131#define BUS_FREE_ST 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132#define SELECT_ST 1
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800133#define SELECT_BDR_ST 2 /* Select w\ Bus Device Reset */
134#define SELECT_SN_ST 3 /* Select w\ Sync Nego */
135#define SELECT_WN_ST 4 /* Select w\ Wide Data Nego */
136#define SELECT_Q_ST 5 /* Select w\ Tagged Q'ing */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137#define COMMAND_ST 6
138#define DATA_OUT_ST 7
139#define DATA_IN_ST 8
140#define DISCONNECT_ST 9
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141#define ABORT_ST 11
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143#define F_HOST_XFER_DIR 0x01
144#define F_ALL_XFERRED 0x02
145#define F_SG_XFER 0x04
146#define F_AUTO_SENSE 0x08
147#define F_ODD_BALL_CNT 0x10
148#define F_NO_DATA_YET 0x80
149
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150#define F_STATUSLOADED 0x01
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151#define F_DEV_SELECTED 0x04
152
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800153#define SCCB_COMPLETE 0x00 /* SCCB completed without error */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154#define SCCB_DATA_UNDER_RUN 0x0C
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800155#define SCCB_SELECTION_TIMEOUT 0x11 /* Set SCSI selection timed out */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156#define SCCB_DATA_OVER_RUN 0x12
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800157#define SCCB_PHASE_SEQUENCE_FAIL 0x14 /* Target bus phase sequence failure */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800159#define SCCB_GROSS_FW_ERR 0x27 /* Major problem! */
160#define SCCB_BM_ERR 0x30 /* BusMaster error. */
161#define SCCB_PARITY_ERR 0x34 /* SCSI parity error */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162
163#define SCCB_IN_PROCESS 0x00
164#define SCCB_SUCCESS 0x01
165#define SCCB_ABORT 0x02
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166#define SCCB_ERROR 0x04
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168#define ORION_FW_REV 3110
169
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800170#define QUEUE_DEPTH 254+1 /*1 for Normal disconnect 32 for Q'ing. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800172#define MAX_MB_CARDS 4 /* Max. no of cards suppoerted on Mother Board */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173
James Bottomley 47b5d692005-04-24 02:38:05 -0500174#define MAX_SCSI_TAR 16
175#define MAX_LUN 32
176#define LUN_MASK 0x1f
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800178#define SG_BUF_CNT 16 /*Number of prefetched elements. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800180#define SG_ELEMENT_SIZE 8 /*Eight byte per element. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181
Alexey Dobriyanad0e1d92006-03-08 00:14:28 -0800182#define RD_HARPOON(ioport) inb((u32)ioport)
183#define RDW_HARPOON(ioport) inw((u32)ioport)
184#define RD_HARP32(ioport,offset,data) (data = inl((u32)(ioport + offset)))
185#define WR_HARPOON(ioport,val) outb((u8) val, (u32)ioport)
186#define WRW_HARPOON(ioport,val) outw((u16)val, (u32)ioport)
187#define WR_HARP32(ioport,offset,data) outl(data, (u32)(ioport + offset))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189#define TAR_SYNC_MASK (BIT(7)+BIT(6))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190#define SYNC_TRYING BIT(6)
191#define SYNC_SUPPORTED (BIT(7)+BIT(6))
192
193#define TAR_WIDE_MASK (BIT(5)+BIT(4))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194#define WIDE_ENABLED BIT(4)
195#define WIDE_NEGOCIATED BIT(5)
196
197#define TAR_TAG_Q_MASK (BIT(3)+BIT(2))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198#define TAG_Q_TRYING BIT(2)
199#define TAG_Q_REJECT BIT(3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200
201#define TAR_ALLOW_DISC BIT(0)
202
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203#define EE_SYNC_MASK (BIT(0)+BIT(1))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204#define EE_SYNC_5MB BIT(0)
205#define EE_SYNC_10MB BIT(1)
206#define EE_SYNC_20MB (BIT(0)+BIT(1))
207
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208#define EE_WIDE_SCSI BIT(7)
209
Alexey Dobriyanf31dc0cd2006-03-08 00:14:31 -0800210struct sccb_mgr_tar_info {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800212 struct sccb *TarSelQ_Head;
213 struct sccb *TarSelQ_Tail;
214 unsigned char TarLUN_CA; /*Contingent Allgiance */
215 unsigned char TarTagQ_Cnt;
216 unsigned char TarSelQ_Cnt;
217 unsigned char TarStatus;
218 unsigned char TarEEValue;
219 unsigned char TarSyncCtrl;
220 unsigned char TarReserved[2]; /* for alignment */
221 unsigned char LunDiscQ_Idx[MAX_LUN];
222 unsigned char TarLUNBusy[MAX_LUN];
Alexey Dobriyanf31dc0cd2006-03-08 00:14:31 -0800223};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224
Alexey Dobriyan68d0c1a2006-03-08 00:14:33 -0800225struct nvram_info {
Khalid Aziz391e2f22013-05-16 19:44:14 -0600226 unsigned char niModel; /* Model No. of card */
227 unsigned char niCardNo; /* Card no. */
228 u32 niBaseAddr; /* Port Address of card */
229 unsigned char niSysConf; /* Adapter Configuration byte -
230 Byte 16 of eeprom map */
231 unsigned char niScsiConf; /* SCSI Configuration byte -
232 Byte 17 of eeprom map */
233 unsigned char niScamConf; /* SCAM Configuration byte -
234 Byte 20 of eeprom map */
235 unsigned char niAdapId; /* Host Adapter ID -
236 Byte 24 of eerpom map */
237 unsigned char niSyncTbl[MAX_SCSI_TAR / 2]; /* Sync/Wide byte
238 of targets */
239 unsigned char niScamTbl[MAX_SCSI_TAR][4]; /* Compressed Scam name
240 string of Targets */
Alexey Dobriyan68d0c1a2006-03-08 00:14:33 -0800241};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243#define MODEL_LT 1
244#define MODEL_DL 2
245#define MODEL_LW 3
246#define MODEL_DW 4
247
Alexey Dobriyan13e68512006-03-08 00:14:34 -0800248struct sccb_card {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800249 struct sccb *currentSCCB;
250 struct sccb_mgr_info *cardInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251
Khalid Aziz391e2f22013-05-16 19:44:14 -0600252 u32 ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800254 unsigned short cmdCounter;
255 unsigned char discQCount;
256 unsigned char tagQ_Lst;
257 unsigned char cardIndex;
258 unsigned char scanIndex;
259 unsigned char globalFlags;
260 unsigned char ourId;
261 struct nvram_info *pNvRamInfo;
262 struct sccb *discQ_Tbl[QUEUE_DEPTH];
263
Alexey Dobriyan13e68512006-03-08 00:14:34 -0800264};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266#define F_TAG_STARTED 0x01
267#define F_CONLUN_IO 0x02
268#define F_DO_RENEGO 0x04
269#define F_NO_FILTER 0x08
270#define F_GREEN_PC 0x10
271#define F_HOST_XFER_ACT 0x20
272#define F_NEW_SCCB_CMD 0x40
273#define F_UPDATE_EEPROM 0x80
274
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275#define ID_STRING_LENGTH 32
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800276#define TYPE_CODE0 0x63 /*Level2 Mstr (bits 7-6), */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800278#define SLV_TYPE_CODE0 0xA3 /*Priority Bit set (bits 7-6), */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279
280#define ASSIGN_ID 0x00
281#define SET_P_FLAG 0x01
282#define CFG_CMPLT 0x03
283#define DOM_MSTR 0x0F
284#define SYNC_PTRN 0x1F
285
286#define ID_0_7 0x18
287#define ID_8_F 0x11
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288#define MISC_CODE 0x14
289#define CLR_P_FLAG 0x18
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291#define INIT_SELTD 0x01
292#define LEVEL2_TAR 0x02
293
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800294enum scam_id_st { ID0, ID1, ID2, ID3, ID4, ID5, ID6, ID7, ID8, ID9, ID10, ID11,
295 ID12,
296 ID13, ID14, ID15, ID_UNUSED, ID_UNASSIGNED, ID_ASSIGNED, LEGACY,
297 CLR_PRIORITY, NO_ID_AVAIL
298};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299
300typedef struct SCCBscam_info {
301
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800302 unsigned char id_string[ID_STRING_LENGTH];
303 enum scam_id_st state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800305} SCCBSCAM_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307#define SCSI_REQUEST_SENSE 0x03
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308#define SCSI_READ 0x08
309#define SCSI_WRITE 0x0A
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310#define SCSI_START_STOP_UNIT 0x1B
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311#define SCSI_READ_EXTENDED 0x28
312#define SCSI_WRITE_EXTENDED 0x2A
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313#define SCSI_WRITE_AND_VERIFY 0x2E
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315#define SSGOOD 0x00
316#define SSCHECK 0x02
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317#define SSQ_FULL 0x28
318
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319#define SMCMD_COMP 0x00
320#define SMEXT 0x01
321#define SMSAVE_DATA_PTR 0x02
322#define SMREST_DATA_PTR 0x03
323#define SMDISC 0x04
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324#define SMABORT 0x06
325#define SMREJECT 0x07
326#define SMNO_OP 0x08
327#define SMPARITY 0x09
328#define SMDEV_RESET 0x0C
329#define SMABORT_TAG 0x0D
330#define SMINIT_RECOVERY 0x0F
331#define SMREL_RECOVERY 0x10
332
333#define SMIDENT 0x80
334#define DISC_PRIV 0x40
335
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336#define SMSYNC 0x01
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337#define SMWDTR 0x03
338#define SM8BIT 0x00
339#define SM16BIT 0x01
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800340#define SMIGNORWR 0x23 /* Ignore Wide Residue */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341
342#define SIX_BYTE_CMD 0x06
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343#define TWELVE_BYTE_CMD 0x0C
344
345#define ASYNC 0x00
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800346#define MAX_OFFSET 0x0F /* Maxbyteoffset for Sync Xfers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347
348#define EEPROM_WD_CNT 256
349
350#define EEPROM_CHECK_SUM 0
351#define FW_SIGNATURE 2
352#define MODEL_NUMB_0 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353#define MODEL_NUMB_2 6
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354#define MODEL_NUMB_4 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355#define SYSTEM_CONFIG 16
356#define SCSI_CONFIG 17
357#define BIOS_CONFIG 18
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358#define SCAM_CONFIG 20
359#define ADAPTER_SCSI_ID 24
360
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361#define IGNORE_B_SCAN 32
362#define SEND_START_ENA 34
363#define DEVICE_ENABLE 36
364
365#define SYNC_RATE_TBL 38
366#define SYNC_RATE_TBL01 38
367#define SYNC_RATE_TBL23 40
368#define SYNC_RATE_TBL45 42
369#define SYNC_RATE_TBL67 44
370#define SYNC_RATE_TBL89 46
371#define SYNC_RATE_TBLab 48
372#define SYNC_RATE_TBLcd 50
373#define SYNC_RATE_TBLef 52
374
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800375#define EE_SCAMBASE 256
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800377#define SCAM_ENABLED BIT(2)
378#define SCAM_LEVEL2 BIT(3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379
Jiri Slaby1cafc302007-10-18 23:40:36 -0700380#define RENEGO_ENA BIT(10)
381#define CONNIO_ENA BIT(11)
382#define GREEN_PC_ENA BIT(12)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800384#define AUTO_RATE_00 00
385#define AUTO_RATE_05 01
386#define AUTO_RATE_10 02
387#define AUTO_RATE_20 03
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800389#define WIDE_NEGO_BIT BIT(7)
390#define DISC_ENABLE_BIT BIT(6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800392#define hp_vendor_id_0 0x00 /* LSB */
393#define ORION_VEND_0 0x4B
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800395#define hp_vendor_id_1 0x01 /* MSB */
396#define ORION_VEND_1 0x10
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800398#define hp_device_id_0 0x02 /* LSB */
399#define ORION_DEV_0 0x30
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800401#define hp_device_id_1 0x03 /* MSB */
402#define ORION_DEV_1 0x81
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403
404 /* Sub Vendor ID and Sub Device ID only available in
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800405 Harpoon Version 2 and higher */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800407#define hp_sub_device_id_0 0x06 /* LSB */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800409#define hp_semaphore 0x0C
410#define SCCB_MGR_ACTIVE BIT(0)
411#define TICKLE_ME BIT(1)
412#define SCCB_MGR_PRESENT BIT(3)
413#define BIOS_IN_USE BIT(4)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800415#define hp_sys_ctrl 0x0F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700416
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800417#define STOP_CLK BIT(0) /*Turn off BusMaster Clock */
418#define DRVR_RST BIT(1) /*Firmware Reset to 80C15 chip */
419#define HALT_MACH BIT(3) /*Halt State Machine */
420#define HARD_ABORT BIT(4) /*Hard Abort */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800422#define hp_host_blk_cnt 0x13
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800424#define XFER_BLK64 0x06 /* 1 1 0 64 byte per block */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800426#define BM_THRESHOLD 0x40 /* PCI mode can only xfer 16 bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800428#define hp_int_mask 0x17
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800430#define INT_CMD_COMPL BIT(0) /* DMA command complete */
431#define INT_EXT_STATUS BIT(1) /* Extended Status Set */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800433#define hp_xfer_cnt_lo 0x18
434#define hp_xfer_cnt_hi 0x1A
435#define hp_xfer_cmd 0x1B
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800437#define XFER_HOST_DMA 0x00 /* 0 0 0 Transfer Host -> DMA */
438#define XFER_DMA_HOST 0x01 /* 0 0 1 Transfer DMA -> Host */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800440#define XFER_HOST_AUTO 0x00 /* 0 0 Auto Transfer Size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800442#define XFER_DMA_8BIT 0x20 /* 0 1 8 BIT Transfer Size */
Alexey Dobriyan85ae97d82006-03-08 00:14:22 -0800443
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800444#define DISABLE_INT BIT(7) /*Do not interrupt at end of cmd. */
Alexey Dobriyan85ae97d82006-03-08 00:14:22 -0800445
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800446#define HOST_WRT_CMD ((DISABLE_INT + XFER_HOST_DMA + XFER_HOST_AUTO + XFER_DMA_8BIT))
447#define HOST_RD_CMD ((DISABLE_INT + XFER_DMA_HOST + XFER_HOST_AUTO + XFER_DMA_8BIT))
Alexey Dobriyan85ae97d82006-03-08 00:14:22 -0800448
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800449#define hp_host_addr_lo 0x1C
450#define hp_host_addr_hmi 0x1E
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800452#define hp_ee_ctrl 0x22
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800454#define EXT_ARB_ACK BIT(7)
455#define SCSI_TERM_ENA_H BIT(6) /* SCSI high byte terminator */
456#define SEE_MS BIT(5)
457#define SEE_CS BIT(3)
458#define SEE_CLK BIT(2)
459#define SEE_DO BIT(1)
460#define SEE_DI BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800462#define EE_READ 0x06
463#define EE_WRITE 0x05
464#define EWEN 0x04
465#define EWEN_ADDR 0x03C0
466#define EWDS 0x04
467#define EWDS_ADDR 0x0000
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800469#define hp_bm_ctrl 0x26
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800471#define SCSI_TERM_ENA_L BIT(0) /*Enable/Disable external terminators */
472#define FLUSH_XFER_CNTR BIT(1) /*Flush transfer counter */
473#define FORCE1_XFER BIT(5) /*Always xfer one byte in byte mode */
474#define FAST_SINGLE BIT(6) /*?? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800476#define BMCTRL_DEFAULT (FORCE1_XFER|FAST_SINGLE|SCSI_TERM_ENA_L)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800478#define hp_sg_addr 0x28
479#define hp_page_ctrl 0x29
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800481#define SCATTER_EN BIT(0)
482#define SGRAM_ARAM BIT(1)
483#define G_INT_DISABLE BIT(3) /* Enable/Disable all Interrupts */
484#define NARROW_SCSI_CARD BIT(4) /* NARROW/WIDE SCSI config pin */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800486#define hp_pci_stat_cfg 0x2D
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800488#define REC_MASTER_ABORT BIT(5) /*received Master abort */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800490#define hp_rev_num 0x33
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800492#define hp_stack_data 0x34
493#define hp_stack_addr 0x35
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800495#define hp_ext_status 0x36
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800497#define BM_FORCE_OFF BIT(0) /*Bus Master is forced to get off */
498#define PCI_TGT_ABORT BIT(0) /*PCI bus master transaction aborted */
499#define PCI_DEV_TMOUT BIT(1) /*PCI Device Time out */
500#define CMD_ABORTED BIT(4) /*Command aborted */
501#define BM_PARITY_ERR BIT(5) /*parity error on data received */
502#define PIO_OVERRUN BIT(6) /*Slave data overrun */
503#define BM_CMD_BUSY BIT(7) /*Bus master transfer command busy */
504#define BAD_EXT_STATUS (BM_FORCE_OFF | PCI_DEV_TMOUT | CMD_ABORTED | \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 BM_PARITY_ERR | PIO_OVERRUN)
506
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800507#define hp_int_status 0x37
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800509#define EXT_STATUS_ON BIT(1) /*Extended status is valid */
510#define SCSI_INTERRUPT BIT(2) /*Global indication of a SCSI int. */
511#define INT_ASSERTED BIT(5) /* */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800513#define hp_fifo_cnt 0x38
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800515#define hp_intena 0x40
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516
Jiri Slaby1cafc302007-10-18 23:40:36 -0700517#define RESET BIT(7)
518#define PROG_HLT BIT(6)
519#define PARITY BIT(5)
520#define FIFO BIT(4)
521#define SEL BIT(3)
522#define SCAM_SEL BIT(2)
523#define RSEL BIT(1)
524#define TIMEOUT BIT(0)
525#define BUS_FREE BIT(15)
526#define XFER_CNT_0 BIT(14)
527#define PHASE BIT(13)
528#define IUNKWN BIT(12)
529#define ICMD_COMP BIT(11)
530#define ITICKLE BIT(10)
531#define IDO_STRT BIT(9)
532#define ITAR_DISC BIT(8)
533#define AUTO_INT (BIT(12)+BIT(11)+BIT(10)+BIT(9)+BIT(8))
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800534#define CLR_ALL_INT 0xFFFF
535#define CLR_ALL_INT_1 0xFF00
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800537#define hp_intstat 0x42
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800539#define hp_scsisig 0x44
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800541#define SCSI_SEL BIT(7)
542#define SCSI_BSY BIT(6)
543#define SCSI_REQ BIT(5)
544#define SCSI_ACK BIT(4)
545#define SCSI_ATN BIT(3)
546#define SCSI_CD BIT(2)
547#define SCSI_MSG BIT(1)
548#define SCSI_IOBIT BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800550#define S_SCSI_PHZ (BIT(2)+BIT(1)+BIT(0))
551#define S_MSGO_PH (BIT(2)+BIT(1) )
552#define S_MSGI_PH (BIT(2)+BIT(1)+BIT(0))
553#define S_DATAI_PH ( BIT(0))
554#define S_DATAO_PH 0x00
555#define S_ILL_PH ( BIT(1) )
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800557#define hp_scsictrl_0 0x45
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800559#define SEL_TAR BIT(6)
560#define ENA_ATN BIT(4)
561#define ENA_RESEL BIT(2)
562#define SCSI_RST BIT(1)
563#define ENA_SCAM_SEL BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800565#define hp_portctrl_0 0x46
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800567#define SCSI_PORT BIT(7)
568#define SCSI_INBIT BIT(6)
569#define DMA_PORT BIT(5)
570#define DMA_RD BIT(4)
571#define HOST_PORT BIT(3)
572#define HOST_WRT BIT(2)
573#define SCSI_BUS_EN BIT(1)
574#define START_TO BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800576#define hp_scsireset 0x47
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800578#define SCSI_INI BIT(6)
579#define SCAM_EN BIT(5)
580#define DMA_RESET BIT(3)
581#define HPSCSI_RESET BIT(2)
582#define PROG_RESET BIT(1)
583#define FIFO_CLR BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800585#define hp_xfercnt_0 0x48
586#define hp_xfercnt_2 0x4A
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800588#define hp_fifodata_0 0x4C
589#define hp_addstat 0x4E
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800591#define SCAM_TIMER BIT(7)
592#define SCSI_MODE8 BIT(3)
593#define SCSI_PAR_ERR BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800595#define hp_prgmcnt_0 0x4F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800597#define hp_selfid_0 0x50
598#define hp_selfid_1 0x51
599#define hp_arb_id 0x52
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800601#define hp_select_id 0x53
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800603#define hp_synctarg_base 0x54
604#define hp_synctarg_12 0x54
605#define hp_synctarg_13 0x55
606#define hp_synctarg_14 0x56
607#define hp_synctarg_15 0x57
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800609#define hp_synctarg_8 0x58
610#define hp_synctarg_9 0x59
611#define hp_synctarg_10 0x5A
612#define hp_synctarg_11 0x5B
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800614#define hp_synctarg_4 0x5C
615#define hp_synctarg_5 0x5D
616#define hp_synctarg_6 0x5E
617#define hp_synctarg_7 0x5F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800619#define hp_synctarg_0 0x60
620#define hp_synctarg_1 0x61
621#define hp_synctarg_2 0x62
622#define hp_synctarg_3 0x63
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800624#define NARROW_SCSI BIT(4)
625#define DEFAULT_OFFSET 0x0F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800627#define hp_autostart_0 0x64
628#define hp_autostart_1 0x65
629#define hp_autostart_3 0x67
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800631#define AUTO_IMMED BIT(5)
632#define SELECT BIT(6)
633#define END_DATA (BIT(7)+BIT(6))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800635#define hp_gp_reg_0 0x68
636#define hp_gp_reg_1 0x69
637#define hp_gp_reg_3 0x6B
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800639#define hp_seltimeout 0x6C
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800641#define TO_4ms 0x67 /* 3.9959ms */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800643#define TO_5ms 0x03 /* 4.9152ms */
644#define TO_10ms 0x07 /* 11.xxxms */
645#define TO_250ms 0x99 /* 250.68ms */
646#define TO_290ms 0xB1 /* 289.99ms */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800648#define hp_clkctrl_0 0x6D
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800650#define PWR_DWN BIT(6)
651#define ACTdeassert BIT(4)
652#define CLK_40MHZ (BIT(1) + BIT(0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800654#define CLKCTRL_DEFAULT (ACTdeassert | CLK_40MHZ)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800656#define hp_fiforead 0x6E
657#define hp_fifowrite 0x6F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800659#define hp_offsetctr 0x70
660#define hp_xferstat 0x71
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800662#define FIFO_EMPTY BIT(6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800664#define hp_portctrl_1 0x72
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800666#define CHK_SCSI_P BIT(3)
667#define HOST_MODE8 BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800669#define hp_xfer_pad 0x73
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800671#define ID_UNLOCK BIT(3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800673#define hp_scsidata_0 0x74
674#define hp_scsidata_1 0x75
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800676#define hp_aramBase 0x80
677#define BIOS_DATA_OFFSET 0x60
678#define BIOS_RELATIVE_CARD 0x64
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679
Jiri Slaby1cafc302007-10-18 23:40:36 -0700680#define AR3 (BIT(9) + BIT(8))
681#define SDATA BIT(10)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682
Jiri Slaby1cafc302007-10-18 23:40:36 -0700683#define CRD_OP BIT(11) /* Cmp Reg. w/ Data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684
Jiri Slaby1cafc302007-10-18 23:40:36 -0700685#define CRR_OP BIT(12) /* Cmp Reg. w. Reg. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686
Jiri Slaby1cafc302007-10-18 23:40:36 -0700687#define CPE_OP (BIT(14)+BIT(11)) /* Cmp SCSI phs & Branch EQ */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688
Jiri Slaby1cafc302007-10-18 23:40:36 -0700689#define CPN_OP (BIT(14)+BIT(12)) /* Cmp SCSI phs & Branch NOT EQ */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800691#define ADATA_OUT 0x00
Jiri Slaby1cafc302007-10-18 23:40:36 -0700692#define ADATA_IN BIT(8)
693#define ACOMMAND BIT(10)
694#define ASTATUS (BIT(10)+BIT(8))
695#define AMSG_OUT (BIT(10)+BIT(9))
696#define AMSG_IN (BIT(10)+BIT(9)+BIT(8))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697
Jiri Slaby1cafc302007-10-18 23:40:36 -0700698#define BRH_OP BIT(13) /* Branch */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800700#define ALWAYS 0x00
Jiri Slaby1cafc302007-10-18 23:40:36 -0700701#define EQUAL BIT(8)
702#define NOT_EQ BIT(9)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703
Jiri Slaby1cafc302007-10-18 23:40:36 -0700704#define TCB_OP (BIT(13)+BIT(11)) /* Test condition & branch */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705
Jiri Slaby1cafc302007-10-18 23:40:36 -0700706#define FIFO_0 BIT(10)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707
Jiri Slaby1cafc302007-10-18 23:40:36 -0700708#define MPM_OP BIT(15) /* Match phase and move data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709
Jiri Slaby1cafc302007-10-18 23:40:36 -0700710#define MRR_OP BIT(14) /* Move DReg. to Reg. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800712#define S_IDREG (BIT(2)+BIT(1)+BIT(0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800714#define D_AR0 0x00
715#define D_AR1 BIT(0)
716#define D_BUCKET (BIT(2) + BIT(1) + BIT(0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717
Jiri Slaby1cafc302007-10-18 23:40:36 -0700718#define RAT_OP (BIT(14)+BIT(13)+BIT(11))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719
Jiri Slaby1cafc302007-10-18 23:40:36 -0700720#define SSI_OP (BIT(15)+BIT(11))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800722#define SSI_ITAR_DISC (ITAR_DISC >> 8)
723#define SSI_IDO_STRT (IDO_STRT >> 8)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800725#define SSI_ICMD_COMP (ICMD_COMP >> 8)
726#define SSI_ITICKLE (ITICKLE >> 8)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800728#define SSI_IUNKWN (IUNKWN >> 8)
729#define SSI_INO_CC (IUNKWN >> 8)
730#define SSI_IRFAIL (IUNKWN >> 8)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800732#define NP 0x10 /*Next Phase */
733#define NTCMD 0x02 /*Non- Tagged Command start */
734#define CMDPZ 0x04 /*Command phase */
735#define DINT 0x12 /*Data Out/In interrupt */
736#define DI 0x13 /*Data Out */
737#define DC 0x19 /*Disconnect Message */
738#define ST 0x1D /*Status Phase */
739#define UNKNWN 0x24 /*Unknown bus action */
740#define CC 0x25 /*Command Completion failure */
741#define TICK 0x26 /*New target reselected us. */
742#define SELCHK 0x28 /*Select & Check SCSI ID latch reg */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800744#define ID_MSG_STRT hp_aramBase + 0x00
745#define NON_TAG_ID_MSG hp_aramBase + 0x06
746#define CMD_STRT hp_aramBase + 0x08
747#define SYNC_MSGS hp_aramBase + 0x08
Alexey Dobriyan85ae97d82006-03-08 00:14:22 -0800748
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800749#define TAG_STRT 0x00
750#define DISCONNECT_START 0x10/2
751#define END_DATA_START 0x14/2
752#define CMD_ONLY_STRT CMDPZ/2
753#define SELCHK_STRT SELCHK/2
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
755#define GET_XFER_CNT(port, xfercnt) {RD_HARP32(port,hp_xfercnt_0,xfercnt); xfercnt &= 0xFFFFFF;}
756/* #define GET_XFER_CNT(port, xfercnt) (xfercnt = RD_HARPOON(port+hp_xfercnt_2), \
757 xfercnt <<= 16,\
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800758 xfercnt |= RDW_HARPOON((unsigned short)(port+hp_xfercnt_0)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 */
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800760#define HP_SETUP_ADDR_CNT(port,addr,count) (WRW_HARPOON((port+hp_host_addr_lo), (unsigned short)(addr & 0x0000FFFFL)),\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 addr >>= 16,\
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800762 WRW_HARPOON((port+hp_host_addr_hmi), (unsigned short)(addr & 0x0000FFFFL)),\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 WR_HARP32(port,hp_xfercnt_0,count),\
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800764 WRW_HARPOON((port+hp_xfer_cnt_lo), (unsigned short)(count & 0x0000FFFFL)),\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 count >>= 16,\
766 WR_HARPOON(port+hp_xfer_cnt_hi, (count & 0xFF)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767
768#define ACCEPT_MSG(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
769 WR_HARPOON(port+hp_scsisig, S_ILL_PH);}
770
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771#define ACCEPT_MSG_ATN(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
772 WR_HARPOON(port+hp_scsisig, (S_ILL_PH|SCSI_ATN));}
773
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774#define DISABLE_AUTO(port) (WR_HARPOON(port+hp_scsireset, PROG_RESET),\
775 WR_HARPOON(port+hp_scsireset, 0x00))
776
777#define ARAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
778 (RD_HARPOON(p_port+hp_page_ctrl) | SGRAM_ARAM)))
779
780#define SGRAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
781 (RD_HARPOON(p_port+hp_page_ctrl) & ~SGRAM_ARAM)))
782
783#define MDISABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
784 (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE)))
785
786#define MENABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
787 (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE)))
788
Khalid Aziz391e2f22013-05-16 19:44:14 -0600789static unsigned char FPT_sisyncn(u32 port, unsigned char p_card,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800790 unsigned char syncFlag);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600791static void FPT_ssel(u32 port, unsigned char p_card);
792static void FPT_sres(u32 port, unsigned char p_card,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800793 struct sccb_card *pCurrCard);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600794static void FPT_shandem(u32 port, unsigned char p_card,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800795 struct sccb *pCurrSCCB);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600796static void FPT_stsyncn(u32 port, unsigned char p_card);
797static void FPT_sisyncr(u32 port, unsigned char sync_pulse,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800798 unsigned char offset);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600799static void FPT_sssyncv(u32 p_port, unsigned char p_id,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800800 unsigned char p_sync_value,
801 struct sccb_mgr_tar_info *currTar_Info);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600802static void FPT_sresb(u32 port, unsigned char p_card);
803static void FPT_sxfrp(u32 p_port, unsigned char p_card);
804static void FPT_schkdd(u32 port, unsigned char p_card);
805static unsigned char FPT_RdStack(u32 port, unsigned char index);
806static void FPT_WrStack(u32 portBase, unsigned char index,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800807 unsigned char data);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600808static unsigned char FPT_ChkIfChipInitialized(u32 ioPort);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809
Khalid Aziz391e2f22013-05-16 19:44:14 -0600810static void FPT_SendMsg(u32 port, unsigned char message);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800811static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
812 unsigned char error_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800814static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card);
815static void FPT_RNVRamData(struct nvram_info *pNvRamInfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816
Khalid Aziz391e2f22013-05-16 19:44:14 -0600817static unsigned char FPT_siwidn(u32 port, unsigned char p_card);
818static void FPT_stwidn(u32 port, unsigned char p_card);
819static void FPT_siwidr(u32 port, unsigned char width);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800821static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
822 unsigned char p_card);
823static void FPT_queueDisconnect(struct sccb *p_SCCB, unsigned char p_card);
824static void FPT_queueCmdComplete(struct sccb_card *pCurrCard,
825 struct sccb *p_SCCB, unsigned char p_card);
826static void FPT_queueSearchSelect(struct sccb_card *pCurrCard,
Alexey Dobriyandb038cf2006-03-08 00:14:24 -0800827 unsigned char p_card);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800828static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code);
829static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char card);
830static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB,
831 unsigned char p_card);
832static void FPT_utilUpdateResidual(struct sccb *p_SCCB);
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800833static unsigned short FPT_CalcCrc16(unsigned char buffer[]);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800834static unsigned char FPT_CalcLrc(unsigned char buffer[]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835
Khalid Aziz391e2f22013-05-16 19:44:14 -0600836static void FPT_Wait1Second(u32 p_port);
837static void FPT_Wait(u32 p_port, unsigned char p_delay);
838static void FPT_utilEEWriteOnOff(u32 p_port, unsigned char p_mode);
839static void FPT_utilEEWrite(u32 p_port, unsigned short ee_data,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800840 unsigned short ee_addr);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600841static unsigned short FPT_utilEERead(u32 p_port,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800842 unsigned short ee_addr);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600843static unsigned short FPT_utilEEReadOrg(u32 p_port,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800844 unsigned short ee_addr);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600845static void FPT_utilEESendCmdAddr(u32 p_port, unsigned char ee_cmd,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800846 unsigned short ee_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847
Khalid Aziz391e2f22013-05-16 19:44:14 -0600848static void FPT_phaseDataOut(u32 port, unsigned char p_card);
849static void FPT_phaseDataIn(u32 port, unsigned char p_card);
850static void FPT_phaseCommand(u32 port, unsigned char p_card);
851static void FPT_phaseStatus(u32 port, unsigned char p_card);
852static void FPT_phaseMsgOut(u32 port, unsigned char p_card);
853static void FPT_phaseMsgIn(u32 port, unsigned char p_card);
854static void FPT_phaseIllegal(u32 port, unsigned char p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855
Khalid Aziz391e2f22013-05-16 19:44:14 -0600856static void FPT_phaseDecode(u32 port, unsigned char p_card);
857static void FPT_phaseChkFifo(u32 port, unsigned char p_card);
858static void FPT_phaseBusFree(u32 p_port, unsigned char p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859
Khalid Aziz391e2f22013-05-16 19:44:14 -0600860static void FPT_XbowInit(u32 port, unsigned char scamFlg);
861static void FPT_BusMasterInit(u32 p_port);
862static void FPT_DiagEEPROM(u32 p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863
Khalid Aziz391e2f22013-05-16 19:44:14 -0600864static void FPT_dataXferProcessor(u32 port,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800865 struct sccb_card *pCurrCard);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600866static void FPT_busMstrSGDataXferStart(u32 port,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800867 struct sccb *pCurrSCCB);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600868static void FPT_busMstrDataXferStart(u32 port,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800869 struct sccb *pCurrSCCB);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600870static void FPT_hostDataXferAbort(u32 port, unsigned char p_card,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800871 struct sccb *pCurrSCCB);
872static void FPT_hostDataXferRestart(struct sccb *currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873
Khalid Aziz391e2f22013-05-16 19:44:14 -0600874static unsigned char FPT_SccbMgr_bad_isr(u32 p_port,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800875 unsigned char p_card,
876 struct sccb_card *pCurrCard,
877 unsigned short p_int);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800879static void FPT_SccbMgrTableInitAll(void);
880static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard,
881 unsigned char p_card);
882static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
883 unsigned char target);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800885static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
886 unsigned char p_power_up);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887
Khalid Aziz391e2f22013-05-16 19:44:14 -0600888static int FPT_scarb(u32 p_port, unsigned char p_sel_type);
889static void FPT_scbusf(u32 p_port);
890static void FPT_scsel(u32 p_port);
891static void FPT_scasid(unsigned char p_card, u32 p_port);
892static unsigned char FPT_scxferc(u32 p_port, unsigned char p_data);
893static unsigned char FPT_scsendi(u32 p_port,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800894 unsigned char p_id_string[]);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600895static unsigned char FPT_sciso(u32 p_port,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800896 unsigned char p_id_string[]);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600897static void FPT_scwirod(u32 p_port, unsigned char p_data_bit);
898static void FPT_scwiros(u32 p_port, unsigned char p_data_bit);
Alexey Dobriyandb038cf2006-03-08 00:14:24 -0800899static unsigned char FPT_scvalq(unsigned char p_quintet);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600900static unsigned char FPT_scsell(u32 p_port, unsigned char targ_id);
901static void FPT_scwtsel(u32 p_port);
902static void FPT_inisci(unsigned char p_card, u32 p_port,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800903 unsigned char p_our_id);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600904static void FPT_scsavdi(unsigned char p_card, u32 p_port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800905static unsigned char FPT_scmachid(unsigned char p_card,
906 unsigned char p_id_string[]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907
Khalid Aziz391e2f22013-05-16 19:44:14 -0600908static void FPT_autoCmdCmplt(u32 p_port, unsigned char p_card);
909static void FPT_autoLoadDefaultMap(u32 p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800911static struct sccb_mgr_tar_info FPT_sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] =
912 { {{0}} };
913static struct sccb_card FPT_BL_Card[MAX_CARDS] = { {0} };
914static SCCBSCAM_INFO FPT_scamInfo[MAX_SCSI_TAR] = { {{0}} };
915static struct nvram_info FPT_nvRamInfo[MAX_MB_CARDS] = { {0} };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916
Alexey Dobriyandb038cf2006-03-08 00:14:24 -0800917static unsigned char FPT_mbCards = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800918static unsigned char FPT_scamHAString[] =
919 { 0x63, 0x07, 'B', 'U', 'S', 'L', 'O', 'G', 'I', 'C',
920 ' ', 'B', 'T', '-', '9', '3', '0',
921 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
922 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
923};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800925static unsigned short FPT_default_intena = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926
Khalid Aziz391e2f22013-05-16 19:44:14 -0600927static void (*FPT_s_PhaseTbl[8]) (u32, unsigned char) = {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08009280};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929
930/*---------------------------------------------------------------------
931 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -0800932 * Function: FlashPoint_ProbeHostAdapter
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 *
934 * Description: Setup and/or Search for cards and return info to caller.
935 *
936 *---------------------------------------------------------------------*/
937
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800938static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800940 static unsigned char first_time = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800942 unsigned char i, j, id, ScamFlg;
943 unsigned short temp, temp2, temp3, temp4, temp5, temp6;
Khalid Aziz391e2f22013-05-16 19:44:14 -0600944 u32 ioport;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800945 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800947 ioport = pCardInfo->si_baseaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800949 if (RD_HARPOON(ioport + hp_vendor_id_0) != ORION_VEND_0)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800950 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800952 if ((RD_HARPOON(ioport + hp_vendor_id_1) != ORION_VEND_1))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800953 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800955 if ((RD_HARPOON(ioport + hp_device_id_0) != ORION_DEV_0))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800956 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800958 if ((RD_HARPOON(ioport + hp_device_id_1) != ORION_DEV_1))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800959 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800961 if (RD_HARPOON(ioport + hp_rev_num) != 0x0f) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962
963/* For new Harpoon then check for sub_device ID LSB
964 the bits(0-3) must be all ZERO for compatible with
965 current version of SCCBMgr, else skip this Harpoon
966 device. */
967
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800968 if (RD_HARPOON(ioport + hp_sub_device_id_0) & 0x0f)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800969 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 }
971
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800972 if (first_time) {
973 FPT_SccbMgrTableInitAll();
974 first_time = 0;
James Bottomley 47b5d692005-04-24 02:38:05 -0500975 FPT_mbCards = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800976 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800978 if (FPT_RdStack(ioport, 0) != 0x00) {
979 if (FPT_ChkIfChipInitialized(ioport) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 pCurrNvRam = NULL;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800981 WR_HARPOON(ioport + hp_semaphore, 0x00);
982 FPT_XbowInit(ioport, 0); /*Must Init the SCSI before attempting */
James Bottomley 47b5d692005-04-24 02:38:05 -0500983 FPT_DiagEEPROM(ioport);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800984 } else {
985 if (FPT_mbCards < MAX_MB_CARDS) {
James Bottomley 47b5d692005-04-24 02:38:05 -0500986 pCurrNvRam = &FPT_nvRamInfo[FPT_mbCards];
987 FPT_mbCards++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 pCurrNvRam->niBaseAddr = ioport;
James Bottomley 47b5d692005-04-24 02:38:05 -0500989 FPT_RNVRamData(pCurrNvRam);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800990 } else
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800991 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800993 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 pCurrNvRam = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800996 WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT);
997 WR_HARPOON(ioport + hp_sys_ctrl, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800999 if (pCurrNvRam)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 pCardInfo->si_id = pCurrNvRam->niAdapId;
1001 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001002 pCardInfo->si_id =
1003 (unsigned
1004 char)(FPT_utilEERead(ioport,
1005 (ADAPTER_SCSI_ID /
1006 2)) & (unsigned char)0x0FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001008 pCardInfo->si_lun = 0x00;
1009 pCardInfo->si_fw_revision = ORION_FW_REV;
1010 temp2 = 0x0000;
1011 temp3 = 0x0000;
1012 temp4 = 0x0000;
1013 temp5 = 0x0000;
1014 temp6 = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001016 for (id = 0; id < (16 / 2); id++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001018 if (pCurrNvRam) {
1019 temp = (unsigned short)pCurrNvRam->niSyncTbl[id];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001021 (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
1022 } else
1023 temp =
1024 FPT_utilEERead(ioport,
1025 (unsigned short)((SYNC_RATE_TBL / 2)
1026 + id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001028 for (i = 0; i < 2; temp >>= 8, i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001030 temp2 >>= 1;
1031 temp3 >>= 1;
1032 temp4 >>= 1;
1033 temp5 >>= 1;
1034 temp6 >>= 1;
1035 switch (temp & 0x3) {
1036 case AUTO_RATE_20: /* Synchronous, 20 mega-transfers/second */
1037 temp6 |= 0x8000; /* Fall through */
1038 case AUTO_RATE_10: /* Synchronous, 10 mega-transfers/second */
1039 temp5 |= 0x8000; /* Fall through */
1040 case AUTO_RATE_05: /* Synchronous, 5 mega-transfers/second */
1041 temp2 |= 0x8000; /* Fall through */
1042 case AUTO_RATE_00: /* Asynchronous */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 break;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001044 }
1045
1046 if (temp & DISC_ENABLE_BIT)
1047 temp3 |= 0x8000;
1048
1049 if (temp & WIDE_NEGO_BIT)
1050 temp4 |= 0x8000;
1051
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 }
1054
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001055 pCardInfo->si_per_targ_init_sync = temp2;
1056 pCardInfo->si_per_targ_no_disc = temp3;
1057 pCardInfo->si_per_targ_wide_nego = temp4;
1058 pCardInfo->si_per_targ_fast_nego = temp5;
1059 pCardInfo->si_per_targ_ultra_nego = temp6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001061 if (pCurrNvRam)
1062 i = pCurrNvRam->niSysConf;
1063 else
1064 i = (unsigned
1065 char)(FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001067 if (pCurrNvRam)
1068 ScamFlg = pCurrNvRam->niScamConf;
1069 else
1070 ScamFlg =
1071 (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001073 pCardInfo->si_flags = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001075 if (i & 0x01)
1076 pCardInfo->si_flags |= SCSI_PARITY_ENA;
1077
1078 if (!(i & 0x02))
1079 pCardInfo->si_flags |= SOFT_RESET;
1080
1081 if (i & 0x10)
1082 pCardInfo->si_flags |= EXTENDED_TRANSLATION;
1083
1084 if (ScamFlg & SCAM_ENABLED)
1085 pCardInfo->si_flags |= FLAG_SCAM_ENABLED;
1086
1087 if (ScamFlg & SCAM_LEVEL2)
1088 pCardInfo->si_flags |= FLAG_SCAM_LEVEL2;
1089
1090 j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
1091 if (i & 0x04) {
1092 j |= SCSI_TERM_ENA_L;
1093 }
1094 WR_HARPOON(ioport + hp_bm_ctrl, j);
1095
1096 j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
1097 if (i & 0x08) {
1098 j |= SCSI_TERM_ENA_H;
1099 }
1100 WR_HARPOON(ioport + hp_ee_ctrl, j);
1101
1102 if (!(RD_HARPOON(ioport + hp_page_ctrl) & NARROW_SCSI_CARD))
1103
1104 pCardInfo->si_flags |= SUPPORT_16TAR_32LUN;
1105
1106 pCardInfo->si_card_family = HARPOON_FAMILY;
1107 pCardInfo->si_bustype = BUSTYPE_PCI;
1108
1109 if (pCurrNvRam) {
1110 pCardInfo->si_card_model[0] = '9';
1111 switch (pCurrNvRam->niModel & 0x0f) {
1112 case MODEL_LT:
1113 pCardInfo->si_card_model[1] = '3';
1114 pCardInfo->si_card_model[2] = '0';
1115 break;
1116 case MODEL_LW:
1117 pCardInfo->si_card_model[1] = '5';
1118 pCardInfo->si_card_model[2] = '0';
1119 break;
1120 case MODEL_DL:
1121 pCardInfo->si_card_model[1] = '3';
1122 pCardInfo->si_card_model[2] = '2';
1123 break;
1124 case MODEL_DW:
1125 pCardInfo->si_card_model[1] = '5';
1126 pCardInfo->si_card_model[2] = '2';
1127 break;
1128 }
1129 } else {
1130 temp = FPT_utilEERead(ioport, (MODEL_NUMB_0 / 2));
1131 pCardInfo->si_card_model[0] = (unsigned char)(temp >> 8);
1132 temp = FPT_utilEERead(ioport, (MODEL_NUMB_2 / 2));
1133
1134 pCardInfo->si_card_model[1] = (unsigned char)(temp & 0x00FF);
1135 pCardInfo->si_card_model[2] = (unsigned char)(temp >> 8);
1136 }
1137
1138 if (pCardInfo->si_card_model[1] == '3') {
1139 if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
1140 pCardInfo->si_flags |= LOW_BYTE_TERM;
1141 } else if (pCardInfo->si_card_model[2] == '0') {
1142 temp = RD_HARPOON(ioport + hp_xfer_pad);
1143 WR_HARPOON(ioport + hp_xfer_pad, (temp & ~BIT(4)));
1144 if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
1145 pCardInfo->si_flags |= LOW_BYTE_TERM;
1146 WR_HARPOON(ioport + hp_xfer_pad, (temp | BIT(4)));
1147 if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
1148 pCardInfo->si_flags |= HIGH_BYTE_TERM;
1149 WR_HARPOON(ioport + hp_xfer_pad, temp);
1150 } else {
1151 temp = RD_HARPOON(ioport + hp_ee_ctrl);
1152 temp2 = RD_HARPOON(ioport + hp_xfer_pad);
1153 WR_HARPOON(ioport + hp_ee_ctrl, (temp | SEE_CS));
1154 WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4)));
1155 temp3 = 0;
1156 for (i = 0; i < 8; i++) {
1157 temp3 <<= 1;
1158 if (!(RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7)))
1159 temp3 |= 1;
1160 WR_HARPOON(ioport + hp_xfer_pad, (temp2 & ~BIT(4)));
1161 WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4)));
1162 }
1163 WR_HARPOON(ioport + hp_ee_ctrl, temp);
1164 WR_HARPOON(ioport + hp_xfer_pad, temp2);
1165 if (!(temp3 & BIT(7)))
1166 pCardInfo->si_flags |= LOW_BYTE_TERM;
1167 if (!(temp3 & BIT(6)))
1168 pCardInfo->si_flags |= HIGH_BYTE_TERM;
1169 }
1170
1171 ARAM_ACCESS(ioport);
1172
1173 for (i = 0; i < 4; i++) {
1174
1175 pCardInfo->si_XlatInfo[i] =
1176 RD_HARPOON(ioport + hp_aramBase + BIOS_DATA_OFFSET + i);
1177 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178
1179 /* return with -1 if no sort, else return with
1180 logical card number sorted by BIOS (zero-based) */
1181
1182 pCardInfo->si_relative_cardnum =
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001183 (unsigned
1184 char)(RD_HARPOON(ioport + hp_aramBase + BIOS_RELATIVE_CARD) - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001186 SGRAM_ACCESS(ioport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001188 FPT_s_PhaseTbl[0] = FPT_phaseDataOut;
1189 FPT_s_PhaseTbl[1] = FPT_phaseDataIn;
1190 FPT_s_PhaseTbl[2] = FPT_phaseIllegal;
1191 FPT_s_PhaseTbl[3] = FPT_phaseIllegal;
1192 FPT_s_PhaseTbl[4] = FPT_phaseCommand;
1193 FPT_s_PhaseTbl[5] = FPT_phaseStatus;
1194 FPT_s_PhaseTbl[6] = FPT_phaseMsgOut;
1195 FPT_s_PhaseTbl[7] = FPT_phaseMsgIn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001197 pCardInfo->si_present = 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001199 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200}
1201
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202/*---------------------------------------------------------------------
1203 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001204 * Function: FlashPoint_HardwareResetHostAdapter
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 *
1206 * Description: Setup adapter for normal operation (hard reset).
1207 *
1208 *---------------------------------------------------------------------*/
1209
Khalid Aziz391e2f22013-05-16 19:44:14 -06001210static void *FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001211 *pCardInfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001213 struct sccb_card *CurrCard = NULL;
1214 struct nvram_info *pCurrNvRam;
1215 unsigned char i, j, thisCard, ScamFlg;
1216 unsigned short temp, sync_bit_map, id;
Khalid Aziz391e2f22013-05-16 19:44:14 -06001217 u32 ioport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001219 ioport = pCardInfo->si_baseaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001221 for (thisCard = 0; thisCard <= MAX_CARDS; thisCard++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222
Khalid Aziz391e2f22013-05-16 19:44:14 -06001223 if (thisCard == MAX_CARDS)
1224 return (void *)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001226 if (FPT_BL_Card[thisCard].ioPort == ioport) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001228 CurrCard = &FPT_BL_Card[thisCard];
1229 FPT_SccbMgrTableInitCard(CurrCard, thisCard);
1230 break;
1231 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001233 else if (FPT_BL_Card[thisCard].ioPort == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001235 FPT_BL_Card[thisCard].ioPort = ioport;
1236 CurrCard = &FPT_BL_Card[thisCard];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001238 if (FPT_mbCards)
1239 for (i = 0; i < FPT_mbCards; i++) {
1240 if (CurrCard->ioPort ==
1241 FPT_nvRamInfo[i].niBaseAddr)
1242 CurrCard->pNvRamInfo =
1243 &FPT_nvRamInfo[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001245 FPT_SccbMgrTableInitCard(CurrCard, thisCard);
1246 CurrCard->cardIndex = thisCard;
1247 CurrCard->cardInfo = pCardInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001249 break;
1250 }
1251 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252
1253 pCurrNvRam = CurrCard->pNvRamInfo;
1254
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001255 if (pCurrNvRam) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 ScamFlg = pCurrNvRam->niScamConf;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001257 } else {
1258 ScamFlg =
1259 (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 }
1261
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001262 FPT_BusMasterInit(ioport);
1263 FPT_XbowInit(ioport, ScamFlg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001265 FPT_autoLoadDefaultMap(ioport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001267 for (i = 0, id = 0x01; i != pCardInfo->si_id; i++, id <<= 1) {
1268 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001270 WR_HARPOON(ioport + hp_selfid_0, id);
1271 WR_HARPOON(ioport + hp_selfid_1, 0x00);
1272 WR_HARPOON(ioport + hp_arb_id, pCardInfo->si_id);
1273 CurrCard->ourId = pCardInfo->si_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001275 i = (unsigned char)pCardInfo->si_flags;
1276 if (i & SCSI_PARITY_ENA)
1277 WR_HARPOON(ioport + hp_portctrl_1, (HOST_MODE8 | CHK_SCSI_P));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001279 j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
1280 if (i & LOW_BYTE_TERM)
1281 j |= SCSI_TERM_ENA_L;
1282 WR_HARPOON(ioport + hp_bm_ctrl, j);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001284 j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
1285 if (i & HIGH_BYTE_TERM)
1286 j |= SCSI_TERM_ENA_H;
1287 WR_HARPOON(ioport + hp_ee_ctrl, j);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001289 if (!(pCardInfo->si_flags & SOFT_RESET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001291 FPT_sresb(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001293 FPT_scini(thisCard, pCardInfo->si_id, 0);
1294 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001296 if (pCardInfo->si_flags & POST_ALL_UNDERRRUNS)
1297 CurrCard->globalFlags |= F_NO_FILTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001299 if (pCurrNvRam) {
1300 if (pCurrNvRam->niSysConf & 0x10)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 CurrCard->globalFlags |= F_GREEN_PC;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001302 } else {
1303 if (FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)) & GREEN_PC_ENA)
1304 CurrCard->globalFlags |= F_GREEN_PC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305 }
1306
1307 /* Set global flag to indicate Re-Negotiation to be done on all
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001308 ckeck condition */
1309 if (pCurrNvRam) {
1310 if (pCurrNvRam->niScsiConf & 0x04)
1311 CurrCard->globalFlags |= F_DO_RENEGO;
1312 } else {
1313 if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & RENEGO_ENA)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 CurrCard->globalFlags |= F_DO_RENEGO;
1315 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001317 if (pCurrNvRam) {
1318 if (pCurrNvRam->niScsiConf & 0x08)
1319 CurrCard->globalFlags |= F_CONLUN_IO;
1320 } else {
1321 if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & CONNIO_ENA)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 CurrCard->globalFlags |= F_CONLUN_IO;
1323 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001324
1325 temp = pCardInfo->si_per_targ_no_disc;
1326
1327 for (i = 0, id = 1; i < MAX_SCSI_TAR; i++, id <<= 1) {
1328
1329 if (temp & id)
1330 FPT_sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331 }
1332
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001333 sync_bit_map = 0x0001;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001335 for (id = 0; id < (MAX_SCSI_TAR / 2); id++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001337 if (pCurrNvRam) {
1338 temp = (unsigned short)pCurrNvRam->niSyncTbl[id];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001340 (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
1341 } else
1342 temp =
1343 FPT_utilEERead(ioport,
1344 (unsigned short)((SYNC_RATE_TBL / 2)
1345 + id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001347 for (i = 0; i < 2; temp >>= 8, i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001349 if (pCardInfo->si_per_targ_init_sync & sync_bit_map) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001351 FPT_sccbMgrTbl[thisCard][id * 2 +
1352 i].TarEEValue =
1353 (unsigned char)temp;
1354 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001356 else {
1357 FPT_sccbMgrTbl[thisCard][id * 2 +
1358 i].TarStatus |=
1359 SYNC_SUPPORTED;
1360 FPT_sccbMgrTbl[thisCard][id * 2 +
1361 i].TarEEValue =
1362 (unsigned char)(temp & ~EE_SYNC_MASK);
1363 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365/* if ((pCardInfo->si_per_targ_wide_nego & sync_bit_map) ||
1366 (id*2+i >= 8)){
1367*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001368 if (pCardInfo->si_per_targ_wide_nego & sync_bit_map) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001370 FPT_sccbMgrTbl[thisCard][id * 2 +
1371 i].TarEEValue |=
1372 EE_WIDE_SCSI;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001374 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001376 else { /* NARROW SCSI */
1377 FPT_sccbMgrTbl[thisCard][id * 2 +
1378 i].TarStatus |=
1379 WIDE_NEGOCIATED;
1380 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001382 sync_bit_map <<= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001384 }
1385 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001387 WR_HARPOON((ioport + hp_semaphore),
1388 (unsigned char)(RD_HARPOON((ioport + hp_semaphore)) |
1389 SCCB_MGR_PRESENT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390
Khalid Aziz391e2f22013-05-16 19:44:14 -06001391 return (void *)CurrCard;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392}
1393
Khalid Aziz391e2f22013-05-16 19:44:14 -06001394static void FlashPoint_ReleaseHostAdapter(void *pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395{
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08001396 unsigned char i;
Khalid Aziz391e2f22013-05-16 19:44:14 -06001397 u32 portBase;
1398 u32 regOffset;
1399 u32 scamData;
1400 u32 *pScamTbl;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001401 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001403 pCurrNvRam = ((struct sccb_card *)pCurrCard)->pNvRamInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001405 if (pCurrNvRam) {
James Bottomley 47b5d692005-04-24 02:38:05 -05001406 FPT_WrStack(pCurrNvRam->niBaseAddr, 0, pCurrNvRam->niModel);
1407 FPT_WrStack(pCurrNvRam->niBaseAddr, 1, pCurrNvRam->niSysConf);
1408 FPT_WrStack(pCurrNvRam->niBaseAddr, 2, pCurrNvRam->niScsiConf);
1409 FPT_WrStack(pCurrNvRam->niBaseAddr, 3, pCurrNvRam->niScamConf);
1410 FPT_WrStack(pCurrNvRam->niBaseAddr, 4, pCurrNvRam->niAdapId);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001412 for (i = 0; i < MAX_SCSI_TAR / 2; i++)
1413 FPT_WrStack(pCurrNvRam->niBaseAddr,
1414 (unsigned char)(i + 5),
1415 pCurrNvRam->niSyncTbl[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416
1417 portBase = pCurrNvRam->niBaseAddr;
1418
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001419 for (i = 0; i < MAX_SCSI_TAR; i++) {
1420 regOffset = hp_aramBase + 64 + i * 4;
Khalid Aziz391e2f22013-05-16 19:44:14 -06001421 pScamTbl = (u32 *)&pCurrNvRam->niScamTbl[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 scamData = *pScamTbl;
1423 WR_HARP32(portBase, regOffset, scamData);
1424 }
1425
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001426 } else {
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001427 FPT_WrStack(((struct sccb_card *)pCurrCard)->ioPort, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 }
1429}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001431static void FPT_RNVRamData(struct nvram_info *pNvRamInfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432{
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08001433 unsigned char i;
Khalid Aziz391e2f22013-05-16 19:44:14 -06001434 u32 portBase;
1435 u32 regOffset;
1436 u32 scamData;
1437 u32 *pScamTbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001439 pNvRamInfo->niModel = FPT_RdStack(pNvRamInfo->niBaseAddr, 0);
1440 pNvRamInfo->niSysConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 1);
James Bottomley 47b5d692005-04-24 02:38:05 -05001441 pNvRamInfo->niScsiConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 2);
1442 pNvRamInfo->niScamConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 3);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001443 pNvRamInfo->niAdapId = FPT_RdStack(pNvRamInfo->niBaseAddr, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001445 for (i = 0; i < MAX_SCSI_TAR / 2; i++)
1446 pNvRamInfo->niSyncTbl[i] =
1447 FPT_RdStack(pNvRamInfo->niBaseAddr, (unsigned char)(i + 5));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448
1449 portBase = pNvRamInfo->niBaseAddr;
1450
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001451 for (i = 0; i < MAX_SCSI_TAR; i++) {
1452 regOffset = hp_aramBase + 64 + i * 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453 RD_HARP32(portBase, regOffset, scamData);
Khalid Aziz391e2f22013-05-16 19:44:14 -06001454 pScamTbl = (u32 *)&pNvRamInfo->niScamTbl[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 *pScamTbl = scamData;
1456 }
1457
1458}
1459
Khalid Aziz391e2f22013-05-16 19:44:14 -06001460static unsigned char FPT_RdStack(u32 portBase, unsigned char index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461{
1462 WR_HARPOON(portBase + hp_stack_addr, index);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001463 return RD_HARPOON(portBase + hp_stack_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464}
1465
Khalid Aziz391e2f22013-05-16 19:44:14 -06001466static void FPT_WrStack(u32 portBase, unsigned char index, unsigned char data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467{
1468 WR_HARPOON(portBase + hp_stack_addr, index);
1469 WR_HARPOON(portBase + hp_stack_data, data);
1470}
1471
Khalid Aziz391e2f22013-05-16 19:44:14 -06001472static unsigned char FPT_ChkIfChipInitialized(u32 ioPort)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001474 if ((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != FPT_RdStack(ioPort, 4))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001475 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001476 if ((RD_HARPOON(ioPort + hp_clkctrl_0) & CLKCTRL_DEFAULT)
1477 != CLKCTRL_DEFAULT)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001478 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001479 if ((RD_HARPOON(ioPort + hp_seltimeout) == TO_250ms) ||
1480 (RD_HARPOON(ioPort + hp_seltimeout) == TO_290ms))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001481 return 1;
1482 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483
1484}
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001485
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486/*---------------------------------------------------------------------
1487 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001488 * Function: FlashPoint_StartCCB
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 *
1490 * Description: Start a command pointed to by p_Sccb. When the
1491 * command is completed it will be returned via the
1492 * callback function.
1493 *
1494 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06001495static void FlashPoint_StartCCB(void *curr_card, struct sccb *p_Sccb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496{
Khalid Aziz391e2f22013-05-16 19:44:14 -06001497 u32 ioport;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001498 unsigned char thisCard, lun;
1499 struct sccb *pSaveSccb;
1500 CALL_BK_FN callback;
Khalid Aziz391e2f22013-05-16 19:44:14 -06001501 struct sccb_card *pCurrCard = curr_card;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502
Khalid Aziz391e2f22013-05-16 19:44:14 -06001503 thisCard = pCurrCard->cardIndex;
1504 ioport = pCurrCard->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505
Adrian Bunk1377d8d2008-04-23 12:51:10 +03001506 if ((p_Sccb->TargID >= MAX_SCSI_TAR) || (p_Sccb->Lun >= MAX_LUN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508 p_Sccb->HostStatus = SCCB_COMPLETE;
1509 p_Sccb->SccbStatus = SCCB_ERROR;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001510 callback = (CALL_BK_FN) p_Sccb->SccbCallback;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 if (callback)
1512 callback(p_Sccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 return;
1515 }
1516
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001517 FPT_sinits(p_Sccb, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518
Khalid Aziz391e2f22013-05-16 19:44:14 -06001519 if (!pCurrCard->cmdCounter) {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001520 WR_HARPOON(ioport + hp_semaphore,
1521 (RD_HARPOON(ioport + hp_semaphore)
1522 | SCCB_MGR_ACTIVE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523
Khalid Aziz391e2f22013-05-16 19:44:14 -06001524 if (pCurrCard->globalFlags & F_GREEN_PC) {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001525 WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT);
1526 WR_HARPOON(ioport + hp_sys_ctrl, 0x00);
1527 }
1528 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529
Khalid Aziz391e2f22013-05-16 19:44:14 -06001530 pCurrCard->cmdCounter++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001532 if (RD_HARPOON(ioport + hp_semaphore) & BIOS_IN_USE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001534 WR_HARPOON(ioport + hp_semaphore,
1535 (RD_HARPOON(ioport + hp_semaphore)
1536 | TICKLE_ME));
1537 if (p_Sccb->OperationCode == RESET_COMMAND) {
1538 pSaveSccb =
Khalid Aziz391e2f22013-05-16 19:44:14 -06001539 pCurrCard->currentSCCB;
1540 pCurrCard->currentSCCB = p_Sccb;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001541 FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
Khalid Aziz391e2f22013-05-16 19:44:14 -06001542 pCurrCard->currentSCCB =
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001543 pSaveSccb;
1544 } else {
1545 FPT_queueAddSccb(p_Sccb, thisCard);
1546 }
1547 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001549 else if ((RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001551 if (p_Sccb->OperationCode == RESET_COMMAND) {
1552 pSaveSccb =
Khalid Aziz391e2f22013-05-16 19:44:14 -06001553 pCurrCard->currentSCCB;
1554 pCurrCard->currentSCCB = p_Sccb;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001555 FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
Khalid Aziz391e2f22013-05-16 19:44:14 -06001556 pCurrCard->currentSCCB =
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001557 pSaveSccb;
1558 } else {
1559 FPT_queueAddSccb(p_Sccb, thisCard);
1560 }
1561 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001563 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001565 MDISABLE_INT(ioport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566
Khalid Aziz391e2f22013-05-16 19:44:14 -06001567 if ((pCurrCard->globalFlags & F_CONLUN_IO) &&
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001568 ((FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].
1569 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570 lun = p_Sccb->Lun;
1571 else
1572 lun = 0;
Khalid Aziz391e2f22013-05-16 19:44:14 -06001573 if ((pCurrCard->currentSCCB == NULL) &&
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001574 (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarSelQ_Cnt == 0)
1575 && (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarLUNBusy[lun]
1576 == 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577
Khalid Aziz391e2f22013-05-16 19:44:14 -06001578 pCurrCard->currentSCCB = p_Sccb;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001579 FPT_ssel(p_Sccb->SccbIOPort, thisCard);
1580 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001582 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001584 if (p_Sccb->OperationCode == RESET_COMMAND) {
Khalid Aziz391e2f22013-05-16 19:44:14 -06001585 pSaveSccb = pCurrCard->currentSCCB;
1586 pCurrCard->currentSCCB = p_Sccb;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001587 FPT_queueSelectFail(&FPT_BL_Card[thisCard],
1588 thisCard);
Khalid Aziz391e2f22013-05-16 19:44:14 -06001589 pCurrCard->currentSCCB = pSaveSccb;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001590 } else {
1591 FPT_queueAddSccb(p_Sccb, thisCard);
1592 }
1593 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001595 MENABLE_INT(ioport);
1596 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598}
1599
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600/*---------------------------------------------------------------------
1601 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001602 * Function: FlashPoint_AbortCCB
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603 *
1604 * Description: Abort the command pointed to by p_Sccb. When the
1605 * command is completed it will be returned via the
1606 * callback function.
1607 *
1608 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06001609static int FlashPoint_AbortCCB(void *pCurrCard, struct sccb *p_Sccb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610{
Khalid Aziz391e2f22013-05-16 19:44:14 -06001611 u32 ioport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08001613 unsigned char thisCard;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 CALL_BK_FN callback;
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08001615 unsigned char TID;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001616 struct sccb *pSaveSCCB;
1617 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001619 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001621 thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001623 if (!(RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001625 if (FPT_queueFindSccb(p_Sccb, thisCard)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001627 ((struct sccb_card *)pCurrCard)->cmdCounter--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001629 if (!((struct sccb_card *)pCurrCard)->cmdCounter)
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001630 WR_HARPOON(ioport + hp_semaphore,
1631 (RD_HARPOON(ioport + hp_semaphore)
1632 & (unsigned
1633 char)(~(SCCB_MGR_ACTIVE |
1634 TICKLE_ME))));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636 p_Sccb->SccbStatus = SCCB_ABORT;
1637 callback = p_Sccb->SccbCallback;
1638 callback(p_Sccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001640 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641 }
1642
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001643 else {
1644 if (((struct sccb_card *)pCurrCard)->currentSCCB ==
1645 p_Sccb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 p_Sccb->SccbStatus = SCCB_ABORT;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001647 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648
1649 }
1650
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001651 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652
1653 TID = p_Sccb->TargID;
1654
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001655 if (p_Sccb->Sccb_tag) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656 MDISABLE_INT(ioport);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001657 if (((struct sccb_card *)pCurrCard)->
1658 discQ_Tbl[p_Sccb->Sccb_tag] ==
1659 p_Sccb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 p_Sccb->SccbStatus = SCCB_ABORT;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001661 p_Sccb->Sccb_scsistat =
1662 ABORT_ST;
1663 p_Sccb->Sccb_scsimsg =
1664 SMABORT_TAG;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001666 if (((struct sccb_card *)
1667 pCurrCard)->currentSCCB ==
1668 NULL) {
1669 ((struct sccb_card *)
1670 pCurrCard)->
1671 currentSCCB = p_Sccb;
1672 FPT_ssel(ioport,
1673 thisCard);
1674 } else {
1675 pSaveSCCB =
1676 ((struct sccb_card
1677 *)pCurrCard)->
1678 currentSCCB;
1679 ((struct sccb_card *)
1680 pCurrCard)->
1681 currentSCCB = p_Sccb;
1682 FPT_queueSelectFail((struct sccb_card *)pCurrCard, thisCard);
1683 ((struct sccb_card *)
1684 pCurrCard)->
1685 currentSCCB = pSaveSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686 }
1687 }
1688 MENABLE_INT(ioport);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001689 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001690 } else {
1691 currTar_Info =
1692 &FPT_sccbMgrTbl[thisCard][p_Sccb->
1693 TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001695 if (FPT_BL_Card[thisCard].
1696 discQ_Tbl[currTar_Info->
1697 LunDiscQ_Idx[p_Sccb->Lun]]
1698 == p_Sccb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 p_Sccb->SccbStatus = SCCB_ABORT;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001700 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701 }
1702 }
1703 }
1704 }
1705 }
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001706 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707}
1708
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709/*---------------------------------------------------------------------
1710 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001711 * Function: FlashPoint_InterruptPending
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 *
1713 * Description: Do a quick check to determine if there is a pending
1714 * interrupt for this card and disable the IRQ Pin if so.
1715 *
1716 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06001717static unsigned char FlashPoint_InterruptPending(void *pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718{
Khalid Aziz391e2f22013-05-16 19:44:14 -06001719 u32 ioport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001721 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001723 if (RD_HARPOON(ioport + hp_int_status) & INT_ASSERTED) {
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001724 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001725 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001727 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001728
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001729 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730}
1731
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732/*---------------------------------------------------------------------
1733 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001734 * Function: FlashPoint_HandleInterrupt
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 *
1736 * Description: This is our entry point when an interrupt is generated
1737 * by the card and the upper level driver passes it on to
1738 * us.
1739 *
1740 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06001741static int FlashPoint_HandleInterrupt(void *pcard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001742{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001743 struct sccb *currSCCB;
1744 unsigned char thisCard, result, bm_status, bm_int_st;
1745 unsigned short hp_int;
1746 unsigned char i, target;
Khalid Aziz391e2f22013-05-16 19:44:14 -06001747 struct sccb_card *pCurrCard = pcard;
1748 u32 ioport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749
Khalid Aziz391e2f22013-05-16 19:44:14 -06001750 thisCard = pCurrCard->cardIndex;
1751 ioport = pCurrCard->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001753 MDISABLE_INT(ioport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001755 if ((bm_int_st = RD_HARPOON(ioport + hp_int_status)) & EXT_STATUS_ON)
Khalid Aziz391e2f22013-05-16 19:44:14 -06001756 bm_status = RD_HARPOON(ioport + hp_ext_status) &
1757 (unsigned char)BAD_EXT_STATUS;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001758 else
1759 bm_status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001760
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001761 WR_HARPOON(ioport + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762
Khalid Aziz391e2f22013-05-16 19:44:14 -06001763 while ((hp_int = RDW_HARPOON((ioport + hp_intstat)) &
1764 FPT_default_intena) | bm_status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765
Khalid Aziz391e2f22013-05-16 19:44:14 -06001766 currSCCB = pCurrCard->currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001768 if (hp_int & (FIFO | TIMEOUT | RESET | SCAM_SEL) || bm_status) {
1769 result =
Khalid Aziz391e2f22013-05-16 19:44:14 -06001770 FPT_SccbMgr_bad_isr(ioport, thisCard, pCurrCard,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001771 hp_int);
1772 WRW_HARPOON((ioport + hp_intstat),
1773 (FIFO | TIMEOUT | RESET | SCAM_SEL));
1774 bm_status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001776 if (result) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001778 MENABLE_INT(ioport);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001779 return result;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001780 }
1781 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001783 else if (hp_int & ICMD_COMP) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001785 if (!(hp_int & BUS_FREE)) {
1786 /* Wait for the BusFree before starting a new command. We
1787 must also check for being reselected since the BusFree
1788 may not show up if another device reselects us in 1.5us or
1789 less. SRR Wednesday, 3/8/1995.
1790 */
1791 while (!
1792 (RDW_HARPOON((ioport + hp_intstat)) &
1793 (BUS_FREE | RSEL))) ;
1794 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795
Khalid Aziz391e2f22013-05-16 19:44:14 -06001796 if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001798 FPT_phaseChkFifo(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799
1800/* WRW_HARPOON((ioport+hp_intstat),
1801 (BUS_FREE | ICMD_COMP | ITAR_DISC | XFER_CNT_0));
1802 */
1803
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001804 WRW_HARPOON((ioport + hp_intstat), CLR_ALL_INT_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001806 FPT_autoCmdCmplt(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001808 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001810 else if (hp_int & ITAR_DISC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811
Khalid Aziz391e2f22013-05-16 19:44:14 -06001812 if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001813 FPT_phaseChkFifo(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814
Khalid Aziz391e2f22013-05-16 19:44:14 -06001815 if (RD_HARPOON(ioport + hp_gp_reg_1) ==
1816 SMSAVE_DATA_PTR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001818 WR_HARPOON(ioport + hp_gp_reg_1, 0x00);
1819 currSCCB->Sccb_XferState |= F_NO_DATA_YET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001821 currSCCB->Sccb_savedATC = currSCCB->Sccb_ATC;
1822 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001824 currSCCB->Sccb_scsistat = DISCONNECT_ST;
1825 FPT_queueDisconnect(currSCCB, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001827 /* Wait for the BusFree before starting a new command. We
1828 must also check for being reselected since the BusFree
1829 may not show up if another device reselects us in 1.5us or
1830 less. SRR Wednesday, 3/8/1995.
1831 */
1832 while (!
1833 (RDW_HARPOON((ioport + hp_intstat)) &
1834 (BUS_FREE | RSEL))
1835 && !((RDW_HARPOON((ioport + hp_intstat)) & PHASE)
1836 && RD_HARPOON((ioport + hp_scsisig)) ==
1837 (SCSI_BSY | SCSI_REQ | SCSI_CD | SCSI_MSG |
1838 SCSI_IOBIT))) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001840 /*
1841 The additional loop exit condition above detects a timing problem
1842 with the revision D/E harpoon chips. The caller should reset the
1843 host adapter to recover when 0xFE is returned.
1844 */
1845 if (!
1846 (RDW_HARPOON((ioport + hp_intstat)) &
1847 (BUS_FREE | RSEL))) {
1848 MENABLE_INT(ioport);
1849 return 0xFE;
1850 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001852 WRW_HARPOON((ioport + hp_intstat),
1853 (BUS_FREE | ITAR_DISC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854
Khalid Aziz391e2f22013-05-16 19:44:14 -06001855 pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001857 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001859 else if (hp_int & RSEL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001860
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001861 WRW_HARPOON((ioport + hp_intstat),
1862 (PROG_HLT | RSEL | PHASE | BUS_FREE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001864 if (RDW_HARPOON((ioport + hp_intstat)) & ITAR_DISC) {
Khalid Aziz391e2f22013-05-16 19:44:14 -06001865 if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001866 FPT_phaseChkFifo(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001868 if (RD_HARPOON(ioport + hp_gp_reg_1) ==
1869 SMSAVE_DATA_PTR) {
1870 WR_HARPOON(ioport + hp_gp_reg_1, 0x00);
1871 currSCCB->Sccb_XferState |=
1872 F_NO_DATA_YET;
1873 currSCCB->Sccb_savedATC =
1874 currSCCB->Sccb_ATC;
1875 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001877 WRW_HARPOON((ioport + hp_intstat),
1878 (BUS_FREE | ITAR_DISC));
1879 currSCCB->Sccb_scsistat = DISCONNECT_ST;
1880 FPT_queueDisconnect(currSCCB, thisCard);
1881 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882
Khalid Aziz391e2f22013-05-16 19:44:14 -06001883 FPT_sres(ioport, thisCard, pCurrCard);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001884 FPT_phaseDecode(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001886 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001887
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001888 else if ((hp_int & IDO_STRT) && (!(hp_int & BUS_FREE))) {
1889
1890 WRW_HARPOON((ioport + hp_intstat),
1891 (IDO_STRT | XFER_CNT_0));
1892 FPT_phaseDecode(ioport, thisCard);
1893
1894 }
1895
1896 else if ((hp_int & IUNKWN) || (hp_int & PROG_HLT)) {
1897 WRW_HARPOON((ioport + hp_intstat),
1898 (PHASE | IUNKWN | PROG_HLT));
1899 if ((RD_HARPOON(ioport + hp_prgmcnt_0) & (unsigned char)
1900 0x3f) < (unsigned char)SELCHK) {
1901 FPT_phaseDecode(ioport, thisCard);
1902 } else {
1903 /* Harpoon problem some SCSI target device respond to selection
1904 with short BUSY pulse (<400ns) this will make the Harpoon is not able
1905 to latch the correct Target ID into reg. x53.
1906 The work around require to correct this reg. But when write to this
1907 reg. (0x53) also increment the FIFO write addr reg (0x6f), thus we
1908 need to read this reg first then restore it later. After update to 0x53 */
1909
1910 i = (unsigned
1911 char)(RD_HARPOON(ioport + hp_fifowrite));
1912 target =
1913 (unsigned
1914 char)(RD_HARPOON(ioport + hp_gp_reg_3));
1915 WR_HARPOON(ioport + hp_xfer_pad,
1916 (unsigned char)ID_UNLOCK);
1917 WR_HARPOON(ioport + hp_select_id,
1918 (unsigned char)(target | target <<
1919 4));
1920 WR_HARPOON(ioport + hp_xfer_pad,
1921 (unsigned char)0x00);
1922 WR_HARPOON(ioport + hp_fifowrite, i);
1923 WR_HARPOON(ioport + hp_autostart_3,
1924 (AUTO_IMMED + TAG_STRT));
1925 }
1926 }
1927
1928 else if (hp_int & XFER_CNT_0) {
1929
1930 WRW_HARPOON((ioport + hp_intstat), XFER_CNT_0);
1931
1932 FPT_schkdd(ioport, thisCard);
1933
1934 }
1935
1936 else if (hp_int & BUS_FREE) {
1937
1938 WRW_HARPOON((ioport + hp_intstat), BUS_FREE);
1939
Khalid Aziz391e2f22013-05-16 19:44:14 -06001940 if (pCurrCard->globalFlags & F_HOST_XFER_ACT) {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001941
1942 FPT_hostDataXferAbort(ioport, thisCard,
1943 currSCCB);
1944 }
1945
1946 FPT_phaseBusFree(ioport, thisCard);
1947 }
1948
1949 else if (hp_int & ITICKLE) {
1950
1951 WRW_HARPOON((ioport + hp_intstat), ITICKLE);
Khalid Aziz391e2f22013-05-16 19:44:14 -06001952 pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001953 }
1954
1955 if (((struct sccb_card *)pCurrCard)->
1956 globalFlags & F_NEW_SCCB_CMD) {
1957
Khalid Aziz391e2f22013-05-16 19:44:14 -06001958 pCurrCard->globalFlags &= ~F_NEW_SCCB_CMD;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001959
Khalid Aziz391e2f22013-05-16 19:44:14 -06001960 if (pCurrCard->currentSCCB == NULL)
1961 FPT_queueSearchSelect(pCurrCard, thisCard);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001962
Khalid Aziz391e2f22013-05-16 19:44:14 -06001963 if (pCurrCard->currentSCCB != NULL) {
1964 pCurrCard->globalFlags &= ~F_NEW_SCCB_CMD;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001965 FPT_ssel(ioport, thisCard);
1966 }
1967
1968 break;
1969
1970 }
1971
1972 } /*end while */
1973
1974 MENABLE_INT(ioport);
1975
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001976 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977}
1978
1979/*---------------------------------------------------------------------
1980 *
1981 * Function: Sccb_bad_isr
1982 *
1983 * Description: Some type of interrupt has occurred which is slightly
1984 * out of the ordinary. We will now decode it fully, in
1985 * this routine. This is broken up in an attempt to save
1986 * processing time.
1987 *
1988 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06001989static unsigned char FPT_SccbMgr_bad_isr(u32 p_port, unsigned char p_card,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001990 struct sccb_card *pCurrCard,
1991 unsigned short p_int)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001993 unsigned char temp, ScamFlg;
1994 struct sccb_mgr_tar_info *currTar_Info;
1995 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001997 if (RD_HARPOON(p_port + hp_ext_status) &
1998 (BM_FORCE_OFF | PCI_DEV_TMOUT | BM_PARITY_ERR | PIO_OVERRUN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002000 if (pCurrCard->globalFlags & F_HOST_XFER_ACT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002002 FPT_hostDataXferAbort(p_port, p_card,
2003 pCurrCard->currentSCCB);
2004 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002006 if (RD_HARPOON(p_port + hp_pci_stat_cfg) & REC_MASTER_ABORT)
2007 {
2008 WR_HARPOON(p_port + hp_pci_stat_cfg,
2009 (RD_HARPOON(p_port + hp_pci_stat_cfg) &
2010 ~REC_MASTER_ABORT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002012 WR_HARPOON(p_port + hp_host_blk_cnt, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002014 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002016 if (pCurrCard->currentSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002018 if (!pCurrCard->currentSCCB->HostStatus)
2019 pCurrCard->currentSCCB->HostStatus =
2020 SCCB_BM_ERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002022 FPT_sxfrp(p_port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002024 temp = (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
2025 (EXT_ARB_ACK | SCSI_TERM_ENA_H));
2026 WR_HARPOON(p_port + hp_ee_ctrl,
2027 ((unsigned char)temp | SEE_MS | SEE_CS));
2028 WR_HARPOON(p_port + hp_ee_ctrl, temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002030 if (!
2031 (RDW_HARPOON((p_port + hp_intstat)) &
2032 (BUS_FREE | RESET))) {
2033 FPT_phaseDecode(p_port, p_card);
2034 }
2035 }
2036 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002038 else if (p_int & RESET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002040 WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
2041 WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
2042 if (pCurrCard->currentSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002044 if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002046 FPT_hostDataXferAbort(p_port, p_card,
2047 pCurrCard->currentSCCB);
2048 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002049
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002050 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002052 FPT_sresb(p_port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002054 while (RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST) {
2055 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002057 pCurrNvRam = pCurrCard->pNvRamInfo;
2058 if (pCurrNvRam) {
2059 ScamFlg = pCurrNvRam->niScamConf;
2060 } else {
2061 ScamFlg =
2062 (unsigned char)FPT_utilEERead(p_port,
2063 SCAM_CONFIG / 2);
2064 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002066 FPT_XbowInit(p_port, ScamFlg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002068 FPT_scini(p_card, pCurrCard->ourId, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002070 return 0xFF;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002071 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002073 else if (p_int & FIFO) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002075 WRW_HARPOON((p_port + hp_intstat), FIFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002077 if (pCurrCard->currentSCCB != NULL)
2078 FPT_sxfrp(p_port, p_card);
2079 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002081 else if (p_int & TIMEOUT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002083 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002085 WRW_HARPOON((p_port + hp_intstat),
2086 (PROG_HLT | TIMEOUT | SEL | BUS_FREE | PHASE |
2087 IUNKWN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002089 pCurrCard->currentSCCB->HostStatus = SCCB_SELECTION_TIMEOUT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002091 currTar_Info =
2092 &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
2093 if ((pCurrCard->globalFlags & F_CONLUN_IO)
2094 && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
2095 TAG_Q_TRYING))
2096 currTar_Info->TarLUNBusy[pCurrCard->currentSCCB->Lun] =
2097 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002099 currTar_Info->TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002101 if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
2102 currTar_Info->TarSyncCtrl = 0;
2103 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2104 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002106 if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
2107 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2108 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002110 FPT_sssyncv(p_port, pCurrCard->currentSCCB->TargID, NARROW_SCSI,
2111 currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002113 FPT_queueCmdComplete(pCurrCard, pCurrCard->currentSCCB, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002115 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002117 else if (p_int & SCAM_SEL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002118
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002119 FPT_scarb(p_port, LEVEL2_TAR);
2120 FPT_scsel(p_port);
2121 FPT_scasid(p_card, p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002123 FPT_scbusf(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002125 WRW_HARPOON((p_port + hp_intstat), SCAM_SEL);
2126 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002128 return 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129}
2130
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131/*---------------------------------------------------------------------
2132 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133 * Function: SccbMgrTableInit
2134 *
2135 * Description: Initialize all Sccb manager data structures.
2136 *
2137 *---------------------------------------------------------------------*/
2138
Sudip Mukherjeecd9d7152015-09-16 19:36:20 +05302139static void FPT_SccbMgrTableInitAll(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002141 unsigned char thisCard;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002143 for (thisCard = 0; thisCard < MAX_CARDS; thisCard++) {
2144 FPT_SccbMgrTableInitCard(&FPT_BL_Card[thisCard], thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002146 FPT_BL_Card[thisCard].ioPort = 0x00;
2147 FPT_BL_Card[thisCard].cardInfo = NULL;
2148 FPT_BL_Card[thisCard].cardIndex = 0xFF;
2149 FPT_BL_Card[thisCard].ourId = 0x00;
2150 FPT_BL_Card[thisCard].pNvRamInfo = NULL;
2151 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152}
2153
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154/*---------------------------------------------------------------------
2155 *
2156 * Function: SccbMgrTableInit
2157 *
2158 * Description: Initialize all Sccb manager data structures.
2159 *
2160 *---------------------------------------------------------------------*/
2161
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002162static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard,
2163 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002165 unsigned char scsiID, qtag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002167 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002168 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 }
2170
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002171 for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
2172 FPT_sccbMgrTbl[p_card][scsiID].TarStatus = 0;
2173 FPT_sccbMgrTbl[p_card][scsiID].TarEEValue = 0;
2174 FPT_SccbMgrTableInitTarget(p_card, scsiID);
2175 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002177 pCurrCard->scanIndex = 0x00;
2178 pCurrCard->currentSCCB = NULL;
2179 pCurrCard->globalFlags = 0x00;
2180 pCurrCard->cmdCounter = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181 pCurrCard->tagQ_Lst = 0x01;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002182 pCurrCard->discQCount = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183
2184}
2185
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186/*---------------------------------------------------------------------
2187 *
2188 * Function: SccbMgrTableInit
2189 *
2190 * Description: Initialize all Sccb manager data structures.
2191 *
2192 *---------------------------------------------------------------------*/
2193
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002194static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
2195 unsigned char target)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196{
2197
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08002198 unsigned char lun, qtag;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002199 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200
James Bottomley 47b5d692005-04-24 02:38:05 -05002201 currTar_Info = &FPT_sccbMgrTbl[p_card][target];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202
2203 currTar_Info->TarSelQ_Cnt = 0;
2204 currTar_Info->TarSyncCtrl = 0;
2205
2206 currTar_Info->TarSelQ_Head = NULL;
2207 currTar_Info->TarSelQ_Tail = NULL;
2208 currTar_Info->TarTagQ_Cnt = 0;
James Bottomley 47b5d692005-04-24 02:38:05 -05002209 currTar_Info->TarLUN_CA = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002211 for (lun = 0; lun < MAX_LUN; lun++) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002212 currTar_Info->TarLUNBusy[lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213 currTar_Info->LunDiscQ_Idx[lun] = 0;
2214 }
2215
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002216 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
2217 if (FPT_BL_Card[p_card].discQ_Tbl[qtag] != NULL) {
2218 if (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
2219 target) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002220 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
2221 FPT_BL_Card[p_card].discQCount--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222 }
2223 }
2224 }
2225}
2226
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227/*---------------------------------------------------------------------
2228 *
2229 * Function: sfetm
2230 *
2231 * Description: Read in a message byte from the SCSI bus, and check
2232 * for a parity error.
2233 *
2234 *---------------------------------------------------------------------*/
2235
Khalid Aziz391e2f22013-05-16 19:44:14 -06002236static unsigned char FPT_sfm(u32 port, struct sccb *pCurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237{
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08002238 unsigned char message;
Alexey Dobriyanc823fee2006-03-08 00:14:25 -08002239 unsigned short TimeOutLoop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240
2241 TimeOutLoop = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002242 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2243 (TimeOutLoop++ < 20000)) {
2244 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002246 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002248 message = RD_HARPOON(port + hp_scsidata_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002250 WR_HARPOON(port + hp_scsisig, SCSI_ACK + S_MSGI_PH);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251
2252 if (TimeOutLoop > 20000)
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002253 message = 0x00; /* force message byte = 0 if Time Out on Req */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002255 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
2256 (RD_HARPOON(port + hp_addstat) & SCSI_PAR_ERR)) {
2257 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2258 WR_HARPOON(port + hp_xferstat, 0);
2259 WR_HARPOON(port + hp_fiforead, 0);
2260 WR_HARPOON(port + hp_fifowrite, 0);
2261 if (pCurrSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262 pCurrSCCB->Sccb_scsimsg = SMPARITY;
2263 }
2264 message = 0x00;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002265 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266 ACCEPT_MSG_ATN(port);
2267 TimeOutLoop = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002268 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2269 (TimeOutLoop++ < 20000)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002271 if (TimeOutLoop > 20000) {
2272 WRW_HARPOON((port + hp_intstat), PARITY);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002273 return message;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002275 if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) !=
2276 S_MSGI_PH) {
2277 WRW_HARPOON((port + hp_intstat), PARITY);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002278 return message;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002279 }
2280 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002282 RD_HARPOON(port + hp_scsidata_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002284 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002286 } while (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287
2288 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002289 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2290 WR_HARPOON(port + hp_xferstat, 0);
2291 WR_HARPOON(port + hp_fiforead, 0);
2292 WR_HARPOON(port + hp_fifowrite, 0);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002293 return message;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294}
2295
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296/*---------------------------------------------------------------------
2297 *
James Bottomley 47b5d692005-04-24 02:38:05 -05002298 * Function: FPT_ssel
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299 *
2300 * Description: Load up automation and select target device.
2301 *
2302 *---------------------------------------------------------------------*/
2303
Khalid Aziz391e2f22013-05-16 19:44:14 -06002304static void FPT_ssel(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305{
2306
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002307 unsigned char auto_loaded, i, target, *theCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308
Khalid Aziz391e2f22013-05-16 19:44:14 -06002309 u32 cdb_reg;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002310 struct sccb_card *CurrCard;
2311 struct sccb *currSCCB;
2312 struct sccb_mgr_tar_info *currTar_Info;
2313 unsigned char lastTag, lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002315 CurrCard = &FPT_BL_Card[p_card];
2316 currSCCB = CurrCard->currentSCCB;
2317 target = currSCCB->TargID;
2318 currTar_Info = &FPT_sccbMgrTbl[p_card][target];
2319 lastTag = CurrCard->tagQ_Lst;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002321 ARAM_ACCESS(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322
2323 if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
2324 currSCCB->ControlByte &= ~F_USE_CMD_Q;
2325
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002326 if (((CurrCard->globalFlags & F_CONLUN_IO) &&
2327 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002329 lun = currSCCB->Lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330 else
2331 lun = 0;
2332
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002333 if (CurrCard->globalFlags & F_TAG_STARTED) {
2334 if (!(currSCCB->ControlByte & F_USE_CMD_Q)) {
2335 if ((currTar_Info->TarLUN_CA == 0)
2336 && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
2337 == TAG_Q_TRYING)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002339 if (currTar_Info->TarTagQ_Cnt != 0) {
2340 currTar_Info->TarLUNBusy[lun] = 1;
2341 FPT_queueSelectFail(CurrCard, p_card);
2342 SGRAM_ACCESS(port);
2343 return;
2344 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002346 else {
2347 currTar_Info->TarLUNBusy[lun] = 1;
2348 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002350 }
2351 /*End non-tagged */
2352 else {
2353 currTar_Info->TarLUNBusy[lun] = 1;
2354 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002356 }
2357 /*!Use cmd Q Tagged */
2358 else {
2359 if (currTar_Info->TarLUN_CA == 1) {
2360 FPT_queueSelectFail(CurrCard, p_card);
2361 SGRAM_ACCESS(port);
2362 return;
2363 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364
James Bottomley 47b5d692005-04-24 02:38:05 -05002365 currTar_Info->TarLUNBusy[lun] = 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002366
2367 } /*else use cmd Q tagged */
2368
2369 }
2370 /*if glob tagged started */
2371 else {
2372 currTar_Info->TarLUNBusy[lun] = 1;
2373 }
2374
2375 if ((((CurrCard->globalFlags & F_CONLUN_IO) &&
2376 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
2377 || (!(currSCCB->ControlByte & F_USE_CMD_Q)))) {
2378 if (CurrCard->discQCount >= QUEUE_DEPTH) {
2379 currTar_Info->TarLUNBusy[lun] = 1;
2380 FPT_queueSelectFail(CurrCard, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381 SGRAM_ACCESS(port);
2382 return;
2383 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002384 for (i = 1; i < QUEUE_DEPTH; i++) {
2385 if (++lastTag >= QUEUE_DEPTH)
2386 lastTag = 1;
2387 if (CurrCard->discQ_Tbl[lastTag] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388 CurrCard->tagQ_Lst = lastTag;
2389 currTar_Info->LunDiscQ_Idx[lun] = lastTag;
2390 CurrCard->discQ_Tbl[lastTag] = currSCCB;
2391 CurrCard->discQCount++;
2392 break;
2393 }
2394 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002395 if (i == QUEUE_DEPTH) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002396 currTar_Info->TarLUNBusy[lun] = 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002397 FPT_queueSelectFail(CurrCard, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 SGRAM_ACCESS(port);
2399 return;
2400 }
2401 }
2402
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002403 auto_loaded = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002405 WR_HARPOON(port + hp_select_id, target);
2406 WR_HARPOON(port + hp_gp_reg_3, target); /* Use by new automation logic */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002408 if (currSCCB->OperationCode == RESET_COMMAND) {
2409 WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
2410 (currSCCB->
2411 Sccb_idmsg & ~DISC_PRIV)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002413 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + NP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002415 currSCCB->Sccb_scsimsg = SMDEV_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002416
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002417 WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
2418 auto_loaded = 1;
2419 currSCCB->Sccb_scsistat = SELECT_BDR_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002421 if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
2422 currTar_Info->TarSyncCtrl = 0;
2423 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424 }
2425
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002426 if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
2427 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2428 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002430 FPT_sssyncv(port, target, NARROW_SCSI, currTar_Info);
2431 FPT_SccbMgrTableInitTarget(p_card, target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002433 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002435 else if (currSCCB->Sccb_scsistat == ABORT_ST) {
2436 WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
2437 (currSCCB->
2438 Sccb_idmsg & ~DISC_PRIV)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002440 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002442 WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT +
2443 (((unsigned
2444 char)(currSCCB->
2445 ControlByte &
2446 TAG_TYPE_MASK)
2447 >> 6) | (unsigned char)
2448 0x20)));
2449 WRW_HARPOON((port + SYNC_MSGS + 2),
2450 (MPM_OP + AMSG_OUT + currSCCB->Sccb_tag));
2451 WRW_HARPOON((port + SYNC_MSGS + 4), (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002453 WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
2454 auto_loaded = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002456 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002458 else if (!(currTar_Info->TarStatus & WIDE_NEGOCIATED)) {
2459 auto_loaded = FPT_siwidn(port, p_card);
2460 currSCCB->Sccb_scsistat = SELECT_WN_ST;
2461 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002463 else if (!((currTar_Info->TarStatus & TAR_SYNC_MASK)
2464 == SYNC_SUPPORTED)) {
2465 auto_loaded = FPT_sisyncn(port, p_card, 0);
2466 currSCCB->Sccb_scsistat = SELECT_SN_ST;
2467 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002469 if (!auto_loaded) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002471 if (currSCCB->ControlByte & F_USE_CMD_Q) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002473 CurrCard->globalFlags |= F_TAG_STARTED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002475 if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
2476 == TAG_Q_REJECT) {
2477 currSCCB->ControlByte &= ~F_USE_CMD_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002479 /* Fix up the start instruction with a jump to
2480 Non-Tag-CMD handling */
2481 WRW_HARPOON((port + ID_MSG_STRT),
2482 BRH_OP + ALWAYS + NTCMD);
2483
2484 WRW_HARPOON((port + NON_TAG_ID_MSG),
2485 (MPM_OP + AMSG_OUT +
2486 currSCCB->Sccb_idmsg));
2487
2488 WR_HARPOON(port + hp_autostart_3,
2489 (SELECT + SELCHK_STRT));
2490
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002491 /* Setup our STATE so we know what happened when
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002492 the wheels fall off. */
2493 currSCCB->Sccb_scsistat = SELECT_ST;
2494
2495 currTar_Info->TarLUNBusy[lun] = 1;
2496 }
2497
2498 else {
2499 WRW_HARPOON((port + ID_MSG_STRT),
2500 (MPM_OP + AMSG_OUT +
2501 currSCCB->Sccb_idmsg));
2502
2503 WRW_HARPOON((port + ID_MSG_STRT + 2),
2504 (MPM_OP + AMSG_OUT +
2505 (((unsigned char)(currSCCB->
2506 ControlByte &
2507 TAG_TYPE_MASK)
2508 >> 6) | (unsigned char)0x20)));
2509
2510 for (i = 1; i < QUEUE_DEPTH; i++) {
2511 if (++lastTag >= QUEUE_DEPTH)
2512 lastTag = 1;
2513 if (CurrCard->discQ_Tbl[lastTag] ==
2514 NULL) {
2515 WRW_HARPOON((port +
2516 ID_MSG_STRT + 6),
2517 (MPM_OP + AMSG_OUT +
2518 lastTag));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519 CurrCard->tagQ_Lst = lastTag;
2520 currSCCB->Sccb_tag = lastTag;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002521 CurrCard->discQ_Tbl[lastTag] =
2522 currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523 CurrCard->discQCount++;
2524 break;
2525 }
2526 }
2527
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002528 if (i == QUEUE_DEPTH) {
2529 currTar_Info->TarLUNBusy[lun] = 1;
2530 FPT_queueSelectFail(CurrCard, p_card);
2531 SGRAM_ACCESS(port);
2532 return;
2533 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002534
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002535 currSCCB->Sccb_scsistat = SELECT_Q_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002537 WR_HARPOON(port + hp_autostart_3,
2538 (SELECT + SELCHK_STRT));
2539 }
2540 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002542 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002544 WRW_HARPOON((port + ID_MSG_STRT),
2545 BRH_OP + ALWAYS + NTCMD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002547 WRW_HARPOON((port + NON_TAG_ID_MSG),
2548 (MPM_OP + AMSG_OUT + currSCCB->Sccb_idmsg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002550 currSCCB->Sccb_scsistat = SELECT_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002552 WR_HARPOON(port + hp_autostart_3,
2553 (SELECT + SELCHK_STRT));
2554 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002556 theCCB = (unsigned char *)&currSCCB->Cdb[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002558 cdb_reg = port + CMD_STRT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002560 for (i = 0; i < currSCCB->CdbLength; i++) {
2561 WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + *theCCB));
2562 cdb_reg += 2;
2563 theCCB++;
2564 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002566 if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
2567 WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002569 }
2570 /* auto_loaded */
2571 WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
2572 WR_HARPOON(port + hp_xferstat, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002574 WRW_HARPOON((port + hp_intstat), (PROG_HLT | TIMEOUT | SEL | BUS_FREE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002575
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002576 WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002578 if (!(currSCCB->Sccb_MGRFlags & F_DEV_SELECTED)) {
2579 WR_HARPOON(port + hp_scsictrl_0,
2580 (SEL_TAR | ENA_ATN | ENA_RESEL | ENA_SCAM_SEL));
2581 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08002583/* auto_loaded = (RD_HARPOON(port+hp_autostart_3) & (unsigned char)0x1F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584 auto_loaded |= AUTO_IMMED; */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002585 auto_loaded = AUTO_IMMED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002587 DISABLE_AUTO(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002589 WR_HARPOON(port + hp_autostart_3, auto_loaded);
2590 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002592 SGRAM_ACCESS(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593}
2594
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595/*---------------------------------------------------------------------
2596 *
James Bottomley 47b5d692005-04-24 02:38:05 -05002597 * Function: FPT_sres
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598 *
2599 * Description: Hookup the correct CCB and handle the incoming messages.
2600 *
2601 *---------------------------------------------------------------------*/
2602
Khalid Aziz391e2f22013-05-16 19:44:14 -06002603static void FPT_sres(u32 port, unsigned char p_card,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002604 struct sccb_card *pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605{
2606
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002607 unsigned char our_target, message, lun = 0, tag, msgRetryCount;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002609 struct sccb_mgr_tar_info *currTar_Info;
2610 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002612 if (pCurrCard->currentSCCB != NULL) {
2613 currTar_Info =
2614 &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615 DISABLE_AUTO(port);
2616
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002617 WR_HARPOON((port + hp_scsictrl_0), (ENA_RESEL | ENA_SCAM_SEL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618
2619 currSCCB = pCurrCard->currentSCCB;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002620 if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2622 currSCCB->Sccb_scsistat = BUS_FREE_ST;
2623 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002624 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2626 currSCCB->Sccb_scsistat = BUS_FREE_ST;
2627 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002628 if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
2629 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
2630 TAG_Q_TRYING))) {
2631 currTar_Info->TarLUNBusy[currSCCB->Lun] = 0;
2632 if (currSCCB->Sccb_scsistat != ABORT_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633 pCurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002634 pCurrCard->discQ_Tbl[currTar_Info->
2635 LunDiscQ_Idx[currSCCB->
2636 Lun]]
2637 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002639 } else {
2640 currTar_Info->TarLUNBusy[0] = 0;
2641 if (currSCCB->Sccb_tag) {
2642 if (currSCCB->Sccb_scsistat != ABORT_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643 pCurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002644 pCurrCard->discQ_Tbl[currSCCB->
2645 Sccb_tag] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002647 } else {
2648 if (currSCCB->Sccb_scsistat != ABORT_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649 pCurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002650 pCurrCard->discQ_Tbl[currTar_Info->
2651 LunDiscQ_Idx[0]] =
2652 NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653 }
2654 }
2655 }
2656
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002657 FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658 }
2659
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002660 WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002662 our_target = (unsigned char)(RD_HARPOON(port + hp_select_id) >> 4);
James Bottomley 47b5d692005-04-24 02:38:05 -05002663 currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665 msgRetryCount = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002666 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667
James Bottomley 47b5d692005-04-24 02:38:05 -05002668 currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669 tag = 0;
2670
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002671 while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
2672 if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002674 WRW_HARPOON((port + hp_intstat), PHASE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675 return;
2676 }
2677 }
2678
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002679 WRW_HARPOON((port + hp_intstat), PHASE);
2680 if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002682 message = FPT_sfm(port, pCurrCard->currentSCCB);
2683 if (message) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002685 if (message <= (0x80 | LUN_MASK)) {
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08002686 lun = message & (unsigned char)LUN_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002688 if ((currTar_Info->
2689 TarStatus & TAR_TAG_Q_MASK) ==
2690 TAG_Q_TRYING) {
2691 if (currTar_Info->TarTagQ_Cnt !=
2692 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002694 if (!
2695 (currTar_Info->
2696 TarLUN_CA)) {
2697 ACCEPT_MSG(port); /*Release the ACK for ID msg. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002699 message =
2700 FPT_sfm
2701 (port,
2702 pCurrCard->
2703 currentSCCB);
2704 if (message) {
2705 ACCEPT_MSG
2706 (port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707 }
2708
2709 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002710 message
2711 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002712
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002713 if (message !=
2714 0) {
2715 tag =
2716 FPT_sfm
2717 (port,
2718 pCurrCard->
2719 currentSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002721 if (!
2722 (tag))
2723 message
2724 =
2725 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726 }
2727
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002728 }
2729 /*C.A. exists! */
2730 }
2731 /*End Q cnt != 0 */
2732 }
2733 /*End Tag cmds supported! */
2734 }
2735 /*End valid ID message. */
2736 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737
2738 ACCEPT_MSG_ATN(port);
2739 }
2740
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002741 }
2742 /* End good id message. */
2743 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002744
James Bottomley 47b5d692005-04-24 02:38:05 -05002745 message = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002747 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748 ACCEPT_MSG_ATN(port);
2749
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002750 while (!
2751 (RDW_HARPOON((port + hp_intstat)) &
2752 (PHASE | RESET))
2753 && !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
2754 && (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755
2756 return;
2757 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002759 if (message == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002760 msgRetryCount++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002761 if (msgRetryCount == 1) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002762 FPT_SendMsg(port, SMPARITY);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002763 } else {
James Bottomley 47b5d692005-04-24 02:38:05 -05002764 FPT_SendMsg(port, SMDEV_RESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002766 FPT_sssyncv(port, our_target, NARROW_SCSI,
2767 currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002769 if (FPT_sccbMgrTbl[p_card][our_target].
2770 TarEEValue & EE_SYNC_MASK) {
2771
2772 FPT_sccbMgrTbl[p_card][our_target].
2773 TarStatus &= ~TAR_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002774
2775 }
2776
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002777 if (FPT_sccbMgrTbl[p_card][our_target].
2778 TarEEValue & EE_WIDE_SCSI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002779
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002780 FPT_sccbMgrTbl[p_card][our_target].
2781 TarStatus &= ~TAR_WIDE_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002782 }
2783
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002784 FPT_queueFlushTargSccb(p_card, our_target,
2785 SCCB_COMPLETE);
2786 FPT_SccbMgrTableInitTarget(p_card, our_target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002787 return;
2788 }
2789 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002790 } while (message == 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002792 if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
2793 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002794 currTar_Info->TarLUNBusy[lun] = 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002795 pCurrCard->currentSCCB =
2796 pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[lun]];
2797 if (pCurrCard->currentSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002799 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800 ACCEPT_MSG_ATN(port);
2801 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002802 } else {
James Bottomley 47b5d692005-04-24 02:38:05 -05002803 currTar_Info->TarLUNBusy[0] = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002805 if (tag) {
2806 if (pCurrCard->discQ_Tbl[tag] != NULL) {
2807 pCurrCard->currentSCCB =
2808 pCurrCard->discQ_Tbl[tag];
2809 currTar_Info->TarTagQ_Cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002810 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002811 } else {
2812 ACCEPT_MSG_ATN(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002814 } else {
2815 pCurrCard->currentSCCB =
2816 pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]];
2817 if (pCurrCard->currentSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002819 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820 ACCEPT_MSG_ATN(port);
2821 }
2822 }
2823 }
2824
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002825 if (pCurrCard->currentSCCB != NULL) {
2826 if (pCurrCard->currentSCCB->Sccb_scsistat == ABORT_ST) {
2827 /* During Abort Tag command, the target could have got re-selected
2828 and completed the command. Check the select Q and remove the CCB
2829 if it is in the Select Q */
James Bottomley 47b5d692005-04-24 02:38:05 -05002830 FPT_queueFindSccb(pCurrCard->currentSCCB, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831 }
2832 }
2833
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002834 while (!(RDW_HARPOON((port + hp_intstat)) & (PHASE | RESET)) &&
2835 !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ) &&
2836 (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837}
2838
Khalid Aziz391e2f22013-05-16 19:44:14 -06002839static void FPT_SendMsg(u32 port, unsigned char message)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002841 while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
2842 if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002844 WRW_HARPOON((port + hp_intstat), PHASE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002845 return;
2846 }
2847 }
2848
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002849 WRW_HARPOON((port + hp_intstat), PHASE);
2850 if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGO_PH) {
2851 WRW_HARPOON((port + hp_intstat),
2852 (BUS_FREE | PHASE | XFER_CNT_0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002853
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002854 WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002856 WR_HARPOON(port + hp_scsidata_0, message);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002857
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002858 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002859
2860 ACCEPT_MSG(port);
2861
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002862 WR_HARPOON(port + hp_portctrl_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002863
2864 if ((message == SMABORT) || (message == SMDEV_RESET) ||
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002865 (message == SMABORT_TAG)) {
2866 while (!
2867 (RDW_HARPOON((port + hp_intstat)) &
2868 (BUS_FREE | PHASE))) {
2869 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002871 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
2872 WRW_HARPOON((port + hp_intstat), BUS_FREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002873 }
2874 }
2875 }
2876}
2877
2878/*---------------------------------------------------------------------
2879 *
James Bottomley 47b5d692005-04-24 02:38:05 -05002880 * Function: FPT_sdecm
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881 *
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002882 * Description: Determine the proper response to the message from the
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883 * target device.
2884 *
2885 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06002886static void FPT_sdecm(unsigned char message, u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002888 struct sccb *currSCCB;
2889 struct sccb_card *CurrCard;
2890 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002891
James Bottomley 47b5d692005-04-24 02:38:05 -05002892 CurrCard = &FPT_BL_Card[p_card];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002893 currSCCB = CurrCard->currentSCCB;
2894
James Bottomley 47b5d692005-04-24 02:38:05 -05002895 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002896
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002897 if (message == SMREST_DATA_PTR) {
2898 if (!(currSCCB->Sccb_XferState & F_NO_DATA_YET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002899 currSCCB->Sccb_ATC = currSCCB->Sccb_savedATC;
2900
James Bottomley 47b5d692005-04-24 02:38:05 -05002901 FPT_hostDataXferRestart(currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902 }
2903
2904 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002905 WR_HARPOON(port + hp_autostart_1,
2906 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002907 }
2908
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002909 else if (message == SMCMD_COMP) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002911 if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
2912 currTar_Info->TarStatus &=
2913 ~(unsigned char)TAR_TAG_Q_MASK;
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08002914 currTar_Info->TarStatus |= (unsigned char)TAG_Q_REJECT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915 }
2916
2917 ACCEPT_MSG(port);
2918
2919 }
2920
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002921 else if ((message == SMNO_OP) || (message >= SMIDENT)
2922 || (message == SMINIT_RECOVERY) || (message == SMREL_RECOVERY)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002923
2924 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002925 WR_HARPOON(port + hp_autostart_1,
2926 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002927 }
2928
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002929 else if (message == SMREJECT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930
2931 if ((currSCCB->Sccb_scsistat == SELECT_SN_ST) ||
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002932 (currSCCB->Sccb_scsistat == SELECT_WN_ST) ||
2933 ((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)
2934 || ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) ==
2935 TAG_Q_TRYING))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002936 {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002937 WRW_HARPOON((port + hp_intstat), BUS_FREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002938
2939 ACCEPT_MSG(port);
2940
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002941 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2942 (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002943 {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002944 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002945
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002946 if (currSCCB->Lun == 0x00) {
2947 if ((currSCCB->Sccb_scsistat == SELECT_SN_ST)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002948
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002949 currTar_Info->TarStatus |=
2950 (unsigned char)SYNC_SUPPORTED;
2951
2952 currTar_Info->TarEEValue &=
2953 ~EE_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002954 }
2955
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002956 else if ((currSCCB->Sccb_scsistat ==
2957 SELECT_WN_ST)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002958
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002959 currTar_Info->TarStatus =
2960 (currTar_Info->
2961 TarStatus & ~WIDE_ENABLED) |
2962 WIDE_NEGOCIATED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002963
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002964 currTar_Info->TarEEValue &=
2965 ~EE_WIDE_SCSI;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002966
2967 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002968
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002969 else if ((currTar_Info->
2970 TarStatus & TAR_TAG_Q_MASK) ==
2971 TAG_Q_TRYING) {
2972 currTar_Info->TarStatus =
2973 (currTar_Info->
2974 TarStatus & ~(unsigned char)
2975 TAR_TAG_Q_MASK) | TAG_Q_REJECT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976
2977 currSCCB->ControlByte &= ~F_USE_CMD_Q;
2978 CurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002979 CurrCard->discQ_Tbl[currSCCB->
2980 Sccb_tag] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981 currSCCB->Sccb_tag = 0x00;
2982
2983 }
2984 }
2985
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002986 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002988 if (currSCCB->Lun == 0x00) {
2989 WRW_HARPOON((port + hp_intstat),
2990 BUS_FREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991 CurrCard->globalFlags |= F_NEW_SCCB_CMD;
2992 }
2993 }
2994
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002995 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002996
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002997 if ((CurrCard->globalFlags & F_CONLUN_IO) &&
2998 ((currTar_Info->
2999 TarStatus & TAR_TAG_Q_MASK) !=
3000 TAG_Q_TRYING))
3001 currTar_Info->TarLUNBusy[currSCCB->
3002 Lun] = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003 else
James Bottomley 47b5d692005-04-24 02:38:05 -05003004 currTar_Info->TarLUNBusy[0] = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003006 currSCCB->ControlByte &=
3007 ~(unsigned char)F_USE_CMD_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003009 WR_HARPOON(port + hp_autostart_1,
3010 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003011
3012 }
3013 }
3014
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003015 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003016 ACCEPT_MSG(port);
3017
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003018 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
3019 (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020 {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003021 }
3022
3023 if (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)) {
3024 WR_HARPOON(port + hp_autostart_1,
3025 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003026 }
3027 }
3028 }
3029
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003030 else if (message == SMEXT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031
3032 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003033 FPT_shandem(port, p_card, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034 }
3035
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003036 else if (message == SMIGNORWR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003038 ACCEPT_MSG(port); /* ACK the RESIDUE MSG */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003040 message = FPT_sfm(port, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003042 if (currSCCB->Sccb_scsimsg != SMPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003043 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003044 WR_HARPOON(port + hp_autostart_1,
3045 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003046 }
3047
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003048 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003049
3050 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
3051 currSCCB->Sccb_scsimsg = SMREJECT;
3052
3053 ACCEPT_MSG_ATN(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003054 WR_HARPOON(port + hp_autostart_1,
3055 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003056 }
3057}
3058
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059/*---------------------------------------------------------------------
3060 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003061 * Function: FPT_shandem
Linus Torvalds1da177e2005-04-16 15:20:36 -07003062 *
3063 * Description: Decide what to do with the extended message.
3064 *
3065 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06003066static void FPT_shandem(u32 port, unsigned char p_card, struct sccb *pCurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003067{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003068 unsigned char length, message;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003070 length = FPT_sfm(port, pCurrSCCB);
3071 if (length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072
3073 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003074 message = FPT_sfm(port, pCurrSCCB);
3075 if (message) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003076
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003077 if (message == SMSYNC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003079 if (length == 0x03) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003080
3081 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003082 FPT_stsyncn(port, p_card);
3083 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003084
3085 pCurrSCCB->Sccb_scsimsg = SMREJECT;
3086 ACCEPT_MSG_ATN(port);
3087 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003088 } else if (message == SMWDTR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003089
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003090 if (length == 0x02) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091
3092 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003093 FPT_stwidn(port, p_card);
3094 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095
3096 pCurrSCCB->Sccb_scsimsg = SMREJECT;
3097 ACCEPT_MSG_ATN(port);
3098
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003099 WR_HARPOON(port + hp_autostart_1,
3100 (AUTO_IMMED +
3101 DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003103 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104
3105 pCurrSCCB->Sccb_scsimsg = SMREJECT;
3106 ACCEPT_MSG_ATN(port);
3107
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003108 WR_HARPOON(port + hp_autostart_1,
3109 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003111 } else {
3112 if (pCurrSCCB->Sccb_scsimsg != SMPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003113 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003114 WR_HARPOON(port + hp_autostart_1,
3115 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003116 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003117 } else {
3118 if (pCurrSCCB->Sccb_scsimsg == SMPARITY)
3119 WR_HARPOON(port + hp_autostart_1,
3120 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003121 }
3122}
3123
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124/*---------------------------------------------------------------------
3125 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003126 * Function: FPT_sisyncn
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127 *
3128 * Description: Read in a message byte from the SCSI bus, and check
3129 * for a parity error.
3130 *
3131 *---------------------------------------------------------------------*/
3132
Khalid Aziz391e2f22013-05-16 19:44:14 -06003133static unsigned char FPT_sisyncn(u32 port, unsigned char p_card,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003134 unsigned char syncFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003135{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003136 struct sccb *currSCCB;
3137 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003139 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3140 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003141
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003142 if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003143
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003144 WRW_HARPOON((port + ID_MSG_STRT),
3145 (MPM_OP + AMSG_OUT +
3146 (currSCCB->
3147 Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003148
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003149 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003151 WRW_HARPOON((port + SYNC_MSGS + 0),
3152 (MPM_OP + AMSG_OUT + SMEXT));
3153 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
3154 WRW_HARPOON((port + SYNC_MSGS + 4),
3155 (MPM_OP + AMSG_OUT + SMSYNC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003156
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003157 if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003158
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003159 WRW_HARPOON((port + SYNC_MSGS + 6),
3160 (MPM_OP + AMSG_OUT + 12));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003161
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003162 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
3163 EE_SYNC_10MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003165 WRW_HARPOON((port + SYNC_MSGS + 6),
3166 (MPM_OP + AMSG_OUT + 25));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003168 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
3169 EE_SYNC_5MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003171 WRW_HARPOON((port + SYNC_MSGS + 6),
3172 (MPM_OP + AMSG_OUT + 50));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003173
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003175 WRW_HARPOON((port + SYNC_MSGS + 6),
3176 (MPM_OP + AMSG_OUT + 00));
3177
3178 WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
3179 WRW_HARPOON((port + SYNC_MSGS + 10),
3180 (MPM_OP + AMSG_OUT + DEFAULT_OFFSET));
3181 WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
3182
3183 if (syncFlag == 0) {
3184 WR_HARPOON(port + hp_autostart_3,
3185 (SELECT + SELCHK_STRT));
3186 currTar_Info->TarStatus =
3187 ((currTar_Info->
3188 TarStatus & ~(unsigned char)TAR_SYNC_MASK) |
3189 (unsigned char)SYNC_TRYING);
3190 } else {
3191 WR_HARPOON(port + hp_autostart_3,
3192 (AUTO_IMMED + CMD_ONLY_STRT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003193 }
3194
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08003195 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003196 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003198 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003199
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003200 currTar_Info->TarStatus |= (unsigned char)SYNC_SUPPORTED;
3201 currTar_Info->TarEEValue &= ~EE_SYNC_MASK;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08003202 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003203 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003204}
3205
Linus Torvalds1da177e2005-04-16 15:20:36 -07003206/*---------------------------------------------------------------------
3207 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003208 * Function: FPT_stsyncn
Linus Torvalds1da177e2005-04-16 15:20:36 -07003209 *
3210 * Description: The has sent us a Sync Nego message so handle it as
3211 * necessary.
3212 *
3213 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06003214static void FPT_stsyncn(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003215{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003216 unsigned char sync_msg, offset, sync_reg, our_sync_msg;
3217 struct sccb *currSCCB;
3218 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003219
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003220 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3221 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003222
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003223 sync_msg = FPT_sfm(port, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003224
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003225 if ((sync_msg == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3226 WR_HARPOON(port + hp_autostart_1,
3227 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003228 return;
3229 }
3230
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003231 ACCEPT_MSG(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003233 offset = FPT_sfm(port, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003234
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003235 if ((offset == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3236 WR_HARPOON(port + hp_autostart_1,
3237 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003238 return;
3239 }
3240
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003241 if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003242
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003243 our_sync_msg = 12; /* Setup our Message to 20mb/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003244
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003245 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_10MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003246
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003247 our_sync_msg = 25; /* Setup our Message to 10mb/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003248
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003249 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_5MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003250
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003251 our_sync_msg = 50; /* Setup our Message to 5mb/s */
3252 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003253
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003254 our_sync_msg = 0; /* Message = Async */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003255
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003256 if (sync_msg < our_sync_msg) {
3257 sync_msg = our_sync_msg; /*if faster, then set to max. */
3258 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003260 if (offset == ASYNC)
3261 sync_msg = ASYNC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003262
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003263 if (offset > MAX_OFFSET)
3264 offset = MAX_OFFSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003265
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003266 sync_reg = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003267
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003268 if (sync_msg > 12)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003270 sync_reg = 0x20; /* Use 10MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003271
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003272 if (sync_msg > 25)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003274 sync_reg = 0x40; /* Use 6.6MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003275
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003276 if (sync_msg > 38)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003277
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003278 sync_reg = 0x60; /* Use 5MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003279
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003280 if (sync_msg > 50)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003281
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003282 sync_reg = 0x80; /* Use 4MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003283
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003284 if (sync_msg > 62)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003285
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003286 sync_reg = 0xA0; /* Use 3.33MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003287
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003288 if (sync_msg > 75)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003289
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003290 sync_reg = 0xC0; /* Use 2.85MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003291
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003292 if (sync_msg > 87)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003293
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003294 sync_reg = 0xE0; /* Use 2.5MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003295
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003296 if (sync_msg > 100) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003297
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003298 sync_reg = 0x00; /* Use ASYNC */
3299 offset = 0x00;
3300 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003301
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003302 if (currTar_Info->TarStatus & WIDE_ENABLED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003303
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003304 sync_reg |= offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003305
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003306 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003307
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003308 sync_reg |= (offset | NARROW_SCSI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003309
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003310 FPT_sssyncv(port, currSCCB->TargID, sync_reg, currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003311
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003312 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003313
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003314 ACCEPT_MSG(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003315
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003316 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3317 ~(unsigned char)TAR_SYNC_MASK) |
3318 (unsigned char)SYNC_SUPPORTED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003319
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003320 WR_HARPOON(port + hp_autostart_1,
3321 (AUTO_IMMED + DISCONNECT_START));
3322 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003323
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003324 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003325
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003326 ACCEPT_MSG_ATN(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003327
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003328 FPT_sisyncr(port, sync_msg, offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003329
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003330 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3331 ~(unsigned char)TAR_SYNC_MASK) |
3332 (unsigned char)SYNC_SUPPORTED);
3333 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003334}
3335
Linus Torvalds1da177e2005-04-16 15:20:36 -07003336/*---------------------------------------------------------------------
3337 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003338 * Function: FPT_sisyncr
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339 *
3340 * Description: Answer the targets sync message.
3341 *
3342 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06003343static void FPT_sisyncr(u32 port, unsigned char sync_pulse,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003344 unsigned char offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003345{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003346 ARAM_ACCESS(port);
3347 WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT));
3348 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
3349 WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMSYNC));
3350 WRW_HARPOON((port + SYNC_MSGS + 6), (MPM_OP + AMSG_OUT + sync_pulse));
3351 WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
3352 WRW_HARPOON((port + SYNC_MSGS + 10), (MPM_OP + AMSG_OUT + offset));
3353 WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
3354 SGRAM_ACCESS(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003355
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003356 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3357 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003358
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003359 WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003360
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003361 while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
3362 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003363}
3364
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365/*---------------------------------------------------------------------
3366 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003367 * Function: FPT_siwidn
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368 *
3369 * Description: Read in a message byte from the SCSI bus, and check
3370 * for a parity error.
3371 *
3372 *---------------------------------------------------------------------*/
3373
Khalid Aziz391e2f22013-05-16 19:44:14 -06003374static unsigned char FPT_siwidn(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003375{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003376 struct sccb *currSCCB;
3377 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003378
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003379 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3380 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003382 if (!((currTar_Info->TarStatus & TAR_WIDE_MASK) == WIDE_NEGOCIATED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003383
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003384 WRW_HARPOON((port + ID_MSG_STRT),
3385 (MPM_OP + AMSG_OUT +
3386 (currSCCB->
3387 Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003388
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003389 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003391 WRW_HARPOON((port + SYNC_MSGS + 0),
3392 (MPM_OP + AMSG_OUT + SMEXT));
3393 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
3394 WRW_HARPOON((port + SYNC_MSGS + 4),
3395 (MPM_OP + AMSG_OUT + SMWDTR));
3396 WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
3397 WRW_HARPOON((port + SYNC_MSGS + 8),
3398 (MPM_OP + AMSG_OUT + SM16BIT));
3399 WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003400
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003401 WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003402
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003403 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3404 ~(unsigned char)TAR_WIDE_MASK) |
3405 (unsigned char)WIDE_ENABLED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003406
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08003407 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003408 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003410 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003411
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003412 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3413 ~(unsigned char)TAR_WIDE_MASK) |
3414 WIDE_NEGOCIATED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003416 currTar_Info->TarEEValue &= ~EE_WIDE_SCSI;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08003417 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003418 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003419}
3420
Linus Torvalds1da177e2005-04-16 15:20:36 -07003421/*---------------------------------------------------------------------
3422 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003423 * Function: FPT_stwidn
Linus Torvalds1da177e2005-04-16 15:20:36 -07003424 *
3425 * Description: The has sent us a Wide Nego message so handle it as
3426 * necessary.
3427 *
3428 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06003429static void FPT_stwidn(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003430{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003431 unsigned char width;
3432 struct sccb *currSCCB;
3433 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003434
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003435 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3436 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003437
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003438 width = FPT_sfm(port, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003439
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003440 if ((width == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3441 WR_HARPOON(port + hp_autostart_1,
3442 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003443 return;
3444 }
3445
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003446 if (!(currTar_Info->TarEEValue & EE_WIDE_SCSI))
3447 width = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003448
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003449 if (width) {
3450 currTar_Info->TarStatus |= WIDE_ENABLED;
3451 width = 0;
3452 } else {
3453 width = NARROW_SCSI;
3454 currTar_Info->TarStatus &= ~WIDE_ENABLED;
3455 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003456
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003457 FPT_sssyncv(port, currSCCB->TargID, width, currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003458
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003459 if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003461 currTar_Info->TarStatus |= WIDE_NEGOCIATED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003462
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003463 if (!
3464 ((currTar_Info->TarStatus & TAR_SYNC_MASK) ==
3465 SYNC_SUPPORTED)) {
3466 ACCEPT_MSG_ATN(port);
3467 ARAM_ACCESS(port);
3468 FPT_sisyncn(port, p_card, 1);
3469 currSCCB->Sccb_scsistat = SELECT_SN_ST;
3470 SGRAM_ACCESS(port);
3471 } else {
3472 ACCEPT_MSG(port);
3473 WR_HARPOON(port + hp_autostart_1,
3474 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003475 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003476 }
3477
3478 else {
3479
3480 ACCEPT_MSG_ATN(port);
3481
3482 if (currTar_Info->TarEEValue & EE_WIDE_SCSI)
3483 width = SM16BIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003484 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003485 width = SM8BIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003486
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003487 FPT_siwidr(port, width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003488
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003489 currTar_Info->TarStatus |= (WIDE_NEGOCIATED | WIDE_ENABLED);
3490 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003491}
3492
Linus Torvalds1da177e2005-04-16 15:20:36 -07003493/*---------------------------------------------------------------------
3494 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003495 * Function: FPT_siwidr
Linus Torvalds1da177e2005-04-16 15:20:36 -07003496 *
3497 * Description: Answer the targets Wide nego message.
3498 *
3499 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06003500static void FPT_siwidr(u32 port, unsigned char width)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003501{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003502 ARAM_ACCESS(port);
3503 WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT));
3504 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
3505 WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMWDTR));
3506 WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
3507 WRW_HARPOON((port + SYNC_MSGS + 8), (MPM_OP + AMSG_OUT + width));
3508 WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
3509 SGRAM_ACCESS(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003510
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003511 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3512 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003513
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003514 WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003515
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003516 while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
3517 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003518}
3519
Linus Torvalds1da177e2005-04-16 15:20:36 -07003520/*---------------------------------------------------------------------
3521 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003522 * Function: FPT_sssyncv
Linus Torvalds1da177e2005-04-16 15:20:36 -07003523 *
3524 * Description: Write the desired value to the Sync Register for the
3525 * ID specified.
3526 *
3527 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06003528static void FPT_sssyncv(u32 p_port, unsigned char p_id,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003529 unsigned char p_sync_value,
3530 struct sccb_mgr_tar_info *currTar_Info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003531{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003532 unsigned char index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003533
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003534 index = p_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003535
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003536 switch (index) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003537
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003538 case 0:
3539 index = 12; /* hp_synctarg_0 */
3540 break;
3541 case 1:
3542 index = 13; /* hp_synctarg_1 */
3543 break;
3544 case 2:
3545 index = 14; /* hp_synctarg_2 */
3546 break;
3547 case 3:
3548 index = 15; /* hp_synctarg_3 */
3549 break;
3550 case 4:
3551 index = 8; /* hp_synctarg_4 */
3552 break;
3553 case 5:
3554 index = 9; /* hp_synctarg_5 */
3555 break;
3556 case 6:
3557 index = 10; /* hp_synctarg_6 */
3558 break;
3559 case 7:
3560 index = 11; /* hp_synctarg_7 */
3561 break;
3562 case 8:
3563 index = 4; /* hp_synctarg_8 */
3564 break;
3565 case 9:
3566 index = 5; /* hp_synctarg_9 */
3567 break;
3568 case 10:
3569 index = 6; /* hp_synctarg_10 */
3570 break;
3571 case 11:
3572 index = 7; /* hp_synctarg_11 */
3573 break;
3574 case 12:
3575 index = 0; /* hp_synctarg_12 */
3576 break;
3577 case 13:
3578 index = 1; /* hp_synctarg_13 */
3579 break;
3580 case 14:
3581 index = 2; /* hp_synctarg_14 */
3582 break;
3583 case 15:
3584 index = 3; /* hp_synctarg_15 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003585
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003586 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003587
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003588 WR_HARPOON(p_port + hp_synctarg_base + index, p_sync_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003589
3590 currTar_Info->TarSyncCtrl = p_sync_value;
3591}
3592
Linus Torvalds1da177e2005-04-16 15:20:36 -07003593/*---------------------------------------------------------------------
3594 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003595 * Function: FPT_sresb
Linus Torvalds1da177e2005-04-16 15:20:36 -07003596 *
3597 * Description: Reset the desired card's SCSI bus.
3598 *
3599 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06003600static void FPT_sresb(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003602 unsigned char scsiID, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003603
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003604 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003605
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003606 WR_HARPOON(port + hp_page_ctrl,
3607 (RD_HARPOON(port + hp_page_ctrl) | G_INT_DISABLE));
3608 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003610 WR_HARPOON(port + hp_scsictrl_0, SCSI_RST);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003611
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003612 scsiID = RD_HARPOON(port + hp_seltimeout);
3613 WR_HARPOON(port + hp_seltimeout, TO_5ms);
3614 WRW_HARPOON((port + hp_intstat), TIMEOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003615
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003616 WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT | START_TO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003618 while (!(RDW_HARPOON((port + hp_intstat)) & TIMEOUT)) {
3619 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003620
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003621 WR_HARPOON(port + hp_seltimeout, scsiID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003623 WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003625 FPT_Wait(port, TO_5ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003627 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003628
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003629 WR_HARPOON(port + hp_int_mask, (RD_HARPOON(port + hp_int_mask) | 0x00));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003630
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003631 for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
3632 currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003634 if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
3635 currTar_Info->TarSyncCtrl = 0;
3636 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
3637 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003638
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003639 if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
3640 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
3641 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003642
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003643 FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003644
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003645 FPT_SccbMgrTableInitTarget(p_card, scsiID);
3646 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003648 FPT_BL_Card[p_card].scanIndex = 0x00;
3649 FPT_BL_Card[p_card].currentSCCB = NULL;
3650 FPT_BL_Card[p_card].globalFlags &= ~(F_TAG_STARTED | F_HOST_XFER_ACT
3651 | F_NEW_SCCB_CMD);
3652 FPT_BL_Card[p_card].cmdCounter = 0x00;
James Bottomley 47b5d692005-04-24 02:38:05 -05003653 FPT_BL_Card[p_card].discQCount = 0x00;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003654 FPT_BL_Card[p_card].tagQ_Lst = 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003655
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003656 for (i = 0; i < QUEUE_DEPTH; i++)
James Bottomley 47b5d692005-04-24 02:38:05 -05003657 FPT_BL_Card[p_card].discQ_Tbl[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003658
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003659 WR_HARPOON(port + hp_page_ctrl,
3660 (RD_HARPOON(port + hp_page_ctrl) & ~G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003661
3662}
3663
3664/*---------------------------------------------------------------------
3665 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003666 * Function: FPT_ssenss
Linus Torvalds1da177e2005-04-16 15:20:36 -07003667 *
3668 * Description: Setup for the Auto Sense command.
3669 *
3670 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003671static void FPT_ssenss(struct sccb_card *pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003672{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003673 unsigned char i;
3674 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003675
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003676 currSCCB = pCurrCard->currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003677
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003678 currSCCB->Save_CdbLen = currSCCB->CdbLength;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003679
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003680 for (i = 0; i < 6; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003681
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003682 currSCCB->Save_Cdb[i] = currSCCB->Cdb[i];
3683 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003684
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003685 currSCCB->CdbLength = SIX_BYTE_CMD;
3686 currSCCB->Cdb[0] = SCSI_REQUEST_SENSE;
3687 currSCCB->Cdb[1] = currSCCB->Cdb[1] & (unsigned char)0xE0; /*Keep LUN. */
3688 currSCCB->Cdb[2] = 0x00;
3689 currSCCB->Cdb[3] = 0x00;
3690 currSCCB->Cdb[4] = currSCCB->RequestSenseLength;
3691 currSCCB->Cdb[5] = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692
Khalid Aziz391e2f22013-05-16 19:44:14 -06003693 currSCCB->Sccb_XferCnt = (u32)currSCCB->RequestSenseLength;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003695 currSCCB->Sccb_ATC = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003697 currSCCB->Sccb_XferState |= F_AUTO_SENSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003698
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003699 currSCCB->Sccb_XferState &= ~F_SG_XFER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003700
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003701 currSCCB->Sccb_idmsg = currSCCB->Sccb_idmsg & ~(unsigned char)DISC_PRIV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003703 currSCCB->ControlByte = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003704
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003705 currSCCB->Sccb_MGRFlags &= F_STATUSLOADED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706}
3707
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708/*---------------------------------------------------------------------
3709 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003710 * Function: FPT_sxfrp
Linus Torvalds1da177e2005-04-16 15:20:36 -07003711 *
3712 * Description: Transfer data into the bit bucket until the device
3713 * decides to switch phase.
3714 *
3715 *---------------------------------------------------------------------*/
3716
Khalid Aziz391e2f22013-05-16 19:44:14 -06003717static void FPT_sxfrp(u32 p_port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003718{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003719 unsigned char curr_phz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003721 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003722
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003723 if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003724
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003725 FPT_hostDataXferAbort(p_port, p_card,
3726 FPT_BL_Card[p_card].currentSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003727
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003728 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003729
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003730 /* If the Automation handled the end of the transfer then do not
3731 match the phase or we will get out of sync with the ISR. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003732
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003733 if (RDW_HARPOON((p_port + hp_intstat)) &
3734 (BUS_FREE | XFER_CNT_0 | AUTO_INT))
3735 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003736
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003737 WR_HARPOON(p_port + hp_xfercnt_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003738
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003739 curr_phz = RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003740
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003741 WRW_HARPOON((p_port + hp_intstat), XFER_CNT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003742
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003743 WR_HARPOON(p_port + hp_scsisig, curr_phz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003744
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003745 while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET)) &&
3746 (curr_phz ==
3747 (RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ)))
3748 {
3749 if (curr_phz & (unsigned char)SCSI_IOBIT) {
3750 WR_HARPOON(p_port + hp_portctrl_0,
3751 (SCSI_PORT | HOST_PORT | SCSI_INBIT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003752
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003753 if (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
3754 RD_HARPOON(p_port + hp_fifodata_0);
3755 }
3756 } else {
3757 WR_HARPOON(p_port + hp_portctrl_0,
3758 (SCSI_PORT | HOST_PORT | HOST_WRT));
3759 if (RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY) {
3760 WR_HARPOON(p_port + hp_fifodata_0, 0xFA);
3761 }
3762 }
3763 } /* End of While loop for padding data I/O phase */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003764
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003765 while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
3766 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ)
3767 break;
3768 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003770 WR_HARPOON(p_port + hp_portctrl_0,
3771 (SCSI_PORT | HOST_PORT | SCSI_INBIT));
3772 while (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
3773 RD_HARPOON(p_port + hp_fifodata_0);
3774 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003776 if (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
3777 WR_HARPOON(p_port + hp_autostart_0,
3778 (AUTO_IMMED + DISCONNECT_START));
3779 while (!(RDW_HARPOON((p_port + hp_intstat)) & AUTO_INT)) {
3780 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003782 if (RDW_HARPOON((p_port + hp_intstat)) &
3783 (ICMD_COMP | ITAR_DISC))
3784 while (!
3785 (RDW_HARPOON((p_port + hp_intstat)) &
3786 (BUS_FREE | RSEL))) ;
3787 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003788}
3789
Linus Torvalds1da177e2005-04-16 15:20:36 -07003790/*---------------------------------------------------------------------
3791 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003792 * Function: FPT_schkdd
Linus Torvalds1da177e2005-04-16 15:20:36 -07003793 *
3794 * Description: Make sure data has been flushed from both FIFOs and abort
3795 * the operations if necessary.
3796 *
3797 *---------------------------------------------------------------------*/
3798
Khalid Aziz391e2f22013-05-16 19:44:14 -06003799static void FPT_schkdd(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003800{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003801 unsigned short TimeOutLoop;
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08003802 unsigned char sPhase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003803
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003804 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003805
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003806 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003807
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003808 if ((currSCCB->Sccb_scsistat != DATA_OUT_ST) &&
3809 (currSCCB->Sccb_scsistat != DATA_IN_ST)) {
3810 return;
3811 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003812
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003813 if (currSCCB->Sccb_XferState & F_ODD_BALL_CNT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003815 currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003816
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003817 currSCCB->Sccb_XferCnt = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003818
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003819 currSCCB->Sccb_XferState &= ~F_ODD_BALL_CNT;
3820 WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
3821 WR_HARPOON(port + hp_xferstat, 0x00);
3822 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003823
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003824 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003825
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003826 currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003827
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003828 currSCCB->Sccb_XferCnt = 0;
3829 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003831 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
3832 (currSCCB->HostStatus == SCCB_COMPLETE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003833
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003834 currSCCB->HostStatus = SCCB_PARITY_ERR;
3835 WRW_HARPOON((port + hp_intstat), PARITY);
3836 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003838 FPT_hostDataXferAbort(port, p_card, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003840 while (RD_HARPOON(port + hp_scsisig) & SCSI_ACK) {
3841 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003842
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003843 TimeOutLoop = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003844
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003845 while (RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY) {
3846 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
3847 return;
3848 }
3849 if (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) {
3850 break;
3851 }
3852 if (RDW_HARPOON((port + hp_intstat)) & RESET) {
3853 return;
3854 }
3855 if ((RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
3856 || (TimeOutLoop++ > 0x3000))
3857 break;
3858 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003859
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003860 sPhase = RD_HARPOON(port + hp_scsisig) & (SCSI_BSY | S_SCSI_PHZ);
3861 if ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) ||
3862 (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) ||
3863 (sPhase == (SCSI_BSY | S_DATAO_PH)) ||
3864 (sPhase == (SCSI_BSY | S_DATAI_PH))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003866 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003867
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003868 if (!(currSCCB->Sccb_XferState & F_ALL_XFERRED)) {
3869 if (currSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
3870 FPT_phaseDataIn(port, p_card);
3871 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003872
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003873 else {
3874 FPT_phaseDataOut(port, p_card);
3875 }
3876 } else {
3877 FPT_sxfrp(port, p_card);
3878 if (!(RDW_HARPOON((port + hp_intstat)) &
3879 (BUS_FREE | ICMD_COMP | ITAR_DISC | RESET))) {
3880 WRW_HARPOON((port + hp_intstat), AUTO_INT);
3881 FPT_phaseDecode(port, p_card);
3882 }
3883 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003884
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003885 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003886
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003887 else {
3888 WR_HARPOON(port + hp_portctrl_0, 0x00);
3889 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003890}
3891
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892/*---------------------------------------------------------------------
3893 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003894 * Function: FPT_sinits
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895 *
3896 * Description: Setup SCCB manager fields in this SCCB.
3897 *
3898 *---------------------------------------------------------------------*/
3899
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003900static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003902 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003903
Dan Carpenter5d7ebb92009-12-28 20:08:39 +02003904 if ((p_sccb->TargID >= MAX_SCSI_TAR) || (p_sccb->Lun >= MAX_LUN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905 return;
3906 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003907 currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003908
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003909 p_sccb->Sccb_XferState = 0x00;
3910 p_sccb->Sccb_XferCnt = p_sccb->DataLength;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003912 if ((p_sccb->OperationCode == SCATTER_GATHER_COMMAND) ||
3913 (p_sccb->OperationCode == RESIDUAL_SG_COMMAND)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003914
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003915 p_sccb->Sccb_SGoffset = 0;
3916 p_sccb->Sccb_XferState = F_SG_XFER;
3917 p_sccb->Sccb_XferCnt = 0x00;
3918 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003919
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003920 if (p_sccb->DataLength == 0x00)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003921
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003922 p_sccb->Sccb_XferState |= F_ALL_XFERRED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003923
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003924 if (p_sccb->ControlByte & F_USE_CMD_Q) {
3925 if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
3926 p_sccb->ControlByte &= ~F_USE_CMD_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003928 else
3929 currTar_Info->TarStatus |= TAG_Q_TRYING;
3930 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003931
3932/* For !single SCSI device in system & device allow Disconnect
3933 or command is tag_q type then send Cmd with Disconnect Enable
3934 else send Cmd with Disconnect Disable */
3935
3936/*
James Bottomley 47b5d692005-04-24 02:38:05 -05003937 if (((!(FPT_BL_Card[p_card].globalFlags & F_SINGLE_DEVICE)) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07003938 (currTar_Info->TarStatus & TAR_ALLOW_DISC)) ||
3939 (currTar_Info->TarStatus & TAG_Q_TRYING)) {
3940*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003941 if ((currTar_Info->TarStatus & TAR_ALLOW_DISC) ||
3942 (currTar_Info->TarStatus & TAG_Q_TRYING)) {
3943 p_sccb->Sccb_idmsg =
3944 (unsigned char)(SMIDENT | DISC_PRIV) | p_sccb->Lun;
3945 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003947 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003949 p_sccb->Sccb_idmsg = (unsigned char)SMIDENT | p_sccb->Lun;
3950 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003951
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003952 p_sccb->HostStatus = 0x00;
3953 p_sccb->TargetStatus = 0x00;
3954 p_sccb->Sccb_tag = 0x00;
3955 p_sccb->Sccb_MGRFlags = 0x00;
3956 p_sccb->Sccb_sgseg = 0x00;
3957 p_sccb->Sccb_ATC = 0x00;
3958 p_sccb->Sccb_savedATC = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003959/*
3960 p_sccb->SccbVirtDataPtr = 0x00;
3961 p_sccb->Sccb_forwardlink = NULL;
3962 p_sccb->Sccb_backlink = NULL;
3963 */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003964 p_sccb->Sccb_scsistat = BUS_FREE_ST;
3965 p_sccb->SccbStatus = SCCB_IN_PROCESS;
3966 p_sccb->Sccb_scsimsg = SMNO_OP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003967
3968}
3969
Linus Torvalds1da177e2005-04-16 15:20:36 -07003970/*---------------------------------------------------------------------
3971 *
3972 * Function: Phase Decode
3973 *
3974 * Description: Determine the phase and call the appropriate function.
3975 *
3976 *---------------------------------------------------------------------*/
3977
Khalid Aziz391e2f22013-05-16 19:44:14 -06003978static void FPT_phaseDecode(u32 p_port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003979{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003980 unsigned char phase_ref;
Khalid Aziz391e2f22013-05-16 19:44:14 -06003981 void (*phase) (u32, unsigned char);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003983 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003984
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003985 phase_ref =
3986 (unsigned char)(RD_HARPOON(p_port + hp_scsisig) & S_SCSI_PHZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003987
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003988 phase = FPT_s_PhaseTbl[phase_ref];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003989
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003990 (*phase) (p_port, p_card); /* Call the correct phase func */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991}
3992
Linus Torvalds1da177e2005-04-16 15:20:36 -07003993/*---------------------------------------------------------------------
3994 *
3995 * Function: Data Out Phase
3996 *
3997 * Description: Start up both the BusMaster and Xbow.
3998 *
3999 *---------------------------------------------------------------------*/
4000
Khalid Aziz391e2f22013-05-16 19:44:14 -06004001static void FPT_phaseDataOut(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002{
4003
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004004 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004005
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004006 currSCCB = FPT_BL_Card[p_card].currentSCCB;
4007 if (currSCCB == NULL) {
4008 return; /* Exit if No SCCB record */
4009 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004010
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004011 currSCCB->Sccb_scsistat = DATA_OUT_ST;
4012 currSCCB->Sccb_XferState &= ~(F_HOST_XFER_DIR | F_NO_DATA_YET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004014 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004015
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004016 WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004017
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004018 WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004019
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004020 FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004021
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004022 if (currSCCB->Sccb_XferCnt == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004023
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004024 if ((currSCCB->ControlByte & SCCB_DATA_XFER_OUT) &&
4025 (currSCCB->HostStatus == SCCB_COMPLETE))
4026 currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004027
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004028 FPT_sxfrp(port, p_card);
4029 if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
4030 FPT_phaseDecode(port, p_card);
4031 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032}
4033
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034/*---------------------------------------------------------------------
4035 *
4036 * Function: Data In Phase
4037 *
4038 * Description: Startup the BusMaster and the XBOW.
4039 *
4040 *---------------------------------------------------------------------*/
4041
Khalid Aziz391e2f22013-05-16 19:44:14 -06004042static void FPT_phaseDataIn(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004043{
4044
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004045 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004047 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004048
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004049 if (currSCCB == NULL) {
4050 return; /* Exit if No SCCB record */
4051 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004052
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004053 currSCCB->Sccb_scsistat = DATA_IN_ST;
4054 currSCCB->Sccb_XferState |= F_HOST_XFER_DIR;
4055 currSCCB->Sccb_XferState &= ~F_NO_DATA_YET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004056
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004057 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004058
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004059 WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004061 WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004062
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004063 FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004065 if (currSCCB->Sccb_XferCnt == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004067 if ((currSCCB->ControlByte & SCCB_DATA_XFER_IN) &&
4068 (currSCCB->HostStatus == SCCB_COMPLETE))
4069 currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004070
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004071 FPT_sxfrp(port, p_card);
4072 if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
4073 FPT_phaseDecode(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004074
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004075 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004076}
4077
4078/*---------------------------------------------------------------------
4079 *
4080 * Function: Command Phase
4081 *
4082 * Description: Load the CDB into the automation and start it up.
4083 *
4084 *---------------------------------------------------------------------*/
4085
Khalid Aziz391e2f22013-05-16 19:44:14 -06004086static void FPT_phaseCommand(u32 p_port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004088 struct sccb *currSCCB;
Khalid Aziz391e2f22013-05-16 19:44:14 -06004089 u32 cdb_reg;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004090 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004092 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004093
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004094 if (currSCCB->OperationCode == RESET_COMMAND) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004096 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4097 currSCCB->CdbLength = SIX_BYTE_CMD;
4098 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004100 WR_HARPOON(p_port + hp_scsisig, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004102 ARAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004103
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004104 cdb_reg = p_port + CMD_STRT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004106 for (i = 0; i < currSCCB->CdbLength; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004107
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004108 if (currSCCB->OperationCode == RESET_COMMAND)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004109
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004110 WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + 0x00));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004111
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004112 else
4113 WRW_HARPOON(cdb_reg,
4114 (MPM_OP + ACOMMAND + currSCCB->Cdb[i]));
4115 cdb_reg += 2;
4116 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004117
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004118 if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
4119 WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004120
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004121 WR_HARPOON(p_port + hp_portctrl_0, (SCSI_PORT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004123 currSCCB->Sccb_scsistat = COMMAND_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004124
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004125 WR_HARPOON(p_port + hp_autostart_3, (AUTO_IMMED | CMD_ONLY_STRT));
4126 SGRAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127}
4128
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129/*---------------------------------------------------------------------
4130 *
4131 * Function: Status phase
4132 *
4133 * Description: Bring in the status and command complete message bytes
4134 *
4135 *---------------------------------------------------------------------*/
4136
Khalid Aziz391e2f22013-05-16 19:44:14 -06004137static void FPT_phaseStatus(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004139 /* Start-up the automation to finish off this command and let the
4140 isr handle the interrupt for command complete when it comes in.
4141 We could wait here for the interrupt to be generated?
4142 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004144 WR_HARPOON(port + hp_scsisig, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004145
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004146 WR_HARPOON(port + hp_autostart_0, (AUTO_IMMED + END_DATA_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004147}
4148
Linus Torvalds1da177e2005-04-16 15:20:36 -07004149/*---------------------------------------------------------------------
4150 *
4151 * Function: Phase Message Out
4152 *
4153 * Description: Send out our message (if we have one) and handle whatever
4154 * else is involed.
4155 *
4156 *---------------------------------------------------------------------*/
4157
Khalid Aziz391e2f22013-05-16 19:44:14 -06004158static void FPT_phaseMsgOut(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004159{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004160 unsigned char message, scsiID;
4161 struct sccb *currSCCB;
4162 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004163
James Bottomley 47b5d692005-04-24 02:38:05 -05004164 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004165
4166 if (currSCCB != NULL) {
4167
4168 message = currSCCB->Sccb_scsimsg;
4169 scsiID = currSCCB->TargID;
4170
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004171 if (message == SMDEV_RESET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004172
James Bottomley 47b5d692005-04-24 02:38:05 -05004173 currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004174 currTar_Info->TarSyncCtrl = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004175 FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004177 if (FPT_sccbMgrTbl[p_card][scsiID].
4178 TarEEValue & EE_SYNC_MASK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004179
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004180 FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
4181 ~TAR_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182
4183 }
4184
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004185 if (FPT_sccbMgrTbl[p_card][scsiID].
4186 TarEEValue & EE_WIDE_SCSI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004187
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004188 FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
4189 ~TAR_WIDE_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004190 }
4191
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004192 FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
4193 FPT_SccbMgrTableInitTarget(p_card, scsiID);
4194 } else if (currSCCB->Sccb_scsistat == ABORT_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004195 currSCCB->HostStatus = SCCB_COMPLETE;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004196 if (FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] !=
4197 NULL) {
4198 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4199 Sccb_tag] = NULL;
James Bottomley 47b5d692005-04-24 02:38:05 -05004200 FPT_sccbMgrTbl[p_card][scsiID].TarTagQ_Cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004201 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004202
Linus Torvalds1da177e2005-04-16 15:20:36 -07004203 }
4204
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004205 else if (currSCCB->Sccb_scsistat < COMMAND_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004206
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004207 if (message == SMNO_OP) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004208 currSCCB->Sccb_MGRFlags |= F_DEV_SELECTED;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004209
4210 FPT_ssel(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004211 return;
4212 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004213 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004214
4215 if (message == SMABORT)
4216
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004217 FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004218 }
4219
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004220 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004221 message = SMABORT;
4222 }
4223
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004224 WRW_HARPOON((port + hp_intstat), (BUS_FREE | PHASE | XFER_CNT_0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004225
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004226 WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004227
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004228 WR_HARPOON(port + hp_scsidata_0, message);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004229
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004230 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004231
4232 ACCEPT_MSG(port);
4233
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004234 WR_HARPOON(port + hp_portctrl_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004235
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004236 if ((message == SMABORT) || (message == SMDEV_RESET) ||
4237 (message == SMABORT_TAG)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004238
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004239 while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | PHASE))) {
4240 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004241
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004242 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
4243 WRW_HARPOON((port + hp_intstat), BUS_FREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004244
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004245 if (currSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004246
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004247 if ((FPT_BL_Card[p_card].
4248 globalFlags & F_CONLUN_IO)
4249 &&
4250 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4251 TarStatus & TAR_TAG_Q_MASK) !=
4252 TAG_Q_TRYING))
4253 FPT_sccbMgrTbl[p_card][currSCCB->
4254 TargID].
4255 TarLUNBusy[currSCCB->Lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004256 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004257 FPT_sccbMgrTbl[p_card][currSCCB->
4258 TargID].
4259 TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004260
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004261 FPT_queueCmdComplete(&FPT_BL_Card[p_card],
4262 currSCCB, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004263 }
4264
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004265 else {
4266 FPT_BL_Card[p_card].globalFlags |=
4267 F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004268 }
4269 }
4270
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004271 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004272
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004273 FPT_sxfrp(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004274 }
4275 }
4276
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004277 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004278
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004279 if (message == SMPARITY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004280 currSCCB->Sccb_scsimsg = SMNO_OP;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004281 WR_HARPOON(port + hp_autostart_1,
4282 (AUTO_IMMED + DISCONNECT_START));
4283 } else {
4284 FPT_sxfrp(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004285 }
4286 }
4287}
4288
Linus Torvalds1da177e2005-04-16 15:20:36 -07004289/*---------------------------------------------------------------------
4290 *
4291 * Function: Message In phase
4292 *
4293 * Description: Bring in the message and determine what to do with it.
4294 *
4295 *---------------------------------------------------------------------*/
4296
Khalid Aziz391e2f22013-05-16 19:44:14 -06004297static void FPT_phaseMsgIn(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004298{
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08004299 unsigned char message;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004300 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004301
James Bottomley 47b5d692005-04-24 02:38:05 -05004302 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004303
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004304 if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305
James Bottomley 47b5d692005-04-24 02:38:05 -05004306 FPT_phaseChkFifo(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004307 }
4308
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004309 message = RD_HARPOON(port + hp_scsidata_0);
4310 if ((message == SMDISC) || (message == SMSAVE_DATA_PTR)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004312 WR_HARPOON(port + hp_autostart_1,
4313 (AUTO_IMMED + END_DATA_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004314
4315 }
4316
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004317 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004318
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004319 message = FPT_sfm(port, currSCCB);
4320 if (message) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004321
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004322 FPT_sdecm(message, port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004323
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004324 } else {
4325 if (currSCCB->Sccb_scsimsg != SMPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004326 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004327 WR_HARPOON(port + hp_autostart_1,
4328 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004329 }
4330 }
4331
4332}
4333
Linus Torvalds1da177e2005-04-16 15:20:36 -07004334/*---------------------------------------------------------------------
4335 *
4336 * Function: Illegal phase
4337 *
4338 * Description: Target switched to some illegal phase, so all we can do
4339 * is report an error back to the host (if that is possible)
4340 * and send an ABORT message to the misbehaving target.
4341 *
4342 *---------------------------------------------------------------------*/
4343
Khalid Aziz391e2f22013-05-16 19:44:14 -06004344static void FPT_phaseIllegal(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004346 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004348 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004349
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004350 WR_HARPOON(port + hp_scsisig, RD_HARPOON(port + hp_scsisig));
4351 if (currSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004352
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004353 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4354 currSCCB->Sccb_scsistat = ABORT_ST;
4355 currSCCB->Sccb_scsimsg = SMABORT;
4356 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004357
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004358 ACCEPT_MSG_ATN(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004359}
4360
Linus Torvalds1da177e2005-04-16 15:20:36 -07004361/*---------------------------------------------------------------------
4362 *
4363 * Function: Phase Check FIFO
4364 *
4365 * Description: Make sure data has been flushed from both FIFOs and abort
4366 * the operations if necessary.
4367 *
4368 *---------------------------------------------------------------------*/
4369
Khalid Aziz391e2f22013-05-16 19:44:14 -06004370static void FPT_phaseChkFifo(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004371{
Khalid Aziz391e2f22013-05-16 19:44:14 -06004372 u32 xfercnt;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004373 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004374
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004375 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004376
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004377 if (currSCCB->Sccb_scsistat == DATA_IN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004378
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004379 while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) &&
4380 (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)) {
4381 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004382
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004383 if (!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) {
4384 currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004385
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004386 currSCCB->Sccb_XferCnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004387
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004388 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
4389 (currSCCB->HostStatus == SCCB_COMPLETE)) {
4390 currSCCB->HostStatus = SCCB_PARITY_ERR;
4391 WRW_HARPOON((port + hp_intstat), PARITY);
4392 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004393
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004394 FPT_hostDataXferAbort(port, p_card, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004395
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004396 FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004397
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004398 while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY))
4399 && (RD_HARPOON(port + hp_ext_status) &
4400 BM_CMD_BUSY)) {
4401 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004402
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004403 }
4404 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004405
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004406 /*End Data In specific code. */
4407 GET_XFER_CNT(port, xfercnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004408
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004409 WR_HARPOON(port + hp_xfercnt_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004410
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004411 WR_HARPOON(port + hp_portctrl_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004413 currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - xfercnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004414
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004415 currSCCB->Sccb_XferCnt = xfercnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004416
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004417 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
4418 (currSCCB->HostStatus == SCCB_COMPLETE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004419
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004420 currSCCB->HostStatus = SCCB_PARITY_ERR;
4421 WRW_HARPOON((port + hp_intstat), PARITY);
4422 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004423
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004424 FPT_hostDataXferAbort(port, p_card, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004425
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004426 WR_HARPOON(port + hp_fifowrite, 0x00);
4427 WR_HARPOON(port + hp_fiforead, 0x00);
4428 WR_HARPOON(port + hp_xferstat, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004429
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004430 WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004431}
4432
Linus Torvalds1da177e2005-04-16 15:20:36 -07004433/*---------------------------------------------------------------------
4434 *
4435 * Function: Phase Bus Free
4436 *
4437 * Description: We just went bus free so figure out if it was
4438 * because of command complete or from a disconnect.
4439 *
4440 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06004441static void FPT_phaseBusFree(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004443 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004444
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004445 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004446
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004447 if (currSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004448
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004449 DISABLE_AUTO(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004450
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004451 if (currSCCB->OperationCode == RESET_COMMAND) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004452
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004453 if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4454 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4455 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4456 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4457 TarLUNBusy[currSCCB->Lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004458 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004459 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4460 TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004461
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004462 FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
4463 p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004464
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004465 FPT_queueSearchSelect(&FPT_BL_Card[p_card], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004466
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004467 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004468
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004469 else if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
4470 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4471 (unsigned char)SYNC_SUPPORTED;
4472 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4473 ~EE_SYNC_MASK;
4474 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004475
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004476 else if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
4477 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
4478 (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4479 TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004480
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004481 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4482 ~EE_WIDE_SCSI;
4483 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004484
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004485 else if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
4486 /* Make sure this is not a phony BUS_FREE. If we were
4487 reselected or if BUSY is NOT on then this is a
4488 valid BUS FREE. SRR Wednesday, 5/10/1995. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004489
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004490 if ((!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ||
4491 (RDW_HARPOON((port + hp_intstat)) & RSEL)) {
4492 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4493 TarStatus &= ~TAR_TAG_Q_MASK;
4494 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4495 TarStatus |= TAG_Q_REJECT;
4496 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004497
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004498 else {
4499 return;
4500 }
4501 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004502
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004503 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004504
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004505 currSCCB->Sccb_scsistat = BUS_FREE_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004506
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004507 if (!currSCCB->HostStatus) {
4508 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4509 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004510
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004511 if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4512 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4513 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4514 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4515 TarLUNBusy[currSCCB->Lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004516 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004517 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4518 TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004519
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004520 FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
4521 p_card);
4522 return;
4523 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004524
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004525 FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004526
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004527 } /*end if !=null */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004528}
4529
Linus Torvalds1da177e2005-04-16 15:20:36 -07004530/*---------------------------------------------------------------------
4531 *
4532 * Function: Auto Load Default Map
4533 *
4534 * Description: Load the Automation RAM with the defualt map values.
4535 *
4536 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06004537static void FPT_autoLoadDefaultMap(u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004538{
Khalid Aziz391e2f22013-05-16 19:44:14 -06004539 u32 map_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004540
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004541 ARAM_ACCESS(p_port);
4542 map_addr = p_port + hp_aramBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004543
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004544 WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0xC0)); /*ID MESSAGE */
4545 map_addr += 2;
4546 WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x20)); /*SIMPLE TAG QUEUEING MSG */
4547 map_addr += 2;
4548 WRW_HARPOON(map_addr, RAT_OP); /*RESET ATTENTION */
4549 map_addr += 2;
4550 WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x00)); /*TAG ID MSG */
4551 map_addr += 2;
4552 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 0 */
4553 map_addr += 2;
4554 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 1 */
4555 map_addr += 2;
4556 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 2 */
4557 map_addr += 2;
4558 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 3 */
4559 map_addr += 2;
4560 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 4 */
4561 map_addr += 2;
4562 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 5 */
4563 map_addr += 2;
4564 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 6 */
4565 map_addr += 2;
4566 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 7 */
4567 map_addr += 2;
4568 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 8 */
4569 map_addr += 2;
4570 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 9 */
4571 map_addr += 2;
4572 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 10 */
4573 map_addr += 2;
4574 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 11 */
4575 map_addr += 2;
4576 WRW_HARPOON(map_addr, (CPE_OP + ADATA_OUT + DINT)); /*JUMP IF DATA OUT */
4577 map_addr += 2;
4578 WRW_HARPOON(map_addr, (TCB_OP + FIFO_0 + DI)); /*JUMP IF NO DATA IN FIFO */
4579 map_addr += 2; /*This means AYNC DATA IN */
4580 WRW_HARPOON(map_addr, (SSI_OP + SSI_IDO_STRT)); /*STOP AND INTERRUPT */
4581 map_addr += 2;
4582 WRW_HARPOON(map_addr, (CPE_OP + ADATA_IN + DINT)); /*JUMP IF NOT DATA IN PHZ */
4583 map_addr += 2;
4584 WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST)); /*IF NOT MSG IN CHECK 4 DATA IN */
4585 map_addr += 2;
4586 WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x02)); /*SAVE DATA PTR MSG? */
4587 map_addr += 2;
4588 WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + DC)); /*GO CHECK FOR DISCONNECT MSG */
4589 map_addr += 2;
4590 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR1)); /*SAVE DATA PTRS MSG */
4591 map_addr += 2;
4592 WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST)); /*IF NOT MSG IN CHECK DATA IN */
4593 map_addr += 2;
4594 WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x04)); /*DISCONNECT MSG? */
4595 map_addr += 2;
4596 WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + UNKNWN)); /*UKNKNOWN MSG */
4597 map_addr += 2;
4598 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET)); /*XFER DISCONNECT MSG */
4599 map_addr += 2;
4600 WRW_HARPOON(map_addr, (SSI_OP + SSI_ITAR_DISC)); /*STOP AND INTERRUPT */
4601 map_addr += 2;
4602 WRW_HARPOON(map_addr, (CPN_OP + ASTATUS + UNKNWN)); /*JUMP IF NOT STATUS PHZ. */
4603 map_addr += 2;
4604 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR0)); /*GET STATUS BYTE */
4605 map_addr += 2;
4606 WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + CC)); /*ERROR IF NOT MSG IN PHZ */
4607 map_addr += 2;
4608 WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x00)); /*CHECK FOR CMD COMPLETE MSG. */
4609 map_addr += 2;
4610 WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + CC)); /*ERROR IF NOT CMD COMPLETE MSG. */
4611 map_addr += 2;
4612 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET)); /*GET CMD COMPLETE MSG */
4613 map_addr += 2;
4614 WRW_HARPOON(map_addr, (SSI_OP + SSI_ICMD_COMP)); /*END OF COMMAND */
4615 map_addr += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004616
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004617 WRW_HARPOON(map_addr, (SSI_OP + SSI_IUNKWN)); /*RECEIVED UNKNOWN MSG BYTE */
4618 map_addr += 2;
4619 WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */
4620 map_addr += 2;
4621 WRW_HARPOON(map_addr, (SSI_OP + SSI_ITICKLE)); /*BIOS Tickled the Mgr */
4622 map_addr += 2;
4623 WRW_HARPOON(map_addr, (SSI_OP + SSI_IRFAIL)); /*EXPECTED ID/TAG MESSAGES AND */
4624 map_addr += 2; /* DIDN'T GET ONE */
4625 WRW_HARPOON(map_addr, (CRR_OP + AR3 + S_IDREG)); /* comp SCSI SEL ID & AR3 */
4626 map_addr += 2;
4627 WRW_HARPOON(map_addr, (BRH_OP + EQUAL + 0x00)); /*SEL ID OK then Conti. */
4628 map_addr += 2;
4629 WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004630
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004631 SGRAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004632}
4633
4634/*---------------------------------------------------------------------
4635 *
4636 * Function: Auto Command Complete
4637 *
4638 * Description: Post command back to host and find another command
4639 * to execute.
4640 *
4641 *---------------------------------------------------------------------*/
4642
Khalid Aziz391e2f22013-05-16 19:44:14 -06004643static void FPT_autoCmdCmplt(u32 p_port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004644{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004645 struct sccb *currSCCB;
4646 unsigned char status_byte;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004647
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004648 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004649
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004650 status_byte = RD_HARPOON(p_port + hp_gp_reg_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004651
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004652 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004653
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004654 if (status_byte != SSGOOD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004655
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004656 if (status_byte == SSQ_FULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004657
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004658 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4659 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4660 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4661 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4662 TarLUNBusy[currSCCB->Lun] = 1;
4663 if (FPT_BL_Card[p_card].discQCount != 0)
James Bottomley 47b5d692005-04-24 02:38:05 -05004664 FPT_BL_Card[p_card].discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004665 FPT_BL_Card[p_card].
4666 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4667 [currSCCB->TargID].
4668 LunDiscQ_Idx[currSCCB->Lun]] =
4669 NULL;
4670 } else {
4671 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4672 TarLUNBusy[0] = 1;
4673 if (currSCCB->Sccb_tag) {
4674 if (FPT_BL_Card[p_card].discQCount != 0)
4675 FPT_BL_Card[p_card].
4676 discQCount--;
4677 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4678 Sccb_tag]
4679 = NULL;
4680 } else {
4681 if (FPT_BL_Card[p_card].discQCount != 0)
4682 FPT_BL_Card[p_card].
4683 discQCount--;
4684 FPT_BL_Card[p_card].
4685 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4686 [currSCCB->TargID].
4687 LunDiscQ_Idx[0]] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004688 }
4689 }
4690
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004691 currSCCB->Sccb_MGRFlags |= F_STATUSLOADED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004692
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004693 FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004694
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004695 return;
4696 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004697
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004698 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
4699 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4700 (unsigned char)SYNC_SUPPORTED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004701
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004702 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4703 ~EE_SYNC_MASK;
4704 FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004705
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004706 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4707 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4708 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4709 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4710 TarLUNBusy[currSCCB->Lun] = 1;
4711 if (FPT_BL_Card[p_card].discQCount != 0)
James Bottomley 47b5d692005-04-24 02:38:05 -05004712 FPT_BL_Card[p_card].discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004713 FPT_BL_Card[p_card].
4714 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4715 [currSCCB->TargID].
4716 LunDiscQ_Idx[currSCCB->Lun]] =
4717 NULL;
4718 } else {
4719 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4720 TarLUNBusy[0] = 1;
4721 if (currSCCB->Sccb_tag) {
4722 if (FPT_BL_Card[p_card].discQCount != 0)
4723 FPT_BL_Card[p_card].
4724 discQCount--;
4725 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4726 Sccb_tag]
4727 = NULL;
4728 } else {
4729 if (FPT_BL_Card[p_card].discQCount != 0)
4730 FPT_BL_Card[p_card].
4731 discQCount--;
4732 FPT_BL_Card[p_card].
4733 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4734 [currSCCB->TargID].
4735 LunDiscQ_Idx[0]] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004736 }
4737 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004738 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004739
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004740 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004741
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004742 if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004743
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004744 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
4745 (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4746 TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004747
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004748 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4749 ~EE_WIDE_SCSI;
4750 FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004751
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004752 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4753 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4754 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4755 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4756 TarLUNBusy[currSCCB->Lun] = 1;
4757 if (FPT_BL_Card[p_card].discQCount != 0)
James Bottomley 47b5d692005-04-24 02:38:05 -05004758 FPT_BL_Card[p_card].discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004759 FPT_BL_Card[p_card].
4760 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4761 [currSCCB->TargID].
4762 LunDiscQ_Idx[currSCCB->Lun]] =
4763 NULL;
4764 } else {
4765 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4766 TarLUNBusy[0] = 1;
4767 if (currSCCB->Sccb_tag) {
4768 if (FPT_BL_Card[p_card].discQCount != 0)
4769 FPT_BL_Card[p_card].
4770 discQCount--;
4771 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4772 Sccb_tag]
4773 = NULL;
4774 } else {
4775 if (FPT_BL_Card[p_card].discQCount != 0)
4776 FPT_BL_Card[p_card].
4777 discQCount--;
4778 FPT_BL_Card[p_card].
4779 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4780 [currSCCB->TargID].
4781 LunDiscQ_Idx[0]] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004782 }
4783 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004784 return;
4785
4786 }
4787
4788 if (status_byte == SSCHECK) {
4789 if (FPT_BL_Card[p_card].globalFlags & F_DO_RENEGO) {
4790 if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4791 TarEEValue & EE_SYNC_MASK) {
4792 FPT_sccbMgrTbl[p_card][currSCCB->
4793 TargID].
4794 TarStatus &= ~TAR_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004795 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004796 if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4797 TarEEValue & EE_WIDE_SCSI) {
4798 FPT_sccbMgrTbl[p_card][currSCCB->
4799 TargID].
4800 TarStatus &= ~TAR_WIDE_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004801 }
4802 }
4803 }
4804
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004805 if (!(currSCCB->Sccb_XferState & F_AUTO_SENSE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004806
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004807 currSCCB->SccbStatus = SCCB_ERROR;
4808 currSCCB->TargetStatus = status_byte;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004809
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004810 if (status_byte == SSCHECK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004811
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004812 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4813 TarLUN_CA = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004814
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004815 if (currSCCB->RequestSenseLength !=
4816 NO_AUTO_REQUEST_SENSE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004817
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004818 if (currSCCB->RequestSenseLength == 0)
4819 currSCCB->RequestSenseLength =
4820 14;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004821
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004822 FPT_ssenss(&FPT_BL_Card[p_card]);
4823 FPT_BL_Card[p_card].globalFlags |=
4824 F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004825
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004826 if (((FPT_BL_Card[p_card].
4827 globalFlags & F_CONLUN_IO)
4828 &&
4829 ((FPT_sccbMgrTbl[p_card]
4830 [currSCCB->TargID].
4831 TarStatus & TAR_TAG_Q_MASK) !=
4832 TAG_Q_TRYING))) {
4833 FPT_sccbMgrTbl[p_card]
4834 [currSCCB->TargID].
4835 TarLUNBusy[currSCCB->Lun] =
4836 1;
4837 if (FPT_BL_Card[p_card].
4838 discQCount != 0)
4839 FPT_BL_Card[p_card].
4840 discQCount--;
4841 FPT_BL_Card[p_card].
4842 discQ_Tbl[FPT_sccbMgrTbl
4843 [p_card]
4844 [currSCCB->
4845 TargID].
4846 LunDiscQ_Idx
4847 [currSCCB->Lun]] =
4848 NULL;
4849 } else {
4850 FPT_sccbMgrTbl[p_card]
4851 [currSCCB->TargID].
4852 TarLUNBusy[0] = 1;
4853 if (currSCCB->Sccb_tag) {
4854 if (FPT_BL_Card[p_card].
4855 discQCount != 0)
4856 FPT_BL_Card
4857 [p_card].
4858 discQCount--;
4859 FPT_BL_Card[p_card].
4860 discQ_Tbl[currSCCB->
4861 Sccb_tag]
4862 = NULL;
4863 } else {
4864 if (FPT_BL_Card[p_card].
4865 discQCount != 0)
4866 FPT_BL_Card
4867 [p_card].
4868 discQCount--;
4869 FPT_BL_Card[p_card].
4870 discQ_Tbl
4871 [FPT_sccbMgrTbl
4872 [p_card][currSCCB->
4873 TargID].
4874 LunDiscQ_Idx[0]] =
4875 NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004876 }
4877 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004878 return;
4879 }
4880 }
4881 }
4882 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004883
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004884 if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4885 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4886 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4887 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->
4888 Lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004889 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004890 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004891
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004892 FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004893}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004894
4895#define SHORT_WAIT 0x0000000F
4896#define LONG_WAIT 0x0000FFFFL
4897
Linus Torvalds1da177e2005-04-16 15:20:36 -07004898/*---------------------------------------------------------------------
4899 *
4900 * Function: Data Transfer Processor
4901 *
4902 * Description: This routine performs two tasks.
4903 * (1) Start data transfer by calling HOST_DATA_XFER_START
4904 * function. Once data transfer is started, (2) Depends
4905 * on the type of data transfer mode Scatter/Gather mode
4906 * or NON Scatter/Gather mode. In NON Scatter/Gather mode,
4907 * this routine checks Sccb_MGRFlag (F_HOST_XFER_ACT bit) for
4908 * data transfer done. In Scatter/Gather mode, this routine
4909 * checks bus master command complete and dual rank busy
4910 * bit to keep chaining SC transfer command. Similarly,
4911 * in Scatter/Gather mode, it checks Sccb_MGRFlag
4912 * (F_HOST_XFER_ACT bit) for data transfer done.
4913 *
4914 *---------------------------------------------------------------------*/
4915
Khalid Aziz391e2f22013-05-16 19:44:14 -06004916static void FPT_dataXferProcessor(u32 port, struct sccb_card *pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004917{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004918 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004919
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004920 currSCCB = pCurrCard->currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004921
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004922 if (currSCCB->Sccb_XferState & F_SG_XFER) {
4923 if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
4924 {
4925 currSCCB->Sccb_sgseg += (unsigned char)SG_BUF_CNT;
4926 currSCCB->Sccb_SGoffset = 0x00;
4927 }
4928 pCurrCard->globalFlags |= F_HOST_XFER_ACT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004929
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004930 FPT_busMstrSGDataXferStart(port, currSCCB);
4931 }
4932
4933 else {
4934 if (!(pCurrCard->globalFlags & F_HOST_XFER_ACT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004935 pCurrCard->globalFlags |= F_HOST_XFER_ACT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004936
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004937 FPT_busMstrDataXferStart(port, currSCCB);
4938 }
4939 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004940}
4941
Linus Torvalds1da177e2005-04-16 15:20:36 -07004942/*---------------------------------------------------------------------
4943 *
4944 * Function: BusMaster Scatter Gather Data Transfer Start
4945 *
4946 * Description:
4947 *
4948 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06004949static void FPT_busMstrSGDataXferStart(u32 p_port, struct sccb *pcurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004950{
Khalid Aziz391e2f22013-05-16 19:44:14 -06004951 u32 count, addr, tmpSGCnt;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004952 unsigned int sg_index;
4953 unsigned char sg_count, i;
Khalid Aziz391e2f22013-05-16 19:44:14 -06004954 u32 reg_offset;
4955 struct blogic_sg_seg *segp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004956
Khalid Aziz391e2f22013-05-16 19:44:14 -06004957 if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)
4958 count = ((u32)HOST_RD_CMD) << 24;
4959 else
4960 count = ((u32)HOST_WRT_CMD) << 24;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004961
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004962 sg_count = 0;
4963 tmpSGCnt = 0;
4964 sg_index = pcurrSCCB->Sccb_sgseg;
4965 reg_offset = hp_aramBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004966
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004967 i = (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
4968 ~(SGRAM_ARAM | SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004969
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004970 WR_HARPOON(p_port + hp_page_ctrl, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004971
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004972 while ((sg_count < (unsigned char)SG_BUF_CNT) &&
Khalid Aziz391e2f22013-05-16 19:44:14 -06004973 ((sg_index * (unsigned int)SG_ELEMENT_SIZE) <
4974 pcurrSCCB->DataLength)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004975
Khalid Aziz391e2f22013-05-16 19:44:14 -06004976 segp = (struct blogic_sg_seg *)(pcurrSCCB->DataPointer) +
4977 sg_index;
4978 tmpSGCnt += segp->segbytes;
4979 count |= segp->segbytes;
4980 addr = segp->segdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004981
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004982 if ((!sg_count) && (pcurrSCCB->Sccb_SGoffset)) {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004983 addr +=
4984 ((count & 0x00FFFFFFL) - pcurrSCCB->Sccb_SGoffset);
4985 count =
4986 (count & 0xFF000000L) | pcurrSCCB->Sccb_SGoffset;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004987 tmpSGCnt = count & 0x00FFFFFFL;
4988 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004989
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004990 WR_HARP32(p_port, reg_offset, addr);
4991 reg_offset += 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004992
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004993 WR_HARP32(p_port, reg_offset, count);
4994 reg_offset += 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004995
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004996 count &= 0xFF000000L;
4997 sg_index++;
4998 sg_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004999
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005000 } /*End While */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005001
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005002 pcurrSCCB->Sccb_XferCnt = tmpSGCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005003
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005004 WR_HARPOON(p_port + hp_sg_addr, (sg_count << 4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005005
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005006 if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005007
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005008 WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005009
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005010 WR_HARPOON(p_port + hp_portctrl_0,
5011 (DMA_PORT | SCSI_PORT | SCSI_INBIT));
5012 WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
5013 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005014
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005015 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005016
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005017 if ((!(RD_HARPOON(p_port + hp_synctarg_0) & NARROW_SCSI)) &&
5018 (tmpSGCnt & 0x000000001)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005019
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005020 pcurrSCCB->Sccb_XferState |= F_ODD_BALL_CNT;
5021 tmpSGCnt--;
5022 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005023
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005024 WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005025
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005026 WR_HARPOON(p_port + hp_portctrl_0,
5027 (SCSI_PORT | DMA_PORT | DMA_RD));
5028 WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
5029 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005030
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005031 WR_HARPOON(p_port + hp_page_ctrl, (unsigned char)(i | SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005032
5033}
5034
Linus Torvalds1da177e2005-04-16 15:20:36 -07005035/*---------------------------------------------------------------------
5036 *
5037 * Function: BusMaster Data Transfer Start
5038 *
5039 * Description:
5040 *
5041 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06005042static void FPT_busMstrDataXferStart(u32 p_port, struct sccb *pcurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005043{
Khalid Aziz391e2f22013-05-16 19:44:14 -06005044 u32 addr, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005045
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005046 if (!(pcurrSCCB->Sccb_XferState & F_AUTO_SENSE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005047
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005048 count = pcurrSCCB->Sccb_XferCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005049
Khalid Aziz391e2f22013-05-16 19:44:14 -06005050 addr = (u32)(unsigned long)pcurrSCCB->DataPointer + pcurrSCCB->Sccb_ATC;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005051 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005052
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005053 else {
5054 addr = pcurrSCCB->SensePointer;
5055 count = pcurrSCCB->RequestSenseLength;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005056
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005057 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005058
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005059 HP_SETUP_ADDR_CNT(p_port, addr, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005060
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005061 if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005062
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005063 WR_HARPOON(p_port + hp_portctrl_0,
5064 (DMA_PORT | SCSI_PORT | SCSI_INBIT));
5065 WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005066
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005067 WR_HARPOON(p_port + hp_xfer_cmd,
5068 (XFER_DMA_HOST | XFER_HOST_AUTO | XFER_DMA_8BIT));
5069 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005070
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005071 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005072
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005073 WR_HARPOON(p_port + hp_portctrl_0,
5074 (SCSI_PORT | DMA_PORT | DMA_RD));
5075 WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005076
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005077 WR_HARPOON(p_port + hp_xfer_cmd,
5078 (XFER_HOST_DMA | XFER_HOST_AUTO | XFER_DMA_8BIT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005079
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005080 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005081}
5082
Linus Torvalds1da177e2005-04-16 15:20:36 -07005083/*---------------------------------------------------------------------
5084 *
5085 * Function: BusMaster Timeout Handler
5086 *
5087 * Description: This function is called after a bus master command busy time
5088 * out is detected. This routines issue halt state machine
5089 * with a software time out for command busy. If command busy
5090 * is still asserted at the end of the time out, it issues
5091 * hard abort with another software time out. It hard abort
5092 * command busy is also time out, it'll just give up.
5093 *
5094 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06005095static unsigned char FPT_busMstrTimeOut(u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005096{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005097 unsigned long timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005098
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005099 timeout = LONG_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005100
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005101 WR_HARPOON(p_port + hp_sys_ctrl, HALT_MACH);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005102
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005103 while ((!(RD_HARPOON(p_port + hp_ext_status) & CMD_ABORTED))
5104 && timeout--) {
5105 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005106
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005107 if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
5108 WR_HARPOON(p_port + hp_sys_ctrl, HARD_ABORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005109
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005110 timeout = LONG_WAIT;
5111 while ((RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY)
5112 && timeout--) {
5113 }
5114 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005115
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005116 RD_HARPOON(p_port + hp_int_status); /*Clear command complete */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005117
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005118 if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005119 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005120 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005121
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005122 else {
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005123 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005124 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005125}
5126
Linus Torvalds1da177e2005-04-16 15:20:36 -07005127/*---------------------------------------------------------------------
5128 *
5129 * Function: Host Data Transfer Abort
5130 *
5131 * Description: Abort any in progress transfer.
5132 *
5133 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06005134static void FPT_hostDataXferAbort(u32 port, unsigned char p_card,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005135 struct sccb *pCurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005136{
5137
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005138 unsigned long timeout;
5139 unsigned long remain_cnt;
Khalid Aziz391e2f22013-05-16 19:44:14 -06005140 u32 sg_ptr;
5141 struct blogic_sg_seg *segp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005142
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005143 FPT_BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005144
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005145 if (pCurrSCCB->Sccb_XferState & F_AUTO_SENSE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005146
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005147 if (!(RD_HARPOON(port + hp_int_status) & INT_CMD_COMPL)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005148
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005149 WR_HARPOON(port + hp_bm_ctrl,
5150 (RD_HARPOON(port + hp_bm_ctrl) |
5151 FLUSH_XFER_CNTR));
5152 timeout = LONG_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005153
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005154 while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
5155 && timeout--) {
5156 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005157
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005158 WR_HARPOON(port + hp_bm_ctrl,
5159 (RD_HARPOON(port + hp_bm_ctrl) &
5160 ~FLUSH_XFER_CNTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005161
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005162 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005163
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005164 if (FPT_busMstrTimeOut(port)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005165
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005166 if (pCurrSCCB->HostStatus == 0x00)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005167
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005168 pCurrSCCB->HostStatus =
5169 SCCB_BM_ERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005170
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005171 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005172
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005173 if (RD_HARPOON(port + hp_int_status) &
5174 INT_EXT_STATUS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005175
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005176 if (RD_HARPOON(port + hp_ext_status) &
5177 BAD_EXT_STATUS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005178
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005179 if (pCurrSCCB->HostStatus ==
5180 0x00)
5181 {
5182 pCurrSCCB->HostStatus =
5183 SCCB_BM_ERR;
5184 }
5185 }
5186 }
5187 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005188
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005189 else if (pCurrSCCB->Sccb_XferCnt) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005190
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005191 if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005192
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005193 WR_HARPOON(port + hp_page_ctrl,
5194 (RD_HARPOON(port + hp_page_ctrl) &
5195 ~SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005196
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005197 WR_HARPOON(port + hp_sg_addr, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005198
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005199 sg_ptr = pCurrSCCB->Sccb_sgseg + SG_BUF_CNT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005200
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005201 if (sg_ptr >
5202 (unsigned int)(pCurrSCCB->DataLength /
5203 SG_ELEMENT_SIZE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005204
Khalid Aziz391e2f22013-05-16 19:44:14 -06005205 sg_ptr = (u32)(pCurrSCCB->DataLength /
5206 SG_ELEMENT_SIZE);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005207 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005208
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005209 remain_cnt = pCurrSCCB->Sccb_XferCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005210
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005211 while (remain_cnt < 0x01000000L) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005212
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005213 sg_ptr--;
Khalid Aziz391e2f22013-05-16 19:44:14 -06005214 segp = (struct blogic_sg_seg *)(pCurrSCCB->
5215 DataPointer) + (sg_ptr * 2);
5216 if (remain_cnt > (unsigned long)segp->segbytes)
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005217 remain_cnt -=
Khalid Aziz391e2f22013-05-16 19:44:14 -06005218 (unsigned long)segp->segbytes;
5219 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005220 break;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005221 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005222
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005223 if (remain_cnt < 0x01000000L) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005224
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005225 pCurrSCCB->Sccb_SGoffset = remain_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005226
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005227 pCurrSCCB->Sccb_sgseg = (unsigned short)sg_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005228
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005229 if ((unsigned long)(sg_ptr * SG_ELEMENT_SIZE) ==
5230 pCurrSCCB->DataLength && (remain_cnt == 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005231
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005232 pCurrSCCB->Sccb_XferState |=
5233 F_ALL_XFERRED;
5234 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005235
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005236 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005237
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005238 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005239
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005240 pCurrSCCB->HostStatus =
5241 SCCB_GROSS_FW_ERR;
5242 }
5243 }
5244 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005245
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005246 if (!(pCurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005247
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005248 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005249
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005250 FPT_busMstrTimeOut(port);
5251 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005252
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005253 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005254
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005255 if (RD_HARPOON(port + hp_int_status) &
5256 INT_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005257
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005258 if (RD_HARPOON(port + hp_ext_status) &
5259 BAD_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005260
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005261 if (pCurrSCCB->HostStatus ==
5262 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005263
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005264 pCurrSCCB->HostStatus =
5265 SCCB_BM_ERR;
5266 }
5267 }
5268 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005269
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005270 }
5271 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005272
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005273 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005274
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005275 if ((RD_HARPOON(port + hp_fifo_cnt)) >= BM_THRESHOLD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005276
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005277 timeout = SHORT_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005278
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005279 while ((RD_HARPOON(port + hp_ext_status) &
5280 BM_CMD_BUSY)
5281 && ((RD_HARPOON(port + hp_fifo_cnt)) >=
5282 BM_THRESHOLD) && timeout--) {
5283 }
5284 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005285
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005286 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005287
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005288 WR_HARPOON(port + hp_bm_ctrl,
5289 (RD_HARPOON(port + hp_bm_ctrl) |
5290 FLUSH_XFER_CNTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005291
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005292 timeout = LONG_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005293
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005294 while ((RD_HARPOON(port + hp_ext_status) &
5295 BM_CMD_BUSY) && timeout--) {
5296 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005297
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005298 WR_HARPOON(port + hp_bm_ctrl,
5299 (RD_HARPOON(port + hp_bm_ctrl) &
5300 ~FLUSH_XFER_CNTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005301
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005302 if (RD_HARPOON(port + hp_ext_status) &
5303 BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005304
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005305 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005306
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005307 pCurrSCCB->HostStatus =
5308 SCCB_BM_ERR;
5309 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005310
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005311 FPT_busMstrTimeOut(port);
5312 }
5313 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005314
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005315 if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005316
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005317 if (RD_HARPOON(port + hp_ext_status) &
5318 BAD_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005319
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005320 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005321
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005322 pCurrSCCB->HostStatus =
5323 SCCB_BM_ERR;
5324 }
5325 }
5326 }
5327 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005328
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005329 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005330
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005331 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005332
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005333 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005334
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005335 timeout = LONG_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005336
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005337 while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
5338 && timeout--) {
5339 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005340
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005341 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005342
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005343 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005344
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005345 pCurrSCCB->HostStatus = SCCB_BM_ERR;
5346 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005347
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005348 FPT_busMstrTimeOut(port);
5349 }
5350 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005351
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005352 if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005353
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005354 if (RD_HARPOON(port + hp_ext_status) & BAD_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005355
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005356 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005357
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005358 pCurrSCCB->HostStatus = SCCB_BM_ERR;
5359 }
5360 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005361
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005362 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005363
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005364 if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005365
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005366 WR_HARPOON(port + hp_page_ctrl,
5367 (RD_HARPOON(port + hp_page_ctrl) &
5368 ~SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005369
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005370 WR_HARPOON(port + hp_sg_addr, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005371
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005372 pCurrSCCB->Sccb_sgseg += SG_BUF_CNT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005373
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005374 pCurrSCCB->Sccb_SGoffset = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005375
Khalid Aziz391e2f22013-05-16 19:44:14 -06005376 if ((u32)(pCurrSCCB->Sccb_sgseg * SG_ELEMENT_SIZE) >=
5377 pCurrSCCB->DataLength) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005378
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005379 pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005380 pCurrSCCB->Sccb_sgseg =
5381 (unsigned short)(pCurrSCCB->DataLength /
5382 SG_ELEMENT_SIZE);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005383 }
5384 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005385
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005386 else {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005387 if (!(pCurrSCCB->Sccb_XferState & F_AUTO_SENSE))
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005388 pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
5389 }
5390 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005391
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005392 WR_HARPOON(port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005393}
5394
Linus Torvalds1da177e2005-04-16 15:20:36 -07005395/*---------------------------------------------------------------------
5396 *
5397 * Function: Host Data Transfer Restart
5398 *
5399 * Description: Reset the available count due to a restore data
5400 * pointers message.
5401 *
5402 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005403static void FPT_hostDataXferRestart(struct sccb *currSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005404{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005405 unsigned long data_count;
5406 unsigned int sg_index;
Khalid Aziz391e2f22013-05-16 19:44:14 -06005407 struct blogic_sg_seg *segp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005408
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005409 if (currSCCB->Sccb_XferState & F_SG_XFER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005410
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005411 currSCCB->Sccb_XferCnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005412
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005413 sg_index = 0xffff; /*Index by long words into sg list. */
Khalid Aziz391e2f22013-05-16 19:44:14 -06005414 data_count = 0; /*Running count of SG xfer counts. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005415
Linus Torvalds1da177e2005-04-16 15:20:36 -07005416
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005417 while (data_count < currSCCB->Sccb_ATC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005418
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005419 sg_index++;
Khalid Aziz391e2f22013-05-16 19:44:14 -06005420 segp = (struct blogic_sg_seg *)(currSCCB->DataPointer) +
5421 (sg_index * 2);
5422 data_count += segp->segbytes;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005423 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005424
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005425 if (data_count == currSCCB->Sccb_ATC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005426
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005427 currSCCB->Sccb_SGoffset = 0;
5428 sg_index++;
5429 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005430
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005431 else {
5432 currSCCB->Sccb_SGoffset =
5433 data_count - currSCCB->Sccb_ATC;
5434 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005435
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005436 currSCCB->Sccb_sgseg = (unsigned short)sg_index;
5437 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005438
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005439 else {
5440 currSCCB->Sccb_XferCnt =
5441 currSCCB->DataLength - currSCCB->Sccb_ATC;
5442 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005443}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005444
Linus Torvalds1da177e2005-04-16 15:20:36 -07005445/*---------------------------------------------------------------------
5446 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005447 * Function: FPT_scini
Linus Torvalds1da177e2005-04-16 15:20:36 -07005448 *
5449 * Description: Setup all data structures necessary for SCAM selection.
5450 *
5451 *---------------------------------------------------------------------*/
5452
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005453static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
5454 unsigned char p_power_up)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005455{
5456
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005457 unsigned char loser, assigned_id;
Khalid Aziz391e2f22013-05-16 19:44:14 -06005458 u32 p_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005459
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005460 unsigned char i, k, ScamFlg;
5461 struct sccb_card *currCard;
5462 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005463
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005464 currCard = &FPT_BL_Card[p_card];
5465 p_port = currCard->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005466 pCurrNvRam = currCard->pNvRamInfo;
5467
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005468 if (pCurrNvRam) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005469 ScamFlg = pCurrNvRam->niScamConf;
5470 i = pCurrNvRam->niSysConf;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005471 } else {
5472 ScamFlg =
5473 (unsigned char)FPT_utilEERead(p_port, SCAM_CONFIG / 2);
5474 i = (unsigned
5475 char)(FPT_utilEERead(p_port, (SYSTEM_CONFIG / 2)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005476 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005477 if (!(i & 0x02)) /* check if reset bus in AutoSCSI parameter set */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005478 return;
5479
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005480 FPT_inisci(p_card, p_port, p_our_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005481
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005482 /* Force to wait 1 sec after SCSI bus reset. Some SCAM device FW
5483 too slow to return to SCAM selection */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005484
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005485 /* if (p_power_up)
5486 FPT_Wait1Second(p_port);
5487 else
5488 FPT_Wait(p_port, TO_250ms); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005489
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005490 FPT_Wait1Second(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005491
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005492 if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2)) {
5493 while (!(FPT_scarb(p_port, INIT_SELTD))) {
5494 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005495
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005496 FPT_scsel(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005497
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005498 do {
5499 FPT_scxferc(p_port, SYNC_PTRN);
5500 FPT_scxferc(p_port, DOM_MSTR);
5501 loser =
5502 FPT_scsendi(p_port,
5503 &FPT_scamInfo[p_our_id].id_string[0]);
5504 } while (loser == 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005505
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005506 FPT_scbusf(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005507
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005508 if ((p_power_up) && (!loser)) {
5509 FPT_sresb(p_port, p_card);
5510 FPT_Wait(p_port, TO_250ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005511
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005512 while (!(FPT_scarb(p_port, INIT_SELTD))) {
5513 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005514
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005515 FPT_scsel(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005516
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005517 do {
5518 FPT_scxferc(p_port, SYNC_PTRN);
5519 FPT_scxferc(p_port, DOM_MSTR);
5520 loser =
5521 FPT_scsendi(p_port,
5522 &FPT_scamInfo[p_our_id].
5523 id_string[0]);
5524 } while (loser == 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005525
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005526 FPT_scbusf(p_port);
5527 }
5528 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005529
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005530 else {
5531 loser = 0;
5532 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005533
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005534 if (!loser) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005535
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005536 FPT_scamInfo[p_our_id].state = ID_ASSIGNED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005537
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005538 if (ScamFlg & SCAM_ENABLED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005539
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005540 for (i = 0; i < MAX_SCSI_TAR; i++) {
5541 if ((FPT_scamInfo[i].state == ID_UNASSIGNED) ||
5542 (FPT_scamInfo[i].state == ID_UNUSED)) {
5543 if (FPT_scsell(p_port, i)) {
5544 FPT_scamInfo[i].state = LEGACY;
5545 if ((FPT_scamInfo[i].
5546 id_string[0] != 0xFF)
5547 || (FPT_scamInfo[i].
5548 id_string[1] != 0xFA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005549
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005550 FPT_scamInfo[i].
5551 id_string[0] = 0xFF;
5552 FPT_scamInfo[i].
5553 id_string[1] = 0xFA;
5554 if (pCurrNvRam == NULL)
5555 currCard->
5556 globalFlags
5557 |=
5558 F_UPDATE_EEPROM;
5559 }
5560 }
5561 }
5562 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005563
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005564 FPT_sresb(p_port, p_card);
5565 FPT_Wait1Second(p_port);
5566 while (!(FPT_scarb(p_port, INIT_SELTD))) {
5567 }
5568 FPT_scsel(p_port);
5569 FPT_scasid(p_card, p_port);
5570 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005571
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005572 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005573
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005574 else if ((loser) && (ScamFlg & SCAM_ENABLED)) {
5575 FPT_scamInfo[p_our_id].id_string[0] = SLV_TYPE_CODE0;
5576 assigned_id = 0;
5577 FPT_scwtsel(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005578
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005579 do {
5580 while (FPT_scxferc(p_port, 0x00) != SYNC_PTRN) {
5581 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005582
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005583 i = FPT_scxferc(p_port, 0x00);
5584 if (i == ASSIGN_ID) {
5585 if (!
5586 (FPT_scsendi
5587 (p_port,
5588 &FPT_scamInfo[p_our_id].id_string[0]))) {
5589 i = FPT_scxferc(p_port, 0x00);
5590 if (FPT_scvalq(i)) {
5591 k = FPT_scxferc(p_port, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005592
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005593 if (FPT_scvalq(k)) {
5594 currCard->ourId =
5595 ((unsigned char)(i
5596 <<
5597 3)
5598 +
5599 (k &
5600 (unsigned char)7))
5601 & (unsigned char)
5602 0x3F;
5603 FPT_inisci(p_card,
5604 p_port,
5605 p_our_id);
5606 FPT_scamInfo[currCard->
5607 ourId].
5608 state = ID_ASSIGNED;
5609 FPT_scamInfo[currCard->
5610 ourId].
5611 id_string[0]
5612 = SLV_TYPE_CODE0;
5613 assigned_id = 1;
5614 }
5615 }
5616 }
5617 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005618
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005619 else if (i == SET_P_FLAG) {
5620 if (!(FPT_scsendi(p_port,
5621 &FPT_scamInfo[p_our_id].
5622 id_string[0])))
5623 FPT_scamInfo[p_our_id].id_string[0] |=
5624 0x80;
5625 }
5626 } while (!assigned_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005627
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005628 while (FPT_scxferc(p_port, 0x00) != CFG_CMPLT) {
5629 }
5630 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005631
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005632 if (ScamFlg & SCAM_ENABLED) {
5633 FPT_scbusf(p_port);
5634 if (currCard->globalFlags & F_UPDATE_EEPROM) {
5635 FPT_scsavdi(p_card, p_port);
5636 currCard->globalFlags &= ~F_UPDATE_EEPROM;
5637 }
5638 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005639
Linus Torvalds1da177e2005-04-16 15:20:36 -07005640/*
5641 for (i=0,k=0; i < MAX_SCSI_TAR; i++)
5642 {
James Bottomley 47b5d692005-04-24 02:38:05 -05005643 if ((FPT_scamInfo[i].state == ID_ASSIGNED) ||
5644 (FPT_scamInfo[i].state == LEGACY))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005645 k++;
5646 }
5647
5648 if (k==2)
5649 currCard->globalFlags |= F_SINGLE_DEVICE;
5650 else
5651 currCard->globalFlags &= ~F_SINGLE_DEVICE;
5652*/
5653}
5654
Linus Torvalds1da177e2005-04-16 15:20:36 -07005655/*---------------------------------------------------------------------
5656 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005657 * Function: FPT_scarb
Linus Torvalds1da177e2005-04-16 15:20:36 -07005658 *
5659 * Description: Gain control of the bus and wait SCAM select time (250ms)
5660 *
5661 *---------------------------------------------------------------------*/
5662
Khalid Aziz391e2f22013-05-16 19:44:14 -06005663static int FPT_scarb(u32 p_port, unsigned char p_sel_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005664{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005665 if (p_sel_type == INIT_SELTD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005666
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005667 while (RD_HARPOON(p_port + hp_scsisig) & (SCSI_SEL | SCSI_BSY)) {
5668 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005669
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005670 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005671 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005672
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005673 if (RD_HARPOON(p_port + hp_scsidata_0) != 00)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005674 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005675
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005676 WR_HARPOON(p_port + hp_scsisig,
5677 (RD_HARPOON(p_port + hp_scsisig) | SCSI_BSY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005678
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005679 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005680
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005681 WR_HARPOON(p_port + hp_scsisig,
5682 (RD_HARPOON(p_port + hp_scsisig) &
5683 ~SCSI_BSY));
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005684 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005685 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005686
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005687 WR_HARPOON(p_port + hp_scsisig,
5688 (RD_HARPOON(p_port + hp_scsisig) | SCSI_SEL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005689
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005690 if (RD_HARPOON(p_port + hp_scsidata_0) != 00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005691
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005692 WR_HARPOON(p_port + hp_scsisig,
5693 (RD_HARPOON(p_port + hp_scsisig) &
5694 ~(SCSI_BSY | SCSI_SEL)));
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005695 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005696 }
5697 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005698
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005699 WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
5700 & ~ACTdeassert));
5701 WR_HARPOON(p_port + hp_scsireset, SCAM_EN);
5702 WR_HARPOON(p_port + hp_scsidata_0, 0x00);
5703 WR_HARPOON(p_port + hp_scsidata_1, 0x00);
5704 WR_HARPOON(p_port + hp_portctrl_0, SCSI_BUS_EN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005705
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005706 WR_HARPOON(p_port + hp_scsisig,
5707 (RD_HARPOON(p_port + hp_scsisig) | SCSI_MSG));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005708
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005709 WR_HARPOON(p_port + hp_scsisig, (RD_HARPOON(p_port + hp_scsisig)
5710 & ~SCSI_BSY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005711
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005712 FPT_Wait(p_port, TO_250ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005713
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005714 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005715}
5716
Linus Torvalds1da177e2005-04-16 15:20:36 -07005717/*---------------------------------------------------------------------
5718 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005719 * Function: FPT_scbusf
Linus Torvalds1da177e2005-04-16 15:20:36 -07005720 *
5721 * Description: Release the SCSI bus and disable SCAM selection.
5722 *
5723 *---------------------------------------------------------------------*/
5724
Khalid Aziz391e2f22013-05-16 19:44:14 -06005725static void FPT_scbusf(u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005726{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005727 WR_HARPOON(p_port + hp_page_ctrl,
5728 (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005729
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005730 WR_HARPOON(p_port + hp_scsidata_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005731
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005732 WR_HARPOON(p_port + hp_portctrl_0, (RD_HARPOON(p_port + hp_portctrl_0)
5733 & ~SCSI_BUS_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005734
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005735 WR_HARPOON(p_port + hp_scsisig, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005736
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005737 WR_HARPOON(p_port + hp_scsireset, (RD_HARPOON(p_port + hp_scsireset)
5738 & ~SCAM_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005739
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005740 WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
5741 | ACTdeassert));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005742
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005743 WRW_HARPOON((p_port + hp_intstat), (BUS_FREE | AUTO_INT | SCAM_SEL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005744
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005745 WR_HARPOON(p_port + hp_page_ctrl,
5746 (RD_HARPOON(p_port + hp_page_ctrl) & ~G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005747}
5748
Linus Torvalds1da177e2005-04-16 15:20:36 -07005749/*---------------------------------------------------------------------
5750 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005751 * Function: FPT_scasid
Linus Torvalds1da177e2005-04-16 15:20:36 -07005752 *
5753 * Description: Assign an ID to all the SCAM devices.
5754 *
5755 *---------------------------------------------------------------------*/
5756
Khalid Aziz391e2f22013-05-16 19:44:14 -06005757static void FPT_scasid(unsigned char p_card, u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005758{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005759 unsigned char temp_id_string[ID_STRING_LENGTH];
Linus Torvalds1da177e2005-04-16 15:20:36 -07005760
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005761 unsigned char i, k, scam_id;
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08005762 unsigned char crcBytes[3];
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005763 struct nvram_info *pCurrNvRam;
5764 unsigned short *pCrcBytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005765
James Bottomley 47b5d692005-04-24 02:38:05 -05005766 pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005767
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005768 i = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005769
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005770 while (!i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005771
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005772 for (k = 0; k < ID_STRING_LENGTH; k++) {
5773 temp_id_string[k] = (unsigned char)0x00;
5774 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005775
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005776 FPT_scxferc(p_port, SYNC_PTRN);
5777 FPT_scxferc(p_port, ASSIGN_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005778
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005779 if (!(FPT_sciso(p_port, &temp_id_string[0]))) {
5780 if (pCurrNvRam) {
Alexey Dobriyanfd1e29e2006-03-08 00:14:27 -08005781 pCrcBytes = (unsigned short *)&crcBytes[0];
James Bottomley 47b5d692005-04-24 02:38:05 -05005782 *pCrcBytes = FPT_CalcCrc16(&temp_id_string[0]);
5783 crcBytes[2] = FPT_CalcLrc(&temp_id_string[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005784 temp_id_string[1] = crcBytes[2];
5785 temp_id_string[2] = crcBytes[0];
5786 temp_id_string[3] = crcBytes[1];
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005787 for (k = 4; k < ID_STRING_LENGTH; k++)
5788 temp_id_string[k] = (unsigned char)0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005789 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005790 i = FPT_scmachid(p_card, temp_id_string);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005791
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005792 if (i == CLR_PRIORITY) {
5793 FPT_scxferc(p_port, MISC_CODE);
5794 FPT_scxferc(p_port, CLR_P_FLAG);
5795 i = 0; /*Not the last ID yet. */
5796 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005797
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005798 else if (i != NO_ID_AVAIL) {
5799 if (i < 8)
5800 FPT_scxferc(p_port, ID_0_7);
5801 else
5802 FPT_scxferc(p_port, ID_8_F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005803
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005804 scam_id = (i & (unsigned char)0x07);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005805
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005806 for (k = 1; k < 0x08; k <<= 1)
5807 if (!(k & i))
5808 scam_id += 0x08; /*Count number of zeros in DB0-3. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005809
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005810 FPT_scxferc(p_port, scam_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005811
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005812 i = 0; /*Not the last ID yet. */
5813 }
5814 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005815
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005816 else {
5817 i = 1;
5818 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005819
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005820 } /*End while */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005821
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005822 FPT_scxferc(p_port, SYNC_PTRN);
5823 FPT_scxferc(p_port, CFG_CMPLT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005824}
5825
Linus Torvalds1da177e2005-04-16 15:20:36 -07005826/*---------------------------------------------------------------------
5827 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005828 * Function: FPT_scsel
Linus Torvalds1da177e2005-04-16 15:20:36 -07005829 *
5830 * Description: Select all the SCAM devices.
5831 *
5832 *---------------------------------------------------------------------*/
5833
Khalid Aziz391e2f22013-05-16 19:44:14 -06005834static void FPT_scsel(u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005835{
5836
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005837 WR_HARPOON(p_port + hp_scsisig, SCSI_SEL);
5838 FPT_scwiros(p_port, SCSI_MSG);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005839
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005840 WR_HARPOON(p_port + hp_scsisig, (SCSI_SEL | SCSI_BSY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005841
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005842 WR_HARPOON(p_port + hp_scsisig,
5843 (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5844 WR_HARPOON(p_port + hp_scsidata_0,
5845 (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) |
5846 (unsigned char)(BIT(7) + BIT(6))));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005847
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005848 WR_HARPOON(p_port + hp_scsisig, (SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5849 FPT_scwiros(p_port, SCSI_SEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005850
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005851 WR_HARPOON(p_port + hp_scsidata_0,
5852 (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) &
5853 ~(unsigned char)BIT(6)));
5854 FPT_scwirod(p_port, BIT(6));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005855
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005856 WR_HARPOON(p_port + hp_scsisig,
5857 (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005858}
5859
Linus Torvalds1da177e2005-04-16 15:20:36 -07005860/*---------------------------------------------------------------------
5861 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005862 * Function: FPT_scxferc
Linus Torvalds1da177e2005-04-16 15:20:36 -07005863 *
5864 * Description: Handshake the p_data (DB4-0) across the bus.
5865 *
5866 *---------------------------------------------------------------------*/
5867
Khalid Aziz391e2f22013-05-16 19:44:14 -06005868static unsigned char FPT_scxferc(u32 p_port, unsigned char p_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005869{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005870 unsigned char curr_data, ret_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005871
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005872 curr_data = p_data | BIT(7) | BIT(5); /*Start with DB7 & DB5 asserted. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005873
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005874 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005875
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005876 curr_data &= ~BIT(7);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005877
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005878 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005879
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005880 FPT_scwirod(p_port, BIT(7)); /*Wait for DB7 to be released. */
5881 while (!(RD_HARPOON(p_port + hp_scsidata_0) & BIT(5))) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005882
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005883 ret_data = (RD_HARPOON(p_port + hp_scsidata_0) & (unsigned char)0x1F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005884
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005885 curr_data |= BIT(6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005886
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005887 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005888
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005889 curr_data &= ~BIT(5);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005890
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005891 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005892
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005893 FPT_scwirod(p_port, BIT(5)); /*Wait for DB5 to be released. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005894
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005895 curr_data &= ~(BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0)); /*Release data bits */
5896 curr_data |= BIT(7);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005897
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005898 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005899
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005900 curr_data &= ~BIT(6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005901
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005902 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005903
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005904 FPT_scwirod(p_port, BIT(6)); /*Wait for DB6 to be released. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005905
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005906 return ret_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005907}
5908
Linus Torvalds1da177e2005-04-16 15:20:36 -07005909/*---------------------------------------------------------------------
5910 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005911 * Function: FPT_scsendi
Linus Torvalds1da177e2005-04-16 15:20:36 -07005912 *
5913 * Description: Transfer our Identification string to determine if we
5914 * will be the dominant master.
5915 *
5916 *---------------------------------------------------------------------*/
5917
Khalid Aziz391e2f22013-05-16 19:44:14 -06005918static unsigned char FPT_scsendi(u32 p_port, unsigned char p_id_string[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07005919{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005920 unsigned char ret_data, byte_cnt, bit_cnt, defer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005921
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005922 defer = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005923
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005924 for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005925
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005926 for (bit_cnt = 0x80; bit_cnt != 0; bit_cnt >>= 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005927
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005928 if (defer)
5929 ret_data = FPT_scxferc(p_port, 00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005930
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005931 else if (p_id_string[byte_cnt] & bit_cnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005932
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005933 ret_data = FPT_scxferc(p_port, 02);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005934
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005935 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005936
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005937 ret_data = FPT_scxferc(p_port, 01);
5938 if (ret_data & 02)
5939 defer = 1;
5940 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005941
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005942 if ((ret_data & 0x1C) == 0x10)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005943 return 0x00; /*End of isolation stage, we won! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005944
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005945 if (ret_data & 0x1C)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005946 return 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005947
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005948 if ((defer) && (!(ret_data & 0x1F)))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005949 return 0x01; /*End of isolation stage, we lost. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005950
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005951 } /*bit loop */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005952
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005953 } /*byte loop */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005954
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005955 if (defer)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005956 return 0x01; /*We lost */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005957 else
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005958 return 0; /*We WON! Yeeessss! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005959}
5960
Linus Torvalds1da177e2005-04-16 15:20:36 -07005961/*---------------------------------------------------------------------
5962 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005963 * Function: FPT_sciso
Linus Torvalds1da177e2005-04-16 15:20:36 -07005964 *
5965 * Description: Transfer the Identification string.
5966 *
5967 *---------------------------------------------------------------------*/
5968
Khalid Aziz391e2f22013-05-16 19:44:14 -06005969static unsigned char FPT_sciso(u32 p_port, unsigned char p_id_string[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07005970{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005971 unsigned char ret_data, the_data, byte_cnt, bit_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005972
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005973 the_data = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005974
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005975 for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005976
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005977 for (bit_cnt = 0; bit_cnt < 8; bit_cnt++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005978
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005979 ret_data = FPT_scxferc(p_port, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005980
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005981 if (ret_data & 0xFC)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005982 return 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005983
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005984 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005985
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005986 the_data <<= 1;
5987 if (ret_data & BIT(1)) {
5988 the_data |= 1;
5989 }
5990 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005991
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005992 if ((ret_data & 0x1F) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005993/*
5994 if(bit_cnt != 0 || bit_cnt != 8)
5995 {
5996 byte_cnt = 0;
5997 bit_cnt = 0;
James Bottomley 47b5d692005-04-24 02:38:05 -05005998 FPT_scxferc(p_port, SYNC_PTRN);
5999 FPT_scxferc(p_port, ASSIGN_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006000 continue;
6001 }
6002*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006003 if (byte_cnt)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006004 return 0x00;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006005 else
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006006 return 0xFF;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006007 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006008
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006009 } /*bit loop */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006010
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006011 p_id_string[byte_cnt] = the_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006012
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006013 } /*byte loop */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006014
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006015 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006016}
6017
Linus Torvalds1da177e2005-04-16 15:20:36 -07006018/*---------------------------------------------------------------------
6019 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006020 * Function: FPT_scwirod
Linus Torvalds1da177e2005-04-16 15:20:36 -07006021 *
6022 * Description: Sample the SCSI data bus making sure the signal has been
6023 * deasserted for the correct number of consecutive samples.
6024 *
6025 *---------------------------------------------------------------------*/
6026
Khalid Aziz391e2f22013-05-16 19:44:14 -06006027static void FPT_scwirod(u32 p_port, unsigned char p_data_bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006028{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006029 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006030
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006031 i = 0;
6032 while (i < MAX_SCSI_TAR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006033
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006034 if (RD_HARPOON(p_port + hp_scsidata_0) & p_data_bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006035
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006036 i = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006037
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006038 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07006039
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006040 i++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006041
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006042 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006043}
6044
Linus Torvalds1da177e2005-04-16 15:20:36 -07006045/*---------------------------------------------------------------------
6046 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006047 * Function: FPT_scwiros
Linus Torvalds1da177e2005-04-16 15:20:36 -07006048 *
6049 * Description: Sample the SCSI Signal lines making sure the signal has been
6050 * deasserted for the correct number of consecutive samples.
6051 *
6052 *---------------------------------------------------------------------*/
6053
Khalid Aziz391e2f22013-05-16 19:44:14 -06006054static void FPT_scwiros(u32 p_port, unsigned char p_data_bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006055{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006056 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006057
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006058 i = 0;
6059 while (i < MAX_SCSI_TAR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006060
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006061 if (RD_HARPOON(p_port + hp_scsisig) & p_data_bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006062
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006063 i = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006064
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006065 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07006066
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006067 i++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006068
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006069 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006070}
6071
Linus Torvalds1da177e2005-04-16 15:20:36 -07006072/*---------------------------------------------------------------------
6073 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006074 * Function: FPT_scvalq
Linus Torvalds1da177e2005-04-16 15:20:36 -07006075 *
6076 * Description: Make sure we received a valid data byte.
6077 *
6078 *---------------------------------------------------------------------*/
6079
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08006080static unsigned char FPT_scvalq(unsigned char p_quintet)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006081{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006082 unsigned char count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006083
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006084 for (count = 1; count < 0x08; count <<= 1) {
6085 if (!(p_quintet & count))
6086 p_quintet -= 0x80;
6087 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006088
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006089 if (p_quintet & 0x18)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006090 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006091
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006092 else
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006093 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006094}
6095
Linus Torvalds1da177e2005-04-16 15:20:36 -07006096/*---------------------------------------------------------------------
6097 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006098 * Function: FPT_scsell
Linus Torvalds1da177e2005-04-16 15:20:36 -07006099 *
6100 * Description: Select the specified device ID using a selection timeout
6101 * less than 4ms. If somebody responds then it is a legacy
6102 * drive and this ID must be marked as such.
6103 *
6104 *---------------------------------------------------------------------*/
6105
Khalid Aziz391e2f22013-05-16 19:44:14 -06006106static unsigned char FPT_scsell(u32 p_port, unsigned char targ_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006107{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006108 unsigned long i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006109
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006110 WR_HARPOON(p_port + hp_page_ctrl,
6111 (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006112
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006113 ARAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006114
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006115 WR_HARPOON(p_port + hp_addstat,
6116 (RD_HARPOON(p_port + hp_addstat) | SCAM_TIMER));
6117 WR_HARPOON(p_port + hp_seltimeout, TO_4ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006118
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006119 for (i = p_port + CMD_STRT; i < p_port + CMD_STRT + 12; i += 2) {
6120 WRW_HARPOON(i, (MPM_OP + ACOMMAND));
6121 }
6122 WRW_HARPOON(i, (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006123
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006124 WRW_HARPOON((p_port + hp_intstat),
6125 (RESET | TIMEOUT | SEL | BUS_FREE | AUTO_INT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006126
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006127 WR_HARPOON(p_port + hp_select_id, targ_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006128
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006129 WR_HARPOON(p_port + hp_portctrl_0, SCSI_PORT);
6130 WR_HARPOON(p_port + hp_autostart_3, (SELECT | CMD_ONLY_STRT));
6131 WR_HARPOON(p_port + hp_scsictrl_0, (SEL_TAR | ENA_RESEL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006132
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006133 while (!(RDW_HARPOON((p_port + hp_intstat)) &
6134 (RESET | PROG_HLT | TIMEOUT | AUTO_INT))) {
6135 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006136
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006137 if (RDW_HARPOON((p_port + hp_intstat)) & RESET)
6138 FPT_Wait(p_port, TO_250ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006139
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006140 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006141
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006142 WR_HARPOON(p_port + hp_addstat,
6143 (RD_HARPOON(p_port + hp_addstat) & ~SCAM_TIMER));
6144 WR_HARPOON(p_port + hp_seltimeout, TO_290ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006145
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006146 SGRAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006147
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006148 if (RDW_HARPOON((p_port + hp_intstat)) & (RESET | TIMEOUT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006149
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006150 WRW_HARPOON((p_port + hp_intstat),
6151 (RESET | TIMEOUT | SEL | BUS_FREE | PHASE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006152
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006153 WR_HARPOON(p_port + hp_page_ctrl,
6154 (RD_HARPOON(p_port + hp_page_ctrl) &
6155 ~G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006156
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006157 return 0; /*No legacy device */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006158 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006159
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006160 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006161
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006162 while (!(RDW_HARPOON((p_port + hp_intstat)) & BUS_FREE)) {
6163 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ) {
6164 WR_HARPOON(p_port + hp_scsisig,
6165 (SCSI_ACK + S_ILL_PH));
6166 ACCEPT_MSG(p_port);
6167 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006168 }
6169
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006170 WRW_HARPOON((p_port + hp_intstat), CLR_ALL_INT_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006171
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006172 WR_HARPOON(p_port + hp_page_ctrl,
6173 (RD_HARPOON(p_port + hp_page_ctrl) &
6174 ~G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006175
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006176 return 1; /*Found one of them oldies! */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006177 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006178}
6179
Linus Torvalds1da177e2005-04-16 15:20:36 -07006180/*---------------------------------------------------------------------
6181 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006182 * Function: FPT_scwtsel
Linus Torvalds1da177e2005-04-16 15:20:36 -07006183 *
6184 * Description: Wait to be selected by another SCAM initiator.
6185 *
6186 *---------------------------------------------------------------------*/
6187
Khalid Aziz391e2f22013-05-16 19:44:14 -06006188static void FPT_scwtsel(u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006189{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006190 while (!(RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL)) {
6191 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006192}
6193
Linus Torvalds1da177e2005-04-16 15:20:36 -07006194/*---------------------------------------------------------------------
6195 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006196 * Function: FPT_inisci
Linus Torvalds1da177e2005-04-16 15:20:36 -07006197 *
6198 * Description: Setup the data Structure with the info from the EEPROM.
6199 *
6200 *---------------------------------------------------------------------*/
6201
Khalid Aziz391e2f22013-05-16 19:44:14 -06006202static void FPT_inisci(unsigned char p_card, u32 p_port, unsigned char p_our_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006203{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006204 unsigned char i, k, max_id;
6205 unsigned short ee_data;
6206 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006207
James Bottomley 47b5d692005-04-24 02:38:05 -05006208 pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006209
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006210 if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6211 max_id = 0x08;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006212
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006213 else
6214 max_id = 0x10;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006215
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006216 if (pCurrNvRam) {
6217 for (i = 0; i < max_id; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006218
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006219 for (k = 0; k < 4; k++)
6220 FPT_scamInfo[i].id_string[k] =
6221 pCurrNvRam->niScamTbl[i][k];
6222 for (k = 4; k < ID_STRING_LENGTH; k++)
6223 FPT_scamInfo[i].id_string[k] =
6224 (unsigned char)0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006225
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006226 if (FPT_scamInfo[i].id_string[0] == 0x00)
6227 FPT_scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */
6228 else
6229 FPT_scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006230
6231 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006232 } else {
6233 for (i = 0; i < max_id; i++) {
6234 for (k = 0; k < ID_STRING_LENGTH; k += 2) {
6235 ee_data =
6236 FPT_utilEERead(p_port,
6237 (unsigned
6238 short)((EE_SCAMBASE / 2) +
6239 (unsigned short)(i *
6240 ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
6241 FPT_scamInfo[i].id_string[k] =
6242 (unsigned char)ee_data;
6243 ee_data >>= 8;
6244 FPT_scamInfo[i].id_string[k + 1] =
6245 (unsigned char)ee_data;
6246 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006247
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006248 if ((FPT_scamInfo[i].id_string[0] == 0x00) ||
6249 (FPT_scamInfo[i].id_string[0] == 0xFF))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006250
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006251 FPT_scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006252
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006253 else
6254 FPT_scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006255
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006256 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006257 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006258 for (k = 0; k < ID_STRING_LENGTH; k++)
James Bottomley 47b5d692005-04-24 02:38:05 -05006259 FPT_scamInfo[p_our_id].id_string[k] = FPT_scamHAString[k];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006260
6261}
6262
6263/*---------------------------------------------------------------------
6264 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006265 * Function: FPT_scmachid
Linus Torvalds1da177e2005-04-16 15:20:36 -07006266 *
6267 * Description: Match the Device ID string with our values stored in
6268 * the EEPROM.
6269 *
6270 *---------------------------------------------------------------------*/
6271
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006272static unsigned char FPT_scmachid(unsigned char p_card,
6273 unsigned char p_id_string[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07006274{
6275
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006276 unsigned char i, k, match;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006277
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006278 for (i = 0; i < MAX_SCSI_TAR; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006279
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006280 match = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006281
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006282 for (k = 0; k < ID_STRING_LENGTH; k++) {
6283 if (p_id_string[k] != FPT_scamInfo[i].id_string[k])
6284 match = 0;
6285 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006286
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006287 if (match) {
6288 FPT_scamInfo[i].state = ID_ASSIGNED;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006289 return i;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006290 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006291
Linus Torvalds1da177e2005-04-16 15:20:36 -07006292 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006293
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006294 if (p_id_string[0] & BIT(5))
6295 i = 8;
6296 else
6297 i = MAX_SCSI_TAR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006298
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006299 if (((p_id_string[0] & 0x06) == 0x02)
6300 || ((p_id_string[0] & 0x06) == 0x04))
6301 match = p_id_string[1] & (unsigned char)0x1F;
6302 else
6303 match = 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006304
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006305 while (i > 0) {
6306 i--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006307
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006308 if (FPT_scamInfo[match].state == ID_UNUSED) {
6309 for (k = 0; k < ID_STRING_LENGTH; k++) {
6310 FPT_scamInfo[match].id_string[k] =
6311 p_id_string[k];
6312 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006313
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006314 FPT_scamInfo[match].state = ID_ASSIGNED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006315
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006316 if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
6317 FPT_BL_Card[p_card].globalFlags |=
6318 F_UPDATE_EEPROM;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006319 return match;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006320
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006321 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006322
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006323 match--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006324
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006325 if (match == 0xFF) {
6326 if (p_id_string[0] & BIT(5))
6327 match = 7;
6328 else
6329 match = MAX_SCSI_TAR - 1;
6330 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006331 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006332
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006333 if (p_id_string[0] & BIT(7)) {
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006334 return CLR_PRIORITY;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006335 }
6336
6337 if (p_id_string[0] & BIT(5))
6338 i = 8;
6339 else
6340 i = MAX_SCSI_TAR;
6341
6342 if (((p_id_string[0] & 0x06) == 0x02)
6343 || ((p_id_string[0] & 0x06) == 0x04))
6344 match = p_id_string[1] & (unsigned char)0x1F;
6345 else
6346 match = 7;
6347
6348 while (i > 0) {
6349
6350 i--;
6351
6352 if (FPT_scamInfo[match].state == ID_UNASSIGNED) {
6353 for (k = 0; k < ID_STRING_LENGTH; k++) {
6354 FPT_scamInfo[match].id_string[k] =
6355 p_id_string[k];
6356 }
6357
6358 FPT_scamInfo[match].id_string[0] |= BIT(7);
6359 FPT_scamInfo[match].state = ID_ASSIGNED;
6360 if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
6361 FPT_BL_Card[p_card].globalFlags |=
6362 F_UPDATE_EEPROM;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006363 return match;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006364
6365 }
6366
6367 match--;
6368
6369 if (match == 0xFF) {
6370 if (p_id_string[0] & BIT(5))
6371 match = 7;
6372 else
6373 match = MAX_SCSI_TAR - 1;
6374 }
6375 }
6376
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006377 return NO_ID_AVAIL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006378}
6379
Linus Torvalds1da177e2005-04-16 15:20:36 -07006380/*---------------------------------------------------------------------
6381 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006382 * Function: FPT_scsavdi
Linus Torvalds1da177e2005-04-16 15:20:36 -07006383 *
6384 * Description: Save off the device SCAM ID strings.
6385 *
6386 *---------------------------------------------------------------------*/
6387
Khalid Aziz391e2f22013-05-16 19:44:14 -06006388static void FPT_scsavdi(unsigned char p_card, u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006389{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006390 unsigned char i, k, max_id;
6391 unsigned short ee_data, sum_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006392
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006393 sum_data = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006394
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006395 for (i = 1; i < EE_SCAMBASE / 2; i++) {
6396 sum_data += FPT_utilEERead(p_port, i);
6397 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006398
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006399 FPT_utilEEWriteOnOff(p_port, 1); /* Enable write access to the EEPROM */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006400
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006401 if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6402 max_id = 0x08;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006403
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006404 else
6405 max_id = 0x10;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006406
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006407 for (i = 0; i < max_id; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006408
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006409 for (k = 0; k < ID_STRING_LENGTH; k += 2) {
6410 ee_data = FPT_scamInfo[i].id_string[k + 1];
6411 ee_data <<= 8;
6412 ee_data |= FPT_scamInfo[i].id_string[k];
6413 sum_data += ee_data;
6414 FPT_utilEEWrite(p_port, ee_data,
6415 (unsigned short)((EE_SCAMBASE / 2) +
6416 (unsigned short)(i *
6417 ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
6418 }
6419 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006420
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006421 FPT_utilEEWrite(p_port, sum_data, EEPROM_CHECK_SUM / 2);
6422 FPT_utilEEWriteOnOff(p_port, 0); /* Turn off write access */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006423}
Linus Torvalds1da177e2005-04-16 15:20:36 -07006424
6425/*---------------------------------------------------------------------
6426 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006427 * Function: FPT_XbowInit
Linus Torvalds1da177e2005-04-16 15:20:36 -07006428 *
6429 * Description: Setup the Xbow for normal operation.
6430 *
6431 *---------------------------------------------------------------------*/
6432
Khalid Aziz391e2f22013-05-16 19:44:14 -06006433static void FPT_XbowInit(u32 port, unsigned char ScamFlg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006434{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006435 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006436
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006437 i = RD_HARPOON(port + hp_page_ctrl);
6438 WR_HARPOON(port + hp_page_ctrl, (unsigned char)(i | G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006439
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006440 WR_HARPOON(port + hp_scsireset, 0x00);
6441 WR_HARPOON(port + hp_portctrl_1, HOST_MODE8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006442
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006443 WR_HARPOON(port + hp_scsireset, (DMA_RESET | HPSCSI_RESET | PROG_RESET |
6444 FIFO_CLR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006445
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006446 WR_HARPOON(port + hp_scsireset, SCSI_INI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006447
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006448 WR_HARPOON(port + hp_clkctrl_0, CLKCTRL_DEFAULT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006449
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006450 WR_HARPOON(port + hp_scsisig, 0x00); /* Clear any signals we might */
6451 WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006452
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006453 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006454
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006455 FPT_default_intena = RESET | RSEL | PROG_HLT | TIMEOUT |
6456 BUS_FREE | XFER_CNT_0 | AUTO_INT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006457
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006458 if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2))
James Bottomley 47b5d692005-04-24 02:38:05 -05006459 FPT_default_intena |= SCAM_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006460
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006461 WRW_HARPOON((port + hp_intena), FPT_default_intena);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006462
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006463 WR_HARPOON(port + hp_seltimeout, TO_290ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006464
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006465 /* Turn on SCSI_MODE8 for narrow cards to fix the
6466 strapping issue with the DUAL CHANNEL card */
6467 if (RD_HARPOON(port + hp_page_ctrl) & NARROW_SCSI_CARD)
6468 WR_HARPOON(port + hp_addstat, SCSI_MODE8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006469
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006470 WR_HARPOON(port + hp_page_ctrl, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006471
6472}
6473
Linus Torvalds1da177e2005-04-16 15:20:36 -07006474/*---------------------------------------------------------------------
6475 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006476 * Function: FPT_BusMasterInit
Linus Torvalds1da177e2005-04-16 15:20:36 -07006477 *
6478 * Description: Initialize the BusMaster for normal operations.
6479 *
6480 *---------------------------------------------------------------------*/
6481
Khalid Aziz391e2f22013-05-16 19:44:14 -06006482static void FPT_BusMasterInit(u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006483{
6484
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006485 WR_HARPOON(p_port + hp_sys_ctrl, DRVR_RST);
6486 WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006487
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006488 WR_HARPOON(p_port + hp_host_blk_cnt, XFER_BLK64);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006489
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006490 WR_HARPOON(p_port + hp_bm_ctrl, (BMCTRL_DEFAULT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006491
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006492 WR_HARPOON(p_port + hp_ee_ctrl, (SCSI_TERM_ENA_H));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006493
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006494 RD_HARPOON(p_port + hp_int_status); /*Clear interrupts. */
6495 WR_HARPOON(p_port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
6496 WR_HARPOON(p_port + hp_page_ctrl, (RD_HARPOON(p_port + hp_page_ctrl) &
6497 ~SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006498}
6499
Linus Torvalds1da177e2005-04-16 15:20:36 -07006500/*---------------------------------------------------------------------
6501 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006502 * Function: FPT_DiagEEPROM
Linus Torvalds1da177e2005-04-16 15:20:36 -07006503 *
6504 * Description: Verfiy checksum and 'Key' and initialize the EEPROM if
6505 * necessary.
6506 *
6507 *---------------------------------------------------------------------*/
6508
Khalid Aziz391e2f22013-05-16 19:44:14 -06006509static void FPT_DiagEEPROM(u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006510{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006511 unsigned short index, temp, max_wd_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006512
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006513 if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6514 max_wd_cnt = EEPROM_WD_CNT;
6515 else
6516 max_wd_cnt = EEPROM_WD_CNT * 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006517
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006518 temp = FPT_utilEERead(p_port, FW_SIGNATURE / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006519
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006520 if (temp == 0x4641) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006521
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006522 for (index = 2; index < max_wd_cnt; index++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006523
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006524 temp += FPT_utilEERead(p_port, index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006525
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006526 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006527
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006528 if (temp == FPT_utilEERead(p_port, EEPROM_CHECK_SUM / 2)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006529
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006530 return; /*EEPROM is Okay so return now! */
6531 }
6532 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006533
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006534 FPT_utilEEWriteOnOff(p_port, (unsigned char)1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006535
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006536 for (index = 0; index < max_wd_cnt; index++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006537
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006538 FPT_utilEEWrite(p_port, 0x0000, index);
6539 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006540
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006541 temp = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006542
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006543 FPT_utilEEWrite(p_port, 0x4641, FW_SIGNATURE / 2);
6544 temp += 0x4641;
6545 FPT_utilEEWrite(p_port, 0x3920, MODEL_NUMB_0 / 2);
6546 temp += 0x3920;
6547 FPT_utilEEWrite(p_port, 0x3033, MODEL_NUMB_2 / 2);
6548 temp += 0x3033;
6549 FPT_utilEEWrite(p_port, 0x2020, MODEL_NUMB_4 / 2);
6550 temp += 0x2020;
6551 FPT_utilEEWrite(p_port, 0x70D3, SYSTEM_CONFIG / 2);
6552 temp += 0x70D3;
6553 FPT_utilEEWrite(p_port, 0x0010, BIOS_CONFIG / 2);
6554 temp += 0x0010;
6555 FPT_utilEEWrite(p_port, 0x0003, SCAM_CONFIG / 2);
6556 temp += 0x0003;
6557 FPT_utilEEWrite(p_port, 0x0007, ADAPTER_SCSI_ID / 2);
6558 temp += 0x0007;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006559
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006560 FPT_utilEEWrite(p_port, 0x0000, IGNORE_B_SCAN / 2);
6561 temp += 0x0000;
6562 FPT_utilEEWrite(p_port, 0x0000, SEND_START_ENA / 2);
6563 temp += 0x0000;
6564 FPT_utilEEWrite(p_port, 0x0000, DEVICE_ENABLE / 2);
6565 temp += 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006566
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006567 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL01 / 2);
6568 temp += 0x4242;
6569 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL23 / 2);
6570 temp += 0x4242;
6571 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL45 / 2);
6572 temp += 0x4242;
6573 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL67 / 2);
6574 temp += 0x4242;
6575 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL89 / 2);
6576 temp += 0x4242;
6577 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLab / 2);
6578 temp += 0x4242;
6579 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLcd / 2);
6580 temp += 0x4242;
6581 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLef / 2);
6582 temp += 0x4242;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006583
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006584 FPT_utilEEWrite(p_port, 0x6C46, 64 / 2); /*PRODUCT ID */
6585 temp += 0x6C46;
6586 FPT_utilEEWrite(p_port, 0x7361, 66 / 2); /* FlashPoint LT */
6587 temp += 0x7361;
6588 FPT_utilEEWrite(p_port, 0x5068, 68 / 2);
6589 temp += 0x5068;
6590 FPT_utilEEWrite(p_port, 0x696F, 70 / 2);
6591 temp += 0x696F;
6592 FPT_utilEEWrite(p_port, 0x746E, 72 / 2);
6593 temp += 0x746E;
6594 FPT_utilEEWrite(p_port, 0x4C20, 74 / 2);
6595 temp += 0x4C20;
6596 FPT_utilEEWrite(p_port, 0x2054, 76 / 2);
6597 temp += 0x2054;
6598 FPT_utilEEWrite(p_port, 0x2020, 78 / 2);
6599 temp += 0x2020;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006600
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006601 index = ((EE_SCAMBASE / 2) + (7 * 16));
6602 FPT_utilEEWrite(p_port, (0x0700 + TYPE_CODE0), index);
6603 temp += (0x0700 + TYPE_CODE0);
6604 index++;
6605 FPT_utilEEWrite(p_port, 0x5542, index); /*Vendor ID code */
6606 temp += 0x5542; /* BUSLOGIC */
6607 index++;
6608 FPT_utilEEWrite(p_port, 0x4C53, index);
6609 temp += 0x4C53;
6610 index++;
6611 FPT_utilEEWrite(p_port, 0x474F, index);
6612 temp += 0x474F;
6613 index++;
6614 FPT_utilEEWrite(p_port, 0x4349, index);
6615 temp += 0x4349;
6616 index++;
6617 FPT_utilEEWrite(p_port, 0x5442, index); /*Vendor unique code */
6618 temp += 0x5442; /* BT- 930 */
6619 index++;
6620 FPT_utilEEWrite(p_port, 0x202D, index);
6621 temp += 0x202D;
6622 index++;
6623 FPT_utilEEWrite(p_port, 0x3339, index);
6624 temp += 0x3339;
6625 index++; /*Serial # */
6626 FPT_utilEEWrite(p_port, 0x2030, index); /* 01234567 */
6627 temp += 0x2030;
6628 index++;
6629 FPT_utilEEWrite(p_port, 0x5453, index);
6630 temp += 0x5453;
6631 index++;
6632 FPT_utilEEWrite(p_port, 0x5645, index);
6633 temp += 0x5645;
6634 index++;
6635 FPT_utilEEWrite(p_port, 0x2045, index);
6636 temp += 0x2045;
6637 index++;
6638 FPT_utilEEWrite(p_port, 0x202F, index);
6639 temp += 0x202F;
6640 index++;
6641 FPT_utilEEWrite(p_port, 0x4F4A, index);
6642 temp += 0x4F4A;
6643 index++;
6644 FPT_utilEEWrite(p_port, 0x204E, index);
6645 temp += 0x204E;
6646 index++;
6647 FPT_utilEEWrite(p_port, 0x3539, index);
6648 temp += 0x3539;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006649
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006650 FPT_utilEEWrite(p_port, temp, EEPROM_CHECK_SUM / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006651
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006652 FPT_utilEEWriteOnOff(p_port, (unsigned char)0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006653
6654}
6655
Linus Torvalds1da177e2005-04-16 15:20:36 -07006656/*---------------------------------------------------------------------
6657 *
6658 * Function: Queue Search Select
6659 *
6660 * Description: Try to find a new command to execute.
6661 *
6662 *---------------------------------------------------------------------*/
6663
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006664static void FPT_queueSearchSelect(struct sccb_card *pCurrCard,
6665 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006666{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006667 unsigned char scan_ptr, lun;
6668 struct sccb_mgr_tar_info *currTar_Info;
6669 struct sccb *pOldSccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006670
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006671 scan_ptr = pCurrCard->scanIndex;
6672 do {
James Bottomley 47b5d692005-04-24 02:38:05 -05006673 currTar_Info = &FPT_sccbMgrTbl[p_card][scan_ptr];
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006674 if ((pCurrCard->globalFlags & F_CONLUN_IO) &&
6675 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
6676 TAG_Q_TRYING)) {
6677 if (currTar_Info->TarSelQ_Cnt != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006678
6679 scan_ptr++;
6680 if (scan_ptr == MAX_SCSI_TAR)
6681 scan_ptr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006682
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006683 for (lun = 0; lun < MAX_LUN; lun++) {
6684 if (currTar_Info->TarLUNBusy[lun] == 0) {
6685
6686 pCurrCard->currentSCCB =
6687 currTar_Info->TarSelQ_Head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006688 pOldSccb = NULL;
6689
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006690 while ((pCurrCard->
6691 currentSCCB != NULL)
6692 && (lun !=
6693 pCurrCard->
6694 currentSCCB->Lun)) {
6695 pOldSccb =
6696 pCurrCard->
6697 currentSCCB;
6698 pCurrCard->currentSCCB =
6699 (struct sccb
6700 *)(pCurrCard->
6701 currentSCCB)->
6702 Sccb_forwardlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006703 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006704 if (pCurrCard->currentSCCB ==
6705 NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006706 continue;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006707 if (pOldSccb != NULL) {
6708 pOldSccb->
6709 Sccb_forwardlink =
6710 (struct sccb
6711 *)(pCurrCard->
6712 currentSCCB)->
6713 Sccb_forwardlink;
6714 pOldSccb->
6715 Sccb_backlink =
6716 (struct sccb
6717 *)(pCurrCard->
6718 currentSCCB)->
6719 Sccb_backlink;
6720 currTar_Info->
6721 TarSelQ_Cnt--;
6722 } else {
6723 currTar_Info->
6724 TarSelQ_Head =
6725 (struct sccb
6726 *)(pCurrCard->
6727 currentSCCB)->
6728 Sccb_forwardlink;
6729
6730 if (currTar_Info->
6731 TarSelQ_Head ==
6732 NULL) {
6733 currTar_Info->
6734 TarSelQ_Tail
6735 = NULL;
6736 currTar_Info->
6737 TarSelQ_Cnt
6738 = 0;
6739 } else {
6740 currTar_Info->
6741 TarSelQ_Cnt--;
6742 currTar_Info->
6743 TarSelQ_Head->
6744 Sccb_backlink
6745 =
6746 (struct sccb
6747 *)NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006748 }
6749 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006750 pCurrCard->scanIndex = scan_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006751
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006752 pCurrCard->globalFlags |=
6753 F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006754
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006755 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006756 }
6757 }
6758 }
6759
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006760 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006761 scan_ptr++;
6762 if (scan_ptr == MAX_SCSI_TAR) {
6763 scan_ptr = 0;
6764 }
6765 }
6766
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006767 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006768 if ((currTar_Info->TarSelQ_Cnt != 0) &&
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006769 (currTar_Info->TarLUNBusy[0] == 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006770
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006771 pCurrCard->currentSCCB =
6772 currTar_Info->TarSelQ_Head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006773
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006774 currTar_Info->TarSelQ_Head =
6775 (struct sccb *)(pCurrCard->currentSCCB)->
6776 Sccb_forwardlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006777
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006778 if (currTar_Info->TarSelQ_Head == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006779 currTar_Info->TarSelQ_Tail = NULL;
6780 currTar_Info->TarSelQ_Cnt = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006781 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006782 currTar_Info->TarSelQ_Cnt--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006783 currTar_Info->TarSelQ_Head->
6784 Sccb_backlink = (struct sccb *)NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006785 }
6786
6787 scan_ptr++;
6788 if (scan_ptr == MAX_SCSI_TAR)
6789 scan_ptr = 0;
6790
6791 pCurrCard->scanIndex = scan_ptr;
6792
6793 pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
6794
6795 break;
6796 }
6797
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006798 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006799 scan_ptr++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006800 if (scan_ptr == MAX_SCSI_TAR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006801 scan_ptr = 0;
6802 }
6803 }
6804 }
6805 } while (scan_ptr != pCurrCard->scanIndex);
6806}
6807
Linus Torvalds1da177e2005-04-16 15:20:36 -07006808/*---------------------------------------------------------------------
6809 *
6810 * Function: Queue Select Fail
6811 *
6812 * Description: Add the current SCCB to the head of the Queue.
6813 *
6814 *---------------------------------------------------------------------*/
6815
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006816static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
6817 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006818{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006819 unsigned char thisTarg;
6820 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006821
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006822 if (pCurrCard->currentSCCB != NULL) {
6823 thisTarg =
6824 (unsigned char)(((struct sccb *)(pCurrCard->currentSCCB))->
6825 TargID);
6826 currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006827
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006828 pCurrCard->currentSCCB->Sccb_backlink = (struct sccb *)NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006829
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006830 pCurrCard->currentSCCB->Sccb_forwardlink =
6831 currTar_Info->TarSelQ_Head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006832
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006833 if (currTar_Info->TarSelQ_Cnt == 0) {
6834 currTar_Info->TarSelQ_Tail = pCurrCard->currentSCCB;
6835 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006836
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006837 else {
6838 currTar_Info->TarSelQ_Head->Sccb_backlink =
6839 pCurrCard->currentSCCB;
6840 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006841
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006842 currTar_Info->TarSelQ_Head = pCurrCard->currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006843
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006844 pCurrCard->currentSCCB = NULL;
6845 currTar_Info->TarSelQ_Cnt++;
6846 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006847}
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006848
Linus Torvalds1da177e2005-04-16 15:20:36 -07006849/*---------------------------------------------------------------------
6850 *
6851 * Function: Queue Command Complete
6852 *
6853 * Description: Call the callback function with the current SCCB.
6854 *
6855 *---------------------------------------------------------------------*/
6856
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006857static void FPT_queueCmdComplete(struct sccb_card *pCurrCard,
6858 struct sccb *p_sccb, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006859{
6860
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006861 unsigned char i, SCSIcmd;
6862 CALL_BK_FN callback;
6863 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006864
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006865 SCSIcmd = p_sccb->Cdb[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006866
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006867 if (!(p_sccb->Sccb_XferState & F_ALL_XFERRED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006868
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006869 if ((p_sccb->
6870 ControlByte & (SCCB_DATA_XFER_OUT | SCCB_DATA_XFER_IN))
6871 && (p_sccb->HostStatus == SCCB_COMPLETE)
6872 && (p_sccb->TargetStatus != SSCHECK))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006873
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006874 if ((SCSIcmd == SCSI_READ) ||
6875 (SCSIcmd == SCSI_WRITE) ||
6876 (SCSIcmd == SCSI_READ_EXTENDED) ||
6877 (SCSIcmd == SCSI_WRITE_EXTENDED) ||
6878 (SCSIcmd == SCSI_WRITE_AND_VERIFY) ||
6879 (SCSIcmd == SCSI_START_STOP_UNIT) ||
6880 (pCurrCard->globalFlags & F_NO_FILTER)
6881 )
6882 p_sccb->HostStatus = SCCB_DATA_UNDER_RUN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006883 }
6884
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006885 if (p_sccb->SccbStatus == SCCB_IN_PROCESS) {
6886 if (p_sccb->HostStatus || p_sccb->TargetStatus)
6887 p_sccb->SccbStatus = SCCB_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006888 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006889 p_sccb->SccbStatus = SCCB_SUCCESS;
6890 }
6891
6892 if (p_sccb->Sccb_XferState & F_AUTO_SENSE) {
6893
6894 p_sccb->CdbLength = p_sccb->Save_CdbLen;
6895 for (i = 0; i < 6; i++) {
6896 p_sccb->Cdb[i] = p_sccb->Save_Cdb[i];
6897 }
6898 }
6899
6900 if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) ||
6901 (p_sccb->OperationCode == RESIDUAL_COMMAND)) {
6902
6903 FPT_utilUpdateResidual(p_sccb);
6904 }
6905
6906 pCurrCard->cmdCounter--;
6907 if (!pCurrCard->cmdCounter) {
6908
6909 if (pCurrCard->globalFlags & F_GREEN_PC) {
6910 WR_HARPOON(pCurrCard->ioPort + hp_clkctrl_0,
6911 (PWR_DWN | CLKCTRL_DEFAULT));
6912 WR_HARPOON(pCurrCard->ioPort + hp_sys_ctrl, STOP_CLK);
6913 }
6914
6915 WR_HARPOON(pCurrCard->ioPort + hp_semaphore,
6916 (RD_HARPOON(pCurrCard->ioPort + hp_semaphore) &
6917 ~SCCB_MGR_ACTIVE));
6918
6919 }
6920
6921 if (pCurrCard->discQCount != 0) {
6922 currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
6923 if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
6924 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
6925 TAG_Q_TRYING))) {
6926 pCurrCard->discQCount--;
6927 pCurrCard->discQ_Tbl[currTar_Info->
6928 LunDiscQ_Idx[p_sccb->Lun]] = NULL;
6929 } else {
6930 if (p_sccb->Sccb_tag) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006931 pCurrCard->discQCount--;
6932 pCurrCard->discQ_Tbl[p_sccb->Sccb_tag] = NULL;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006933 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006934 pCurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006935 pCurrCard->discQ_Tbl[currTar_Info->
6936 LunDiscQ_Idx[0]] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006937 }
6938 }
6939
6940 }
6941
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006942 callback = (CALL_BK_FN) p_sccb->SccbCallback;
6943 callback(p_sccb);
6944 pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
6945 pCurrCard->currentSCCB = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006946}
Linus Torvalds1da177e2005-04-16 15:20:36 -07006947
Linus Torvalds1da177e2005-04-16 15:20:36 -07006948/*---------------------------------------------------------------------
6949 *
6950 * Function: Queue Disconnect
6951 *
6952 * Description: Add SCCB to our disconnect array.
6953 *
6954 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006955static void FPT_queueDisconnect(struct sccb *p_sccb, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006956{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006957 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006958
James Bottomley 47b5d692005-04-24 02:38:05 -05006959 currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006960
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006961 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
6962 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
6963 FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
6964 LunDiscQ_Idx[p_sccb->Lun]] =
6965 p_sccb;
6966 } else {
6967 if (p_sccb->Sccb_tag) {
6968 FPT_BL_Card[p_card].discQ_Tbl[p_sccb->Sccb_tag] =
6969 p_sccb;
6970 FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarLUNBusy[0] =
6971 0;
James Bottomley 47b5d692005-04-24 02:38:05 -05006972 FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarTagQ_Cnt++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006973 } else {
6974 FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
6975 LunDiscQ_Idx[0]] = p_sccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006976 }
6977 }
James Bottomley 47b5d692005-04-24 02:38:05 -05006978 FPT_BL_Card[p_card].currentSCCB = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006979}
6980
Linus Torvalds1da177e2005-04-16 15:20:36 -07006981/*---------------------------------------------------------------------
6982 *
6983 * Function: Queue Flush SCCB
6984 *
6985 * Description: Flush all SCCB's back to the host driver for this target.
6986 *
6987 *---------------------------------------------------------------------*/
6988
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006989static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006990{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006991 unsigned char qtag, thisTarg;
6992 struct sccb *currSCCB;
6993 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006994
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006995 currSCCB = FPT_BL_Card[p_card].currentSCCB;
6996 if (currSCCB != NULL) {
6997 thisTarg = (unsigned char)currSCCB->TargID;
6998 currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006999
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007000 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007001
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007002 if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
7003 (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
7004 thisTarg)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007005
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007006 FPT_BL_Card[p_card].discQ_Tbl[qtag]->
7007 HostStatus = (unsigned char)error_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007008
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007009 FPT_queueCmdComplete(&FPT_BL_Card[p_card],
7010 FPT_BL_Card[p_card].
7011 discQ_Tbl[qtag], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007012
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007013 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
7014 currTar_Info->TarTagQ_Cnt--;
7015
7016 }
7017 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007018 }
7019
7020}
7021
7022/*---------------------------------------------------------------------
7023 *
7024 * Function: Queue Flush Target SCCB
7025 *
7026 * Description: Flush all SCCB's back to the host driver for this target.
7027 *
7028 *---------------------------------------------------------------------*/
7029
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007030static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
7031 unsigned char error_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007032{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007033 unsigned char qtag;
7034 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007035
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007036 currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007037
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007038 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007039
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007040 if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
7041 (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007042
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007043 FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus =
7044 (unsigned char)error_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007045
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007046 FPT_queueCmdComplete(&FPT_BL_Card[p_card],
7047 FPT_BL_Card[p_card].
7048 discQ_Tbl[qtag], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007049
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007050 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
7051 currTar_Info->TarTagQ_Cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007052
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007053 }
7054 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007055
7056}
7057
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007058static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007059{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007060 struct sccb_mgr_tar_info *currTar_Info;
7061 currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007062
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007063 p_SCCB->Sccb_forwardlink = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007064
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007065 p_SCCB->Sccb_backlink = currTar_Info->TarSelQ_Tail;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007066
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007067 if (currTar_Info->TarSelQ_Cnt == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007068
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007069 currTar_Info->TarSelQ_Head = p_SCCB;
7070 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007071
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007072 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007073
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007074 currTar_Info->TarSelQ_Tail->Sccb_forwardlink = p_SCCB;
7075 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007076
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007077 currTar_Info->TarSelQ_Tail = p_SCCB;
7078 currTar_Info->TarSelQ_Cnt++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007079}
7080
Linus Torvalds1da177e2005-04-16 15:20:36 -07007081/*---------------------------------------------------------------------
7082 *
7083 * Function: Queue Find SCCB
7084 *
7085 * Description: Search the target select Queue for this SCCB, and
7086 * remove it if found.
7087 *
7088 *---------------------------------------------------------------------*/
7089
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007090static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB,
7091 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007092{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007093 struct sccb *q_ptr;
7094 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007095
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007096 currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007097
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007098 q_ptr = currTar_Info->TarSelQ_Head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007099
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007100 while (q_ptr != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007101
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007102 if (q_ptr == p_SCCB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007103
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007104 if (currTar_Info->TarSelQ_Head == q_ptr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007105
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007106 currTar_Info->TarSelQ_Head =
7107 q_ptr->Sccb_forwardlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007108 }
7109
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007110 if (currTar_Info->TarSelQ_Tail == q_ptr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007111
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007112 currTar_Info->TarSelQ_Tail =
7113 q_ptr->Sccb_backlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007114 }
7115
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007116 if (q_ptr->Sccb_forwardlink != NULL) {
7117 q_ptr->Sccb_forwardlink->Sccb_backlink =
7118 q_ptr->Sccb_backlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007119 }
7120
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007121 if (q_ptr->Sccb_backlink != NULL) {
7122 q_ptr->Sccb_backlink->Sccb_forwardlink =
7123 q_ptr->Sccb_forwardlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007124 }
7125
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007126 currTar_Info->TarSelQ_Cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007127
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007128 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007129 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007130
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007131 else {
7132 q_ptr = q_ptr->Sccb_forwardlink;
7133 }
7134 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007135
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007136 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007137
7138}
7139
Linus Torvalds1da177e2005-04-16 15:20:36 -07007140/*---------------------------------------------------------------------
7141 *
7142 * Function: Utility Update Residual Count
7143 *
7144 * Description: Update the XferCnt to the remaining byte count.
7145 * If we transferred all the data then just write zero.
7146 * If Non-SG transfer then report Total Cnt - Actual Transfer
7147 * Cnt. For SG transfers add the count fields of all
7148 * remaining SG elements, as well as any partial remaining
7149 * element.
7150 *
7151 *---------------------------------------------------------------------*/
7152
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007153static void FPT_utilUpdateResidual(struct sccb *p_SCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007154{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007155 unsigned long partial_cnt;
7156 unsigned int sg_index;
Khalid Aziz391e2f22013-05-16 19:44:14 -06007157 struct blogic_sg_seg *segp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007158
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007159 if (p_SCCB->Sccb_XferState & F_ALL_XFERRED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007160
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007161 p_SCCB->DataLength = 0x0000;
7162 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007163
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007164 else if (p_SCCB->Sccb_XferState & F_SG_XFER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007165
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007166 partial_cnt = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007167
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007168 sg_index = p_SCCB->Sccb_sgseg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007169
Linus Torvalds1da177e2005-04-16 15:20:36 -07007170
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007171 if (p_SCCB->Sccb_SGoffset) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007172
7173 partial_cnt = p_SCCB->Sccb_SGoffset;
7174 sg_index++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007175 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007176
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007177 while (((unsigned long)sg_index *
7178 (unsigned long)SG_ELEMENT_SIZE) < p_SCCB->DataLength) {
Khalid Aziz391e2f22013-05-16 19:44:14 -06007179 segp = (struct blogic_sg_seg *)(p_SCCB->DataPointer) +
7180 (sg_index * 2);
7181 partial_cnt += segp->segbytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007182 sg_index++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007183 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007184
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007185 p_SCCB->DataLength = partial_cnt;
7186 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007187
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007188 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007189
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007190 p_SCCB->DataLength -= p_SCCB->Sccb_ATC;
7191 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007192}
7193
Linus Torvalds1da177e2005-04-16 15:20:36 -07007194/*---------------------------------------------------------------------
7195 *
7196 * Function: Wait 1 Second
7197 *
7198 * Description: Wait for 1 second.
7199 *
7200 *---------------------------------------------------------------------*/
7201
Khalid Aziz391e2f22013-05-16 19:44:14 -06007202static void FPT_Wait1Second(u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007203{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007204 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007205
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007206 for (i = 0; i < 4; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007207
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007208 FPT_Wait(p_port, TO_250ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007209
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007210 if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
7211 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007212
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007213 if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
7214 break;
7215 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007216}
7217
Linus Torvalds1da177e2005-04-16 15:20:36 -07007218/*---------------------------------------------------------------------
7219 *
James Bottomley 47b5d692005-04-24 02:38:05 -05007220 * Function: FPT_Wait
Linus Torvalds1da177e2005-04-16 15:20:36 -07007221 *
7222 * Description: Wait the desired delay.
7223 *
7224 *---------------------------------------------------------------------*/
7225
Khalid Aziz391e2f22013-05-16 19:44:14 -06007226static void FPT_Wait(u32 p_port, unsigned char p_delay)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007227{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007228 unsigned char old_timer;
7229 unsigned char green_flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007230
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007231 old_timer = RD_HARPOON(p_port + hp_seltimeout);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007232
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007233 green_flag = RD_HARPOON(p_port + hp_clkctrl_0);
7234 WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007235
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007236 WR_HARPOON(p_port + hp_seltimeout, p_delay);
7237 WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
7238 WRW_HARPOON((p_port + hp_intena), (FPT_default_intena & ~TIMEOUT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007239
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007240 WR_HARPOON(p_port + hp_portctrl_0,
7241 (RD_HARPOON(p_port + hp_portctrl_0) | START_TO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007242
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007243 while (!(RDW_HARPOON((p_port + hp_intstat)) & TIMEOUT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007244
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007245 if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
7246 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007247
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007248 if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
7249 break;
7250 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007251
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007252 WR_HARPOON(p_port + hp_portctrl_0,
7253 (RD_HARPOON(p_port + hp_portctrl_0) & ~START_TO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007254
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007255 WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
7256 WRW_HARPOON((p_port + hp_intena), FPT_default_intena);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007257
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007258 WR_HARPOON(p_port + hp_clkctrl_0, green_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007259
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007260 WR_HARPOON(p_port + hp_seltimeout, old_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007261}
7262
Linus Torvalds1da177e2005-04-16 15:20:36 -07007263/*---------------------------------------------------------------------
7264 *
7265 * Function: Enable/Disable Write to EEPROM
7266 *
7267 * Description: The EEPROM must first be enabled for writes
7268 * A total of 9 clocks are needed.
7269 *
7270 *---------------------------------------------------------------------*/
7271
Khalid Aziz391e2f22013-05-16 19:44:14 -06007272static void FPT_utilEEWriteOnOff(u32 p_port, unsigned char p_mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007273{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007274 unsigned char ee_value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007275
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007276 ee_value =
7277 (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
7278 (EXT_ARB_ACK | SCSI_TERM_ENA_H));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007279
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007280 if (p_mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007281
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007282 FPT_utilEESendCmdAddr(p_port, EWEN, EWEN_ADDR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007283
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007284 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07007285
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007286 FPT_utilEESendCmdAddr(p_port, EWDS, EWDS_ADDR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007287
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007288 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */
7289 WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /*Turn off Master Select */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007290}
7291
Linus Torvalds1da177e2005-04-16 15:20:36 -07007292/*---------------------------------------------------------------------
7293 *
7294 * Function: Write EEPROM
7295 *
7296 * Description: Write a word to the EEPROM at the specified
7297 * address.
7298 *
7299 *---------------------------------------------------------------------*/
7300
Khalid Aziz391e2f22013-05-16 19:44:14 -06007301static void FPT_utilEEWrite(u32 p_port, unsigned short ee_data,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007302 unsigned short ee_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007303{
7304
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007305 unsigned char ee_value;
7306 unsigned short i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007307
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007308 ee_value =
7309 (unsigned
7310 char)((RD_HARPOON(p_port + hp_ee_ctrl) &
7311 (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007312
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007313 FPT_utilEESendCmdAddr(p_port, EE_WRITE, ee_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007314
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007315 ee_value |= (SEE_MS + SEE_CS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007316
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007317 for (i = 0x8000; i != 0; i >>= 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007318
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007319 if (i & ee_data)
7320 ee_value |= SEE_DO;
7321 else
7322 ee_value &= ~SEE_DO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007323
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007324 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7325 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7326 ee_value |= SEE_CLK; /* Clock data! */
7327 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7328 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7329 ee_value &= ~SEE_CLK;
7330 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7331 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7332 }
7333 ee_value &= (EXT_ARB_ACK | SCSI_TERM_ENA_H);
7334 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007335
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007336 FPT_Wait(p_port, TO_10ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007337
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007338 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS | SEE_CS)); /* Set CS to EEPROM */
7339 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /* Turn off CS */
7340 WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /* Turn off Master Select */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007341}
7342
7343/*---------------------------------------------------------------------
7344 *
7345 * Function: Read EEPROM
7346 *
7347 * Description: Read a word from the EEPROM at the desired
7348 * address.
7349 *
7350 *---------------------------------------------------------------------*/
7351
Khalid Aziz391e2f22013-05-16 19:44:14 -06007352static unsigned short FPT_utilEERead(u32 p_port,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007353 unsigned short ee_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007354{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007355 unsigned short i, ee_data1, ee_data2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007356
7357 i = 0;
James Bottomley 47b5d692005-04-24 02:38:05 -05007358 ee_data1 = FPT_utilEEReadOrg(p_port, ee_addr);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007359 do {
James Bottomley 47b5d692005-04-24 02:38:05 -05007360 ee_data2 = FPT_utilEEReadOrg(p_port, ee_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007361
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007362 if (ee_data1 == ee_data2)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007363 return ee_data1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007364
7365 ee_data1 = ee_data2;
7366 i++;
7367
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007368 } while (i < 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007369
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007370 return ee_data1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007371}
7372
7373/*---------------------------------------------------------------------
7374 *
7375 * Function: Read EEPROM Original
7376 *
7377 * Description: Read a word from the EEPROM at the desired
7378 * address.
7379 *
7380 *---------------------------------------------------------------------*/
7381
Khalid Aziz391e2f22013-05-16 19:44:14 -06007382static unsigned short FPT_utilEEReadOrg(u32 p_port, unsigned short ee_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007383{
7384
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007385 unsigned char ee_value;
7386 unsigned short i, ee_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007387
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007388 ee_value =
7389 (unsigned
7390 char)((RD_HARPOON(p_port + hp_ee_ctrl) &
7391 (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007392
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007393 FPT_utilEESendCmdAddr(p_port, EE_READ, ee_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007394
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007395 ee_value |= (SEE_MS + SEE_CS);
7396 ee_data = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007397
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007398 for (i = 1; i <= 16; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007399
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007400 ee_value |= SEE_CLK; /* Clock data! */
7401 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7402 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7403 ee_value &= ~SEE_CLK;
7404 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7405 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007406
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007407 ee_data <<= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007408
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007409 if (RD_HARPOON(p_port + hp_ee_ctrl) & SEE_DI)
7410 ee_data |= 1;
7411 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007412
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007413 ee_value &= ~(SEE_MS + SEE_CS);
7414 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */
7415 WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /*Turn off Master Select */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007416
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007417 return ee_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007418}
7419
Linus Torvalds1da177e2005-04-16 15:20:36 -07007420/*---------------------------------------------------------------------
7421 *
7422 * Function: Send EE command and Address to the EEPROM
7423 *
7424 * Description: Transfers the correct command and sends the address
7425 * to the eeprom.
7426 *
7427 *---------------------------------------------------------------------*/
7428
Khalid Aziz391e2f22013-05-16 19:44:14 -06007429static void FPT_utilEESendCmdAddr(u32 p_port, unsigned char ee_cmd,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007430 unsigned short ee_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007431{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007432 unsigned char ee_value;
7433 unsigned char narrow_flg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007434
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007435 unsigned short i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007436
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007437 narrow_flg =
7438 (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
7439 NARROW_SCSI_CARD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007440
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007441 ee_value = SEE_MS;
7442 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007443
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007444 ee_value |= SEE_CS; /* Set CS to EEPROM */
7445 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007446
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007447 for (i = 0x04; i != 0; i >>= 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007448
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007449 if (i & ee_cmd)
7450 ee_value |= SEE_DO;
7451 else
7452 ee_value &= ~SEE_DO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007453
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007454 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7455 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7456 ee_value |= SEE_CLK; /* Clock data! */
7457 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7458 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7459 ee_value &= ~SEE_CLK;
7460 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7461 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7462 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007463
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007464 if (narrow_flg)
7465 i = 0x0080;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007466
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007467 else
7468 i = 0x0200;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007469
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007470 while (i != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007471
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007472 if (i & ee_addr)
7473 ee_value |= SEE_DO;
7474 else
7475 ee_value &= ~SEE_DO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007476
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007477 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7478 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7479 ee_value |= SEE_CLK; /* Clock data! */
7480 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7481 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7482 ee_value &= ~SEE_CLK;
7483 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7484 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007485
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007486 i >>= 1;
7487 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007488}
7489
Alexey Dobriyanc823fee2006-03-08 00:14:25 -08007490static unsigned short FPT_CalcCrc16(unsigned char buffer[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07007491{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007492 unsigned short crc = 0;
7493 int i, j;
7494 unsigned short ch;
7495 for (i = 0; i < ID_STRING_LENGTH; i++) {
7496 ch = (unsigned short)buffer[i];
7497 for (j = 0; j < 8; j++) {
7498 if ((crc ^ ch) & 1)
7499 crc = (crc >> 1) ^ CRCMASK;
7500 else
7501 crc >>= 1;
7502 ch >>= 1;
7503 }
7504 }
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007505 return crc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007506}
7507
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08007508static unsigned char FPT_CalcLrc(unsigned char buffer[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07007509{
7510 int i;
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08007511 unsigned char lrc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007512 lrc = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007513 for (i = 0; i < ID_STRING_LENGTH; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007514 lrc ^= buffer[i];
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007515 return lrc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007516}
7517
Linus Torvalds1da177e2005-04-16 15:20:36 -07007518/*
7519 The following inline definitions avoid type conflicts.
7520*/
7521
7522static inline unsigned char
Khalid Aziz839cb992013-05-16 19:44:13 -06007523FlashPoint__ProbeHostAdapter(struct fpoint_info *FlashPointInfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007524{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007525 return FlashPoint_ProbeHostAdapter((struct sccb_mgr_info *)
7526 FlashPointInfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007527}
7528
Khalid Aziz391e2f22013-05-16 19:44:14 -06007529static inline void *
Khalid Aziz839cb992013-05-16 19:44:13 -06007530FlashPoint__HardwareResetHostAdapter(struct fpoint_info *FlashPointInfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007531{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007532 return FlashPoint_HardwareResetHostAdapter((struct sccb_mgr_info *)
7533 FlashPointInfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007534}
7535
7536static inline void
Khalid Aziz391e2f22013-05-16 19:44:14 -06007537FlashPoint__ReleaseHostAdapter(void *CardHandle)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007538{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007539 FlashPoint_ReleaseHostAdapter(CardHandle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007540}
7541
Linus Torvalds1da177e2005-04-16 15:20:36 -07007542static inline void
Khalid Aziz391e2f22013-05-16 19:44:14 -06007543FlashPoint__StartCCB(void *CardHandle, struct blogic_ccb *CCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007544{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007545 FlashPoint_StartCCB(CardHandle, (struct sccb *)CCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007546}
7547
Linus Torvalds1da177e2005-04-16 15:20:36 -07007548static inline void
Khalid Aziz391e2f22013-05-16 19:44:14 -06007549FlashPoint__AbortCCB(void *CardHandle, struct blogic_ccb *CCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007550{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007551 FlashPoint_AbortCCB(CardHandle, (struct sccb *)CCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007552}
7553
Richard Knutsson2065e312007-02-05 16:39:01 -08007554static inline bool
Khalid Aziz391e2f22013-05-16 19:44:14 -06007555FlashPoint__InterruptPending(void *CardHandle)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007556{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007557 return FlashPoint_InterruptPending(CardHandle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007558}
7559
Linus Torvalds1da177e2005-04-16 15:20:36 -07007560static inline int
Khalid Aziz391e2f22013-05-16 19:44:14 -06007561FlashPoint__HandleInterrupt(void *CardHandle)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007562{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007563 return FlashPoint_HandleInterrupt(CardHandle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007564}
7565
Linus Torvalds1da177e2005-04-16 15:20:36 -07007566#define FlashPoint_ProbeHostAdapter FlashPoint__ProbeHostAdapter
7567#define FlashPoint_HardwareResetHostAdapter FlashPoint__HardwareResetHostAdapter
7568#define FlashPoint_ReleaseHostAdapter FlashPoint__ReleaseHostAdapter
7569#define FlashPoint_StartCCB FlashPoint__StartCCB
7570#define FlashPoint_AbortCCB FlashPoint__AbortCCB
7571#define FlashPoint_InterruptPending FlashPoint__InterruptPending
7572#define FlashPoint_HandleInterrupt FlashPoint__HandleInterrupt
7573
Matthew Wilcox78b4b052008-03-13 06:55:08 -06007574#else /* !CONFIG_SCSI_FLASHPOINT */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007575
7576/*
7577 Define prototypes for the FlashPoint SCCB Manager Functions.
7578*/
7579
Khalid Aziz839cb992013-05-16 19:44:13 -06007580extern unsigned char FlashPoint_ProbeHostAdapter(struct fpoint_info *);
Khalid Aziz391e2f22013-05-16 19:44:14 -06007581extern void *FlashPoint_HardwareResetHostAdapter(struct fpoint_info *);
7582extern void FlashPoint_StartCCB(void *, struct blogic_ccb *);
7583extern int FlashPoint_AbortCCB(void *, struct blogic_ccb *);
7584extern bool FlashPoint_InterruptPending(void *);
7585extern int FlashPoint_HandleInterrupt(void *);
7586extern void FlashPoint_ReleaseHostAdapter(void *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007587
Matthew Wilcox78b4b052008-03-13 06:55:08 -06007588#endif /* CONFIG_SCSI_FLASHPOINT */