blob: 24ace18240480a212137e277b3bfa864d90cb6b3 [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 Dobriyandb038cf82006-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 Dobriyandb038cf82006-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 Dobriyandb038cf82006-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 */
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001037 temp6 |= 0x8000;
1038 fallthrough;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001039 case AUTO_RATE_10: /* Synchronous, 10 mega-transfers/second */
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001040 temp5 |= 0x8000;
1041 fallthrough;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001042 case AUTO_RATE_05: /* Synchronous, 5 mega-transfers/second */
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001043 temp2 |= 0x8000;
1044 fallthrough;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001045 case AUTO_RATE_00: /* Asynchronous */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 break;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001047 }
1048
1049 if (temp & DISC_ENABLE_BIT)
1050 temp3 |= 0x8000;
1051
1052 if (temp & WIDE_NEGO_BIT)
1053 temp4 |= 0x8000;
1054
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 }
1057
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001058 pCardInfo->si_per_targ_init_sync = temp2;
1059 pCardInfo->si_per_targ_no_disc = temp3;
1060 pCardInfo->si_per_targ_wide_nego = temp4;
1061 pCardInfo->si_per_targ_fast_nego = temp5;
1062 pCardInfo->si_per_targ_ultra_nego = temp6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001064 if (pCurrNvRam)
1065 i = pCurrNvRam->niSysConf;
1066 else
1067 i = (unsigned
1068 char)(FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001070 if (pCurrNvRam)
1071 ScamFlg = pCurrNvRam->niScamConf;
1072 else
1073 ScamFlg =
1074 (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001075
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001076 pCardInfo->si_flags = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001078 if (i & 0x01)
1079 pCardInfo->si_flags |= SCSI_PARITY_ENA;
1080
1081 if (!(i & 0x02))
1082 pCardInfo->si_flags |= SOFT_RESET;
1083
1084 if (i & 0x10)
1085 pCardInfo->si_flags |= EXTENDED_TRANSLATION;
1086
1087 if (ScamFlg & SCAM_ENABLED)
1088 pCardInfo->si_flags |= FLAG_SCAM_ENABLED;
1089
1090 if (ScamFlg & SCAM_LEVEL2)
1091 pCardInfo->si_flags |= FLAG_SCAM_LEVEL2;
1092
1093 j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
1094 if (i & 0x04) {
1095 j |= SCSI_TERM_ENA_L;
1096 }
1097 WR_HARPOON(ioport + hp_bm_ctrl, j);
1098
1099 j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
1100 if (i & 0x08) {
1101 j |= SCSI_TERM_ENA_H;
1102 }
1103 WR_HARPOON(ioport + hp_ee_ctrl, j);
1104
1105 if (!(RD_HARPOON(ioport + hp_page_ctrl) & NARROW_SCSI_CARD))
1106
1107 pCardInfo->si_flags |= SUPPORT_16TAR_32LUN;
1108
1109 pCardInfo->si_card_family = HARPOON_FAMILY;
1110 pCardInfo->si_bustype = BUSTYPE_PCI;
1111
1112 if (pCurrNvRam) {
1113 pCardInfo->si_card_model[0] = '9';
1114 switch (pCurrNvRam->niModel & 0x0f) {
1115 case MODEL_LT:
1116 pCardInfo->si_card_model[1] = '3';
1117 pCardInfo->si_card_model[2] = '0';
1118 break;
1119 case MODEL_LW:
1120 pCardInfo->si_card_model[1] = '5';
1121 pCardInfo->si_card_model[2] = '0';
1122 break;
1123 case MODEL_DL:
1124 pCardInfo->si_card_model[1] = '3';
1125 pCardInfo->si_card_model[2] = '2';
1126 break;
1127 case MODEL_DW:
1128 pCardInfo->si_card_model[1] = '5';
1129 pCardInfo->si_card_model[2] = '2';
1130 break;
1131 }
1132 } else {
1133 temp = FPT_utilEERead(ioport, (MODEL_NUMB_0 / 2));
1134 pCardInfo->si_card_model[0] = (unsigned char)(temp >> 8);
1135 temp = FPT_utilEERead(ioport, (MODEL_NUMB_2 / 2));
1136
1137 pCardInfo->si_card_model[1] = (unsigned char)(temp & 0x00FF);
1138 pCardInfo->si_card_model[2] = (unsigned char)(temp >> 8);
1139 }
1140
1141 if (pCardInfo->si_card_model[1] == '3') {
1142 if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
1143 pCardInfo->si_flags |= LOW_BYTE_TERM;
1144 } else if (pCardInfo->si_card_model[2] == '0') {
1145 temp = RD_HARPOON(ioport + hp_xfer_pad);
1146 WR_HARPOON(ioport + hp_xfer_pad, (temp & ~BIT(4)));
1147 if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
1148 pCardInfo->si_flags |= LOW_BYTE_TERM;
1149 WR_HARPOON(ioport + hp_xfer_pad, (temp | BIT(4)));
1150 if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
1151 pCardInfo->si_flags |= HIGH_BYTE_TERM;
1152 WR_HARPOON(ioport + hp_xfer_pad, temp);
1153 } else {
1154 temp = RD_HARPOON(ioport + hp_ee_ctrl);
1155 temp2 = RD_HARPOON(ioport + hp_xfer_pad);
1156 WR_HARPOON(ioport + hp_ee_ctrl, (temp | SEE_CS));
1157 WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4)));
1158 temp3 = 0;
1159 for (i = 0; i < 8; i++) {
1160 temp3 <<= 1;
1161 if (!(RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7)))
1162 temp3 |= 1;
1163 WR_HARPOON(ioport + hp_xfer_pad, (temp2 & ~BIT(4)));
1164 WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4)));
1165 }
1166 WR_HARPOON(ioport + hp_ee_ctrl, temp);
1167 WR_HARPOON(ioport + hp_xfer_pad, temp2);
1168 if (!(temp3 & BIT(7)))
1169 pCardInfo->si_flags |= LOW_BYTE_TERM;
1170 if (!(temp3 & BIT(6)))
1171 pCardInfo->si_flags |= HIGH_BYTE_TERM;
1172 }
1173
1174 ARAM_ACCESS(ioport);
1175
1176 for (i = 0; i < 4; i++) {
1177
1178 pCardInfo->si_XlatInfo[i] =
1179 RD_HARPOON(ioport + hp_aramBase + BIOS_DATA_OFFSET + i);
1180 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181
1182 /* return with -1 if no sort, else return with
1183 logical card number sorted by BIOS (zero-based) */
1184
1185 pCardInfo->si_relative_cardnum =
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001186 (unsigned
1187 char)(RD_HARPOON(ioport + hp_aramBase + BIOS_RELATIVE_CARD) - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001189 SGRAM_ACCESS(ioport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001191 FPT_s_PhaseTbl[0] = FPT_phaseDataOut;
1192 FPT_s_PhaseTbl[1] = FPT_phaseDataIn;
1193 FPT_s_PhaseTbl[2] = FPT_phaseIllegal;
1194 FPT_s_PhaseTbl[3] = FPT_phaseIllegal;
1195 FPT_s_PhaseTbl[4] = FPT_phaseCommand;
1196 FPT_s_PhaseTbl[5] = FPT_phaseStatus;
1197 FPT_s_PhaseTbl[6] = FPT_phaseMsgOut;
1198 FPT_s_PhaseTbl[7] = FPT_phaseMsgIn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001200 pCardInfo->si_present = 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001202 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203}
1204
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205/*---------------------------------------------------------------------
1206 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001207 * Function: FlashPoint_HardwareResetHostAdapter
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 *
1209 * Description: Setup adapter for normal operation (hard reset).
1210 *
1211 *---------------------------------------------------------------------*/
1212
Khalid Aziz391e2f22013-05-16 19:44:14 -06001213static void *FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001214 *pCardInfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001216 struct sccb_card *CurrCard = NULL;
1217 struct nvram_info *pCurrNvRam;
1218 unsigned char i, j, thisCard, ScamFlg;
1219 unsigned short temp, sync_bit_map, id;
Khalid Aziz391e2f22013-05-16 19:44:14 -06001220 u32 ioport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001222 ioport = pCardInfo->si_baseaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001224 for (thisCard = 0; thisCard <= MAX_CARDS; thisCard++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225
Khalid Aziz391e2f22013-05-16 19:44:14 -06001226 if (thisCard == MAX_CARDS)
1227 return (void *)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001229 if (FPT_BL_Card[thisCard].ioPort == ioport) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001231 CurrCard = &FPT_BL_Card[thisCard];
1232 FPT_SccbMgrTableInitCard(CurrCard, thisCard);
1233 break;
1234 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001236 else if (FPT_BL_Card[thisCard].ioPort == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001238 FPT_BL_Card[thisCard].ioPort = ioport;
1239 CurrCard = &FPT_BL_Card[thisCard];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001241 if (FPT_mbCards)
1242 for (i = 0; i < FPT_mbCards; i++) {
1243 if (CurrCard->ioPort ==
1244 FPT_nvRamInfo[i].niBaseAddr)
1245 CurrCard->pNvRamInfo =
1246 &FPT_nvRamInfo[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001248 FPT_SccbMgrTableInitCard(CurrCard, thisCard);
1249 CurrCard->cardIndex = thisCard;
1250 CurrCard->cardInfo = pCardInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001252 break;
1253 }
1254 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255
1256 pCurrNvRam = CurrCard->pNvRamInfo;
1257
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001258 if (pCurrNvRam) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 ScamFlg = pCurrNvRam->niScamConf;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001260 } else {
1261 ScamFlg =
1262 (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 }
1264
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001265 FPT_BusMasterInit(ioport);
1266 FPT_XbowInit(ioport, ScamFlg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001268 FPT_autoLoadDefaultMap(ioport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001270 for (i = 0, id = 0x01; i != pCardInfo->si_id; i++, id <<= 1) {
1271 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001273 WR_HARPOON(ioport + hp_selfid_0, id);
1274 WR_HARPOON(ioport + hp_selfid_1, 0x00);
1275 WR_HARPOON(ioport + hp_arb_id, pCardInfo->si_id);
1276 CurrCard->ourId = pCardInfo->si_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001278 i = (unsigned char)pCardInfo->si_flags;
1279 if (i & SCSI_PARITY_ENA)
1280 WR_HARPOON(ioport + hp_portctrl_1, (HOST_MODE8 | CHK_SCSI_P));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001282 j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
1283 if (i & LOW_BYTE_TERM)
1284 j |= SCSI_TERM_ENA_L;
1285 WR_HARPOON(ioport + hp_bm_ctrl, j);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001287 j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
1288 if (i & HIGH_BYTE_TERM)
1289 j |= SCSI_TERM_ENA_H;
1290 WR_HARPOON(ioport + hp_ee_ctrl, j);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001292 if (!(pCardInfo->si_flags & SOFT_RESET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001294 FPT_sresb(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001296 FPT_scini(thisCard, pCardInfo->si_id, 0);
1297 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001299 if (pCardInfo->si_flags & POST_ALL_UNDERRRUNS)
1300 CurrCard->globalFlags |= F_NO_FILTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001302 if (pCurrNvRam) {
1303 if (pCurrNvRam->niSysConf & 0x10)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 CurrCard->globalFlags |= F_GREEN_PC;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001305 } else {
1306 if (FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)) & GREEN_PC_ENA)
1307 CurrCard->globalFlags |= F_GREEN_PC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 }
1309
1310 /* Set global flag to indicate Re-Negotiation to be done on all
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001311 ckeck condition */
1312 if (pCurrNvRam) {
1313 if (pCurrNvRam->niScsiConf & 0x04)
1314 CurrCard->globalFlags |= F_DO_RENEGO;
1315 } else {
1316 if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & RENEGO_ENA)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 CurrCard->globalFlags |= F_DO_RENEGO;
1318 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001320 if (pCurrNvRam) {
1321 if (pCurrNvRam->niScsiConf & 0x08)
1322 CurrCard->globalFlags |= F_CONLUN_IO;
1323 } else {
1324 if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & CONNIO_ENA)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 CurrCard->globalFlags |= F_CONLUN_IO;
1326 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001327
1328 temp = pCardInfo->si_per_targ_no_disc;
1329
1330 for (i = 0, id = 1; i < MAX_SCSI_TAR; i++, id <<= 1) {
1331
1332 if (temp & id)
1333 FPT_sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 }
1335
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001336 sync_bit_map = 0x0001;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001338 for (id = 0; id < (MAX_SCSI_TAR / 2); id++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001340 if (pCurrNvRam) {
1341 temp = (unsigned short)pCurrNvRam->niSyncTbl[id];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342 temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001343 (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
1344 } else
1345 temp =
1346 FPT_utilEERead(ioport,
1347 (unsigned short)((SYNC_RATE_TBL / 2)
1348 + id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001350 for (i = 0; i < 2; temp >>= 8, i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001352 if (pCardInfo->si_per_targ_init_sync & sync_bit_map) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001354 FPT_sccbMgrTbl[thisCard][id * 2 +
1355 i].TarEEValue =
1356 (unsigned char)temp;
1357 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001359 else {
1360 FPT_sccbMgrTbl[thisCard][id * 2 +
1361 i].TarStatus |=
1362 SYNC_SUPPORTED;
1363 FPT_sccbMgrTbl[thisCard][id * 2 +
1364 i].TarEEValue =
1365 (unsigned char)(temp & ~EE_SYNC_MASK);
1366 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368/* if ((pCardInfo->si_per_targ_wide_nego & sync_bit_map) ||
1369 (id*2+i >= 8)){
1370*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001371 if (pCardInfo->si_per_targ_wide_nego & sync_bit_map) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001373 FPT_sccbMgrTbl[thisCard][id * 2 +
1374 i].TarEEValue |=
1375 EE_WIDE_SCSI;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001377 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001379 else { /* NARROW SCSI */
1380 FPT_sccbMgrTbl[thisCard][id * 2 +
1381 i].TarStatus |=
1382 WIDE_NEGOCIATED;
1383 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001385 sync_bit_map <<= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001387 }
1388 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001390 WR_HARPOON((ioport + hp_semaphore),
1391 (unsigned char)(RD_HARPOON((ioport + hp_semaphore)) |
1392 SCCB_MGR_PRESENT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393
Khalid Aziz391e2f22013-05-16 19:44:14 -06001394 return (void *)CurrCard;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395}
1396
Khalid Aziz391e2f22013-05-16 19:44:14 -06001397static void FlashPoint_ReleaseHostAdapter(void *pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398{
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08001399 unsigned char i;
Khalid Aziz391e2f22013-05-16 19:44:14 -06001400 u32 portBase;
1401 u32 regOffset;
1402 u32 scamData;
1403 u32 *pScamTbl;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001404 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001406 pCurrNvRam = ((struct sccb_card *)pCurrCard)->pNvRamInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001408 if (pCurrNvRam) {
James Bottomley 47b5d692005-04-24 02:38:05 -05001409 FPT_WrStack(pCurrNvRam->niBaseAddr, 0, pCurrNvRam->niModel);
1410 FPT_WrStack(pCurrNvRam->niBaseAddr, 1, pCurrNvRam->niSysConf);
1411 FPT_WrStack(pCurrNvRam->niBaseAddr, 2, pCurrNvRam->niScsiConf);
1412 FPT_WrStack(pCurrNvRam->niBaseAddr, 3, pCurrNvRam->niScamConf);
1413 FPT_WrStack(pCurrNvRam->niBaseAddr, 4, pCurrNvRam->niAdapId);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001415 for (i = 0; i < MAX_SCSI_TAR / 2; i++)
1416 FPT_WrStack(pCurrNvRam->niBaseAddr,
1417 (unsigned char)(i + 5),
1418 pCurrNvRam->niSyncTbl[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419
1420 portBase = pCurrNvRam->niBaseAddr;
1421
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001422 for (i = 0; i < MAX_SCSI_TAR; i++) {
1423 regOffset = hp_aramBase + 64 + i * 4;
Khalid Aziz391e2f22013-05-16 19:44:14 -06001424 pScamTbl = (u32 *)&pCurrNvRam->niScamTbl[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425 scamData = *pScamTbl;
1426 WR_HARP32(portBase, regOffset, scamData);
1427 }
1428
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001429 } else {
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001430 FPT_WrStack(((struct sccb_card *)pCurrCard)->ioPort, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 }
1432}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001434static void FPT_RNVRamData(struct nvram_info *pNvRamInfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435{
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08001436 unsigned char i;
Khalid Aziz391e2f22013-05-16 19:44:14 -06001437 u32 portBase;
1438 u32 regOffset;
1439 u32 scamData;
1440 u32 *pScamTbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001442 pNvRamInfo->niModel = FPT_RdStack(pNvRamInfo->niBaseAddr, 0);
1443 pNvRamInfo->niSysConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 1);
James Bottomley 47b5d692005-04-24 02:38:05 -05001444 pNvRamInfo->niScsiConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 2);
1445 pNvRamInfo->niScamConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 3);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001446 pNvRamInfo->niAdapId = FPT_RdStack(pNvRamInfo->niBaseAddr, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001448 for (i = 0; i < MAX_SCSI_TAR / 2; i++)
1449 pNvRamInfo->niSyncTbl[i] =
1450 FPT_RdStack(pNvRamInfo->niBaseAddr, (unsigned char)(i + 5));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451
1452 portBase = pNvRamInfo->niBaseAddr;
1453
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001454 for (i = 0; i < MAX_SCSI_TAR; i++) {
1455 regOffset = hp_aramBase + 64 + i * 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 RD_HARP32(portBase, regOffset, scamData);
Khalid Aziz391e2f22013-05-16 19:44:14 -06001457 pScamTbl = (u32 *)&pNvRamInfo->niScamTbl[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458 *pScamTbl = scamData;
1459 }
1460
1461}
1462
Khalid Aziz391e2f22013-05-16 19:44:14 -06001463static unsigned char FPT_RdStack(u32 portBase, unsigned char index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464{
1465 WR_HARPOON(portBase + hp_stack_addr, index);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001466 return RD_HARPOON(portBase + hp_stack_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467}
1468
Khalid Aziz391e2f22013-05-16 19:44:14 -06001469static void FPT_WrStack(u32 portBase, unsigned char index, unsigned char data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470{
1471 WR_HARPOON(portBase + hp_stack_addr, index);
1472 WR_HARPOON(portBase + hp_stack_data, data);
1473}
1474
Khalid Aziz391e2f22013-05-16 19:44:14 -06001475static unsigned char FPT_ChkIfChipInitialized(u32 ioPort)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001477 if ((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != FPT_RdStack(ioPort, 4))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001478 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001479 if ((RD_HARPOON(ioPort + hp_clkctrl_0) & CLKCTRL_DEFAULT)
1480 != CLKCTRL_DEFAULT)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001481 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001482 if ((RD_HARPOON(ioPort + hp_seltimeout) == TO_250ms) ||
1483 (RD_HARPOON(ioPort + hp_seltimeout) == TO_290ms))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001484 return 1;
1485 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486
1487}
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001488
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489/*---------------------------------------------------------------------
1490 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001491 * Function: FlashPoint_StartCCB
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492 *
1493 * Description: Start a command pointed to by p_Sccb. When the
1494 * command is completed it will be returned via the
1495 * callback function.
1496 *
1497 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06001498static void FlashPoint_StartCCB(void *curr_card, struct sccb *p_Sccb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499{
Khalid Aziz391e2f22013-05-16 19:44:14 -06001500 u32 ioport;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001501 unsigned char thisCard, lun;
1502 struct sccb *pSaveSccb;
1503 CALL_BK_FN callback;
Khalid Aziz391e2f22013-05-16 19:44:14 -06001504 struct sccb_card *pCurrCard = curr_card;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505
Khalid Aziz391e2f22013-05-16 19:44:14 -06001506 thisCard = pCurrCard->cardIndex;
1507 ioport = pCurrCard->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508
Adrian Bunk1377d8d2008-04-23 12:51:10 +03001509 if ((p_Sccb->TargID >= MAX_SCSI_TAR) || (p_Sccb->Lun >= MAX_LUN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 p_Sccb->HostStatus = SCCB_COMPLETE;
1512 p_Sccb->SccbStatus = SCCB_ERROR;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001513 callback = (CALL_BK_FN) p_Sccb->SccbCallback;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 if (callback)
1515 callback(p_Sccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 return;
1518 }
1519
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001520 FPT_sinits(p_Sccb, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521
Khalid Aziz391e2f22013-05-16 19:44:14 -06001522 if (!pCurrCard->cmdCounter) {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001523 WR_HARPOON(ioport + hp_semaphore,
1524 (RD_HARPOON(ioport + hp_semaphore)
1525 | SCCB_MGR_ACTIVE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526
Khalid Aziz391e2f22013-05-16 19:44:14 -06001527 if (pCurrCard->globalFlags & F_GREEN_PC) {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001528 WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT);
1529 WR_HARPOON(ioport + hp_sys_ctrl, 0x00);
1530 }
1531 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532
Khalid Aziz391e2f22013-05-16 19:44:14 -06001533 pCurrCard->cmdCounter++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001535 if (RD_HARPOON(ioport + hp_semaphore) & BIOS_IN_USE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001537 WR_HARPOON(ioport + hp_semaphore,
1538 (RD_HARPOON(ioport + hp_semaphore)
1539 | TICKLE_ME));
1540 if (p_Sccb->OperationCode == RESET_COMMAND) {
1541 pSaveSccb =
Khalid Aziz391e2f22013-05-16 19:44:14 -06001542 pCurrCard->currentSCCB;
1543 pCurrCard->currentSCCB = p_Sccb;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001544 FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
Khalid Aziz391e2f22013-05-16 19:44:14 -06001545 pCurrCard->currentSCCB =
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001546 pSaveSccb;
1547 } else {
1548 FPT_queueAddSccb(p_Sccb, thisCard);
1549 }
1550 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001552 else if ((RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001554 if (p_Sccb->OperationCode == RESET_COMMAND) {
1555 pSaveSccb =
Khalid Aziz391e2f22013-05-16 19:44:14 -06001556 pCurrCard->currentSCCB;
1557 pCurrCard->currentSCCB = p_Sccb;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001558 FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
Khalid Aziz391e2f22013-05-16 19:44:14 -06001559 pCurrCard->currentSCCB =
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001560 pSaveSccb;
1561 } else {
1562 FPT_queueAddSccb(p_Sccb, thisCard);
1563 }
1564 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001566 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001568 MDISABLE_INT(ioport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569
Khalid Aziz391e2f22013-05-16 19:44:14 -06001570 if ((pCurrCard->globalFlags & F_CONLUN_IO) &&
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001571 ((FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].
1572 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573 lun = p_Sccb->Lun;
1574 else
1575 lun = 0;
Khalid Aziz391e2f22013-05-16 19:44:14 -06001576 if ((pCurrCard->currentSCCB == NULL) &&
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001577 (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarSelQ_Cnt == 0)
1578 && (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarLUNBusy[lun]
1579 == 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580
Khalid Aziz391e2f22013-05-16 19:44:14 -06001581 pCurrCard->currentSCCB = p_Sccb;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001582 FPT_ssel(p_Sccb->SccbIOPort, thisCard);
1583 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001585 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001587 if (p_Sccb->OperationCode == RESET_COMMAND) {
Khalid Aziz391e2f22013-05-16 19:44:14 -06001588 pSaveSccb = pCurrCard->currentSCCB;
1589 pCurrCard->currentSCCB = p_Sccb;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001590 FPT_queueSelectFail(&FPT_BL_Card[thisCard],
1591 thisCard);
Khalid Aziz391e2f22013-05-16 19:44:14 -06001592 pCurrCard->currentSCCB = pSaveSccb;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001593 } else {
1594 FPT_queueAddSccb(p_Sccb, thisCard);
1595 }
1596 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001598 MENABLE_INT(ioport);
1599 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601}
1602
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603/*---------------------------------------------------------------------
1604 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001605 * Function: FlashPoint_AbortCCB
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 *
1607 * Description: Abort the command pointed to by p_Sccb. When the
1608 * command is completed it will be returned via the
1609 * callback function.
1610 *
1611 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06001612static int FlashPoint_AbortCCB(void *pCurrCard, struct sccb *p_Sccb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613{
Khalid Aziz391e2f22013-05-16 19:44:14 -06001614 u32 ioport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08001616 unsigned char thisCard;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617 CALL_BK_FN callback;
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08001618 unsigned char TID;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001619 struct sccb *pSaveSCCB;
1620 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001622 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001624 thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001626 if (!(RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001628 if (FPT_queueFindSccb(p_Sccb, thisCard)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001630 ((struct sccb_card *)pCurrCard)->cmdCounter--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001632 if (!((struct sccb_card *)pCurrCard)->cmdCounter)
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001633 WR_HARPOON(ioport + hp_semaphore,
1634 (RD_HARPOON(ioport + hp_semaphore)
1635 & (unsigned
1636 char)(~(SCCB_MGR_ACTIVE |
1637 TICKLE_ME))));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639 p_Sccb->SccbStatus = SCCB_ABORT;
1640 callback = p_Sccb->SccbCallback;
1641 callback(p_Sccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001643 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 }
1645
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001646 else {
1647 if (((struct sccb_card *)pCurrCard)->currentSCCB ==
1648 p_Sccb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649 p_Sccb->SccbStatus = SCCB_ABORT;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001650 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651
1652 }
1653
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001654 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655
1656 TID = p_Sccb->TargID;
1657
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001658 if (p_Sccb->Sccb_tag) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 MDISABLE_INT(ioport);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001660 if (((struct sccb_card *)pCurrCard)->
1661 discQ_Tbl[p_Sccb->Sccb_tag] ==
1662 p_Sccb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 p_Sccb->SccbStatus = SCCB_ABORT;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001664 p_Sccb->Sccb_scsistat =
1665 ABORT_ST;
1666 p_Sccb->Sccb_scsimsg =
1667 SMABORT_TAG;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001669 if (((struct sccb_card *)
1670 pCurrCard)->currentSCCB ==
1671 NULL) {
1672 ((struct sccb_card *)
1673 pCurrCard)->
1674 currentSCCB = p_Sccb;
1675 FPT_ssel(ioport,
1676 thisCard);
1677 } else {
1678 pSaveSCCB =
1679 ((struct sccb_card
1680 *)pCurrCard)->
1681 currentSCCB;
1682 ((struct sccb_card *)
1683 pCurrCard)->
1684 currentSCCB = p_Sccb;
1685 FPT_queueSelectFail((struct sccb_card *)pCurrCard, thisCard);
1686 ((struct sccb_card *)
1687 pCurrCard)->
1688 currentSCCB = pSaveSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 }
1690 }
1691 MENABLE_INT(ioport);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001692 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001693 } else {
1694 currTar_Info =
1695 &FPT_sccbMgrTbl[thisCard][p_Sccb->
1696 TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001698 if (FPT_BL_Card[thisCard].
1699 discQ_Tbl[currTar_Info->
1700 LunDiscQ_Idx[p_Sccb->Lun]]
1701 == p_Sccb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 p_Sccb->SccbStatus = SCCB_ABORT;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001703 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 }
1705 }
1706 }
1707 }
1708 }
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001709 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710}
1711
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712/*---------------------------------------------------------------------
1713 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001714 * Function: FlashPoint_InterruptPending
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715 *
1716 * Description: Do a quick check to determine if there is a pending
1717 * interrupt for this card and disable the IRQ Pin if so.
1718 *
1719 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06001720static unsigned char FlashPoint_InterruptPending(void *pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721{
Khalid Aziz391e2f22013-05-16 19:44:14 -06001722 u32 ioport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001724 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001726 if (RD_HARPOON(ioport + hp_int_status) & INT_ASSERTED) {
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001727 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001728 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001730 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001732 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733}
1734
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735/*---------------------------------------------------------------------
1736 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001737 * Function: FlashPoint_HandleInterrupt
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738 *
1739 * Description: This is our entry point when an interrupt is generated
1740 * by the card and the upper level driver passes it on to
1741 * us.
1742 *
1743 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06001744static int FlashPoint_HandleInterrupt(void *pcard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001746 struct sccb *currSCCB;
1747 unsigned char thisCard, result, bm_status, bm_int_st;
1748 unsigned short hp_int;
1749 unsigned char i, target;
Khalid Aziz391e2f22013-05-16 19:44:14 -06001750 struct sccb_card *pCurrCard = pcard;
1751 u32 ioport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752
Khalid Aziz391e2f22013-05-16 19:44:14 -06001753 thisCard = pCurrCard->cardIndex;
1754 ioport = pCurrCard->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001756 MDISABLE_INT(ioport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001758 if ((bm_int_st = RD_HARPOON(ioport + hp_int_status)) & EXT_STATUS_ON)
Khalid Aziz391e2f22013-05-16 19:44:14 -06001759 bm_status = RD_HARPOON(ioport + hp_ext_status) &
1760 (unsigned char)BAD_EXT_STATUS;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001761 else
1762 bm_status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001764 WR_HARPOON(ioport + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765
Khalid Aziz391e2f22013-05-16 19:44:14 -06001766 while ((hp_int = RDW_HARPOON((ioport + hp_intstat)) &
1767 FPT_default_intena) | bm_status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768
Khalid Aziz391e2f22013-05-16 19:44:14 -06001769 currSCCB = pCurrCard->currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001771 if (hp_int & (FIFO | TIMEOUT | RESET | SCAM_SEL) || bm_status) {
1772 result =
Khalid Aziz391e2f22013-05-16 19:44:14 -06001773 FPT_SccbMgr_bad_isr(ioport, thisCard, pCurrCard,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001774 hp_int);
1775 WRW_HARPOON((ioport + hp_intstat),
1776 (FIFO | TIMEOUT | RESET | SCAM_SEL));
1777 bm_status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001779 if (result) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001781 MENABLE_INT(ioport);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001782 return result;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001783 }
1784 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001786 else if (hp_int & ICMD_COMP) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001788 if (!(hp_int & BUS_FREE)) {
1789 /* Wait for the BusFree before starting a new command. We
1790 must also check for being reselected since the BusFree
1791 may not show up if another device reselects us in 1.5us or
1792 less. SRR Wednesday, 3/8/1995.
1793 */
1794 while (!
1795 (RDW_HARPOON((ioport + hp_intstat)) &
1796 (BUS_FREE | RSEL))) ;
1797 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798
Khalid Aziz391e2f22013-05-16 19:44:14 -06001799 if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001800
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001801 FPT_phaseChkFifo(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802
1803/* WRW_HARPOON((ioport+hp_intstat),
1804 (BUS_FREE | ICMD_COMP | ITAR_DISC | XFER_CNT_0));
1805 */
1806
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001807 WRW_HARPOON((ioport + hp_intstat), CLR_ALL_INT_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001809 FPT_autoCmdCmplt(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001811 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001813 else if (hp_int & ITAR_DISC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814
Khalid Aziz391e2f22013-05-16 19:44:14 -06001815 if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001816 FPT_phaseChkFifo(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817
Khalid Aziz391e2f22013-05-16 19:44:14 -06001818 if (RD_HARPOON(ioport + hp_gp_reg_1) ==
1819 SMSAVE_DATA_PTR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001821 WR_HARPOON(ioport + hp_gp_reg_1, 0x00);
1822 currSCCB->Sccb_XferState |= F_NO_DATA_YET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001824 currSCCB->Sccb_savedATC = currSCCB->Sccb_ATC;
1825 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001827 currSCCB->Sccb_scsistat = DISCONNECT_ST;
1828 FPT_queueDisconnect(currSCCB, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001830 /* Wait for the BusFree before starting a new command. We
1831 must also check for being reselected since the BusFree
1832 may not show up if another device reselects us in 1.5us or
1833 less. SRR Wednesday, 3/8/1995.
1834 */
1835 while (!
1836 (RDW_HARPOON((ioport + hp_intstat)) &
1837 (BUS_FREE | RSEL))
1838 && !((RDW_HARPOON((ioport + hp_intstat)) & PHASE)
1839 && RD_HARPOON((ioport + hp_scsisig)) ==
1840 (SCSI_BSY | SCSI_REQ | SCSI_CD | SCSI_MSG |
1841 SCSI_IOBIT))) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001843 /*
1844 The additional loop exit condition above detects a timing problem
1845 with the revision D/E harpoon chips. The caller should reset the
1846 host adapter to recover when 0xFE is returned.
1847 */
1848 if (!
1849 (RDW_HARPOON((ioport + hp_intstat)) &
1850 (BUS_FREE | RSEL))) {
1851 MENABLE_INT(ioport);
1852 return 0xFE;
1853 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001854
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001855 WRW_HARPOON((ioport + hp_intstat),
1856 (BUS_FREE | ITAR_DISC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857
Khalid Aziz391e2f22013-05-16 19:44:14 -06001858 pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001860 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001862 else if (hp_int & RSEL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001863
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001864 WRW_HARPOON((ioport + hp_intstat),
1865 (PROG_HLT | RSEL | PHASE | BUS_FREE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001867 if (RDW_HARPOON((ioport + hp_intstat)) & ITAR_DISC) {
Khalid Aziz391e2f22013-05-16 19:44:14 -06001868 if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001869 FPT_phaseChkFifo(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001871 if (RD_HARPOON(ioport + hp_gp_reg_1) ==
1872 SMSAVE_DATA_PTR) {
1873 WR_HARPOON(ioport + hp_gp_reg_1, 0x00);
1874 currSCCB->Sccb_XferState |=
1875 F_NO_DATA_YET;
1876 currSCCB->Sccb_savedATC =
1877 currSCCB->Sccb_ATC;
1878 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001879
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001880 WRW_HARPOON((ioport + hp_intstat),
1881 (BUS_FREE | ITAR_DISC));
1882 currSCCB->Sccb_scsistat = DISCONNECT_ST;
1883 FPT_queueDisconnect(currSCCB, thisCard);
1884 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001885
Khalid Aziz391e2f22013-05-16 19:44:14 -06001886 FPT_sres(ioport, thisCard, pCurrCard);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001887 FPT_phaseDecode(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001888
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001889 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001891 else if ((hp_int & IDO_STRT) && (!(hp_int & BUS_FREE))) {
1892
1893 WRW_HARPOON((ioport + hp_intstat),
1894 (IDO_STRT | XFER_CNT_0));
1895 FPT_phaseDecode(ioport, thisCard);
1896
1897 }
1898
1899 else if ((hp_int & IUNKWN) || (hp_int & PROG_HLT)) {
1900 WRW_HARPOON((ioport + hp_intstat),
1901 (PHASE | IUNKWN | PROG_HLT));
1902 if ((RD_HARPOON(ioport + hp_prgmcnt_0) & (unsigned char)
1903 0x3f) < (unsigned char)SELCHK) {
1904 FPT_phaseDecode(ioport, thisCard);
1905 } else {
1906 /* Harpoon problem some SCSI target device respond to selection
1907 with short BUSY pulse (<400ns) this will make the Harpoon is not able
1908 to latch the correct Target ID into reg. x53.
1909 The work around require to correct this reg. But when write to this
1910 reg. (0x53) also increment the FIFO write addr reg (0x6f), thus we
1911 need to read this reg first then restore it later. After update to 0x53 */
1912
1913 i = (unsigned
1914 char)(RD_HARPOON(ioport + hp_fifowrite));
1915 target =
1916 (unsigned
1917 char)(RD_HARPOON(ioport + hp_gp_reg_3));
1918 WR_HARPOON(ioport + hp_xfer_pad,
1919 (unsigned char)ID_UNLOCK);
1920 WR_HARPOON(ioport + hp_select_id,
1921 (unsigned char)(target | target <<
1922 4));
1923 WR_HARPOON(ioport + hp_xfer_pad,
1924 (unsigned char)0x00);
1925 WR_HARPOON(ioport + hp_fifowrite, i);
1926 WR_HARPOON(ioport + hp_autostart_3,
1927 (AUTO_IMMED + TAG_STRT));
1928 }
1929 }
1930
1931 else if (hp_int & XFER_CNT_0) {
1932
1933 WRW_HARPOON((ioport + hp_intstat), XFER_CNT_0);
1934
1935 FPT_schkdd(ioport, thisCard);
1936
1937 }
1938
1939 else if (hp_int & BUS_FREE) {
1940
1941 WRW_HARPOON((ioport + hp_intstat), BUS_FREE);
1942
Khalid Aziz391e2f22013-05-16 19:44:14 -06001943 if (pCurrCard->globalFlags & F_HOST_XFER_ACT) {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001944
1945 FPT_hostDataXferAbort(ioport, thisCard,
1946 currSCCB);
1947 }
1948
1949 FPT_phaseBusFree(ioport, thisCard);
1950 }
1951
1952 else if (hp_int & ITICKLE) {
1953
1954 WRW_HARPOON((ioport + hp_intstat), ITICKLE);
Khalid Aziz391e2f22013-05-16 19:44:14 -06001955 pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001956 }
1957
1958 if (((struct sccb_card *)pCurrCard)->
1959 globalFlags & F_NEW_SCCB_CMD) {
1960
Khalid Aziz391e2f22013-05-16 19:44:14 -06001961 pCurrCard->globalFlags &= ~F_NEW_SCCB_CMD;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001962
Khalid Aziz391e2f22013-05-16 19:44:14 -06001963 if (pCurrCard->currentSCCB == NULL)
1964 FPT_queueSearchSelect(pCurrCard, thisCard);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001965
Khalid Aziz391e2f22013-05-16 19:44:14 -06001966 if (pCurrCard->currentSCCB != NULL) {
1967 pCurrCard->globalFlags &= ~F_NEW_SCCB_CMD;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001968 FPT_ssel(ioport, thisCard);
1969 }
1970
1971 break;
1972
1973 }
1974
1975 } /*end while */
1976
1977 MENABLE_INT(ioport);
1978
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001979 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001980}
1981
1982/*---------------------------------------------------------------------
1983 *
1984 * Function: Sccb_bad_isr
1985 *
1986 * Description: Some type of interrupt has occurred which is slightly
1987 * out of the ordinary. We will now decode it fully, in
1988 * this routine. This is broken up in an attempt to save
1989 * processing time.
1990 *
1991 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06001992static unsigned char FPT_SccbMgr_bad_isr(u32 p_port, unsigned char p_card,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001993 struct sccb_card *pCurrCard,
1994 unsigned short p_int)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001995{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001996 unsigned char temp, ScamFlg;
1997 struct sccb_mgr_tar_info *currTar_Info;
1998 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001999
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002000 if (RD_HARPOON(p_port + hp_ext_status) &
2001 (BM_FORCE_OFF | PCI_DEV_TMOUT | BM_PARITY_ERR | PIO_OVERRUN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002002
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002003 if (pCurrCard->globalFlags & F_HOST_XFER_ACT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002005 FPT_hostDataXferAbort(p_port, p_card,
2006 pCurrCard->currentSCCB);
2007 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002009 if (RD_HARPOON(p_port + hp_pci_stat_cfg) & REC_MASTER_ABORT)
2010 {
2011 WR_HARPOON(p_port + hp_pci_stat_cfg,
2012 (RD_HARPOON(p_port + hp_pci_stat_cfg) &
2013 ~REC_MASTER_ABORT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002015 WR_HARPOON(p_port + hp_host_blk_cnt, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002017 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002018
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002019 if (pCurrCard->currentSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002021 if (!pCurrCard->currentSCCB->HostStatus)
2022 pCurrCard->currentSCCB->HostStatus =
2023 SCCB_BM_ERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002025 FPT_sxfrp(p_port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002027 temp = (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
2028 (EXT_ARB_ACK | SCSI_TERM_ENA_H));
2029 WR_HARPOON(p_port + hp_ee_ctrl,
2030 ((unsigned char)temp | SEE_MS | SEE_CS));
2031 WR_HARPOON(p_port + hp_ee_ctrl, temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002033 if (!
2034 (RDW_HARPOON((p_port + hp_intstat)) &
2035 (BUS_FREE | RESET))) {
2036 FPT_phaseDecode(p_port, p_card);
2037 }
2038 }
2039 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002041 else if (p_int & RESET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002043 WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
2044 WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
2045 if (pCurrCard->currentSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002047 if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002049 FPT_hostDataXferAbort(p_port, p_card,
2050 pCurrCard->currentSCCB);
2051 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002053 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002055 FPT_sresb(p_port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002056
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002057 while (RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST) {
2058 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002060 pCurrNvRam = pCurrCard->pNvRamInfo;
2061 if (pCurrNvRam) {
2062 ScamFlg = pCurrNvRam->niScamConf;
2063 } else {
2064 ScamFlg =
2065 (unsigned char)FPT_utilEERead(p_port,
2066 SCAM_CONFIG / 2);
2067 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002069 FPT_XbowInit(p_port, ScamFlg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002071 FPT_scini(p_card, pCurrCard->ourId, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002073 return 0xFF;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002074 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002076 else if (p_int & FIFO) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002078 WRW_HARPOON((p_port + hp_intstat), FIFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002080 if (pCurrCard->currentSCCB != NULL)
2081 FPT_sxfrp(p_port, p_card);
2082 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002084 else if (p_int & TIMEOUT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002086 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002088 WRW_HARPOON((p_port + hp_intstat),
2089 (PROG_HLT | TIMEOUT | SEL | BUS_FREE | PHASE |
2090 IUNKWN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002092 pCurrCard->currentSCCB->HostStatus = SCCB_SELECTION_TIMEOUT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002094 currTar_Info =
2095 &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
2096 if ((pCurrCard->globalFlags & F_CONLUN_IO)
2097 && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
2098 TAG_Q_TRYING))
2099 currTar_Info->TarLUNBusy[pCurrCard->currentSCCB->Lun] =
2100 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002102 currTar_Info->TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002104 if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
2105 currTar_Info->TarSyncCtrl = 0;
2106 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2107 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002109 if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
2110 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2111 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002113 FPT_sssyncv(p_port, pCurrCard->currentSCCB->TargID, NARROW_SCSI,
2114 currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002116 FPT_queueCmdComplete(pCurrCard, pCurrCard->currentSCCB, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002117
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002118 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002120 else if (p_int & SCAM_SEL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002122 FPT_scarb(p_port, LEVEL2_TAR);
2123 FPT_scsel(p_port);
2124 FPT_scasid(p_card, p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002126 FPT_scbusf(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002128 WRW_HARPOON((p_port + hp_intstat), SCAM_SEL);
2129 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002131 return 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132}
2133
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134/*---------------------------------------------------------------------
2135 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 * Function: SccbMgrTableInit
2137 *
2138 * Description: Initialize all Sccb manager data structures.
2139 *
2140 *---------------------------------------------------------------------*/
2141
Sudip Mukherjeecd9d7152015-09-16 19:36:20 +05302142static void FPT_SccbMgrTableInitAll(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002144 unsigned char thisCard;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002146 for (thisCard = 0; thisCard < MAX_CARDS; thisCard++) {
2147 FPT_SccbMgrTableInitCard(&FPT_BL_Card[thisCard], thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002149 FPT_BL_Card[thisCard].ioPort = 0x00;
2150 FPT_BL_Card[thisCard].cardInfo = NULL;
2151 FPT_BL_Card[thisCard].cardIndex = 0xFF;
2152 FPT_BL_Card[thisCard].ourId = 0x00;
2153 FPT_BL_Card[thisCard].pNvRamInfo = NULL;
2154 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155}
2156
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157/*---------------------------------------------------------------------
2158 *
2159 * Function: SccbMgrTableInit
2160 *
2161 * Description: Initialize all Sccb manager data structures.
2162 *
2163 *---------------------------------------------------------------------*/
2164
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002165static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard,
2166 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002168 unsigned char scsiID, qtag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002170 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002171 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172 }
2173
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002174 for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
2175 FPT_sccbMgrTbl[p_card][scsiID].TarStatus = 0;
2176 FPT_sccbMgrTbl[p_card][scsiID].TarEEValue = 0;
2177 FPT_SccbMgrTableInitTarget(p_card, scsiID);
2178 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002180 pCurrCard->scanIndex = 0x00;
2181 pCurrCard->currentSCCB = NULL;
2182 pCurrCard->globalFlags = 0x00;
2183 pCurrCard->cmdCounter = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184 pCurrCard->tagQ_Lst = 0x01;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002185 pCurrCard->discQCount = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186
2187}
2188
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189/*---------------------------------------------------------------------
2190 *
2191 * Function: SccbMgrTableInit
2192 *
2193 * Description: Initialize all Sccb manager data structures.
2194 *
2195 *---------------------------------------------------------------------*/
2196
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002197static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
2198 unsigned char target)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199{
2200
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08002201 unsigned char lun, qtag;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002202 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203
James Bottomley 47b5d692005-04-24 02:38:05 -05002204 currTar_Info = &FPT_sccbMgrTbl[p_card][target];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205
2206 currTar_Info->TarSelQ_Cnt = 0;
2207 currTar_Info->TarSyncCtrl = 0;
2208
2209 currTar_Info->TarSelQ_Head = NULL;
2210 currTar_Info->TarSelQ_Tail = NULL;
2211 currTar_Info->TarTagQ_Cnt = 0;
James Bottomley 47b5d692005-04-24 02:38:05 -05002212 currTar_Info->TarLUN_CA = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002214 for (lun = 0; lun < MAX_LUN; lun++) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002215 currTar_Info->TarLUNBusy[lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216 currTar_Info->LunDiscQ_Idx[lun] = 0;
2217 }
2218
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002219 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
2220 if (FPT_BL_Card[p_card].discQ_Tbl[qtag] != NULL) {
2221 if (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
2222 target) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002223 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
2224 FPT_BL_Card[p_card].discQCount--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225 }
2226 }
2227 }
2228}
2229
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230/*---------------------------------------------------------------------
2231 *
2232 * Function: sfetm
2233 *
2234 * Description: Read in a message byte from the SCSI bus, and check
2235 * for a parity error.
2236 *
2237 *---------------------------------------------------------------------*/
2238
Khalid Aziz391e2f22013-05-16 19:44:14 -06002239static unsigned char FPT_sfm(u32 port, struct sccb *pCurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002240{
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08002241 unsigned char message;
Alexey Dobriyanc823fee2006-03-08 00:14:25 -08002242 unsigned short TimeOutLoop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243
2244 TimeOutLoop = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002245 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2246 (TimeOutLoop++ < 20000)) {
2247 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002249 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002251 message = RD_HARPOON(port + hp_scsidata_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002252
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002253 WR_HARPOON(port + hp_scsisig, SCSI_ACK + S_MSGI_PH);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254
2255 if (TimeOutLoop > 20000)
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002256 message = 0x00; /* force message byte = 0 if Time Out on Req */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002258 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
2259 (RD_HARPOON(port + hp_addstat) & SCSI_PAR_ERR)) {
2260 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2261 WR_HARPOON(port + hp_xferstat, 0);
2262 WR_HARPOON(port + hp_fiforead, 0);
2263 WR_HARPOON(port + hp_fifowrite, 0);
2264 if (pCurrSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265 pCurrSCCB->Sccb_scsimsg = SMPARITY;
2266 }
2267 message = 0x00;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002268 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269 ACCEPT_MSG_ATN(port);
2270 TimeOutLoop = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002271 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2272 (TimeOutLoop++ < 20000)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002274 if (TimeOutLoop > 20000) {
2275 WRW_HARPOON((port + hp_intstat), PARITY);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002276 return message;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002278 if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) !=
2279 S_MSGI_PH) {
2280 WRW_HARPOON((port + hp_intstat), PARITY);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002281 return message;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002282 }
2283 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002285 RD_HARPOON(port + hp_scsidata_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002287 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002289 } while (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290
2291 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002292 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2293 WR_HARPOON(port + hp_xferstat, 0);
2294 WR_HARPOON(port + hp_fiforead, 0);
2295 WR_HARPOON(port + hp_fifowrite, 0);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002296 return message;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297}
2298
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299/*---------------------------------------------------------------------
2300 *
James Bottomley 47b5d692005-04-24 02:38:05 -05002301 * Function: FPT_ssel
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 *
2303 * Description: Load up automation and select target device.
2304 *
2305 *---------------------------------------------------------------------*/
2306
Khalid Aziz391e2f22013-05-16 19:44:14 -06002307static void FPT_ssel(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308{
2309
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002310 unsigned char auto_loaded, i, target, *theCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311
Khalid Aziz391e2f22013-05-16 19:44:14 -06002312 u32 cdb_reg;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002313 struct sccb_card *CurrCard;
2314 struct sccb *currSCCB;
2315 struct sccb_mgr_tar_info *currTar_Info;
2316 unsigned char lastTag, lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002318 CurrCard = &FPT_BL_Card[p_card];
2319 currSCCB = CurrCard->currentSCCB;
2320 target = currSCCB->TargID;
2321 currTar_Info = &FPT_sccbMgrTbl[p_card][target];
2322 lastTag = CurrCard->tagQ_Lst;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002324 ARAM_ACCESS(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002325
2326 if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
2327 currSCCB->ControlByte &= ~F_USE_CMD_Q;
2328
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002329 if (((CurrCard->globalFlags & F_CONLUN_IO) &&
2330 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002332 lun = currSCCB->Lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333 else
2334 lun = 0;
2335
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002336 if (CurrCard->globalFlags & F_TAG_STARTED) {
2337 if (!(currSCCB->ControlByte & F_USE_CMD_Q)) {
2338 if ((currTar_Info->TarLUN_CA == 0)
2339 && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
2340 == TAG_Q_TRYING)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002342 if (currTar_Info->TarTagQ_Cnt != 0) {
2343 currTar_Info->TarLUNBusy[lun] = 1;
2344 FPT_queueSelectFail(CurrCard, p_card);
2345 SGRAM_ACCESS(port);
2346 return;
2347 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002349 else {
2350 currTar_Info->TarLUNBusy[lun] = 1;
2351 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002353 }
2354 /*End non-tagged */
2355 else {
2356 currTar_Info->TarLUNBusy[lun] = 1;
2357 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002359 }
2360 /*!Use cmd Q Tagged */
2361 else {
2362 if (currTar_Info->TarLUN_CA == 1) {
2363 FPT_queueSelectFail(CurrCard, p_card);
2364 SGRAM_ACCESS(port);
2365 return;
2366 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367
James Bottomley 47b5d692005-04-24 02:38:05 -05002368 currTar_Info->TarLUNBusy[lun] = 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002369
2370 } /*else use cmd Q tagged */
2371
2372 }
2373 /*if glob tagged started */
2374 else {
2375 currTar_Info->TarLUNBusy[lun] = 1;
2376 }
2377
2378 if ((((CurrCard->globalFlags & F_CONLUN_IO) &&
2379 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
2380 || (!(currSCCB->ControlByte & F_USE_CMD_Q)))) {
2381 if (CurrCard->discQCount >= QUEUE_DEPTH) {
2382 currTar_Info->TarLUNBusy[lun] = 1;
2383 FPT_queueSelectFail(CurrCard, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384 SGRAM_ACCESS(port);
2385 return;
2386 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002387 for (i = 1; i < QUEUE_DEPTH; i++) {
2388 if (++lastTag >= QUEUE_DEPTH)
2389 lastTag = 1;
2390 if (CurrCard->discQ_Tbl[lastTag] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 CurrCard->tagQ_Lst = lastTag;
2392 currTar_Info->LunDiscQ_Idx[lun] = lastTag;
2393 CurrCard->discQ_Tbl[lastTag] = currSCCB;
2394 CurrCard->discQCount++;
2395 break;
2396 }
2397 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002398 if (i == QUEUE_DEPTH) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002399 currTar_Info->TarLUNBusy[lun] = 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002400 FPT_queueSelectFail(CurrCard, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401 SGRAM_ACCESS(port);
2402 return;
2403 }
2404 }
2405
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002406 auto_loaded = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002408 WR_HARPOON(port + hp_select_id, target);
2409 WR_HARPOON(port + hp_gp_reg_3, target); /* Use by new automation logic */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002411 if (currSCCB->OperationCode == RESET_COMMAND) {
2412 WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
2413 (currSCCB->
2414 Sccb_idmsg & ~DISC_PRIV)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002416 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + NP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002417
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002418 currSCCB->Sccb_scsimsg = SMDEV_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002420 WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
2421 auto_loaded = 1;
2422 currSCCB->Sccb_scsistat = SELECT_BDR_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002424 if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
2425 currTar_Info->TarSyncCtrl = 0;
2426 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427 }
2428
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002429 if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
2430 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2431 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002433 FPT_sssyncv(port, target, NARROW_SCSI, currTar_Info);
2434 FPT_SccbMgrTableInitTarget(p_card, target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002436 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002438 else if (currSCCB->Sccb_scsistat == ABORT_ST) {
2439 WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
2440 (currSCCB->
2441 Sccb_idmsg & ~DISC_PRIV)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002443 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002445 WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT +
2446 (((unsigned
2447 char)(currSCCB->
2448 ControlByte &
2449 TAG_TYPE_MASK)
2450 >> 6) | (unsigned char)
2451 0x20)));
2452 WRW_HARPOON((port + SYNC_MSGS + 2),
2453 (MPM_OP + AMSG_OUT + currSCCB->Sccb_tag));
2454 WRW_HARPOON((port + SYNC_MSGS + 4), (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002456 WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
2457 auto_loaded = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002459 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002461 else if (!(currTar_Info->TarStatus & WIDE_NEGOCIATED)) {
2462 auto_loaded = FPT_siwidn(port, p_card);
2463 currSCCB->Sccb_scsistat = SELECT_WN_ST;
2464 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002466 else if (!((currTar_Info->TarStatus & TAR_SYNC_MASK)
2467 == SYNC_SUPPORTED)) {
2468 auto_loaded = FPT_sisyncn(port, p_card, 0);
2469 currSCCB->Sccb_scsistat = SELECT_SN_ST;
2470 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002472 if (!auto_loaded) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002474 if (currSCCB->ControlByte & F_USE_CMD_Q) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002476 CurrCard->globalFlags |= F_TAG_STARTED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002478 if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
2479 == TAG_Q_REJECT) {
2480 currSCCB->ControlByte &= ~F_USE_CMD_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002482 /* Fix up the start instruction with a jump to
2483 Non-Tag-CMD handling */
2484 WRW_HARPOON((port + ID_MSG_STRT),
2485 BRH_OP + ALWAYS + NTCMD);
2486
2487 WRW_HARPOON((port + NON_TAG_ID_MSG),
2488 (MPM_OP + AMSG_OUT +
2489 currSCCB->Sccb_idmsg));
2490
2491 WR_HARPOON(port + hp_autostart_3,
2492 (SELECT + SELCHK_STRT));
2493
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002494 /* Setup our STATE so we know what happened when
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002495 the wheels fall off. */
2496 currSCCB->Sccb_scsistat = SELECT_ST;
2497
2498 currTar_Info->TarLUNBusy[lun] = 1;
2499 }
2500
2501 else {
2502 WRW_HARPOON((port + ID_MSG_STRT),
2503 (MPM_OP + AMSG_OUT +
2504 currSCCB->Sccb_idmsg));
2505
2506 WRW_HARPOON((port + ID_MSG_STRT + 2),
2507 (MPM_OP + AMSG_OUT +
2508 (((unsigned char)(currSCCB->
2509 ControlByte &
2510 TAG_TYPE_MASK)
2511 >> 6) | (unsigned char)0x20)));
2512
2513 for (i = 1; i < QUEUE_DEPTH; i++) {
2514 if (++lastTag >= QUEUE_DEPTH)
2515 lastTag = 1;
2516 if (CurrCard->discQ_Tbl[lastTag] ==
2517 NULL) {
2518 WRW_HARPOON((port +
2519 ID_MSG_STRT + 6),
2520 (MPM_OP + AMSG_OUT +
2521 lastTag));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522 CurrCard->tagQ_Lst = lastTag;
2523 currSCCB->Sccb_tag = lastTag;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002524 CurrCard->discQ_Tbl[lastTag] =
2525 currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526 CurrCard->discQCount++;
2527 break;
2528 }
2529 }
2530
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002531 if (i == QUEUE_DEPTH) {
2532 currTar_Info->TarLUNBusy[lun] = 1;
2533 FPT_queueSelectFail(CurrCard, p_card);
2534 SGRAM_ACCESS(port);
2535 return;
2536 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002538 currSCCB->Sccb_scsistat = SELECT_Q_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002539
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002540 WR_HARPOON(port + hp_autostart_3,
2541 (SELECT + SELCHK_STRT));
2542 }
2543 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002545 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002547 WRW_HARPOON((port + ID_MSG_STRT),
2548 BRH_OP + ALWAYS + NTCMD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002550 WRW_HARPOON((port + NON_TAG_ID_MSG),
2551 (MPM_OP + AMSG_OUT + currSCCB->Sccb_idmsg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002552
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002553 currSCCB->Sccb_scsistat = SELECT_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002555 WR_HARPOON(port + hp_autostart_3,
2556 (SELECT + SELCHK_STRT));
2557 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002559 theCCB = (unsigned char *)&currSCCB->Cdb[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002561 cdb_reg = port + CMD_STRT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002562
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002563 for (i = 0; i < currSCCB->CdbLength; i++) {
2564 WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + *theCCB));
2565 cdb_reg += 2;
2566 theCCB++;
2567 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002569 if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
2570 WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002572 }
2573 /* auto_loaded */
2574 WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
2575 WR_HARPOON(port + hp_xferstat, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002577 WRW_HARPOON((port + hp_intstat), (PROG_HLT | TIMEOUT | SEL | BUS_FREE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002579 WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002581 if (!(currSCCB->Sccb_MGRFlags & F_DEV_SELECTED)) {
2582 WR_HARPOON(port + hp_scsictrl_0,
2583 (SEL_TAR | ENA_ATN | ENA_RESEL | ENA_SCAM_SEL));
2584 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08002586/* auto_loaded = (RD_HARPOON(port+hp_autostart_3) & (unsigned char)0x1F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587 auto_loaded |= AUTO_IMMED; */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002588 auto_loaded = AUTO_IMMED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002590 DISABLE_AUTO(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002592 WR_HARPOON(port + hp_autostart_3, auto_loaded);
2593 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002595 SGRAM_ACCESS(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596}
2597
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598/*---------------------------------------------------------------------
2599 *
James Bottomley 47b5d692005-04-24 02:38:05 -05002600 * Function: FPT_sres
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 *
2602 * Description: Hookup the correct CCB and handle the incoming messages.
2603 *
2604 *---------------------------------------------------------------------*/
2605
Khalid Aziz391e2f22013-05-16 19:44:14 -06002606static void FPT_sres(u32 port, unsigned char p_card,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002607 struct sccb_card *pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608{
2609
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002610 unsigned char our_target, message, lun = 0, tag, msgRetryCount;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002612 struct sccb_mgr_tar_info *currTar_Info;
2613 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002615 if (pCurrCard->currentSCCB != NULL) {
2616 currTar_Info =
2617 &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618 DISABLE_AUTO(port);
2619
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002620 WR_HARPOON((port + hp_scsictrl_0), (ENA_RESEL | ENA_SCAM_SEL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621
2622 currSCCB = pCurrCard->currentSCCB;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002623 if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2625 currSCCB->Sccb_scsistat = BUS_FREE_ST;
2626 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002627 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2629 currSCCB->Sccb_scsistat = BUS_FREE_ST;
2630 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002631 if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
2632 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
2633 TAG_Q_TRYING))) {
2634 currTar_Info->TarLUNBusy[currSCCB->Lun] = 0;
2635 if (currSCCB->Sccb_scsistat != ABORT_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636 pCurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002637 pCurrCard->discQ_Tbl[currTar_Info->
2638 LunDiscQ_Idx[currSCCB->
2639 Lun]]
2640 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002641 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002642 } else {
2643 currTar_Info->TarLUNBusy[0] = 0;
2644 if (currSCCB->Sccb_tag) {
2645 if (currSCCB->Sccb_scsistat != ABORT_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646 pCurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002647 pCurrCard->discQ_Tbl[currSCCB->
2648 Sccb_tag] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002650 } else {
2651 if (currSCCB->Sccb_scsistat != ABORT_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002652 pCurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002653 pCurrCard->discQ_Tbl[currTar_Info->
2654 LunDiscQ_Idx[0]] =
2655 NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656 }
2657 }
2658 }
2659
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002660 FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661 }
2662
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002663 WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002665 our_target = (unsigned char)(RD_HARPOON(port + hp_select_id) >> 4);
James Bottomley 47b5d692005-04-24 02:38:05 -05002666 currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668 msgRetryCount = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002669 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670
James Bottomley 47b5d692005-04-24 02:38:05 -05002671 currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672 tag = 0;
2673
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002674 while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
2675 if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002677 WRW_HARPOON((port + hp_intstat), PHASE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002678 return;
2679 }
2680 }
2681
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002682 WRW_HARPOON((port + hp_intstat), PHASE);
2683 if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002685 message = FPT_sfm(port, pCurrCard->currentSCCB);
2686 if (message) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002687
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002688 if (message <= (0x80 | LUN_MASK)) {
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08002689 lun = message & (unsigned char)LUN_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002691 if ((currTar_Info->
2692 TarStatus & TAR_TAG_Q_MASK) ==
2693 TAG_Q_TRYING) {
2694 if (currTar_Info->TarTagQ_Cnt !=
2695 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002697 if (!
2698 (currTar_Info->
2699 TarLUN_CA)) {
2700 ACCEPT_MSG(port); /*Release the ACK for ID msg. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002701
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002702 message =
2703 FPT_sfm
2704 (port,
2705 pCurrCard->
2706 currentSCCB);
2707 if (message) {
2708 ACCEPT_MSG
2709 (port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002710 }
2711
2712 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002713 message
2714 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002716 if (message !=
2717 0) {
2718 tag =
2719 FPT_sfm
2720 (port,
2721 pCurrCard->
2722 currentSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002724 if (!
2725 (tag))
2726 message
2727 =
2728 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729 }
2730
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002731 }
2732 /*C.A. exists! */
2733 }
2734 /*End Q cnt != 0 */
2735 }
2736 /*End Tag cmds supported! */
2737 }
2738 /*End valid ID message. */
2739 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740
2741 ACCEPT_MSG_ATN(port);
2742 }
2743
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002744 }
2745 /* End good id message. */
2746 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747
James Bottomley 47b5d692005-04-24 02:38:05 -05002748 message = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002750 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751 ACCEPT_MSG_ATN(port);
2752
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002753 while (!
2754 (RDW_HARPOON((port + hp_intstat)) &
2755 (PHASE | RESET))
2756 && !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
2757 && (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758
2759 return;
2760 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002762 if (message == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763 msgRetryCount++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002764 if (msgRetryCount == 1) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002765 FPT_SendMsg(port, SMPARITY);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002766 } else {
James Bottomley 47b5d692005-04-24 02:38:05 -05002767 FPT_SendMsg(port, SMDEV_RESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002769 FPT_sssyncv(port, our_target, NARROW_SCSI,
2770 currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002772 if (FPT_sccbMgrTbl[p_card][our_target].
2773 TarEEValue & EE_SYNC_MASK) {
2774
2775 FPT_sccbMgrTbl[p_card][our_target].
2776 TarStatus &= ~TAR_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777
2778 }
2779
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002780 if (FPT_sccbMgrTbl[p_card][our_target].
2781 TarEEValue & EE_WIDE_SCSI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002782
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002783 FPT_sccbMgrTbl[p_card][our_target].
2784 TarStatus &= ~TAR_WIDE_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785 }
2786
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002787 FPT_queueFlushTargSccb(p_card, our_target,
2788 SCCB_COMPLETE);
2789 FPT_SccbMgrTableInitTarget(p_card, our_target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790 return;
2791 }
2792 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002793 } while (message == 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002795 if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
2796 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002797 currTar_Info->TarLUNBusy[lun] = 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002798 pCurrCard->currentSCCB =
2799 pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[lun]];
2800 if (pCurrCard->currentSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002801 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002802 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803 ACCEPT_MSG_ATN(port);
2804 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002805 } else {
James Bottomley 47b5d692005-04-24 02:38:05 -05002806 currTar_Info->TarLUNBusy[0] = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002808 if (tag) {
2809 if (pCurrCard->discQ_Tbl[tag] != NULL) {
2810 pCurrCard->currentSCCB =
2811 pCurrCard->discQ_Tbl[tag];
2812 currTar_Info->TarTagQ_Cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002814 } else {
2815 ACCEPT_MSG_ATN(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002817 } else {
2818 pCurrCard->currentSCCB =
2819 pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]];
2820 if (pCurrCard->currentSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002822 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823 ACCEPT_MSG_ATN(port);
2824 }
2825 }
2826 }
2827
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002828 if (pCurrCard->currentSCCB != NULL) {
2829 if (pCurrCard->currentSCCB->Sccb_scsistat == ABORT_ST) {
2830 /* During Abort Tag command, the target could have got re-selected
2831 and completed the command. Check the select Q and remove the CCB
2832 if it is in the Select Q */
James Bottomley 47b5d692005-04-24 02:38:05 -05002833 FPT_queueFindSccb(pCurrCard->currentSCCB, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834 }
2835 }
2836
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002837 while (!(RDW_HARPOON((port + hp_intstat)) & (PHASE | RESET)) &&
2838 !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ) &&
2839 (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840}
2841
Khalid Aziz391e2f22013-05-16 19:44:14 -06002842static void FPT_SendMsg(u32 port, unsigned char message)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002844 while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
2845 if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002846
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002847 WRW_HARPOON((port + hp_intstat), PHASE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002848 return;
2849 }
2850 }
2851
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002852 WRW_HARPOON((port + hp_intstat), PHASE);
2853 if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGO_PH) {
2854 WRW_HARPOON((port + hp_intstat),
2855 (BUS_FREE | PHASE | XFER_CNT_0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002856
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002857 WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002858
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002859 WR_HARPOON(port + hp_scsidata_0, message);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002861 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862
2863 ACCEPT_MSG(port);
2864
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002865 WR_HARPOON(port + hp_portctrl_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002866
2867 if ((message == SMABORT) || (message == SMDEV_RESET) ||
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002868 (message == SMABORT_TAG)) {
2869 while (!
2870 (RDW_HARPOON((port + hp_intstat)) &
2871 (BUS_FREE | PHASE))) {
2872 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002873
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002874 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
2875 WRW_HARPOON((port + hp_intstat), BUS_FREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002876 }
2877 }
2878 }
2879}
2880
2881/*---------------------------------------------------------------------
2882 *
James Bottomley 47b5d692005-04-24 02:38:05 -05002883 * Function: FPT_sdecm
Linus Torvalds1da177e2005-04-16 15:20:36 -07002884 *
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002885 * Description: Determine the proper response to the message from the
Linus Torvalds1da177e2005-04-16 15:20:36 -07002886 * target device.
2887 *
2888 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06002889static void FPT_sdecm(unsigned char message, u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002890{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002891 struct sccb *currSCCB;
2892 struct sccb_card *CurrCard;
2893 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002894
James Bottomley 47b5d692005-04-24 02:38:05 -05002895 CurrCard = &FPT_BL_Card[p_card];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002896 currSCCB = CurrCard->currentSCCB;
2897
James Bottomley 47b5d692005-04-24 02:38:05 -05002898 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002899
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002900 if (message == SMREST_DATA_PTR) {
2901 if (!(currSCCB->Sccb_XferState & F_NO_DATA_YET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902 currSCCB->Sccb_ATC = currSCCB->Sccb_savedATC;
2903
James Bottomley 47b5d692005-04-24 02:38:05 -05002904 FPT_hostDataXferRestart(currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002905 }
2906
2907 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002908 WR_HARPOON(port + hp_autostart_1,
2909 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910 }
2911
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002912 else if (message == SMCMD_COMP) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002913
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002914 if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
2915 currTar_Info->TarStatus &=
2916 ~(unsigned char)TAR_TAG_Q_MASK;
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08002917 currTar_Info->TarStatus |= (unsigned char)TAG_Q_REJECT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002918 }
2919
2920 ACCEPT_MSG(port);
2921
2922 }
2923
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002924 else if ((message == SMNO_OP) || (message >= SMIDENT)
2925 || (message == SMINIT_RECOVERY) || (message == SMREL_RECOVERY)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926
2927 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002928 WR_HARPOON(port + hp_autostart_1,
2929 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930 }
2931
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002932 else if (message == SMREJECT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002933
2934 if ((currSCCB->Sccb_scsistat == SELECT_SN_ST) ||
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002935 (currSCCB->Sccb_scsistat == SELECT_WN_ST) ||
2936 ((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)
2937 || ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) ==
2938 TAG_Q_TRYING))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002939 {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002940 WRW_HARPOON((port + hp_intstat), BUS_FREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002941
2942 ACCEPT_MSG(port);
2943
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002944 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2945 (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002946 {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002947 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002948
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002949 if (currSCCB->Lun == 0x00) {
Nathan Chancelloradb11022018-09-20 14:10:32 -07002950 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002952 currTar_Info->TarStatus |=
2953 (unsigned char)SYNC_SUPPORTED;
2954
2955 currTar_Info->TarEEValue &=
2956 ~EE_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002957 }
2958
Nathan Chancelloradb11022018-09-20 14:10:32 -07002959 else if (currSCCB->Sccb_scsistat ==
2960 SELECT_WN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002961
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002962 currTar_Info->TarStatus =
2963 (currTar_Info->
2964 TarStatus & ~WIDE_ENABLED) |
2965 WIDE_NEGOCIATED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002966
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002967 currTar_Info->TarEEValue &=
2968 ~EE_WIDE_SCSI;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002969
2970 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002971
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002972 else if ((currTar_Info->
2973 TarStatus & TAR_TAG_Q_MASK) ==
2974 TAG_Q_TRYING) {
2975 currTar_Info->TarStatus =
2976 (currTar_Info->
2977 TarStatus & ~(unsigned char)
2978 TAR_TAG_Q_MASK) | TAG_Q_REJECT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979
2980 currSCCB->ControlByte &= ~F_USE_CMD_Q;
2981 CurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002982 CurrCard->discQ_Tbl[currSCCB->
2983 Sccb_tag] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002984 currSCCB->Sccb_tag = 0x00;
2985
2986 }
2987 }
2988
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002989 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002990
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002991 if (currSCCB->Lun == 0x00) {
2992 WRW_HARPOON((port + hp_intstat),
2993 BUS_FREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002994 CurrCard->globalFlags |= F_NEW_SCCB_CMD;
2995 }
2996 }
2997
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002998 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003000 if ((CurrCard->globalFlags & F_CONLUN_IO) &&
3001 ((currTar_Info->
3002 TarStatus & TAR_TAG_Q_MASK) !=
3003 TAG_Q_TRYING))
3004 currTar_Info->TarLUNBusy[currSCCB->
3005 Lun] = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006 else
James Bottomley 47b5d692005-04-24 02:38:05 -05003007 currTar_Info->TarLUNBusy[0] = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003009 currSCCB->ControlByte &=
3010 ~(unsigned char)F_USE_CMD_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003011
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003012 WR_HARPOON(port + hp_autostart_1,
3013 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014
3015 }
3016 }
3017
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003018 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003019 ACCEPT_MSG(port);
3020
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003021 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
3022 (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023 {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003024 }
3025
3026 if (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)) {
3027 WR_HARPOON(port + hp_autostart_1,
3028 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029 }
3030 }
3031 }
3032
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003033 else if (message == SMEXT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034
3035 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003036 FPT_shandem(port, p_card, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037 }
3038
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003039 else if (message == SMIGNORWR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003040
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003041 ACCEPT_MSG(port); /* ACK the RESIDUE MSG */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003042
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003043 message = FPT_sfm(port, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003044
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003045 if (currSCCB->Sccb_scsimsg != SMPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003046 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003047 WR_HARPOON(port + hp_autostart_1,
3048 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003049 }
3050
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003051 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003052
3053 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
3054 currSCCB->Sccb_scsimsg = SMREJECT;
3055
3056 ACCEPT_MSG_ATN(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003057 WR_HARPOON(port + hp_autostart_1,
3058 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059 }
3060}
3061
Linus Torvalds1da177e2005-04-16 15:20:36 -07003062/*---------------------------------------------------------------------
3063 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003064 * Function: FPT_shandem
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065 *
3066 * Description: Decide what to do with the extended message.
3067 *
3068 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06003069static void FPT_shandem(u32 port, unsigned char p_card, struct sccb *pCurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003071 unsigned char length, message;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003073 length = FPT_sfm(port, pCurrSCCB);
3074 if (length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075
3076 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003077 message = FPT_sfm(port, pCurrSCCB);
3078 if (message) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003079
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003080 if (message == SMSYNC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003082 if (length == 0x03) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003083
3084 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003085 FPT_stsyncn(port, p_card);
3086 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087
3088 pCurrSCCB->Sccb_scsimsg = SMREJECT;
3089 ACCEPT_MSG_ATN(port);
3090 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003091 } else if (message == SMWDTR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003092
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003093 if (length == 0x02) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003094
3095 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003096 FPT_stwidn(port, p_card);
3097 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003098
3099 pCurrSCCB->Sccb_scsimsg = SMREJECT;
3100 ACCEPT_MSG_ATN(port);
3101
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003102 WR_HARPOON(port + hp_autostart_1,
3103 (AUTO_IMMED +
3104 DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003106 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107
3108 pCurrSCCB->Sccb_scsimsg = SMREJECT;
3109 ACCEPT_MSG_ATN(port);
3110
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003111 WR_HARPOON(port + hp_autostart_1,
3112 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003113 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003114 } else {
3115 if (pCurrSCCB->Sccb_scsimsg != SMPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003116 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003117 WR_HARPOON(port + hp_autostart_1,
3118 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003120 } else {
3121 if (pCurrSCCB->Sccb_scsimsg == SMPARITY)
3122 WR_HARPOON(port + hp_autostart_1,
3123 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124 }
3125}
3126
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127/*---------------------------------------------------------------------
3128 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003129 * Function: FPT_sisyncn
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130 *
3131 * Description: Read in a message byte from the SCSI bus, and check
3132 * for a parity error.
3133 *
3134 *---------------------------------------------------------------------*/
3135
Khalid Aziz391e2f22013-05-16 19:44:14 -06003136static unsigned char FPT_sisyncn(u32 port, unsigned char p_card,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003137 unsigned char syncFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003139 struct sccb *currSCCB;
3140 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003141
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003142 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3143 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003145 if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003146
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003147 WRW_HARPOON((port + ID_MSG_STRT),
3148 (MPM_OP + AMSG_OUT +
3149 (currSCCB->
3150 Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003151
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003152 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003153
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003154 WRW_HARPOON((port + SYNC_MSGS + 0),
3155 (MPM_OP + AMSG_OUT + SMEXT));
3156 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
3157 WRW_HARPOON((port + SYNC_MSGS + 4),
3158 (MPM_OP + AMSG_OUT + SMSYNC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003160 if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003161
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003162 WRW_HARPOON((port + SYNC_MSGS + 6),
3163 (MPM_OP + AMSG_OUT + 12));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003165 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
3166 EE_SYNC_10MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003168 WRW_HARPOON((port + SYNC_MSGS + 6),
3169 (MPM_OP + AMSG_OUT + 25));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003171 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
3172 EE_SYNC_5MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003173
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003174 WRW_HARPOON((port + SYNC_MSGS + 6),
3175 (MPM_OP + AMSG_OUT + 50));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003178 WRW_HARPOON((port + SYNC_MSGS + 6),
3179 (MPM_OP + AMSG_OUT + 00));
3180
3181 WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
3182 WRW_HARPOON((port + SYNC_MSGS + 10),
3183 (MPM_OP + AMSG_OUT + DEFAULT_OFFSET));
3184 WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
3185
3186 if (syncFlag == 0) {
3187 WR_HARPOON(port + hp_autostart_3,
3188 (SELECT + SELCHK_STRT));
3189 currTar_Info->TarStatus =
3190 ((currTar_Info->
3191 TarStatus & ~(unsigned char)TAR_SYNC_MASK) |
3192 (unsigned char)SYNC_TRYING);
3193 } else {
3194 WR_HARPOON(port + hp_autostart_3,
3195 (AUTO_IMMED + CMD_ONLY_STRT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003196 }
3197
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08003198 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003199 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003200
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003201 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003202
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003203 currTar_Info->TarStatus |= (unsigned char)SYNC_SUPPORTED;
3204 currTar_Info->TarEEValue &= ~EE_SYNC_MASK;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08003205 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003206 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003207}
3208
Linus Torvalds1da177e2005-04-16 15:20:36 -07003209/*---------------------------------------------------------------------
3210 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003211 * Function: FPT_stsyncn
Linus Torvalds1da177e2005-04-16 15:20:36 -07003212 *
3213 * Description: The has sent us a Sync Nego message so handle it as
3214 * necessary.
3215 *
3216 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06003217static void FPT_stsyncn(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003218{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003219 unsigned char sync_msg, offset, sync_reg, our_sync_msg;
3220 struct sccb *currSCCB;
3221 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003222
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003223 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3224 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003225
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003226 sync_msg = FPT_sfm(port, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003228 if ((sync_msg == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3229 WR_HARPOON(port + hp_autostart_1,
3230 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231 return;
3232 }
3233
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003234 ACCEPT_MSG(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003236 offset = FPT_sfm(port, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003237
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003238 if ((offset == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3239 WR_HARPOON(port + hp_autostart_1,
3240 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003241 return;
3242 }
3243
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003244 if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003245
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003246 our_sync_msg = 12; /* Setup our Message to 20mb/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003247
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003248 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_10MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003249
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003250 our_sync_msg = 25; /* Setup our Message to 10mb/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003251
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003252 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_5MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003253
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003254 our_sync_msg = 50; /* Setup our Message to 5mb/s */
3255 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003256
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003257 our_sync_msg = 0; /* Message = Async */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003258
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003259 if (sync_msg < our_sync_msg) {
3260 sync_msg = our_sync_msg; /*if faster, then set to max. */
3261 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003262
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003263 if (offset == ASYNC)
3264 sync_msg = ASYNC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003265
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003266 if (offset > MAX_OFFSET)
3267 offset = MAX_OFFSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003268
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003269 sync_reg = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003270
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003271 if (sync_msg > 12)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003272
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003273 sync_reg = 0x20; /* Use 10MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003274
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003275 if (sync_msg > 25)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003276
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003277 sync_reg = 0x40; /* Use 6.6MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003278
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003279 if (sync_msg > 38)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003280
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003281 sync_reg = 0x60; /* Use 5MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003282
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003283 if (sync_msg > 50)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003284
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003285 sync_reg = 0x80; /* Use 4MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003286
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003287 if (sync_msg > 62)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003288
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003289 sync_reg = 0xA0; /* Use 3.33MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003290
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003291 if (sync_msg > 75)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003292
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003293 sync_reg = 0xC0; /* Use 2.85MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003294
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003295 if (sync_msg > 87)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003296
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003297 sync_reg = 0xE0; /* Use 2.5MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003298
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003299 if (sync_msg > 100) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003300
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003301 sync_reg = 0x00; /* Use ASYNC */
3302 offset = 0x00;
3303 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003304
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003305 if (currTar_Info->TarStatus & WIDE_ENABLED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003306
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003307 sync_reg |= offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003308
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003309 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003310
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003311 sync_reg |= (offset | NARROW_SCSI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003312
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003313 FPT_sssyncv(port, currSCCB->TargID, sync_reg, currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003314
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003315 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003316
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003317 ACCEPT_MSG(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003318
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003319 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3320 ~(unsigned char)TAR_SYNC_MASK) |
3321 (unsigned char)SYNC_SUPPORTED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003322
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003323 WR_HARPOON(port + hp_autostart_1,
3324 (AUTO_IMMED + DISCONNECT_START));
3325 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003326
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003327 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003328
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003329 ACCEPT_MSG_ATN(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003330
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003331 FPT_sisyncr(port, sync_msg, offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003332
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003333 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3334 ~(unsigned char)TAR_SYNC_MASK) |
3335 (unsigned char)SYNC_SUPPORTED);
3336 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003337}
3338
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339/*---------------------------------------------------------------------
3340 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003341 * Function: FPT_sisyncr
Linus Torvalds1da177e2005-04-16 15:20:36 -07003342 *
3343 * Description: Answer the targets sync message.
3344 *
3345 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06003346static void FPT_sisyncr(u32 port, unsigned char sync_pulse,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003347 unsigned char offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003348{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003349 ARAM_ACCESS(port);
3350 WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT));
3351 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
3352 WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMSYNC));
3353 WRW_HARPOON((port + SYNC_MSGS + 6), (MPM_OP + AMSG_OUT + sync_pulse));
3354 WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
3355 WRW_HARPOON((port + SYNC_MSGS + 10), (MPM_OP + AMSG_OUT + offset));
3356 WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
3357 SGRAM_ACCESS(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003358
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003359 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3360 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003362 WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003363
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003364 while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
3365 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003366}
3367
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368/*---------------------------------------------------------------------
3369 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003370 * Function: FPT_siwidn
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371 *
3372 * Description: Read in a message byte from the SCSI bus, and check
3373 * for a parity error.
3374 *
3375 *---------------------------------------------------------------------*/
3376
Khalid Aziz391e2f22013-05-16 19:44:14 -06003377static unsigned char FPT_siwidn(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003378{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003379 struct sccb *currSCCB;
3380 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003382 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3383 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003384
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003385 if (!((currTar_Info->TarStatus & TAR_WIDE_MASK) == WIDE_NEGOCIATED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003386
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003387 WRW_HARPOON((port + ID_MSG_STRT),
3388 (MPM_OP + AMSG_OUT +
3389 (currSCCB->
3390 Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003392 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003393
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003394 WRW_HARPOON((port + SYNC_MSGS + 0),
3395 (MPM_OP + AMSG_OUT + SMEXT));
3396 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
3397 WRW_HARPOON((port + SYNC_MSGS + 4),
3398 (MPM_OP + AMSG_OUT + SMWDTR));
3399 WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
3400 WRW_HARPOON((port + SYNC_MSGS + 8),
3401 (MPM_OP + AMSG_OUT + SM16BIT));
3402 WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003403
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003404 WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003406 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3407 ~(unsigned char)TAR_WIDE_MASK) |
3408 (unsigned char)WIDE_ENABLED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08003410 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003411 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003412
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003413 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003414
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003415 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3416 ~(unsigned char)TAR_WIDE_MASK) |
3417 WIDE_NEGOCIATED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003418
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003419 currTar_Info->TarEEValue &= ~EE_WIDE_SCSI;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08003420 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003421 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003422}
3423
Linus Torvalds1da177e2005-04-16 15:20:36 -07003424/*---------------------------------------------------------------------
3425 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003426 * Function: FPT_stwidn
Linus Torvalds1da177e2005-04-16 15:20:36 -07003427 *
3428 * Description: The has sent us a Wide Nego message so handle it as
3429 * necessary.
3430 *
3431 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06003432static void FPT_stwidn(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003433{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003434 unsigned char width;
3435 struct sccb *currSCCB;
3436 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003437
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003438 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3439 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003440
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003441 width = FPT_sfm(port, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003442
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003443 if ((width == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3444 WR_HARPOON(port + hp_autostart_1,
3445 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003446 return;
3447 }
3448
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003449 if (!(currTar_Info->TarEEValue & EE_WIDE_SCSI))
3450 width = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003451
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003452 if (width) {
3453 currTar_Info->TarStatus |= WIDE_ENABLED;
3454 width = 0;
3455 } else {
3456 width = NARROW_SCSI;
3457 currTar_Info->TarStatus &= ~WIDE_ENABLED;
3458 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003459
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003460 FPT_sssyncv(port, currSCCB->TargID, width, currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003461
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003462 if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003463
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003464 currTar_Info->TarStatus |= WIDE_NEGOCIATED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003465
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003466 if (!
3467 ((currTar_Info->TarStatus & TAR_SYNC_MASK) ==
3468 SYNC_SUPPORTED)) {
3469 ACCEPT_MSG_ATN(port);
3470 ARAM_ACCESS(port);
3471 FPT_sisyncn(port, p_card, 1);
3472 currSCCB->Sccb_scsistat = SELECT_SN_ST;
3473 SGRAM_ACCESS(port);
3474 } else {
3475 ACCEPT_MSG(port);
3476 WR_HARPOON(port + hp_autostart_1,
3477 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003478 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003479 }
3480
3481 else {
3482
3483 ACCEPT_MSG_ATN(port);
3484
3485 if (currTar_Info->TarEEValue & EE_WIDE_SCSI)
3486 width = SM16BIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003487 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003488 width = SM8BIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003490 FPT_siwidr(port, width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003491
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003492 currTar_Info->TarStatus |= (WIDE_NEGOCIATED | WIDE_ENABLED);
3493 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003494}
3495
Linus Torvalds1da177e2005-04-16 15:20:36 -07003496/*---------------------------------------------------------------------
3497 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003498 * Function: FPT_siwidr
Linus Torvalds1da177e2005-04-16 15:20:36 -07003499 *
3500 * Description: Answer the targets Wide nego message.
3501 *
3502 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06003503static void FPT_siwidr(u32 port, unsigned char width)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003504{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003505 ARAM_ACCESS(port);
3506 WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT));
3507 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
3508 WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMWDTR));
3509 WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
3510 WRW_HARPOON((port + SYNC_MSGS + 8), (MPM_OP + AMSG_OUT + width));
3511 WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
3512 SGRAM_ACCESS(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003513
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003514 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3515 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003516
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003517 WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003518
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003519 while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
3520 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003521}
3522
Linus Torvalds1da177e2005-04-16 15:20:36 -07003523/*---------------------------------------------------------------------
3524 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003525 * Function: FPT_sssyncv
Linus Torvalds1da177e2005-04-16 15:20:36 -07003526 *
3527 * Description: Write the desired value to the Sync Register for the
3528 * ID specified.
3529 *
3530 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06003531static void FPT_sssyncv(u32 p_port, unsigned char p_id,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003532 unsigned char p_sync_value,
3533 struct sccb_mgr_tar_info *currTar_Info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003534{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003535 unsigned char index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003536
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003537 index = p_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003538
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003539 switch (index) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003540
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003541 case 0:
3542 index = 12; /* hp_synctarg_0 */
3543 break;
3544 case 1:
3545 index = 13; /* hp_synctarg_1 */
3546 break;
3547 case 2:
3548 index = 14; /* hp_synctarg_2 */
3549 break;
3550 case 3:
3551 index = 15; /* hp_synctarg_3 */
3552 break;
3553 case 4:
3554 index = 8; /* hp_synctarg_4 */
3555 break;
3556 case 5:
3557 index = 9; /* hp_synctarg_5 */
3558 break;
3559 case 6:
3560 index = 10; /* hp_synctarg_6 */
3561 break;
3562 case 7:
3563 index = 11; /* hp_synctarg_7 */
3564 break;
3565 case 8:
3566 index = 4; /* hp_synctarg_8 */
3567 break;
3568 case 9:
3569 index = 5; /* hp_synctarg_9 */
3570 break;
3571 case 10:
3572 index = 6; /* hp_synctarg_10 */
3573 break;
3574 case 11:
3575 index = 7; /* hp_synctarg_11 */
3576 break;
3577 case 12:
3578 index = 0; /* hp_synctarg_12 */
3579 break;
3580 case 13:
3581 index = 1; /* hp_synctarg_13 */
3582 break;
3583 case 14:
3584 index = 2; /* hp_synctarg_14 */
3585 break;
3586 case 15:
3587 index = 3; /* hp_synctarg_15 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003588
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003589 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003590
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003591 WR_HARPOON(p_port + hp_synctarg_base + index, p_sync_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003592
3593 currTar_Info->TarSyncCtrl = p_sync_value;
3594}
3595
Linus Torvalds1da177e2005-04-16 15:20:36 -07003596/*---------------------------------------------------------------------
3597 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003598 * Function: FPT_sresb
Linus Torvalds1da177e2005-04-16 15:20:36 -07003599 *
3600 * Description: Reset the desired card's SCSI bus.
3601 *
3602 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06003603static void FPT_sresb(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003604{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003605 unsigned char scsiID, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003606
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003607 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003608
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003609 WR_HARPOON(port + hp_page_ctrl,
3610 (RD_HARPOON(port + hp_page_ctrl) | G_INT_DISABLE));
3611 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003612
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003613 WR_HARPOON(port + hp_scsictrl_0, SCSI_RST);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003615 scsiID = RD_HARPOON(port + hp_seltimeout);
3616 WR_HARPOON(port + hp_seltimeout, TO_5ms);
3617 WRW_HARPOON((port + hp_intstat), TIMEOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003618
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003619 WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT | START_TO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003620
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003621 while (!(RDW_HARPOON((port + hp_intstat)) & TIMEOUT)) {
3622 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003623
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003624 WR_HARPOON(port + hp_seltimeout, scsiID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003625
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003626 WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003627
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003628 FPT_Wait(port, TO_5ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003630 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003632 WR_HARPOON(port + hp_int_mask, (RD_HARPOON(port + hp_int_mask) | 0x00));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003633
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003634 for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
3635 currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003636
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003637 if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
3638 currTar_Info->TarSyncCtrl = 0;
3639 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
3640 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003641
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003642 if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
3643 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
3644 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003645
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003646 FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003648 FPT_SccbMgrTableInitTarget(p_card, scsiID);
3649 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003650
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003651 FPT_BL_Card[p_card].scanIndex = 0x00;
3652 FPT_BL_Card[p_card].currentSCCB = NULL;
3653 FPT_BL_Card[p_card].globalFlags &= ~(F_TAG_STARTED | F_HOST_XFER_ACT
3654 | F_NEW_SCCB_CMD);
3655 FPT_BL_Card[p_card].cmdCounter = 0x00;
James Bottomley 47b5d692005-04-24 02:38:05 -05003656 FPT_BL_Card[p_card].discQCount = 0x00;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003657 FPT_BL_Card[p_card].tagQ_Lst = 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003658
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003659 for (i = 0; i < QUEUE_DEPTH; i++)
James Bottomley 47b5d692005-04-24 02:38:05 -05003660 FPT_BL_Card[p_card].discQ_Tbl[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003661
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003662 WR_HARPOON(port + hp_page_ctrl,
3663 (RD_HARPOON(port + hp_page_ctrl) & ~G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003664
3665}
3666
3667/*---------------------------------------------------------------------
3668 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003669 * Function: FPT_ssenss
Linus Torvalds1da177e2005-04-16 15:20:36 -07003670 *
3671 * Description: Setup for the Auto Sense command.
3672 *
3673 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003674static void FPT_ssenss(struct sccb_card *pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003675{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003676 unsigned char i;
3677 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003678
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003679 currSCCB = pCurrCard->currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003681 currSCCB->Save_CdbLen = currSCCB->CdbLength;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003683 for (i = 0; i < 6; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003684
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003685 currSCCB->Save_Cdb[i] = currSCCB->Cdb[i];
3686 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003688 currSCCB->CdbLength = SIX_BYTE_CMD;
3689 currSCCB->Cdb[0] = SCSI_REQUEST_SENSE;
3690 currSCCB->Cdb[1] = currSCCB->Cdb[1] & (unsigned char)0xE0; /*Keep LUN. */
3691 currSCCB->Cdb[2] = 0x00;
3692 currSCCB->Cdb[3] = 0x00;
3693 currSCCB->Cdb[4] = currSCCB->RequestSenseLength;
3694 currSCCB->Cdb[5] = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003695
Khalid Aziz391e2f22013-05-16 19:44:14 -06003696 currSCCB->Sccb_XferCnt = (u32)currSCCB->RequestSenseLength;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003697
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003698 currSCCB->Sccb_ATC = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003699
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003700 currSCCB->Sccb_XferState |= F_AUTO_SENSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003702 currSCCB->Sccb_XferState &= ~F_SG_XFER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003703
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003704 currSCCB->Sccb_idmsg = currSCCB->Sccb_idmsg & ~(unsigned char)DISC_PRIV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003705
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003706 currSCCB->ControlByte = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003708 currSCCB->Sccb_MGRFlags &= F_STATUSLOADED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709}
3710
Linus Torvalds1da177e2005-04-16 15:20:36 -07003711/*---------------------------------------------------------------------
3712 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003713 * Function: FPT_sxfrp
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714 *
3715 * Description: Transfer data into the bit bucket until the device
3716 * decides to switch phase.
3717 *
3718 *---------------------------------------------------------------------*/
3719
Khalid Aziz391e2f22013-05-16 19:44:14 -06003720static void FPT_sxfrp(u32 p_port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003721{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003722 unsigned char curr_phz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003724 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003726 if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003727
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003728 FPT_hostDataXferAbort(p_port, p_card,
3729 FPT_BL_Card[p_card].currentSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003730
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003731 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003732
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003733 /* If the Automation handled the end of the transfer then do not
3734 match the phase or we will get out of sync with the ISR. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003735
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003736 if (RDW_HARPOON((p_port + hp_intstat)) &
3737 (BUS_FREE | XFER_CNT_0 | AUTO_INT))
3738 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003739
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003740 WR_HARPOON(p_port + hp_xfercnt_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003741
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003742 curr_phz = RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003743
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003744 WRW_HARPOON((p_port + hp_intstat), XFER_CNT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003745
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003746 WR_HARPOON(p_port + hp_scsisig, curr_phz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003747
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003748 while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET)) &&
3749 (curr_phz ==
3750 (RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ)))
3751 {
3752 if (curr_phz & (unsigned char)SCSI_IOBIT) {
3753 WR_HARPOON(p_port + hp_portctrl_0,
3754 (SCSI_PORT | HOST_PORT | SCSI_INBIT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003755
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003756 if (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
3757 RD_HARPOON(p_port + hp_fifodata_0);
3758 }
3759 } else {
3760 WR_HARPOON(p_port + hp_portctrl_0,
3761 (SCSI_PORT | HOST_PORT | HOST_WRT));
3762 if (RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY) {
3763 WR_HARPOON(p_port + hp_fifodata_0, 0xFA);
3764 }
3765 }
3766 } /* End of While loop for padding data I/O phase */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003767
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003768 while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
3769 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ)
3770 break;
3771 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003772
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003773 WR_HARPOON(p_port + hp_portctrl_0,
3774 (SCSI_PORT | HOST_PORT | SCSI_INBIT));
3775 while (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
3776 RD_HARPOON(p_port + hp_fifodata_0);
3777 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003779 if (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
3780 WR_HARPOON(p_port + hp_autostart_0,
3781 (AUTO_IMMED + DISCONNECT_START));
3782 while (!(RDW_HARPOON((p_port + hp_intstat)) & AUTO_INT)) {
3783 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003784
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003785 if (RDW_HARPOON((p_port + hp_intstat)) &
3786 (ICMD_COMP | ITAR_DISC))
3787 while (!
3788 (RDW_HARPOON((p_port + hp_intstat)) &
3789 (BUS_FREE | RSEL))) ;
3790 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791}
3792
Linus Torvalds1da177e2005-04-16 15:20:36 -07003793/*---------------------------------------------------------------------
3794 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003795 * Function: FPT_schkdd
Linus Torvalds1da177e2005-04-16 15:20:36 -07003796 *
3797 * Description: Make sure data has been flushed from both FIFOs and abort
3798 * the operations if necessary.
3799 *
3800 *---------------------------------------------------------------------*/
3801
Khalid Aziz391e2f22013-05-16 19:44:14 -06003802static void FPT_schkdd(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003803{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003804 unsigned short TimeOutLoop;
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08003805 unsigned char sPhase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003806
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003807 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003808
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003809 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003811 if ((currSCCB->Sccb_scsistat != DATA_OUT_ST) &&
3812 (currSCCB->Sccb_scsistat != DATA_IN_ST)) {
3813 return;
3814 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003815
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003816 if (currSCCB->Sccb_XferState & F_ODD_BALL_CNT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003817
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003818 currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003819
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003820 currSCCB->Sccb_XferCnt = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003821
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003822 currSCCB->Sccb_XferState &= ~F_ODD_BALL_CNT;
3823 WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
3824 WR_HARPOON(port + hp_xferstat, 0x00);
3825 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003826
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003827 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003829 currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003831 currSCCB->Sccb_XferCnt = 0;
3832 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003833
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003834 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
3835 (currSCCB->HostStatus == SCCB_COMPLETE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003836
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003837 currSCCB->HostStatus = SCCB_PARITY_ERR;
3838 WRW_HARPOON((port + hp_intstat), PARITY);
3839 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003840
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003841 FPT_hostDataXferAbort(port, p_card, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003842
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003843 while (RD_HARPOON(port + hp_scsisig) & SCSI_ACK) {
3844 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003846 TimeOutLoop = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003847
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003848 while (RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY) {
3849 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
3850 return;
3851 }
3852 if (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) {
3853 break;
3854 }
3855 if (RDW_HARPOON((port + hp_intstat)) & RESET) {
3856 return;
3857 }
3858 if ((RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
3859 || (TimeOutLoop++ > 0x3000))
3860 break;
3861 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003863 sPhase = RD_HARPOON(port + hp_scsisig) & (SCSI_BSY | S_SCSI_PHZ);
3864 if ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) ||
3865 (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) ||
3866 (sPhase == (SCSI_BSY | S_DATAO_PH)) ||
3867 (sPhase == (SCSI_BSY | S_DATAI_PH))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003868
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003869 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003871 if (!(currSCCB->Sccb_XferState & F_ALL_XFERRED)) {
3872 if (currSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
3873 FPT_phaseDataIn(port, p_card);
3874 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003875
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003876 else {
3877 FPT_phaseDataOut(port, p_card);
3878 }
3879 } else {
3880 FPT_sxfrp(port, p_card);
3881 if (!(RDW_HARPOON((port + hp_intstat)) &
3882 (BUS_FREE | ICMD_COMP | ITAR_DISC | RESET))) {
3883 WRW_HARPOON((port + hp_intstat), AUTO_INT);
3884 FPT_phaseDecode(port, p_card);
3885 }
3886 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003887
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003888 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003890 else {
3891 WR_HARPOON(port + hp_portctrl_0, 0x00);
3892 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003893}
3894
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895/*---------------------------------------------------------------------
3896 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003897 * Function: FPT_sinits
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898 *
3899 * Description: Setup SCCB manager fields in this SCCB.
3900 *
3901 *---------------------------------------------------------------------*/
3902
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003903static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003904{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003905 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003906
Dan Carpenter5d7ebb92009-12-28 20:08:39 +02003907 if ((p_sccb->TargID >= MAX_SCSI_TAR) || (p_sccb->Lun >= MAX_LUN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003908 return;
3909 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003910 currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003912 p_sccb->Sccb_XferState = 0x00;
3913 p_sccb->Sccb_XferCnt = p_sccb->DataLength;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003914
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003915 if ((p_sccb->OperationCode == SCATTER_GATHER_COMMAND) ||
3916 (p_sccb->OperationCode == RESIDUAL_SG_COMMAND)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003917
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003918 p_sccb->Sccb_SGoffset = 0;
3919 p_sccb->Sccb_XferState = F_SG_XFER;
3920 p_sccb->Sccb_XferCnt = 0x00;
3921 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003923 if (p_sccb->DataLength == 0x00)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003924
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003925 p_sccb->Sccb_XferState |= F_ALL_XFERRED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003927 if (p_sccb->ControlByte & F_USE_CMD_Q) {
3928 if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
3929 p_sccb->ControlByte &= ~F_USE_CMD_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003931 else
3932 currTar_Info->TarStatus |= TAG_Q_TRYING;
3933 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934
3935/* For !single SCSI device in system & device allow Disconnect
3936 or command is tag_q type then send Cmd with Disconnect Enable
3937 else send Cmd with Disconnect Disable */
3938
3939/*
James Bottomley 47b5d692005-04-24 02:38:05 -05003940 if (((!(FPT_BL_Card[p_card].globalFlags & F_SINGLE_DEVICE)) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07003941 (currTar_Info->TarStatus & TAR_ALLOW_DISC)) ||
3942 (currTar_Info->TarStatus & TAG_Q_TRYING)) {
3943*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003944 if ((currTar_Info->TarStatus & TAR_ALLOW_DISC) ||
3945 (currTar_Info->TarStatus & TAG_Q_TRYING)) {
3946 p_sccb->Sccb_idmsg =
3947 (unsigned char)(SMIDENT | DISC_PRIV) | p_sccb->Lun;
3948 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003950 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003951
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003952 p_sccb->Sccb_idmsg = (unsigned char)SMIDENT | p_sccb->Lun;
3953 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003955 p_sccb->HostStatus = 0x00;
3956 p_sccb->TargetStatus = 0x00;
3957 p_sccb->Sccb_tag = 0x00;
3958 p_sccb->Sccb_MGRFlags = 0x00;
3959 p_sccb->Sccb_sgseg = 0x00;
3960 p_sccb->Sccb_ATC = 0x00;
3961 p_sccb->Sccb_savedATC = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962/*
3963 p_sccb->SccbVirtDataPtr = 0x00;
3964 p_sccb->Sccb_forwardlink = NULL;
3965 p_sccb->Sccb_backlink = NULL;
3966 */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003967 p_sccb->Sccb_scsistat = BUS_FREE_ST;
3968 p_sccb->SccbStatus = SCCB_IN_PROCESS;
3969 p_sccb->Sccb_scsimsg = SMNO_OP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003970
3971}
3972
Linus Torvalds1da177e2005-04-16 15:20:36 -07003973/*---------------------------------------------------------------------
3974 *
3975 * Function: Phase Decode
3976 *
3977 * Description: Determine the phase and call the appropriate function.
3978 *
3979 *---------------------------------------------------------------------*/
3980
Khalid Aziz391e2f22013-05-16 19:44:14 -06003981static void FPT_phaseDecode(u32 p_port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003983 unsigned char phase_ref;
Khalid Aziz391e2f22013-05-16 19:44:14 -06003984 void (*phase) (u32, unsigned char);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003986 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003987
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003988 phase_ref =
3989 (unsigned char)(RD_HARPOON(p_port + hp_scsisig) & S_SCSI_PHZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003990
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003991 phase = FPT_s_PhaseTbl[phase_ref];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003992
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003993 (*phase) (p_port, p_card); /* Call the correct phase func */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994}
3995
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996/*---------------------------------------------------------------------
3997 *
3998 * Function: Data Out Phase
3999 *
4000 * Description: Start up both the BusMaster and Xbow.
4001 *
4002 *---------------------------------------------------------------------*/
4003
Khalid Aziz391e2f22013-05-16 19:44:14 -06004004static void FPT_phaseDataOut(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004005{
4006
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004007 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004008
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004009 currSCCB = FPT_BL_Card[p_card].currentSCCB;
4010 if (currSCCB == NULL) {
4011 return; /* Exit if No SCCB record */
4012 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004014 currSCCB->Sccb_scsistat = DATA_OUT_ST;
4015 currSCCB->Sccb_XferState &= ~(F_HOST_XFER_DIR | F_NO_DATA_YET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004017 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004018
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004019 WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004020
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004021 WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004022
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004023 FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004024
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004025 if (currSCCB->Sccb_XferCnt == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004026
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004027 if ((currSCCB->ControlByte & SCCB_DATA_XFER_OUT) &&
4028 (currSCCB->HostStatus == SCCB_COMPLETE))
4029 currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004030
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004031 FPT_sxfrp(port, p_card);
4032 if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
4033 FPT_phaseDecode(port, p_card);
4034 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004035}
4036
Linus Torvalds1da177e2005-04-16 15:20:36 -07004037/*---------------------------------------------------------------------
4038 *
4039 * Function: Data In Phase
4040 *
4041 * Description: Startup the BusMaster and the XBOW.
4042 *
4043 *---------------------------------------------------------------------*/
4044
Khalid Aziz391e2f22013-05-16 19:44:14 -06004045static void FPT_phaseDataIn(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046{
4047
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004048 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004049
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004050 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004052 if (currSCCB == NULL) {
4053 return; /* Exit if No SCCB record */
4054 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004056 currSCCB->Sccb_scsistat = DATA_IN_ST;
4057 currSCCB->Sccb_XferState |= F_HOST_XFER_DIR;
4058 currSCCB->Sccb_XferState &= ~F_NO_DATA_YET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004059
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004060 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004061
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004062 WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004064 WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004066 FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004068 if (currSCCB->Sccb_XferCnt == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004070 if ((currSCCB->ControlByte & SCCB_DATA_XFER_IN) &&
4071 (currSCCB->HostStatus == SCCB_COMPLETE))
4072 currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004073
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004074 FPT_sxfrp(port, p_card);
4075 if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
4076 FPT_phaseDecode(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004077
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004078 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079}
4080
4081/*---------------------------------------------------------------------
4082 *
4083 * Function: Command Phase
4084 *
4085 * Description: Load the CDB into the automation and start it up.
4086 *
4087 *---------------------------------------------------------------------*/
4088
Khalid Aziz391e2f22013-05-16 19:44:14 -06004089static void FPT_phaseCommand(u32 p_port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004090{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004091 struct sccb *currSCCB;
Khalid Aziz391e2f22013-05-16 19:44:14 -06004092 u32 cdb_reg;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004093 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004094
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004095 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004096
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004097 if (currSCCB->OperationCode == RESET_COMMAND) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004098
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004099 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4100 currSCCB->CdbLength = SIX_BYTE_CMD;
4101 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004102
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004103 WR_HARPOON(p_port + hp_scsisig, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004104
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004105 ARAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004106
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004107 cdb_reg = p_port + CMD_STRT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004108
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004109 for (i = 0; i < currSCCB->CdbLength; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004111 if (currSCCB->OperationCode == RESET_COMMAND)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004112
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004113 WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + 0x00));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004115 else
4116 WRW_HARPOON(cdb_reg,
4117 (MPM_OP + ACOMMAND + currSCCB->Cdb[i]));
4118 cdb_reg += 2;
4119 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004120
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004121 if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
4122 WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004123
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004124 WR_HARPOON(p_port + hp_portctrl_0, (SCSI_PORT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004125
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004126 currSCCB->Sccb_scsistat = COMMAND_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004128 WR_HARPOON(p_port + hp_autostart_3, (AUTO_IMMED | CMD_ONLY_STRT));
4129 SGRAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004130}
4131
Linus Torvalds1da177e2005-04-16 15:20:36 -07004132/*---------------------------------------------------------------------
4133 *
4134 * Function: Status phase
4135 *
4136 * Description: Bring in the status and command complete message bytes
4137 *
4138 *---------------------------------------------------------------------*/
4139
Khalid Aziz391e2f22013-05-16 19:44:14 -06004140static void FPT_phaseStatus(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004141{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004142 /* Start-up the automation to finish off this command and let the
4143 isr handle the interrupt for command complete when it comes in.
4144 We could wait here for the interrupt to be generated?
4145 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004147 WR_HARPOON(port + hp_scsisig, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004149 WR_HARPOON(port + hp_autostart_0, (AUTO_IMMED + END_DATA_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004150}
4151
Linus Torvalds1da177e2005-04-16 15:20:36 -07004152/*---------------------------------------------------------------------
4153 *
4154 * Function: Phase Message Out
4155 *
4156 * Description: Send out our message (if we have one) and handle whatever
4157 * else is involed.
4158 *
4159 *---------------------------------------------------------------------*/
4160
Khalid Aziz391e2f22013-05-16 19:44:14 -06004161static void FPT_phaseMsgOut(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004162{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004163 unsigned char message, scsiID;
4164 struct sccb *currSCCB;
4165 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004166
James Bottomley 47b5d692005-04-24 02:38:05 -05004167 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168
4169 if (currSCCB != NULL) {
4170
4171 message = currSCCB->Sccb_scsimsg;
4172 scsiID = currSCCB->TargID;
4173
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004174 if (message == SMDEV_RESET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175
James Bottomley 47b5d692005-04-24 02:38:05 -05004176 currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004177 currTar_Info->TarSyncCtrl = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004178 FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004179
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004180 if (FPT_sccbMgrTbl[p_card][scsiID].
4181 TarEEValue & EE_SYNC_MASK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004183 FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
4184 ~TAR_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185
4186 }
4187
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004188 if (FPT_sccbMgrTbl[p_card][scsiID].
4189 TarEEValue & EE_WIDE_SCSI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004190
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004191 FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
4192 ~TAR_WIDE_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004193 }
4194
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004195 FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
4196 FPT_SccbMgrTableInitTarget(p_card, scsiID);
4197 } else if (currSCCB->Sccb_scsistat == ABORT_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004198 currSCCB->HostStatus = SCCB_COMPLETE;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004199 if (FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] !=
4200 NULL) {
4201 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4202 Sccb_tag] = NULL;
James Bottomley 47b5d692005-04-24 02:38:05 -05004203 FPT_sccbMgrTbl[p_card][scsiID].TarTagQ_Cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004204 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004205
Linus Torvalds1da177e2005-04-16 15:20:36 -07004206 }
4207
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004208 else if (currSCCB->Sccb_scsistat < COMMAND_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004210 if (message == SMNO_OP) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004211 currSCCB->Sccb_MGRFlags |= F_DEV_SELECTED;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004212
4213 FPT_ssel(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004214 return;
4215 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004216 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004217
4218 if (message == SMABORT)
4219
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004220 FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004221 }
4222
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004223 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004224 message = SMABORT;
4225 }
4226
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004227 WRW_HARPOON((port + hp_intstat), (BUS_FREE | PHASE | XFER_CNT_0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004228
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004229 WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004231 WR_HARPOON(port + hp_scsidata_0, message);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004232
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004233 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004234
4235 ACCEPT_MSG(port);
4236
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004237 WR_HARPOON(port + hp_portctrl_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004238
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004239 if ((message == SMABORT) || (message == SMDEV_RESET) ||
4240 (message == SMABORT_TAG)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004241
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004242 while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | PHASE))) {
4243 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004244
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004245 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
4246 WRW_HARPOON((port + hp_intstat), BUS_FREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004248 if (currSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004249
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004250 if ((FPT_BL_Card[p_card].
4251 globalFlags & F_CONLUN_IO)
4252 &&
4253 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4254 TarStatus & TAR_TAG_Q_MASK) !=
4255 TAG_Q_TRYING))
4256 FPT_sccbMgrTbl[p_card][currSCCB->
4257 TargID].
4258 TarLUNBusy[currSCCB->Lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004259 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004260 FPT_sccbMgrTbl[p_card][currSCCB->
4261 TargID].
4262 TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004263
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004264 FPT_queueCmdComplete(&FPT_BL_Card[p_card],
4265 currSCCB, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004266 }
4267
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004268 else {
4269 FPT_BL_Card[p_card].globalFlags |=
4270 F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271 }
4272 }
4273
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004274 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004275
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004276 FPT_sxfrp(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004277 }
4278 }
4279
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004280 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004281
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004282 if (message == SMPARITY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283 currSCCB->Sccb_scsimsg = SMNO_OP;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004284 WR_HARPOON(port + hp_autostart_1,
4285 (AUTO_IMMED + DISCONNECT_START));
4286 } else {
4287 FPT_sxfrp(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004288 }
4289 }
4290}
4291
Linus Torvalds1da177e2005-04-16 15:20:36 -07004292/*---------------------------------------------------------------------
4293 *
4294 * Function: Message In phase
4295 *
4296 * Description: Bring in the message and determine what to do with it.
4297 *
4298 *---------------------------------------------------------------------*/
4299
Khalid Aziz391e2f22013-05-16 19:44:14 -06004300static void FPT_phaseMsgIn(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004301{
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08004302 unsigned char message;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004303 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004304
James Bottomley 47b5d692005-04-24 02:38:05 -05004305 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004306
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004307 if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004308
James Bottomley 47b5d692005-04-24 02:38:05 -05004309 FPT_phaseChkFifo(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004310 }
4311
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004312 message = RD_HARPOON(port + hp_scsidata_0);
4313 if ((message == SMDISC) || (message == SMSAVE_DATA_PTR)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004314
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004315 WR_HARPOON(port + hp_autostart_1,
4316 (AUTO_IMMED + END_DATA_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317
4318 }
4319
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004320 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004321
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004322 message = FPT_sfm(port, currSCCB);
4323 if (message) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004324
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004325 FPT_sdecm(message, port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004326
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004327 } else {
4328 if (currSCCB->Sccb_scsimsg != SMPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004329 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004330 WR_HARPOON(port + hp_autostart_1,
4331 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332 }
4333 }
4334
4335}
4336
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337/*---------------------------------------------------------------------
4338 *
4339 * Function: Illegal phase
4340 *
4341 * Description: Target switched to some illegal phase, so all we can do
4342 * is report an error back to the host (if that is possible)
4343 * and send an ABORT message to the misbehaving target.
4344 *
4345 *---------------------------------------------------------------------*/
4346
Khalid Aziz391e2f22013-05-16 19:44:14 -06004347static void FPT_phaseIllegal(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004348{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004349 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004351 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004352
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004353 WR_HARPOON(port + hp_scsisig, RD_HARPOON(port + hp_scsisig));
4354 if (currSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004355
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004356 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4357 currSCCB->Sccb_scsistat = ABORT_ST;
4358 currSCCB->Sccb_scsimsg = SMABORT;
4359 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004360
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004361 ACCEPT_MSG_ATN(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004362}
4363
Linus Torvalds1da177e2005-04-16 15:20:36 -07004364/*---------------------------------------------------------------------
4365 *
4366 * Function: Phase Check FIFO
4367 *
4368 * Description: Make sure data has been flushed from both FIFOs and abort
4369 * the operations if necessary.
4370 *
4371 *---------------------------------------------------------------------*/
4372
Khalid Aziz391e2f22013-05-16 19:44:14 -06004373static void FPT_phaseChkFifo(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004374{
Khalid Aziz391e2f22013-05-16 19:44:14 -06004375 u32 xfercnt;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004376 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004377
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004378 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004379
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004380 if (currSCCB->Sccb_scsistat == DATA_IN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004381
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004382 while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) &&
4383 (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)) {
4384 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004385
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004386 if (!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) {
4387 currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004388
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004389 currSCCB->Sccb_XferCnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004390
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004391 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
4392 (currSCCB->HostStatus == SCCB_COMPLETE)) {
4393 currSCCB->HostStatus = SCCB_PARITY_ERR;
4394 WRW_HARPOON((port + hp_intstat), PARITY);
4395 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004396
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004397 FPT_hostDataXferAbort(port, p_card, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004399 FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004400
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004401 while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY))
4402 && (RD_HARPOON(port + hp_ext_status) &
4403 BM_CMD_BUSY)) {
4404 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004405
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004406 }
4407 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004408
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004409 /*End Data In specific code. */
4410 GET_XFER_CNT(port, xfercnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004411
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004412 WR_HARPOON(port + hp_xfercnt_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004413
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004414 WR_HARPOON(port + hp_portctrl_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004415
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004416 currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - xfercnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004417
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004418 currSCCB->Sccb_XferCnt = xfercnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004419
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004420 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
4421 (currSCCB->HostStatus == SCCB_COMPLETE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004422
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004423 currSCCB->HostStatus = SCCB_PARITY_ERR;
4424 WRW_HARPOON((port + hp_intstat), PARITY);
4425 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004426
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004427 FPT_hostDataXferAbort(port, p_card, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004428
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004429 WR_HARPOON(port + hp_fifowrite, 0x00);
4430 WR_HARPOON(port + hp_fiforead, 0x00);
4431 WR_HARPOON(port + hp_xferstat, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004432
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004433 WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004434}
4435
Linus Torvalds1da177e2005-04-16 15:20:36 -07004436/*---------------------------------------------------------------------
4437 *
4438 * Function: Phase Bus Free
4439 *
4440 * Description: We just went bus free so figure out if it was
4441 * because of command complete or from a disconnect.
4442 *
4443 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06004444static void FPT_phaseBusFree(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004445{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004446 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004447
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004448 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004449
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004450 if (currSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004451
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004452 DISABLE_AUTO(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004453
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004454 if (currSCCB->OperationCode == RESET_COMMAND) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004455
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004456 if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4457 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4458 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4459 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4460 TarLUNBusy[currSCCB->Lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004461 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004462 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4463 TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004464
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004465 FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
4466 p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004467
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004468 FPT_queueSearchSelect(&FPT_BL_Card[p_card], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004469
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004470 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004471
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004472 else if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
4473 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4474 (unsigned char)SYNC_SUPPORTED;
4475 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4476 ~EE_SYNC_MASK;
4477 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004478
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004479 else if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
4480 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
4481 (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4482 TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004483
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004484 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4485 ~EE_WIDE_SCSI;
4486 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004487
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004488 else if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
4489 /* Make sure this is not a phony BUS_FREE. If we were
4490 reselected or if BUSY is NOT on then this is a
4491 valid BUS FREE. SRR Wednesday, 5/10/1995. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004492
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004493 if ((!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ||
4494 (RDW_HARPOON((port + hp_intstat)) & RSEL)) {
4495 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4496 TarStatus &= ~TAR_TAG_Q_MASK;
4497 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4498 TarStatus |= TAG_Q_REJECT;
4499 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004500
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004501 else {
4502 return;
4503 }
4504 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004505
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004506 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004507
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004508 currSCCB->Sccb_scsistat = BUS_FREE_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004509
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004510 if (!currSCCB->HostStatus) {
4511 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4512 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004513
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004514 if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4515 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4516 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4517 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4518 TarLUNBusy[currSCCB->Lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004519 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004520 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4521 TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004522
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004523 FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
4524 p_card);
4525 return;
4526 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004527
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004528 FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004529
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004530 } /*end if !=null */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004531}
4532
Linus Torvalds1da177e2005-04-16 15:20:36 -07004533/*---------------------------------------------------------------------
4534 *
4535 * Function: Auto Load Default Map
4536 *
4537 * Description: Load the Automation RAM with the defualt map values.
4538 *
4539 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06004540static void FPT_autoLoadDefaultMap(u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004541{
Khalid Aziz391e2f22013-05-16 19:44:14 -06004542 u32 map_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004543
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004544 ARAM_ACCESS(p_port);
4545 map_addr = p_port + hp_aramBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004546
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004547 WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0xC0)); /*ID MESSAGE */
4548 map_addr += 2;
4549 WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x20)); /*SIMPLE TAG QUEUEING MSG */
4550 map_addr += 2;
4551 WRW_HARPOON(map_addr, RAT_OP); /*RESET ATTENTION */
4552 map_addr += 2;
4553 WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x00)); /*TAG ID MSG */
4554 map_addr += 2;
4555 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 0 */
4556 map_addr += 2;
4557 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 1 */
4558 map_addr += 2;
4559 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 2 */
4560 map_addr += 2;
4561 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 3 */
4562 map_addr += 2;
4563 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 4 */
4564 map_addr += 2;
4565 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 5 */
4566 map_addr += 2;
4567 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 6 */
4568 map_addr += 2;
4569 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 7 */
4570 map_addr += 2;
4571 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 8 */
4572 map_addr += 2;
4573 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 9 */
4574 map_addr += 2;
4575 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 10 */
4576 map_addr += 2;
4577 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 11 */
4578 map_addr += 2;
4579 WRW_HARPOON(map_addr, (CPE_OP + ADATA_OUT + DINT)); /*JUMP IF DATA OUT */
4580 map_addr += 2;
4581 WRW_HARPOON(map_addr, (TCB_OP + FIFO_0 + DI)); /*JUMP IF NO DATA IN FIFO */
4582 map_addr += 2; /*This means AYNC DATA IN */
4583 WRW_HARPOON(map_addr, (SSI_OP + SSI_IDO_STRT)); /*STOP AND INTERRUPT */
4584 map_addr += 2;
4585 WRW_HARPOON(map_addr, (CPE_OP + ADATA_IN + DINT)); /*JUMP IF NOT DATA IN PHZ */
4586 map_addr += 2;
4587 WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST)); /*IF NOT MSG IN CHECK 4 DATA IN */
4588 map_addr += 2;
4589 WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x02)); /*SAVE DATA PTR MSG? */
4590 map_addr += 2;
4591 WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + DC)); /*GO CHECK FOR DISCONNECT MSG */
4592 map_addr += 2;
4593 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR1)); /*SAVE DATA PTRS MSG */
4594 map_addr += 2;
4595 WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST)); /*IF NOT MSG IN CHECK DATA IN */
4596 map_addr += 2;
4597 WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x04)); /*DISCONNECT MSG? */
4598 map_addr += 2;
4599 WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + UNKNWN)); /*UKNKNOWN MSG */
4600 map_addr += 2;
4601 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET)); /*XFER DISCONNECT MSG */
4602 map_addr += 2;
4603 WRW_HARPOON(map_addr, (SSI_OP + SSI_ITAR_DISC)); /*STOP AND INTERRUPT */
4604 map_addr += 2;
4605 WRW_HARPOON(map_addr, (CPN_OP + ASTATUS + UNKNWN)); /*JUMP IF NOT STATUS PHZ. */
4606 map_addr += 2;
4607 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR0)); /*GET STATUS BYTE */
4608 map_addr += 2;
4609 WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + CC)); /*ERROR IF NOT MSG IN PHZ */
4610 map_addr += 2;
4611 WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x00)); /*CHECK FOR CMD COMPLETE MSG. */
4612 map_addr += 2;
4613 WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + CC)); /*ERROR IF NOT CMD COMPLETE MSG. */
4614 map_addr += 2;
4615 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET)); /*GET CMD COMPLETE MSG */
4616 map_addr += 2;
4617 WRW_HARPOON(map_addr, (SSI_OP + SSI_ICMD_COMP)); /*END OF COMMAND */
4618 map_addr += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004619
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004620 WRW_HARPOON(map_addr, (SSI_OP + SSI_IUNKWN)); /*RECEIVED UNKNOWN MSG BYTE */
4621 map_addr += 2;
4622 WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */
4623 map_addr += 2;
4624 WRW_HARPOON(map_addr, (SSI_OP + SSI_ITICKLE)); /*BIOS Tickled the Mgr */
4625 map_addr += 2;
4626 WRW_HARPOON(map_addr, (SSI_OP + SSI_IRFAIL)); /*EXPECTED ID/TAG MESSAGES AND */
4627 map_addr += 2; /* DIDN'T GET ONE */
4628 WRW_HARPOON(map_addr, (CRR_OP + AR3 + S_IDREG)); /* comp SCSI SEL ID & AR3 */
4629 map_addr += 2;
4630 WRW_HARPOON(map_addr, (BRH_OP + EQUAL + 0x00)); /*SEL ID OK then Conti. */
4631 map_addr += 2;
4632 WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004633
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004634 SGRAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004635}
4636
4637/*---------------------------------------------------------------------
4638 *
4639 * Function: Auto Command Complete
4640 *
4641 * Description: Post command back to host and find another command
4642 * to execute.
4643 *
4644 *---------------------------------------------------------------------*/
4645
Khalid Aziz391e2f22013-05-16 19:44:14 -06004646static void FPT_autoCmdCmplt(u32 p_port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004647{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004648 struct sccb *currSCCB;
4649 unsigned char status_byte;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004650
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004651 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004652
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004653 status_byte = RD_HARPOON(p_port + hp_gp_reg_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004654
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004655 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004656
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004657 if (status_byte != SSGOOD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004658
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004659 if (status_byte == SSQ_FULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004660
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004661 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4662 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4663 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4664 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4665 TarLUNBusy[currSCCB->Lun] = 1;
4666 if (FPT_BL_Card[p_card].discQCount != 0)
James Bottomley 47b5d692005-04-24 02:38:05 -05004667 FPT_BL_Card[p_card].discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004668 FPT_BL_Card[p_card].
4669 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4670 [currSCCB->TargID].
4671 LunDiscQ_Idx[currSCCB->Lun]] =
4672 NULL;
4673 } else {
4674 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4675 TarLUNBusy[0] = 1;
4676 if (currSCCB->Sccb_tag) {
4677 if (FPT_BL_Card[p_card].discQCount != 0)
4678 FPT_BL_Card[p_card].
4679 discQCount--;
4680 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4681 Sccb_tag]
4682 = NULL;
4683 } else {
4684 if (FPT_BL_Card[p_card].discQCount != 0)
4685 FPT_BL_Card[p_card].
4686 discQCount--;
4687 FPT_BL_Card[p_card].
4688 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4689 [currSCCB->TargID].
4690 LunDiscQ_Idx[0]] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004691 }
4692 }
4693
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004694 currSCCB->Sccb_MGRFlags |= F_STATUSLOADED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004695
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004696 FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004697
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004698 return;
4699 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004700
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004701 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
4702 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4703 (unsigned char)SYNC_SUPPORTED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004704
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004705 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4706 ~EE_SYNC_MASK;
4707 FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004708
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004709 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4710 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4711 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4712 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4713 TarLUNBusy[currSCCB->Lun] = 1;
4714 if (FPT_BL_Card[p_card].discQCount != 0)
James Bottomley 47b5d692005-04-24 02:38:05 -05004715 FPT_BL_Card[p_card].discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004716 FPT_BL_Card[p_card].
4717 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4718 [currSCCB->TargID].
4719 LunDiscQ_Idx[currSCCB->Lun]] =
4720 NULL;
4721 } else {
4722 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4723 TarLUNBusy[0] = 1;
4724 if (currSCCB->Sccb_tag) {
4725 if (FPT_BL_Card[p_card].discQCount != 0)
4726 FPT_BL_Card[p_card].
4727 discQCount--;
4728 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4729 Sccb_tag]
4730 = NULL;
4731 } else {
4732 if (FPT_BL_Card[p_card].discQCount != 0)
4733 FPT_BL_Card[p_card].
4734 discQCount--;
4735 FPT_BL_Card[p_card].
4736 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4737 [currSCCB->TargID].
4738 LunDiscQ_Idx[0]] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004739 }
4740 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004741 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004742
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004743 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004744
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004745 if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004746
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004747 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
4748 (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4749 TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004750
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004751 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4752 ~EE_WIDE_SCSI;
4753 FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004754
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004755 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4756 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4757 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4758 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4759 TarLUNBusy[currSCCB->Lun] = 1;
4760 if (FPT_BL_Card[p_card].discQCount != 0)
James Bottomley 47b5d692005-04-24 02:38:05 -05004761 FPT_BL_Card[p_card].discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004762 FPT_BL_Card[p_card].
4763 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4764 [currSCCB->TargID].
4765 LunDiscQ_Idx[currSCCB->Lun]] =
4766 NULL;
4767 } else {
4768 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4769 TarLUNBusy[0] = 1;
4770 if (currSCCB->Sccb_tag) {
4771 if (FPT_BL_Card[p_card].discQCount != 0)
4772 FPT_BL_Card[p_card].
4773 discQCount--;
4774 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4775 Sccb_tag]
4776 = NULL;
4777 } else {
4778 if (FPT_BL_Card[p_card].discQCount != 0)
4779 FPT_BL_Card[p_card].
4780 discQCount--;
4781 FPT_BL_Card[p_card].
4782 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4783 [currSCCB->TargID].
4784 LunDiscQ_Idx[0]] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004785 }
4786 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004787 return;
4788
4789 }
4790
4791 if (status_byte == SSCHECK) {
4792 if (FPT_BL_Card[p_card].globalFlags & F_DO_RENEGO) {
4793 if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4794 TarEEValue & EE_SYNC_MASK) {
4795 FPT_sccbMgrTbl[p_card][currSCCB->
4796 TargID].
4797 TarStatus &= ~TAR_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004798 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004799 if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4800 TarEEValue & EE_WIDE_SCSI) {
4801 FPT_sccbMgrTbl[p_card][currSCCB->
4802 TargID].
4803 TarStatus &= ~TAR_WIDE_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004804 }
4805 }
4806 }
4807
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004808 if (!(currSCCB->Sccb_XferState & F_AUTO_SENSE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004809
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004810 currSCCB->SccbStatus = SCCB_ERROR;
4811 currSCCB->TargetStatus = status_byte;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004812
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004813 if (status_byte == SSCHECK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004814
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004815 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4816 TarLUN_CA = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004817
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004818 if (currSCCB->RequestSenseLength !=
4819 NO_AUTO_REQUEST_SENSE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004820
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004821 if (currSCCB->RequestSenseLength == 0)
4822 currSCCB->RequestSenseLength =
4823 14;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004824
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004825 FPT_ssenss(&FPT_BL_Card[p_card]);
4826 FPT_BL_Card[p_card].globalFlags |=
4827 F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004828
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004829 if (((FPT_BL_Card[p_card].
4830 globalFlags & F_CONLUN_IO)
4831 &&
4832 ((FPT_sccbMgrTbl[p_card]
4833 [currSCCB->TargID].
4834 TarStatus & TAR_TAG_Q_MASK) !=
4835 TAG_Q_TRYING))) {
4836 FPT_sccbMgrTbl[p_card]
4837 [currSCCB->TargID].
4838 TarLUNBusy[currSCCB->Lun] =
4839 1;
4840 if (FPT_BL_Card[p_card].
4841 discQCount != 0)
4842 FPT_BL_Card[p_card].
4843 discQCount--;
4844 FPT_BL_Card[p_card].
4845 discQ_Tbl[FPT_sccbMgrTbl
4846 [p_card]
4847 [currSCCB->
4848 TargID].
4849 LunDiscQ_Idx
4850 [currSCCB->Lun]] =
4851 NULL;
4852 } else {
4853 FPT_sccbMgrTbl[p_card]
4854 [currSCCB->TargID].
4855 TarLUNBusy[0] = 1;
4856 if (currSCCB->Sccb_tag) {
4857 if (FPT_BL_Card[p_card].
4858 discQCount != 0)
4859 FPT_BL_Card
4860 [p_card].
4861 discQCount--;
4862 FPT_BL_Card[p_card].
4863 discQ_Tbl[currSCCB->
4864 Sccb_tag]
4865 = NULL;
4866 } else {
4867 if (FPT_BL_Card[p_card].
4868 discQCount != 0)
4869 FPT_BL_Card
4870 [p_card].
4871 discQCount--;
4872 FPT_BL_Card[p_card].
4873 discQ_Tbl
4874 [FPT_sccbMgrTbl
4875 [p_card][currSCCB->
4876 TargID].
4877 LunDiscQ_Idx[0]] =
4878 NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004879 }
4880 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004881 return;
4882 }
4883 }
4884 }
4885 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004886
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004887 if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4888 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4889 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4890 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->
4891 Lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004892 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004893 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004894
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004895 FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004896}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004897
4898#define SHORT_WAIT 0x0000000F
4899#define LONG_WAIT 0x0000FFFFL
4900
Linus Torvalds1da177e2005-04-16 15:20:36 -07004901/*---------------------------------------------------------------------
4902 *
4903 * Function: Data Transfer Processor
4904 *
4905 * Description: This routine performs two tasks.
4906 * (1) Start data transfer by calling HOST_DATA_XFER_START
4907 * function. Once data transfer is started, (2) Depends
4908 * on the type of data transfer mode Scatter/Gather mode
4909 * or NON Scatter/Gather mode. In NON Scatter/Gather mode,
4910 * this routine checks Sccb_MGRFlag (F_HOST_XFER_ACT bit) for
4911 * data transfer done. In Scatter/Gather mode, this routine
4912 * checks bus master command complete and dual rank busy
4913 * bit to keep chaining SC transfer command. Similarly,
4914 * in Scatter/Gather mode, it checks Sccb_MGRFlag
4915 * (F_HOST_XFER_ACT bit) for data transfer done.
4916 *
4917 *---------------------------------------------------------------------*/
4918
Khalid Aziz391e2f22013-05-16 19:44:14 -06004919static void FPT_dataXferProcessor(u32 port, struct sccb_card *pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004920{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004921 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004922
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004923 currSCCB = pCurrCard->currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004924
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004925 if (currSCCB->Sccb_XferState & F_SG_XFER) {
4926 if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
4927 {
4928 currSCCB->Sccb_sgseg += (unsigned char)SG_BUF_CNT;
4929 currSCCB->Sccb_SGoffset = 0x00;
4930 }
4931 pCurrCard->globalFlags |= F_HOST_XFER_ACT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004932
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004933 FPT_busMstrSGDataXferStart(port, currSCCB);
4934 }
4935
4936 else {
4937 if (!(pCurrCard->globalFlags & F_HOST_XFER_ACT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004938 pCurrCard->globalFlags |= F_HOST_XFER_ACT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004939
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004940 FPT_busMstrDataXferStart(port, currSCCB);
4941 }
4942 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004943}
4944
Linus Torvalds1da177e2005-04-16 15:20:36 -07004945/*---------------------------------------------------------------------
4946 *
4947 * Function: BusMaster Scatter Gather Data Transfer Start
4948 *
4949 * Description:
4950 *
4951 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06004952static void FPT_busMstrSGDataXferStart(u32 p_port, struct sccb *pcurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004953{
Khalid Aziz391e2f22013-05-16 19:44:14 -06004954 u32 count, addr, tmpSGCnt;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004955 unsigned int sg_index;
4956 unsigned char sg_count, i;
Khalid Aziz391e2f22013-05-16 19:44:14 -06004957 u32 reg_offset;
4958 struct blogic_sg_seg *segp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004959
Khalid Aziz391e2f22013-05-16 19:44:14 -06004960 if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)
4961 count = ((u32)HOST_RD_CMD) << 24;
4962 else
4963 count = ((u32)HOST_WRT_CMD) << 24;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004964
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004965 sg_count = 0;
4966 tmpSGCnt = 0;
4967 sg_index = pcurrSCCB->Sccb_sgseg;
4968 reg_offset = hp_aramBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004969
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004970 i = (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
4971 ~(SGRAM_ARAM | SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004972
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004973 WR_HARPOON(p_port + hp_page_ctrl, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004974
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004975 while ((sg_count < (unsigned char)SG_BUF_CNT) &&
Khalid Aziz391e2f22013-05-16 19:44:14 -06004976 ((sg_index * (unsigned int)SG_ELEMENT_SIZE) <
4977 pcurrSCCB->DataLength)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004978
Khalid Aziz391e2f22013-05-16 19:44:14 -06004979 segp = (struct blogic_sg_seg *)(pcurrSCCB->DataPointer) +
4980 sg_index;
4981 tmpSGCnt += segp->segbytes;
4982 count |= segp->segbytes;
4983 addr = segp->segdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004984
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004985 if ((!sg_count) && (pcurrSCCB->Sccb_SGoffset)) {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004986 addr +=
4987 ((count & 0x00FFFFFFL) - pcurrSCCB->Sccb_SGoffset);
4988 count =
4989 (count & 0xFF000000L) | pcurrSCCB->Sccb_SGoffset;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004990 tmpSGCnt = count & 0x00FFFFFFL;
4991 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004992
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004993 WR_HARP32(p_port, reg_offset, addr);
4994 reg_offset += 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004995
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004996 WR_HARP32(p_port, reg_offset, count);
4997 reg_offset += 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004998
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004999 count &= 0xFF000000L;
5000 sg_index++;
5001 sg_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005002
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005003 } /*End While */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005004
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005005 pcurrSCCB->Sccb_XferCnt = tmpSGCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005006
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005007 WR_HARPOON(p_port + hp_sg_addr, (sg_count << 4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005008
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005009 if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005010
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005011 WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005012
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005013 WR_HARPOON(p_port + hp_portctrl_0,
5014 (DMA_PORT | SCSI_PORT | SCSI_INBIT));
5015 WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
5016 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005017
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005018 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005019
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005020 if ((!(RD_HARPOON(p_port + hp_synctarg_0) & NARROW_SCSI)) &&
5021 (tmpSGCnt & 0x000000001)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005022
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005023 pcurrSCCB->Sccb_XferState |= F_ODD_BALL_CNT;
5024 tmpSGCnt--;
5025 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005026
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005027 WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005028
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005029 WR_HARPOON(p_port + hp_portctrl_0,
5030 (SCSI_PORT | DMA_PORT | DMA_RD));
5031 WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
5032 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005033
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005034 WR_HARPOON(p_port + hp_page_ctrl, (unsigned char)(i | SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005035
5036}
5037
Linus Torvalds1da177e2005-04-16 15:20:36 -07005038/*---------------------------------------------------------------------
5039 *
5040 * Function: BusMaster Data Transfer Start
5041 *
5042 * Description:
5043 *
5044 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06005045static void FPT_busMstrDataXferStart(u32 p_port, struct sccb *pcurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005046{
Khalid Aziz391e2f22013-05-16 19:44:14 -06005047 u32 addr, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005048
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005049 if (!(pcurrSCCB->Sccb_XferState & F_AUTO_SENSE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005050
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005051 count = pcurrSCCB->Sccb_XferCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005052
Khalid Aziz391e2f22013-05-16 19:44:14 -06005053 addr = (u32)(unsigned long)pcurrSCCB->DataPointer + pcurrSCCB->Sccb_ATC;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005054 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005055
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005056 else {
5057 addr = pcurrSCCB->SensePointer;
5058 count = pcurrSCCB->RequestSenseLength;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005059
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005060 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005061
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005062 HP_SETUP_ADDR_CNT(p_port, addr, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005063
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005064 if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005065
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005066 WR_HARPOON(p_port + hp_portctrl_0,
5067 (DMA_PORT | SCSI_PORT | SCSI_INBIT));
5068 WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005069
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005070 WR_HARPOON(p_port + hp_xfer_cmd,
5071 (XFER_DMA_HOST | XFER_HOST_AUTO | XFER_DMA_8BIT));
5072 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005073
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005074 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005075
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005076 WR_HARPOON(p_port + hp_portctrl_0,
5077 (SCSI_PORT | DMA_PORT | DMA_RD));
5078 WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005079
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005080 WR_HARPOON(p_port + hp_xfer_cmd,
5081 (XFER_HOST_DMA | XFER_HOST_AUTO | XFER_DMA_8BIT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005082
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005083 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005084}
5085
Linus Torvalds1da177e2005-04-16 15:20:36 -07005086/*---------------------------------------------------------------------
5087 *
5088 * Function: BusMaster Timeout Handler
5089 *
5090 * Description: This function is called after a bus master command busy time
5091 * out is detected. This routines issue halt state machine
5092 * with a software time out for command busy. If command busy
5093 * is still asserted at the end of the time out, it issues
5094 * hard abort with another software time out. It hard abort
5095 * command busy is also time out, it'll just give up.
5096 *
5097 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06005098static unsigned char FPT_busMstrTimeOut(u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005099{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005100 unsigned long timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005101
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005102 timeout = LONG_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005103
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005104 WR_HARPOON(p_port + hp_sys_ctrl, HALT_MACH);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005105
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005106 while ((!(RD_HARPOON(p_port + hp_ext_status) & CMD_ABORTED))
5107 && timeout--) {
5108 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005109
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005110 if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
5111 WR_HARPOON(p_port + hp_sys_ctrl, HARD_ABORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005112
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005113 timeout = LONG_WAIT;
5114 while ((RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY)
5115 && timeout--) {
5116 }
5117 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005118
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005119 RD_HARPOON(p_port + hp_int_status); /*Clear command complete */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005120
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005121 if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005122 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005123 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005124
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005125 else {
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005126 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005127 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005128}
5129
Linus Torvalds1da177e2005-04-16 15:20:36 -07005130/*---------------------------------------------------------------------
5131 *
5132 * Function: Host Data Transfer Abort
5133 *
5134 * Description: Abort any in progress transfer.
5135 *
5136 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06005137static void FPT_hostDataXferAbort(u32 port, unsigned char p_card,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005138 struct sccb *pCurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005139{
5140
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005141 unsigned long timeout;
5142 unsigned long remain_cnt;
Khalid Aziz391e2f22013-05-16 19:44:14 -06005143 u32 sg_ptr;
5144 struct blogic_sg_seg *segp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005145
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005146 FPT_BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005147
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005148 if (pCurrSCCB->Sccb_XferState & F_AUTO_SENSE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005149
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005150 if (!(RD_HARPOON(port + hp_int_status) & INT_CMD_COMPL)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005151
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005152 WR_HARPOON(port + hp_bm_ctrl,
5153 (RD_HARPOON(port + hp_bm_ctrl) |
5154 FLUSH_XFER_CNTR));
5155 timeout = LONG_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005156
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005157 while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
5158 && timeout--) {
5159 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005160
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005161 WR_HARPOON(port + hp_bm_ctrl,
5162 (RD_HARPOON(port + hp_bm_ctrl) &
5163 ~FLUSH_XFER_CNTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005164
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005165 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005166
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005167 if (FPT_busMstrTimeOut(port)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005168
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005169 if (pCurrSCCB->HostStatus == 0x00)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005170
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005171 pCurrSCCB->HostStatus =
5172 SCCB_BM_ERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005173
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005174 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005175
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005176 if (RD_HARPOON(port + hp_int_status) &
5177 INT_EXT_STATUS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005178
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005179 if (RD_HARPOON(port + hp_ext_status) &
5180 BAD_EXT_STATUS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005181
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005182 if (pCurrSCCB->HostStatus ==
5183 0x00)
5184 {
5185 pCurrSCCB->HostStatus =
5186 SCCB_BM_ERR;
5187 }
5188 }
5189 }
5190 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005191
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005192 else if (pCurrSCCB->Sccb_XferCnt) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005193
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005194 if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005195
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005196 WR_HARPOON(port + hp_page_ctrl,
5197 (RD_HARPOON(port + hp_page_ctrl) &
5198 ~SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005199
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005200 WR_HARPOON(port + hp_sg_addr, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005201
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005202 sg_ptr = pCurrSCCB->Sccb_sgseg + SG_BUF_CNT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005203
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005204 if (sg_ptr >
5205 (unsigned int)(pCurrSCCB->DataLength /
5206 SG_ELEMENT_SIZE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005207
Khalid Aziz391e2f22013-05-16 19:44:14 -06005208 sg_ptr = (u32)(pCurrSCCB->DataLength /
5209 SG_ELEMENT_SIZE);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005210 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005211
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005212 remain_cnt = pCurrSCCB->Sccb_XferCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005213
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005214 while (remain_cnt < 0x01000000L) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005215
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005216 sg_ptr--;
Khalid Aziz391e2f22013-05-16 19:44:14 -06005217 segp = (struct blogic_sg_seg *)(pCurrSCCB->
5218 DataPointer) + (sg_ptr * 2);
5219 if (remain_cnt > (unsigned long)segp->segbytes)
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005220 remain_cnt -=
Khalid Aziz391e2f22013-05-16 19:44:14 -06005221 (unsigned long)segp->segbytes;
5222 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005223 break;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005224 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005225
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005226 if (remain_cnt < 0x01000000L) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005227
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005228 pCurrSCCB->Sccb_SGoffset = remain_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005229
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005230 pCurrSCCB->Sccb_sgseg = (unsigned short)sg_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005231
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005232 if ((unsigned long)(sg_ptr * SG_ELEMENT_SIZE) ==
5233 pCurrSCCB->DataLength && (remain_cnt == 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005234
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005235 pCurrSCCB->Sccb_XferState |=
5236 F_ALL_XFERRED;
5237 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005238
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005239 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005240
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005241 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005242
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005243 pCurrSCCB->HostStatus =
5244 SCCB_GROSS_FW_ERR;
5245 }
5246 }
5247 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005248
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005249 if (!(pCurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005250
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005251 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005252
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005253 FPT_busMstrTimeOut(port);
5254 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005255
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005256 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005257
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005258 if (RD_HARPOON(port + hp_int_status) &
5259 INT_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005260
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005261 if (RD_HARPOON(port + hp_ext_status) &
5262 BAD_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005263
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005264 if (pCurrSCCB->HostStatus ==
5265 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005266
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005267 pCurrSCCB->HostStatus =
5268 SCCB_BM_ERR;
5269 }
5270 }
5271 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005272
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005273 }
5274 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005275
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005276 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005277
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005278 if ((RD_HARPOON(port + hp_fifo_cnt)) >= BM_THRESHOLD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005279
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005280 timeout = SHORT_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005281
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005282 while ((RD_HARPOON(port + hp_ext_status) &
5283 BM_CMD_BUSY)
5284 && ((RD_HARPOON(port + hp_fifo_cnt)) >=
5285 BM_THRESHOLD) && timeout--) {
5286 }
5287 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005288
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005289 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005290
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005291 WR_HARPOON(port + hp_bm_ctrl,
5292 (RD_HARPOON(port + hp_bm_ctrl) |
5293 FLUSH_XFER_CNTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005294
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005295 timeout = LONG_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005296
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005297 while ((RD_HARPOON(port + hp_ext_status) &
5298 BM_CMD_BUSY) && timeout--) {
5299 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005300
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005301 WR_HARPOON(port + hp_bm_ctrl,
5302 (RD_HARPOON(port + hp_bm_ctrl) &
5303 ~FLUSH_XFER_CNTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005304
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005305 if (RD_HARPOON(port + hp_ext_status) &
5306 BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005307
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005308 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005309
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005310 pCurrSCCB->HostStatus =
5311 SCCB_BM_ERR;
5312 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005313
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005314 FPT_busMstrTimeOut(port);
5315 }
5316 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005317
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005318 if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005319
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005320 if (RD_HARPOON(port + hp_ext_status) &
5321 BAD_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005322
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005323 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005324
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005325 pCurrSCCB->HostStatus =
5326 SCCB_BM_ERR;
5327 }
5328 }
5329 }
5330 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005331
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005332 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005333
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005334 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005335
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005336 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005337
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005338 timeout = LONG_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005339
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005340 while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
5341 && timeout--) {
5342 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005343
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005344 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005345
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005346 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005347
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005348 pCurrSCCB->HostStatus = SCCB_BM_ERR;
5349 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005350
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005351 FPT_busMstrTimeOut(port);
5352 }
5353 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005354
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005355 if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005356
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005357 if (RD_HARPOON(port + hp_ext_status) & BAD_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005358
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005359 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005360
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005361 pCurrSCCB->HostStatus = SCCB_BM_ERR;
5362 }
5363 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005364
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005365 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005366
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005367 if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005368
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005369 WR_HARPOON(port + hp_page_ctrl,
5370 (RD_HARPOON(port + hp_page_ctrl) &
5371 ~SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005372
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005373 WR_HARPOON(port + hp_sg_addr, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005374
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005375 pCurrSCCB->Sccb_sgseg += SG_BUF_CNT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005376
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005377 pCurrSCCB->Sccb_SGoffset = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005378
Khalid Aziz391e2f22013-05-16 19:44:14 -06005379 if ((u32)(pCurrSCCB->Sccb_sgseg * SG_ELEMENT_SIZE) >=
5380 pCurrSCCB->DataLength) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005381
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005382 pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005383 pCurrSCCB->Sccb_sgseg =
5384 (unsigned short)(pCurrSCCB->DataLength /
5385 SG_ELEMENT_SIZE);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005386 }
5387 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005388
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005389 else {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005390 if (!(pCurrSCCB->Sccb_XferState & F_AUTO_SENSE))
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005391 pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
5392 }
5393 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005394
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005395 WR_HARPOON(port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005396}
5397
Linus Torvalds1da177e2005-04-16 15:20:36 -07005398/*---------------------------------------------------------------------
5399 *
5400 * Function: Host Data Transfer Restart
5401 *
5402 * Description: Reset the available count due to a restore data
5403 * pointers message.
5404 *
5405 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005406static void FPT_hostDataXferRestart(struct sccb *currSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005407{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005408 unsigned long data_count;
5409 unsigned int sg_index;
Khalid Aziz391e2f22013-05-16 19:44:14 -06005410 struct blogic_sg_seg *segp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005411
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005412 if (currSCCB->Sccb_XferState & F_SG_XFER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005413
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005414 currSCCB->Sccb_XferCnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005415
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005416 sg_index = 0xffff; /*Index by long words into sg list. */
Khalid Aziz391e2f22013-05-16 19:44:14 -06005417 data_count = 0; /*Running count of SG xfer counts. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005418
Linus Torvalds1da177e2005-04-16 15:20:36 -07005419
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005420 while (data_count < currSCCB->Sccb_ATC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005421
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005422 sg_index++;
Khalid Aziz391e2f22013-05-16 19:44:14 -06005423 segp = (struct blogic_sg_seg *)(currSCCB->DataPointer) +
5424 (sg_index * 2);
5425 data_count += segp->segbytes;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005426 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005427
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005428 if (data_count == currSCCB->Sccb_ATC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005429
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005430 currSCCB->Sccb_SGoffset = 0;
5431 sg_index++;
5432 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005433
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005434 else {
5435 currSCCB->Sccb_SGoffset =
5436 data_count - currSCCB->Sccb_ATC;
5437 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005438
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005439 currSCCB->Sccb_sgseg = (unsigned short)sg_index;
5440 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005441
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005442 else {
5443 currSCCB->Sccb_XferCnt =
5444 currSCCB->DataLength - currSCCB->Sccb_ATC;
5445 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005446}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005447
Linus Torvalds1da177e2005-04-16 15:20:36 -07005448/*---------------------------------------------------------------------
5449 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005450 * Function: FPT_scini
Linus Torvalds1da177e2005-04-16 15:20:36 -07005451 *
5452 * Description: Setup all data structures necessary for SCAM selection.
5453 *
5454 *---------------------------------------------------------------------*/
5455
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005456static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
5457 unsigned char p_power_up)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005458{
5459
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005460 unsigned char loser, assigned_id;
Khalid Aziz391e2f22013-05-16 19:44:14 -06005461 u32 p_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005462
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005463 unsigned char i, k, ScamFlg;
5464 struct sccb_card *currCard;
5465 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005466
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005467 currCard = &FPT_BL_Card[p_card];
5468 p_port = currCard->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005469 pCurrNvRam = currCard->pNvRamInfo;
5470
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005471 if (pCurrNvRam) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005472 ScamFlg = pCurrNvRam->niScamConf;
5473 i = pCurrNvRam->niSysConf;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005474 } else {
5475 ScamFlg =
5476 (unsigned char)FPT_utilEERead(p_port, SCAM_CONFIG / 2);
5477 i = (unsigned
5478 char)(FPT_utilEERead(p_port, (SYSTEM_CONFIG / 2)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005479 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005480 if (!(i & 0x02)) /* check if reset bus in AutoSCSI parameter set */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005481 return;
5482
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005483 FPT_inisci(p_card, p_port, p_our_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005484
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005485 /* Force to wait 1 sec after SCSI bus reset. Some SCAM device FW
5486 too slow to return to SCAM selection */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005487
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005488 /* if (p_power_up)
5489 FPT_Wait1Second(p_port);
5490 else
5491 FPT_Wait(p_port, TO_250ms); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005492
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005493 FPT_Wait1Second(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005494
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005495 if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2)) {
5496 while (!(FPT_scarb(p_port, INIT_SELTD))) {
5497 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005498
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005499 FPT_scsel(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005500
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005501 do {
5502 FPT_scxferc(p_port, SYNC_PTRN);
5503 FPT_scxferc(p_port, DOM_MSTR);
5504 loser =
5505 FPT_scsendi(p_port,
5506 &FPT_scamInfo[p_our_id].id_string[0]);
5507 } while (loser == 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005508
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005509 FPT_scbusf(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005510
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005511 if ((p_power_up) && (!loser)) {
5512 FPT_sresb(p_port, p_card);
5513 FPT_Wait(p_port, TO_250ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005514
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005515 while (!(FPT_scarb(p_port, INIT_SELTD))) {
5516 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005517
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005518 FPT_scsel(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005519
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005520 do {
5521 FPT_scxferc(p_port, SYNC_PTRN);
5522 FPT_scxferc(p_port, DOM_MSTR);
5523 loser =
5524 FPT_scsendi(p_port,
5525 &FPT_scamInfo[p_our_id].
5526 id_string[0]);
5527 } while (loser == 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005528
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005529 FPT_scbusf(p_port);
5530 }
5531 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005532
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005533 else {
5534 loser = 0;
5535 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005536
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005537 if (!loser) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005538
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005539 FPT_scamInfo[p_our_id].state = ID_ASSIGNED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005540
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005541 if (ScamFlg & SCAM_ENABLED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005542
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005543 for (i = 0; i < MAX_SCSI_TAR; i++) {
5544 if ((FPT_scamInfo[i].state == ID_UNASSIGNED) ||
5545 (FPT_scamInfo[i].state == ID_UNUSED)) {
5546 if (FPT_scsell(p_port, i)) {
5547 FPT_scamInfo[i].state = LEGACY;
5548 if ((FPT_scamInfo[i].
5549 id_string[0] != 0xFF)
5550 || (FPT_scamInfo[i].
5551 id_string[1] != 0xFA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005552
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005553 FPT_scamInfo[i].
5554 id_string[0] = 0xFF;
5555 FPT_scamInfo[i].
5556 id_string[1] = 0xFA;
5557 if (pCurrNvRam == NULL)
5558 currCard->
5559 globalFlags
5560 |=
5561 F_UPDATE_EEPROM;
5562 }
5563 }
5564 }
5565 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005566
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005567 FPT_sresb(p_port, p_card);
5568 FPT_Wait1Second(p_port);
5569 while (!(FPT_scarb(p_port, INIT_SELTD))) {
5570 }
5571 FPT_scsel(p_port);
5572 FPT_scasid(p_card, p_port);
5573 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005574
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005575 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005576
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005577 else if ((loser) && (ScamFlg & SCAM_ENABLED)) {
5578 FPT_scamInfo[p_our_id].id_string[0] = SLV_TYPE_CODE0;
5579 assigned_id = 0;
5580 FPT_scwtsel(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005581
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005582 do {
5583 while (FPT_scxferc(p_port, 0x00) != SYNC_PTRN) {
5584 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005585
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005586 i = FPT_scxferc(p_port, 0x00);
5587 if (i == ASSIGN_ID) {
5588 if (!
5589 (FPT_scsendi
5590 (p_port,
5591 &FPT_scamInfo[p_our_id].id_string[0]))) {
5592 i = FPT_scxferc(p_port, 0x00);
5593 if (FPT_scvalq(i)) {
5594 k = FPT_scxferc(p_port, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005595
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005596 if (FPT_scvalq(k)) {
5597 currCard->ourId =
5598 ((unsigned char)(i
5599 <<
5600 3)
5601 +
5602 (k &
5603 (unsigned char)7))
5604 & (unsigned char)
5605 0x3F;
5606 FPT_inisci(p_card,
5607 p_port,
5608 p_our_id);
5609 FPT_scamInfo[currCard->
5610 ourId].
5611 state = ID_ASSIGNED;
5612 FPT_scamInfo[currCard->
5613 ourId].
5614 id_string[0]
5615 = SLV_TYPE_CODE0;
5616 assigned_id = 1;
5617 }
5618 }
5619 }
5620 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005621
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005622 else if (i == SET_P_FLAG) {
5623 if (!(FPT_scsendi(p_port,
5624 &FPT_scamInfo[p_our_id].
5625 id_string[0])))
5626 FPT_scamInfo[p_our_id].id_string[0] |=
5627 0x80;
5628 }
5629 } while (!assigned_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005630
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005631 while (FPT_scxferc(p_port, 0x00) != CFG_CMPLT) {
5632 }
5633 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005634
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005635 if (ScamFlg & SCAM_ENABLED) {
5636 FPT_scbusf(p_port);
5637 if (currCard->globalFlags & F_UPDATE_EEPROM) {
5638 FPT_scsavdi(p_card, p_port);
5639 currCard->globalFlags &= ~F_UPDATE_EEPROM;
5640 }
5641 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005642
Linus Torvalds1da177e2005-04-16 15:20:36 -07005643/*
5644 for (i=0,k=0; i < MAX_SCSI_TAR; i++)
5645 {
James Bottomley 47b5d692005-04-24 02:38:05 -05005646 if ((FPT_scamInfo[i].state == ID_ASSIGNED) ||
5647 (FPT_scamInfo[i].state == LEGACY))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005648 k++;
5649 }
5650
5651 if (k==2)
5652 currCard->globalFlags |= F_SINGLE_DEVICE;
5653 else
5654 currCard->globalFlags &= ~F_SINGLE_DEVICE;
5655*/
5656}
5657
Linus Torvalds1da177e2005-04-16 15:20:36 -07005658/*---------------------------------------------------------------------
5659 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005660 * Function: FPT_scarb
Linus Torvalds1da177e2005-04-16 15:20:36 -07005661 *
5662 * Description: Gain control of the bus and wait SCAM select time (250ms)
5663 *
5664 *---------------------------------------------------------------------*/
5665
Khalid Aziz391e2f22013-05-16 19:44:14 -06005666static int FPT_scarb(u32 p_port, unsigned char p_sel_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005667{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005668 if (p_sel_type == INIT_SELTD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005669
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005670 while (RD_HARPOON(p_port + hp_scsisig) & (SCSI_SEL | SCSI_BSY)) {
5671 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005672
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005673 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL)
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 if (RD_HARPOON(p_port + hp_scsidata_0) != 00)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005677 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005678
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005679 WR_HARPOON(p_port + hp_scsisig,
5680 (RD_HARPOON(p_port + hp_scsisig) | SCSI_BSY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005681
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005682 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005683
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005684 WR_HARPOON(p_port + hp_scsisig,
5685 (RD_HARPOON(p_port + hp_scsisig) &
5686 ~SCSI_BSY));
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005687 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005688 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005689
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005690 WR_HARPOON(p_port + hp_scsisig,
5691 (RD_HARPOON(p_port + hp_scsisig) | SCSI_SEL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005692
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005693 if (RD_HARPOON(p_port + hp_scsidata_0) != 00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005694
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005695 WR_HARPOON(p_port + hp_scsisig,
5696 (RD_HARPOON(p_port + hp_scsisig) &
5697 ~(SCSI_BSY | SCSI_SEL)));
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005698 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005699 }
5700 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005701
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005702 WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
5703 & ~ACTdeassert));
5704 WR_HARPOON(p_port + hp_scsireset, SCAM_EN);
5705 WR_HARPOON(p_port + hp_scsidata_0, 0x00);
5706 WR_HARPOON(p_port + hp_scsidata_1, 0x00);
5707 WR_HARPOON(p_port + hp_portctrl_0, SCSI_BUS_EN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005708
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005709 WR_HARPOON(p_port + hp_scsisig,
5710 (RD_HARPOON(p_port + hp_scsisig) | SCSI_MSG));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005711
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005712 WR_HARPOON(p_port + hp_scsisig, (RD_HARPOON(p_port + hp_scsisig)
5713 & ~SCSI_BSY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005714
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005715 FPT_Wait(p_port, TO_250ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005716
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005717 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005718}
5719
Linus Torvalds1da177e2005-04-16 15:20:36 -07005720/*---------------------------------------------------------------------
5721 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005722 * Function: FPT_scbusf
Linus Torvalds1da177e2005-04-16 15:20:36 -07005723 *
5724 * Description: Release the SCSI bus and disable SCAM selection.
5725 *
5726 *---------------------------------------------------------------------*/
5727
Khalid Aziz391e2f22013-05-16 19:44:14 -06005728static void FPT_scbusf(u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005729{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005730 WR_HARPOON(p_port + hp_page_ctrl,
5731 (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005732
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005733 WR_HARPOON(p_port + hp_scsidata_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005734
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005735 WR_HARPOON(p_port + hp_portctrl_0, (RD_HARPOON(p_port + hp_portctrl_0)
5736 & ~SCSI_BUS_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005737
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005738 WR_HARPOON(p_port + hp_scsisig, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005739
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005740 WR_HARPOON(p_port + hp_scsireset, (RD_HARPOON(p_port + hp_scsireset)
5741 & ~SCAM_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005742
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005743 WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
5744 | ACTdeassert));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005745
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005746 WRW_HARPOON((p_port + hp_intstat), (BUS_FREE | AUTO_INT | SCAM_SEL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005747
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005748 WR_HARPOON(p_port + hp_page_ctrl,
5749 (RD_HARPOON(p_port + hp_page_ctrl) & ~G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005750}
5751
Linus Torvalds1da177e2005-04-16 15:20:36 -07005752/*---------------------------------------------------------------------
5753 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005754 * Function: FPT_scasid
Linus Torvalds1da177e2005-04-16 15:20:36 -07005755 *
5756 * Description: Assign an ID to all the SCAM devices.
5757 *
5758 *---------------------------------------------------------------------*/
5759
Khalid Aziz391e2f22013-05-16 19:44:14 -06005760static void FPT_scasid(unsigned char p_card, u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005761{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005762 unsigned char temp_id_string[ID_STRING_LENGTH];
Linus Torvalds1da177e2005-04-16 15:20:36 -07005763
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005764 unsigned char i, k, scam_id;
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08005765 unsigned char crcBytes[3];
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005766 struct nvram_info *pCurrNvRam;
5767 unsigned short *pCrcBytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005768
James Bottomley 47b5d692005-04-24 02:38:05 -05005769 pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005770
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005771 i = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005772
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005773 while (!i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005774
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005775 for (k = 0; k < ID_STRING_LENGTH; k++) {
5776 temp_id_string[k] = (unsigned char)0x00;
5777 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005778
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005779 FPT_scxferc(p_port, SYNC_PTRN);
5780 FPT_scxferc(p_port, ASSIGN_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005781
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005782 if (!(FPT_sciso(p_port, &temp_id_string[0]))) {
5783 if (pCurrNvRam) {
Alexey Dobriyanfd1e29e2006-03-08 00:14:27 -08005784 pCrcBytes = (unsigned short *)&crcBytes[0];
James Bottomley 47b5d692005-04-24 02:38:05 -05005785 *pCrcBytes = FPT_CalcCrc16(&temp_id_string[0]);
5786 crcBytes[2] = FPT_CalcLrc(&temp_id_string[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005787 temp_id_string[1] = crcBytes[2];
5788 temp_id_string[2] = crcBytes[0];
5789 temp_id_string[3] = crcBytes[1];
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005790 for (k = 4; k < ID_STRING_LENGTH; k++)
5791 temp_id_string[k] = (unsigned char)0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005792 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005793 i = FPT_scmachid(p_card, temp_id_string);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005794
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005795 if (i == CLR_PRIORITY) {
5796 FPT_scxferc(p_port, MISC_CODE);
5797 FPT_scxferc(p_port, CLR_P_FLAG);
5798 i = 0; /*Not the last ID yet. */
5799 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005800
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005801 else if (i != NO_ID_AVAIL) {
5802 if (i < 8)
5803 FPT_scxferc(p_port, ID_0_7);
5804 else
5805 FPT_scxferc(p_port, ID_8_F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005806
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005807 scam_id = (i & (unsigned char)0x07);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005808
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005809 for (k = 1; k < 0x08; k <<= 1)
5810 if (!(k & i))
5811 scam_id += 0x08; /*Count number of zeros in DB0-3. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005812
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005813 FPT_scxferc(p_port, scam_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005814
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005815 i = 0; /*Not the last ID yet. */
5816 }
5817 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005818
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005819 else {
5820 i = 1;
5821 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005822
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005823 } /*End while */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005824
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005825 FPT_scxferc(p_port, SYNC_PTRN);
5826 FPT_scxferc(p_port, CFG_CMPLT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005827}
5828
Linus Torvalds1da177e2005-04-16 15:20:36 -07005829/*---------------------------------------------------------------------
5830 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005831 * Function: FPT_scsel
Linus Torvalds1da177e2005-04-16 15:20:36 -07005832 *
5833 * Description: Select all the SCAM devices.
5834 *
5835 *---------------------------------------------------------------------*/
5836
Khalid Aziz391e2f22013-05-16 19:44:14 -06005837static void FPT_scsel(u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005838{
5839
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005840 WR_HARPOON(p_port + hp_scsisig, SCSI_SEL);
5841 FPT_scwiros(p_port, SCSI_MSG);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005842
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005843 WR_HARPOON(p_port + hp_scsisig, (SCSI_SEL | SCSI_BSY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005844
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005845 WR_HARPOON(p_port + hp_scsisig,
5846 (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5847 WR_HARPOON(p_port + hp_scsidata_0,
5848 (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) |
5849 (unsigned char)(BIT(7) + BIT(6))));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005850
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005851 WR_HARPOON(p_port + hp_scsisig, (SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5852 FPT_scwiros(p_port, SCSI_SEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005853
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005854 WR_HARPOON(p_port + hp_scsidata_0,
5855 (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) &
5856 ~(unsigned char)BIT(6)));
5857 FPT_scwirod(p_port, BIT(6));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005858
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005859 WR_HARPOON(p_port + hp_scsisig,
5860 (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005861}
5862
Linus Torvalds1da177e2005-04-16 15:20:36 -07005863/*---------------------------------------------------------------------
5864 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005865 * Function: FPT_scxferc
Linus Torvalds1da177e2005-04-16 15:20:36 -07005866 *
5867 * Description: Handshake the p_data (DB4-0) across the bus.
5868 *
5869 *---------------------------------------------------------------------*/
5870
Khalid Aziz391e2f22013-05-16 19:44:14 -06005871static unsigned char FPT_scxferc(u32 p_port, unsigned char p_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005872{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005873 unsigned char curr_data, ret_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005874
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005875 curr_data = p_data | BIT(7) | BIT(5); /*Start with DB7 & DB5 asserted. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005876
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005877 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005878
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005879 curr_data &= ~BIT(7);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005880
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005881 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005882
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005883 FPT_scwirod(p_port, BIT(7)); /*Wait for DB7 to be released. */
5884 while (!(RD_HARPOON(p_port + hp_scsidata_0) & BIT(5))) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005885
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005886 ret_data = (RD_HARPOON(p_port + hp_scsidata_0) & (unsigned char)0x1F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005887
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005888 curr_data |= BIT(6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005889
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005890 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005891
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005892 curr_data &= ~BIT(5);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005893
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005894 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005895
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005896 FPT_scwirod(p_port, BIT(5)); /*Wait for DB5 to be released. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005897
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005898 curr_data &= ~(BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0)); /*Release data bits */
5899 curr_data |= BIT(7);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005900
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005901 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005902
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005903 curr_data &= ~BIT(6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005904
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005905 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005906
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005907 FPT_scwirod(p_port, BIT(6)); /*Wait for DB6 to be released. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005908
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005909 return ret_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005910}
5911
Linus Torvalds1da177e2005-04-16 15:20:36 -07005912/*---------------------------------------------------------------------
5913 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005914 * Function: FPT_scsendi
Linus Torvalds1da177e2005-04-16 15:20:36 -07005915 *
5916 * Description: Transfer our Identification string to determine if we
5917 * will be the dominant master.
5918 *
5919 *---------------------------------------------------------------------*/
5920
Khalid Aziz391e2f22013-05-16 19:44:14 -06005921static unsigned char FPT_scsendi(u32 p_port, unsigned char p_id_string[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07005922{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005923 unsigned char ret_data, byte_cnt, bit_cnt, defer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005924
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005925 defer = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005926
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005927 for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005928
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005929 for (bit_cnt = 0x80; bit_cnt != 0; bit_cnt >>= 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005930
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005931 if (defer)
5932 ret_data = FPT_scxferc(p_port, 00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005933
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005934 else if (p_id_string[byte_cnt] & bit_cnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005935
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005936 ret_data = FPT_scxferc(p_port, 02);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005937
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005938 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005939
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005940 ret_data = FPT_scxferc(p_port, 01);
5941 if (ret_data & 02)
5942 defer = 1;
5943 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005944
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005945 if ((ret_data & 0x1C) == 0x10)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005946 return 0x00; /*End of isolation stage, we won! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005947
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005948 if (ret_data & 0x1C)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005949 return 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005950
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005951 if ((defer) && (!(ret_data & 0x1F)))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005952 return 0x01; /*End of isolation stage, we lost. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005953
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005954 } /*bit loop */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005955
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005956 } /*byte loop */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005957
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005958 if (defer)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005959 return 0x01; /*We lost */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005960 else
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005961 return 0; /*We WON! Yeeessss! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005962}
5963
Linus Torvalds1da177e2005-04-16 15:20:36 -07005964/*---------------------------------------------------------------------
5965 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005966 * Function: FPT_sciso
Linus Torvalds1da177e2005-04-16 15:20:36 -07005967 *
5968 * Description: Transfer the Identification string.
5969 *
5970 *---------------------------------------------------------------------*/
5971
Khalid Aziz391e2f22013-05-16 19:44:14 -06005972static unsigned char FPT_sciso(u32 p_port, unsigned char p_id_string[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07005973{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005974 unsigned char ret_data, the_data, byte_cnt, bit_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005975
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005976 the_data = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005977
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005978 for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005979
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005980 for (bit_cnt = 0; bit_cnt < 8; bit_cnt++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005981
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005982 ret_data = FPT_scxferc(p_port, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005983
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005984 if (ret_data & 0xFC)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005985 return 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005986
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005987 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005988
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005989 the_data <<= 1;
5990 if (ret_data & BIT(1)) {
5991 the_data |= 1;
5992 }
5993 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005994
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005995 if ((ret_data & 0x1F) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005996/*
5997 if(bit_cnt != 0 || bit_cnt != 8)
5998 {
5999 byte_cnt = 0;
6000 bit_cnt = 0;
James Bottomley 47b5d692005-04-24 02:38:05 -05006001 FPT_scxferc(p_port, SYNC_PTRN);
6002 FPT_scxferc(p_port, ASSIGN_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006003 continue;
6004 }
6005*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006006 if (byte_cnt)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006007 return 0x00;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006008 else
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006009 return 0xFF;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006010 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006011
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006012 } /*bit loop */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006013
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006014 p_id_string[byte_cnt] = the_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006015
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006016 } /*byte loop */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006017
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006018 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006019}
6020
Linus Torvalds1da177e2005-04-16 15:20:36 -07006021/*---------------------------------------------------------------------
6022 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006023 * Function: FPT_scwirod
Linus Torvalds1da177e2005-04-16 15:20:36 -07006024 *
6025 * Description: Sample the SCSI data bus making sure the signal has been
6026 * deasserted for the correct number of consecutive samples.
6027 *
6028 *---------------------------------------------------------------------*/
6029
Khalid Aziz391e2f22013-05-16 19:44:14 -06006030static void FPT_scwirod(u32 p_port, unsigned char p_data_bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006031{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006032 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006033
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006034 i = 0;
6035 while (i < MAX_SCSI_TAR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006036
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006037 if (RD_HARPOON(p_port + hp_scsidata_0) & p_data_bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006038
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006039 i = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006040
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006041 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07006042
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006043 i++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006044
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006045 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006046}
6047
Linus Torvalds1da177e2005-04-16 15:20:36 -07006048/*---------------------------------------------------------------------
6049 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006050 * Function: FPT_scwiros
Linus Torvalds1da177e2005-04-16 15:20:36 -07006051 *
6052 * Description: Sample the SCSI Signal lines making sure the signal has been
6053 * deasserted for the correct number of consecutive samples.
6054 *
6055 *---------------------------------------------------------------------*/
6056
Khalid Aziz391e2f22013-05-16 19:44:14 -06006057static void FPT_scwiros(u32 p_port, unsigned char p_data_bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006058{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006059 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006060
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006061 i = 0;
6062 while (i < MAX_SCSI_TAR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006063
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006064 if (RD_HARPOON(p_port + hp_scsisig) & p_data_bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006065
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006066 i = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006067
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006068 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07006069
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006070 i++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006071
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006072 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006073}
6074
Linus Torvalds1da177e2005-04-16 15:20:36 -07006075/*---------------------------------------------------------------------
6076 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006077 * Function: FPT_scvalq
Linus Torvalds1da177e2005-04-16 15:20:36 -07006078 *
6079 * Description: Make sure we received a valid data byte.
6080 *
6081 *---------------------------------------------------------------------*/
6082
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08006083static unsigned char FPT_scvalq(unsigned char p_quintet)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006084{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006085 unsigned char count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006086
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006087 for (count = 1; count < 0x08; count <<= 1) {
6088 if (!(p_quintet & count))
6089 p_quintet -= 0x80;
6090 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006091
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006092 if (p_quintet & 0x18)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006093 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006094
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006095 else
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006096 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006097}
6098
Linus Torvalds1da177e2005-04-16 15:20:36 -07006099/*---------------------------------------------------------------------
6100 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006101 * Function: FPT_scsell
Linus Torvalds1da177e2005-04-16 15:20:36 -07006102 *
6103 * Description: Select the specified device ID using a selection timeout
6104 * less than 4ms. If somebody responds then it is a legacy
6105 * drive and this ID must be marked as such.
6106 *
6107 *---------------------------------------------------------------------*/
6108
Khalid Aziz391e2f22013-05-16 19:44:14 -06006109static unsigned char FPT_scsell(u32 p_port, unsigned char targ_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006110{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006111 unsigned long i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006112
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006113 WR_HARPOON(p_port + hp_page_ctrl,
6114 (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006115
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006116 ARAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006117
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006118 WR_HARPOON(p_port + hp_addstat,
6119 (RD_HARPOON(p_port + hp_addstat) | SCAM_TIMER));
6120 WR_HARPOON(p_port + hp_seltimeout, TO_4ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006121
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006122 for (i = p_port + CMD_STRT; i < p_port + CMD_STRT + 12; i += 2) {
6123 WRW_HARPOON(i, (MPM_OP + ACOMMAND));
6124 }
6125 WRW_HARPOON(i, (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006126
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006127 WRW_HARPOON((p_port + hp_intstat),
6128 (RESET | TIMEOUT | SEL | BUS_FREE | AUTO_INT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006129
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006130 WR_HARPOON(p_port + hp_select_id, targ_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006131
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006132 WR_HARPOON(p_port + hp_portctrl_0, SCSI_PORT);
6133 WR_HARPOON(p_port + hp_autostart_3, (SELECT | CMD_ONLY_STRT));
6134 WR_HARPOON(p_port + hp_scsictrl_0, (SEL_TAR | ENA_RESEL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006135
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006136 while (!(RDW_HARPOON((p_port + hp_intstat)) &
6137 (RESET | PROG_HLT | TIMEOUT | AUTO_INT))) {
6138 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006139
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006140 if (RDW_HARPOON((p_port + hp_intstat)) & RESET)
6141 FPT_Wait(p_port, TO_250ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006142
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006143 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006144
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006145 WR_HARPOON(p_port + hp_addstat,
6146 (RD_HARPOON(p_port + hp_addstat) & ~SCAM_TIMER));
6147 WR_HARPOON(p_port + hp_seltimeout, TO_290ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006148
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006149 SGRAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006150
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006151 if (RDW_HARPOON((p_port + hp_intstat)) & (RESET | TIMEOUT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006152
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006153 WRW_HARPOON((p_port + hp_intstat),
6154 (RESET | TIMEOUT | SEL | BUS_FREE | PHASE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006155
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006156 WR_HARPOON(p_port + hp_page_ctrl,
6157 (RD_HARPOON(p_port + hp_page_ctrl) &
6158 ~G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006159
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006160 return 0; /*No legacy device */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006161 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006162
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006163 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006164
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006165 while (!(RDW_HARPOON((p_port + hp_intstat)) & BUS_FREE)) {
6166 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ) {
6167 WR_HARPOON(p_port + hp_scsisig,
6168 (SCSI_ACK + S_ILL_PH));
6169 ACCEPT_MSG(p_port);
6170 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006171 }
6172
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006173 WRW_HARPOON((p_port + hp_intstat), CLR_ALL_INT_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006174
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006175 WR_HARPOON(p_port + hp_page_ctrl,
6176 (RD_HARPOON(p_port + hp_page_ctrl) &
6177 ~G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006178
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006179 return 1; /*Found one of them oldies! */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006180 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006181}
6182
Linus Torvalds1da177e2005-04-16 15:20:36 -07006183/*---------------------------------------------------------------------
6184 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006185 * Function: FPT_scwtsel
Linus Torvalds1da177e2005-04-16 15:20:36 -07006186 *
6187 * Description: Wait to be selected by another SCAM initiator.
6188 *
6189 *---------------------------------------------------------------------*/
6190
Khalid Aziz391e2f22013-05-16 19:44:14 -06006191static void FPT_scwtsel(u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006192{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006193 while (!(RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL)) {
6194 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006195}
6196
Linus Torvalds1da177e2005-04-16 15:20:36 -07006197/*---------------------------------------------------------------------
6198 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006199 * Function: FPT_inisci
Linus Torvalds1da177e2005-04-16 15:20:36 -07006200 *
6201 * Description: Setup the data Structure with the info from the EEPROM.
6202 *
6203 *---------------------------------------------------------------------*/
6204
Khalid Aziz391e2f22013-05-16 19:44:14 -06006205static void FPT_inisci(unsigned char p_card, u32 p_port, unsigned char p_our_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006206{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006207 unsigned char i, k, max_id;
6208 unsigned short ee_data;
6209 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006210
James Bottomley 47b5d692005-04-24 02:38:05 -05006211 pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006212
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006213 if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6214 max_id = 0x08;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006215
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006216 else
6217 max_id = 0x10;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006218
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006219 if (pCurrNvRam) {
6220 for (i = 0; i < max_id; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006221
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006222 for (k = 0; k < 4; k++)
6223 FPT_scamInfo[i].id_string[k] =
6224 pCurrNvRam->niScamTbl[i][k];
6225 for (k = 4; k < ID_STRING_LENGTH; k++)
6226 FPT_scamInfo[i].id_string[k] =
6227 (unsigned char)0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006228
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006229 if (FPT_scamInfo[i].id_string[0] == 0x00)
6230 FPT_scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */
6231 else
6232 FPT_scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006233
6234 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006235 } else {
6236 for (i = 0; i < max_id; i++) {
6237 for (k = 0; k < ID_STRING_LENGTH; k += 2) {
6238 ee_data =
6239 FPT_utilEERead(p_port,
6240 (unsigned
6241 short)((EE_SCAMBASE / 2) +
6242 (unsigned short)(i *
6243 ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
6244 FPT_scamInfo[i].id_string[k] =
6245 (unsigned char)ee_data;
6246 ee_data >>= 8;
6247 FPT_scamInfo[i].id_string[k + 1] =
6248 (unsigned char)ee_data;
6249 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006250
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006251 if ((FPT_scamInfo[i].id_string[0] == 0x00) ||
6252 (FPT_scamInfo[i].id_string[0] == 0xFF))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006253
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006254 FPT_scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006255
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006256 else
6257 FPT_scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006258
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006259 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006260 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006261 for (k = 0; k < ID_STRING_LENGTH; k++)
James Bottomley 47b5d692005-04-24 02:38:05 -05006262 FPT_scamInfo[p_our_id].id_string[k] = FPT_scamHAString[k];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006263
6264}
6265
6266/*---------------------------------------------------------------------
6267 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006268 * Function: FPT_scmachid
Linus Torvalds1da177e2005-04-16 15:20:36 -07006269 *
6270 * Description: Match the Device ID string with our values stored in
6271 * the EEPROM.
6272 *
6273 *---------------------------------------------------------------------*/
6274
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006275static unsigned char FPT_scmachid(unsigned char p_card,
6276 unsigned char p_id_string[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07006277{
6278
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006279 unsigned char i, k, match;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006280
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006281 for (i = 0; i < MAX_SCSI_TAR; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006282
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006283 match = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006284
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006285 for (k = 0; k < ID_STRING_LENGTH; k++) {
6286 if (p_id_string[k] != FPT_scamInfo[i].id_string[k])
6287 match = 0;
6288 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006289
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006290 if (match) {
6291 FPT_scamInfo[i].state = ID_ASSIGNED;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006292 return i;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006293 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006294
Linus Torvalds1da177e2005-04-16 15:20:36 -07006295 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006296
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006297 if (p_id_string[0] & BIT(5))
6298 i = 8;
6299 else
6300 i = MAX_SCSI_TAR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006301
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006302 if (((p_id_string[0] & 0x06) == 0x02)
6303 || ((p_id_string[0] & 0x06) == 0x04))
6304 match = p_id_string[1] & (unsigned char)0x1F;
6305 else
6306 match = 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006307
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006308 while (i > 0) {
6309 i--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006310
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006311 if (FPT_scamInfo[match].state == ID_UNUSED) {
6312 for (k = 0; k < ID_STRING_LENGTH; k++) {
6313 FPT_scamInfo[match].id_string[k] =
6314 p_id_string[k];
6315 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006316
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006317 FPT_scamInfo[match].state = ID_ASSIGNED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006318
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006319 if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
6320 FPT_BL_Card[p_card].globalFlags |=
6321 F_UPDATE_EEPROM;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006322 return match;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006323
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006324 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006325
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006326 match--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006327
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006328 if (match == 0xFF) {
6329 if (p_id_string[0] & BIT(5))
6330 match = 7;
6331 else
6332 match = MAX_SCSI_TAR - 1;
6333 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006334 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006335
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006336 if (p_id_string[0] & BIT(7)) {
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006337 return CLR_PRIORITY;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006338 }
6339
6340 if (p_id_string[0] & BIT(5))
6341 i = 8;
6342 else
6343 i = MAX_SCSI_TAR;
6344
6345 if (((p_id_string[0] & 0x06) == 0x02)
6346 || ((p_id_string[0] & 0x06) == 0x04))
6347 match = p_id_string[1] & (unsigned char)0x1F;
6348 else
6349 match = 7;
6350
6351 while (i > 0) {
6352
6353 i--;
6354
6355 if (FPT_scamInfo[match].state == ID_UNASSIGNED) {
6356 for (k = 0; k < ID_STRING_LENGTH; k++) {
6357 FPT_scamInfo[match].id_string[k] =
6358 p_id_string[k];
6359 }
6360
6361 FPT_scamInfo[match].id_string[0] |= BIT(7);
6362 FPT_scamInfo[match].state = ID_ASSIGNED;
6363 if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
6364 FPT_BL_Card[p_card].globalFlags |=
6365 F_UPDATE_EEPROM;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006366 return match;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006367
6368 }
6369
6370 match--;
6371
6372 if (match == 0xFF) {
6373 if (p_id_string[0] & BIT(5))
6374 match = 7;
6375 else
6376 match = MAX_SCSI_TAR - 1;
6377 }
6378 }
6379
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006380 return NO_ID_AVAIL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006381}
6382
Linus Torvalds1da177e2005-04-16 15:20:36 -07006383/*---------------------------------------------------------------------
6384 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006385 * Function: FPT_scsavdi
Linus Torvalds1da177e2005-04-16 15:20:36 -07006386 *
6387 * Description: Save off the device SCAM ID strings.
6388 *
6389 *---------------------------------------------------------------------*/
6390
Khalid Aziz391e2f22013-05-16 19:44:14 -06006391static void FPT_scsavdi(unsigned char p_card, u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006392{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006393 unsigned char i, k, max_id;
6394 unsigned short ee_data, sum_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006395
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006396 sum_data = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006397
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006398 for (i = 1; i < EE_SCAMBASE / 2; i++) {
6399 sum_data += FPT_utilEERead(p_port, i);
6400 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006401
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006402 FPT_utilEEWriteOnOff(p_port, 1); /* Enable write access to the EEPROM */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006403
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006404 if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6405 max_id = 0x08;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006406
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006407 else
6408 max_id = 0x10;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006409
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006410 for (i = 0; i < max_id; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006411
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006412 for (k = 0; k < ID_STRING_LENGTH; k += 2) {
6413 ee_data = FPT_scamInfo[i].id_string[k + 1];
6414 ee_data <<= 8;
6415 ee_data |= FPT_scamInfo[i].id_string[k];
6416 sum_data += ee_data;
6417 FPT_utilEEWrite(p_port, ee_data,
6418 (unsigned short)((EE_SCAMBASE / 2) +
6419 (unsigned short)(i *
6420 ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
6421 }
6422 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006423
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006424 FPT_utilEEWrite(p_port, sum_data, EEPROM_CHECK_SUM / 2);
6425 FPT_utilEEWriteOnOff(p_port, 0); /* Turn off write access */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006426}
Linus Torvalds1da177e2005-04-16 15:20:36 -07006427
6428/*---------------------------------------------------------------------
6429 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006430 * Function: FPT_XbowInit
Linus Torvalds1da177e2005-04-16 15:20:36 -07006431 *
6432 * Description: Setup the Xbow for normal operation.
6433 *
6434 *---------------------------------------------------------------------*/
6435
Khalid Aziz391e2f22013-05-16 19:44:14 -06006436static void FPT_XbowInit(u32 port, unsigned char ScamFlg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006437{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006438 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006439
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006440 i = RD_HARPOON(port + hp_page_ctrl);
6441 WR_HARPOON(port + hp_page_ctrl, (unsigned char)(i | G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006442
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006443 WR_HARPOON(port + hp_scsireset, 0x00);
6444 WR_HARPOON(port + hp_portctrl_1, HOST_MODE8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006445
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006446 WR_HARPOON(port + hp_scsireset, (DMA_RESET | HPSCSI_RESET | PROG_RESET |
6447 FIFO_CLR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006448
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006449 WR_HARPOON(port + hp_scsireset, SCSI_INI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006450
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006451 WR_HARPOON(port + hp_clkctrl_0, CLKCTRL_DEFAULT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006452
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006453 WR_HARPOON(port + hp_scsisig, 0x00); /* Clear any signals we might */
6454 WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006455
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006456 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006457
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006458 FPT_default_intena = RESET | RSEL | PROG_HLT | TIMEOUT |
6459 BUS_FREE | XFER_CNT_0 | AUTO_INT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006460
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006461 if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2))
James Bottomley 47b5d692005-04-24 02:38:05 -05006462 FPT_default_intena |= SCAM_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006463
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006464 WRW_HARPOON((port + hp_intena), FPT_default_intena);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006465
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006466 WR_HARPOON(port + hp_seltimeout, TO_290ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006467
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006468 /* Turn on SCSI_MODE8 for narrow cards to fix the
6469 strapping issue with the DUAL CHANNEL card */
6470 if (RD_HARPOON(port + hp_page_ctrl) & NARROW_SCSI_CARD)
6471 WR_HARPOON(port + hp_addstat, SCSI_MODE8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006472
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006473 WR_HARPOON(port + hp_page_ctrl, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006474
6475}
6476
Linus Torvalds1da177e2005-04-16 15:20:36 -07006477/*---------------------------------------------------------------------
6478 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006479 * Function: FPT_BusMasterInit
Linus Torvalds1da177e2005-04-16 15:20:36 -07006480 *
6481 * Description: Initialize the BusMaster for normal operations.
6482 *
6483 *---------------------------------------------------------------------*/
6484
Khalid Aziz391e2f22013-05-16 19:44:14 -06006485static void FPT_BusMasterInit(u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006486{
6487
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006488 WR_HARPOON(p_port + hp_sys_ctrl, DRVR_RST);
6489 WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006490
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006491 WR_HARPOON(p_port + hp_host_blk_cnt, XFER_BLK64);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006492
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006493 WR_HARPOON(p_port + hp_bm_ctrl, (BMCTRL_DEFAULT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006494
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006495 WR_HARPOON(p_port + hp_ee_ctrl, (SCSI_TERM_ENA_H));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006496
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006497 RD_HARPOON(p_port + hp_int_status); /*Clear interrupts. */
6498 WR_HARPOON(p_port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
6499 WR_HARPOON(p_port + hp_page_ctrl, (RD_HARPOON(p_port + hp_page_ctrl) &
6500 ~SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006501}
6502
Linus Torvalds1da177e2005-04-16 15:20:36 -07006503/*---------------------------------------------------------------------
6504 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006505 * Function: FPT_DiagEEPROM
Linus Torvalds1da177e2005-04-16 15:20:36 -07006506 *
6507 * Description: Verfiy checksum and 'Key' and initialize the EEPROM if
6508 * necessary.
6509 *
6510 *---------------------------------------------------------------------*/
6511
Khalid Aziz391e2f22013-05-16 19:44:14 -06006512static void FPT_DiagEEPROM(u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006513{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006514 unsigned short index, temp, max_wd_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006515
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006516 if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6517 max_wd_cnt = EEPROM_WD_CNT;
6518 else
6519 max_wd_cnt = EEPROM_WD_CNT * 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006520
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006521 temp = FPT_utilEERead(p_port, FW_SIGNATURE / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006522
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006523 if (temp == 0x4641) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006524
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006525 for (index = 2; index < max_wd_cnt; index++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006526
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006527 temp += FPT_utilEERead(p_port, index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006528
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006529 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006530
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006531 if (temp == FPT_utilEERead(p_port, EEPROM_CHECK_SUM / 2)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006532
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006533 return; /*EEPROM is Okay so return now! */
6534 }
6535 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006536
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006537 FPT_utilEEWriteOnOff(p_port, (unsigned char)1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006538
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006539 for (index = 0; index < max_wd_cnt; index++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006540
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006541 FPT_utilEEWrite(p_port, 0x0000, index);
6542 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006543
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006544 temp = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006545
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006546 FPT_utilEEWrite(p_port, 0x4641, FW_SIGNATURE / 2);
6547 temp += 0x4641;
6548 FPT_utilEEWrite(p_port, 0x3920, MODEL_NUMB_0 / 2);
6549 temp += 0x3920;
6550 FPT_utilEEWrite(p_port, 0x3033, MODEL_NUMB_2 / 2);
6551 temp += 0x3033;
6552 FPT_utilEEWrite(p_port, 0x2020, MODEL_NUMB_4 / 2);
6553 temp += 0x2020;
6554 FPT_utilEEWrite(p_port, 0x70D3, SYSTEM_CONFIG / 2);
6555 temp += 0x70D3;
6556 FPT_utilEEWrite(p_port, 0x0010, BIOS_CONFIG / 2);
6557 temp += 0x0010;
6558 FPT_utilEEWrite(p_port, 0x0003, SCAM_CONFIG / 2);
6559 temp += 0x0003;
6560 FPT_utilEEWrite(p_port, 0x0007, ADAPTER_SCSI_ID / 2);
6561 temp += 0x0007;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006562
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006563 FPT_utilEEWrite(p_port, 0x0000, IGNORE_B_SCAN / 2);
6564 temp += 0x0000;
6565 FPT_utilEEWrite(p_port, 0x0000, SEND_START_ENA / 2);
6566 temp += 0x0000;
6567 FPT_utilEEWrite(p_port, 0x0000, DEVICE_ENABLE / 2);
6568 temp += 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006569
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006570 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL01 / 2);
6571 temp += 0x4242;
6572 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL23 / 2);
6573 temp += 0x4242;
6574 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL45 / 2);
6575 temp += 0x4242;
6576 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL67 / 2);
6577 temp += 0x4242;
6578 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL89 / 2);
6579 temp += 0x4242;
6580 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLab / 2);
6581 temp += 0x4242;
6582 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLcd / 2);
6583 temp += 0x4242;
6584 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLef / 2);
6585 temp += 0x4242;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006586
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006587 FPT_utilEEWrite(p_port, 0x6C46, 64 / 2); /*PRODUCT ID */
6588 temp += 0x6C46;
6589 FPT_utilEEWrite(p_port, 0x7361, 66 / 2); /* FlashPoint LT */
6590 temp += 0x7361;
6591 FPT_utilEEWrite(p_port, 0x5068, 68 / 2);
6592 temp += 0x5068;
6593 FPT_utilEEWrite(p_port, 0x696F, 70 / 2);
6594 temp += 0x696F;
6595 FPT_utilEEWrite(p_port, 0x746E, 72 / 2);
6596 temp += 0x746E;
6597 FPT_utilEEWrite(p_port, 0x4C20, 74 / 2);
6598 temp += 0x4C20;
6599 FPT_utilEEWrite(p_port, 0x2054, 76 / 2);
6600 temp += 0x2054;
6601 FPT_utilEEWrite(p_port, 0x2020, 78 / 2);
6602 temp += 0x2020;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006603
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006604 index = ((EE_SCAMBASE / 2) + (7 * 16));
6605 FPT_utilEEWrite(p_port, (0x0700 + TYPE_CODE0), index);
6606 temp += (0x0700 + TYPE_CODE0);
6607 index++;
6608 FPT_utilEEWrite(p_port, 0x5542, index); /*Vendor ID code */
6609 temp += 0x5542; /* BUSLOGIC */
6610 index++;
6611 FPT_utilEEWrite(p_port, 0x4C53, index);
6612 temp += 0x4C53;
6613 index++;
6614 FPT_utilEEWrite(p_port, 0x474F, index);
6615 temp += 0x474F;
6616 index++;
6617 FPT_utilEEWrite(p_port, 0x4349, index);
6618 temp += 0x4349;
6619 index++;
6620 FPT_utilEEWrite(p_port, 0x5442, index); /*Vendor unique code */
6621 temp += 0x5442; /* BT- 930 */
6622 index++;
6623 FPT_utilEEWrite(p_port, 0x202D, index);
6624 temp += 0x202D;
6625 index++;
6626 FPT_utilEEWrite(p_port, 0x3339, index);
6627 temp += 0x3339;
6628 index++; /*Serial # */
6629 FPT_utilEEWrite(p_port, 0x2030, index); /* 01234567 */
6630 temp += 0x2030;
6631 index++;
6632 FPT_utilEEWrite(p_port, 0x5453, index);
6633 temp += 0x5453;
6634 index++;
6635 FPT_utilEEWrite(p_port, 0x5645, index);
6636 temp += 0x5645;
6637 index++;
6638 FPT_utilEEWrite(p_port, 0x2045, index);
6639 temp += 0x2045;
6640 index++;
6641 FPT_utilEEWrite(p_port, 0x202F, index);
6642 temp += 0x202F;
6643 index++;
6644 FPT_utilEEWrite(p_port, 0x4F4A, index);
6645 temp += 0x4F4A;
6646 index++;
6647 FPT_utilEEWrite(p_port, 0x204E, index);
6648 temp += 0x204E;
6649 index++;
6650 FPT_utilEEWrite(p_port, 0x3539, index);
6651 temp += 0x3539;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006652
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006653 FPT_utilEEWrite(p_port, temp, EEPROM_CHECK_SUM / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006654
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006655 FPT_utilEEWriteOnOff(p_port, (unsigned char)0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006656
6657}
6658
Linus Torvalds1da177e2005-04-16 15:20:36 -07006659/*---------------------------------------------------------------------
6660 *
6661 * Function: Queue Search Select
6662 *
6663 * Description: Try to find a new command to execute.
6664 *
6665 *---------------------------------------------------------------------*/
6666
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006667static void FPT_queueSearchSelect(struct sccb_card *pCurrCard,
6668 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006669{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006670 unsigned char scan_ptr, lun;
6671 struct sccb_mgr_tar_info *currTar_Info;
6672 struct sccb *pOldSccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006673
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006674 scan_ptr = pCurrCard->scanIndex;
6675 do {
James Bottomley 47b5d692005-04-24 02:38:05 -05006676 currTar_Info = &FPT_sccbMgrTbl[p_card][scan_ptr];
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006677 if ((pCurrCard->globalFlags & F_CONLUN_IO) &&
6678 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
6679 TAG_Q_TRYING)) {
6680 if (currTar_Info->TarSelQ_Cnt != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006681
6682 scan_ptr++;
6683 if (scan_ptr == MAX_SCSI_TAR)
6684 scan_ptr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006685
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006686 for (lun = 0; lun < MAX_LUN; lun++) {
6687 if (currTar_Info->TarLUNBusy[lun] == 0) {
6688
6689 pCurrCard->currentSCCB =
6690 currTar_Info->TarSelQ_Head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006691 pOldSccb = NULL;
6692
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006693 while ((pCurrCard->
6694 currentSCCB != NULL)
6695 && (lun !=
6696 pCurrCard->
6697 currentSCCB->Lun)) {
6698 pOldSccb =
6699 pCurrCard->
6700 currentSCCB;
6701 pCurrCard->currentSCCB =
6702 (struct sccb
6703 *)(pCurrCard->
6704 currentSCCB)->
6705 Sccb_forwardlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006706 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006707 if (pCurrCard->currentSCCB ==
6708 NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006709 continue;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006710 if (pOldSccb != NULL) {
6711 pOldSccb->
6712 Sccb_forwardlink =
6713 (struct sccb
6714 *)(pCurrCard->
6715 currentSCCB)->
6716 Sccb_forwardlink;
6717 pOldSccb->
6718 Sccb_backlink =
6719 (struct sccb
6720 *)(pCurrCard->
6721 currentSCCB)->
6722 Sccb_backlink;
6723 currTar_Info->
6724 TarSelQ_Cnt--;
6725 } else {
6726 currTar_Info->
6727 TarSelQ_Head =
6728 (struct sccb
6729 *)(pCurrCard->
6730 currentSCCB)->
6731 Sccb_forwardlink;
6732
6733 if (currTar_Info->
6734 TarSelQ_Head ==
6735 NULL) {
6736 currTar_Info->
6737 TarSelQ_Tail
6738 = NULL;
6739 currTar_Info->
6740 TarSelQ_Cnt
6741 = 0;
6742 } else {
6743 currTar_Info->
6744 TarSelQ_Cnt--;
6745 currTar_Info->
6746 TarSelQ_Head->
6747 Sccb_backlink
6748 =
6749 (struct sccb
6750 *)NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006751 }
6752 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006753 pCurrCard->scanIndex = scan_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006754
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006755 pCurrCard->globalFlags |=
6756 F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006757
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006758 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006759 }
6760 }
6761 }
6762
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006763 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006764 scan_ptr++;
6765 if (scan_ptr == MAX_SCSI_TAR) {
6766 scan_ptr = 0;
6767 }
6768 }
6769
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006770 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006771 if ((currTar_Info->TarSelQ_Cnt != 0) &&
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006772 (currTar_Info->TarLUNBusy[0] == 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006773
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006774 pCurrCard->currentSCCB =
6775 currTar_Info->TarSelQ_Head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006776
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006777 currTar_Info->TarSelQ_Head =
6778 (struct sccb *)(pCurrCard->currentSCCB)->
6779 Sccb_forwardlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006780
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006781 if (currTar_Info->TarSelQ_Head == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006782 currTar_Info->TarSelQ_Tail = NULL;
6783 currTar_Info->TarSelQ_Cnt = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006784 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006785 currTar_Info->TarSelQ_Cnt--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006786 currTar_Info->TarSelQ_Head->
6787 Sccb_backlink = (struct sccb *)NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006788 }
6789
6790 scan_ptr++;
6791 if (scan_ptr == MAX_SCSI_TAR)
6792 scan_ptr = 0;
6793
6794 pCurrCard->scanIndex = scan_ptr;
6795
6796 pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
6797
6798 break;
6799 }
6800
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006801 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006802 scan_ptr++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006803 if (scan_ptr == MAX_SCSI_TAR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006804 scan_ptr = 0;
6805 }
6806 }
6807 }
6808 } while (scan_ptr != pCurrCard->scanIndex);
6809}
6810
Linus Torvalds1da177e2005-04-16 15:20:36 -07006811/*---------------------------------------------------------------------
6812 *
6813 * Function: Queue Select Fail
6814 *
6815 * Description: Add the current SCCB to the head of the Queue.
6816 *
6817 *---------------------------------------------------------------------*/
6818
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006819static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
6820 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006821{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006822 unsigned char thisTarg;
6823 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006824
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006825 if (pCurrCard->currentSCCB != NULL) {
6826 thisTarg =
6827 (unsigned char)(((struct sccb *)(pCurrCard->currentSCCB))->
6828 TargID);
6829 currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006830
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006831 pCurrCard->currentSCCB->Sccb_backlink = (struct sccb *)NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006832
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006833 pCurrCard->currentSCCB->Sccb_forwardlink =
6834 currTar_Info->TarSelQ_Head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006835
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006836 if (currTar_Info->TarSelQ_Cnt == 0) {
6837 currTar_Info->TarSelQ_Tail = pCurrCard->currentSCCB;
6838 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006839
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006840 else {
6841 currTar_Info->TarSelQ_Head->Sccb_backlink =
6842 pCurrCard->currentSCCB;
6843 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006844
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006845 currTar_Info->TarSelQ_Head = pCurrCard->currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006846
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006847 pCurrCard->currentSCCB = NULL;
6848 currTar_Info->TarSelQ_Cnt++;
6849 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006850}
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006851
Linus Torvalds1da177e2005-04-16 15:20:36 -07006852/*---------------------------------------------------------------------
6853 *
6854 * Function: Queue Command Complete
6855 *
6856 * Description: Call the callback function with the current SCCB.
6857 *
6858 *---------------------------------------------------------------------*/
6859
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006860static void FPT_queueCmdComplete(struct sccb_card *pCurrCard,
6861 struct sccb *p_sccb, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006862{
6863
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006864 unsigned char i, SCSIcmd;
6865 CALL_BK_FN callback;
6866 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006867
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006868 SCSIcmd = p_sccb->Cdb[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006869
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006870 if (!(p_sccb->Sccb_XferState & F_ALL_XFERRED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006871
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006872 if ((p_sccb->
6873 ControlByte & (SCCB_DATA_XFER_OUT | SCCB_DATA_XFER_IN))
6874 && (p_sccb->HostStatus == SCCB_COMPLETE)
6875 && (p_sccb->TargetStatus != SSCHECK))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006876
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006877 if ((SCSIcmd == SCSI_READ) ||
6878 (SCSIcmd == SCSI_WRITE) ||
6879 (SCSIcmd == SCSI_READ_EXTENDED) ||
6880 (SCSIcmd == SCSI_WRITE_EXTENDED) ||
6881 (SCSIcmd == SCSI_WRITE_AND_VERIFY) ||
6882 (SCSIcmd == SCSI_START_STOP_UNIT) ||
6883 (pCurrCard->globalFlags & F_NO_FILTER)
6884 )
6885 p_sccb->HostStatus = SCCB_DATA_UNDER_RUN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006886 }
6887
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006888 if (p_sccb->SccbStatus == SCCB_IN_PROCESS) {
6889 if (p_sccb->HostStatus || p_sccb->TargetStatus)
6890 p_sccb->SccbStatus = SCCB_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006891 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006892 p_sccb->SccbStatus = SCCB_SUCCESS;
6893 }
6894
6895 if (p_sccb->Sccb_XferState & F_AUTO_SENSE) {
6896
6897 p_sccb->CdbLength = p_sccb->Save_CdbLen;
6898 for (i = 0; i < 6; i++) {
6899 p_sccb->Cdb[i] = p_sccb->Save_Cdb[i];
6900 }
6901 }
6902
6903 if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) ||
6904 (p_sccb->OperationCode == RESIDUAL_COMMAND)) {
6905
6906 FPT_utilUpdateResidual(p_sccb);
6907 }
6908
6909 pCurrCard->cmdCounter--;
6910 if (!pCurrCard->cmdCounter) {
6911
6912 if (pCurrCard->globalFlags & F_GREEN_PC) {
6913 WR_HARPOON(pCurrCard->ioPort + hp_clkctrl_0,
6914 (PWR_DWN | CLKCTRL_DEFAULT));
6915 WR_HARPOON(pCurrCard->ioPort + hp_sys_ctrl, STOP_CLK);
6916 }
6917
6918 WR_HARPOON(pCurrCard->ioPort + hp_semaphore,
6919 (RD_HARPOON(pCurrCard->ioPort + hp_semaphore) &
6920 ~SCCB_MGR_ACTIVE));
6921
6922 }
6923
6924 if (pCurrCard->discQCount != 0) {
6925 currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
6926 if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
6927 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
6928 TAG_Q_TRYING))) {
6929 pCurrCard->discQCount--;
6930 pCurrCard->discQ_Tbl[currTar_Info->
6931 LunDiscQ_Idx[p_sccb->Lun]] = NULL;
6932 } else {
6933 if (p_sccb->Sccb_tag) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006934 pCurrCard->discQCount--;
6935 pCurrCard->discQ_Tbl[p_sccb->Sccb_tag] = NULL;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006936 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006937 pCurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006938 pCurrCard->discQ_Tbl[currTar_Info->
6939 LunDiscQ_Idx[0]] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006940 }
6941 }
6942
6943 }
6944
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006945 callback = (CALL_BK_FN) p_sccb->SccbCallback;
6946 callback(p_sccb);
6947 pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
6948 pCurrCard->currentSCCB = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006949}
Linus Torvalds1da177e2005-04-16 15:20:36 -07006950
Linus Torvalds1da177e2005-04-16 15:20:36 -07006951/*---------------------------------------------------------------------
6952 *
6953 * Function: Queue Disconnect
6954 *
6955 * Description: Add SCCB to our disconnect array.
6956 *
6957 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006958static void FPT_queueDisconnect(struct sccb *p_sccb, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006959{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006960 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006961
James Bottomley 47b5d692005-04-24 02:38:05 -05006962 currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006963
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006964 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
6965 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
6966 FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
6967 LunDiscQ_Idx[p_sccb->Lun]] =
6968 p_sccb;
6969 } else {
6970 if (p_sccb->Sccb_tag) {
6971 FPT_BL_Card[p_card].discQ_Tbl[p_sccb->Sccb_tag] =
6972 p_sccb;
6973 FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarLUNBusy[0] =
6974 0;
James Bottomley 47b5d692005-04-24 02:38:05 -05006975 FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarTagQ_Cnt++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006976 } else {
6977 FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
6978 LunDiscQ_Idx[0]] = p_sccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006979 }
6980 }
James Bottomley 47b5d692005-04-24 02:38:05 -05006981 FPT_BL_Card[p_card].currentSCCB = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006982}
6983
Linus Torvalds1da177e2005-04-16 15:20:36 -07006984/*---------------------------------------------------------------------
6985 *
6986 * Function: Queue Flush SCCB
6987 *
6988 * Description: Flush all SCCB's back to the host driver for this target.
6989 *
6990 *---------------------------------------------------------------------*/
6991
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006992static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006993{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006994 unsigned char qtag, thisTarg;
6995 struct sccb *currSCCB;
6996 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006997
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006998 currSCCB = FPT_BL_Card[p_card].currentSCCB;
6999 if (currSCCB != NULL) {
7000 thisTarg = (unsigned char)currSCCB->TargID;
7001 currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007002
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007003 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007004
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007005 if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
7006 (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
7007 thisTarg)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007008
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007009 FPT_BL_Card[p_card].discQ_Tbl[qtag]->
7010 HostStatus = (unsigned char)error_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007011
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007012 FPT_queueCmdComplete(&FPT_BL_Card[p_card],
7013 FPT_BL_Card[p_card].
7014 discQ_Tbl[qtag], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007015
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007016 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
7017 currTar_Info->TarTagQ_Cnt--;
7018
7019 }
7020 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007021 }
7022
7023}
7024
7025/*---------------------------------------------------------------------
7026 *
7027 * Function: Queue Flush Target SCCB
7028 *
7029 * Description: Flush all SCCB's back to the host driver for this target.
7030 *
7031 *---------------------------------------------------------------------*/
7032
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007033static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
7034 unsigned char error_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007035{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007036 unsigned char qtag;
7037 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007038
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007039 currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007040
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007041 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007042
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007043 if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
7044 (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007045
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007046 FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus =
7047 (unsigned char)error_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007048
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007049 FPT_queueCmdComplete(&FPT_BL_Card[p_card],
7050 FPT_BL_Card[p_card].
7051 discQ_Tbl[qtag], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007052
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007053 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
7054 currTar_Info->TarTagQ_Cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007055
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007056 }
7057 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007058
7059}
7060
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007061static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007062{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007063 struct sccb_mgr_tar_info *currTar_Info;
7064 currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007065
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007066 p_SCCB->Sccb_forwardlink = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007067
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007068 p_SCCB->Sccb_backlink = currTar_Info->TarSelQ_Tail;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007069
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007070 if (currTar_Info->TarSelQ_Cnt == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007071
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007072 currTar_Info->TarSelQ_Head = p_SCCB;
7073 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007074
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007075 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007076
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007077 currTar_Info->TarSelQ_Tail->Sccb_forwardlink = p_SCCB;
7078 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007079
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007080 currTar_Info->TarSelQ_Tail = p_SCCB;
7081 currTar_Info->TarSelQ_Cnt++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007082}
7083
Linus Torvalds1da177e2005-04-16 15:20:36 -07007084/*---------------------------------------------------------------------
7085 *
7086 * Function: Queue Find SCCB
7087 *
7088 * Description: Search the target select Queue for this SCCB, and
7089 * remove it if found.
7090 *
7091 *---------------------------------------------------------------------*/
7092
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007093static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB,
7094 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007095{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007096 struct sccb *q_ptr;
7097 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007098
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007099 currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007100
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007101 q_ptr = currTar_Info->TarSelQ_Head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007102
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007103 while (q_ptr != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007104
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007105 if (q_ptr == p_SCCB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007106
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007107 if (currTar_Info->TarSelQ_Head == q_ptr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007108
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007109 currTar_Info->TarSelQ_Head =
7110 q_ptr->Sccb_forwardlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007111 }
7112
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007113 if (currTar_Info->TarSelQ_Tail == q_ptr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007114
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007115 currTar_Info->TarSelQ_Tail =
7116 q_ptr->Sccb_backlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007117 }
7118
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007119 if (q_ptr->Sccb_forwardlink != NULL) {
7120 q_ptr->Sccb_forwardlink->Sccb_backlink =
7121 q_ptr->Sccb_backlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007122 }
7123
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007124 if (q_ptr->Sccb_backlink != NULL) {
7125 q_ptr->Sccb_backlink->Sccb_forwardlink =
7126 q_ptr->Sccb_forwardlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007127 }
7128
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007129 currTar_Info->TarSelQ_Cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007130
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007131 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007132 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007133
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007134 else {
7135 q_ptr = q_ptr->Sccb_forwardlink;
7136 }
7137 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007138
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007139 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007140
7141}
7142
Linus Torvalds1da177e2005-04-16 15:20:36 -07007143/*---------------------------------------------------------------------
7144 *
7145 * Function: Utility Update Residual Count
7146 *
7147 * Description: Update the XferCnt to the remaining byte count.
7148 * If we transferred all the data then just write zero.
7149 * If Non-SG transfer then report Total Cnt - Actual Transfer
7150 * Cnt. For SG transfers add the count fields of all
7151 * remaining SG elements, as well as any partial remaining
7152 * element.
7153 *
7154 *---------------------------------------------------------------------*/
7155
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007156static void FPT_utilUpdateResidual(struct sccb *p_SCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007157{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007158 unsigned long partial_cnt;
7159 unsigned int sg_index;
Khalid Aziz391e2f22013-05-16 19:44:14 -06007160 struct blogic_sg_seg *segp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007161
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007162 if (p_SCCB->Sccb_XferState & F_ALL_XFERRED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007163
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007164 p_SCCB->DataLength = 0x0000;
7165 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007166
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007167 else if (p_SCCB->Sccb_XferState & F_SG_XFER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007168
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007169 partial_cnt = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007170
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007171 sg_index = p_SCCB->Sccb_sgseg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007172
Linus Torvalds1da177e2005-04-16 15:20:36 -07007173
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007174 if (p_SCCB->Sccb_SGoffset) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007175
7176 partial_cnt = p_SCCB->Sccb_SGoffset;
7177 sg_index++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007178 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007179
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007180 while (((unsigned long)sg_index *
7181 (unsigned long)SG_ELEMENT_SIZE) < p_SCCB->DataLength) {
Khalid Aziz391e2f22013-05-16 19:44:14 -06007182 segp = (struct blogic_sg_seg *)(p_SCCB->DataPointer) +
7183 (sg_index * 2);
7184 partial_cnt += segp->segbytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007185 sg_index++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007186 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007187
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007188 p_SCCB->DataLength = partial_cnt;
7189 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007190
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007191 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007192
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007193 p_SCCB->DataLength -= p_SCCB->Sccb_ATC;
7194 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007195}
7196
Linus Torvalds1da177e2005-04-16 15:20:36 -07007197/*---------------------------------------------------------------------
7198 *
7199 * Function: Wait 1 Second
7200 *
7201 * Description: Wait for 1 second.
7202 *
7203 *---------------------------------------------------------------------*/
7204
Khalid Aziz391e2f22013-05-16 19:44:14 -06007205static void FPT_Wait1Second(u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007206{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007207 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007208
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007209 for (i = 0; i < 4; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007210
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007211 FPT_Wait(p_port, TO_250ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007212
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007213 if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
7214 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007215
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007216 if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
7217 break;
7218 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007219}
7220
Linus Torvalds1da177e2005-04-16 15:20:36 -07007221/*---------------------------------------------------------------------
7222 *
James Bottomley 47b5d692005-04-24 02:38:05 -05007223 * Function: FPT_Wait
Linus Torvalds1da177e2005-04-16 15:20:36 -07007224 *
7225 * Description: Wait the desired delay.
7226 *
7227 *---------------------------------------------------------------------*/
7228
Khalid Aziz391e2f22013-05-16 19:44:14 -06007229static void FPT_Wait(u32 p_port, unsigned char p_delay)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007230{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007231 unsigned char old_timer;
7232 unsigned char green_flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007233
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007234 old_timer = RD_HARPOON(p_port + hp_seltimeout);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007235
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007236 green_flag = RD_HARPOON(p_port + hp_clkctrl_0);
7237 WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007238
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007239 WR_HARPOON(p_port + hp_seltimeout, p_delay);
7240 WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
7241 WRW_HARPOON((p_port + hp_intena), (FPT_default_intena & ~TIMEOUT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007242
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007243 WR_HARPOON(p_port + hp_portctrl_0,
7244 (RD_HARPOON(p_port + hp_portctrl_0) | START_TO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007245
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007246 while (!(RDW_HARPOON((p_port + hp_intstat)) & TIMEOUT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007247
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007248 if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
7249 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007250
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007251 if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
7252 break;
7253 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007254
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007255 WR_HARPOON(p_port + hp_portctrl_0,
7256 (RD_HARPOON(p_port + hp_portctrl_0) & ~START_TO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007257
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007258 WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
7259 WRW_HARPOON((p_port + hp_intena), FPT_default_intena);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007260
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007261 WR_HARPOON(p_port + hp_clkctrl_0, green_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007262
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007263 WR_HARPOON(p_port + hp_seltimeout, old_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007264}
7265
Linus Torvalds1da177e2005-04-16 15:20:36 -07007266/*---------------------------------------------------------------------
7267 *
7268 * Function: Enable/Disable Write to EEPROM
7269 *
7270 * Description: The EEPROM must first be enabled for writes
7271 * A total of 9 clocks are needed.
7272 *
7273 *---------------------------------------------------------------------*/
7274
Khalid Aziz391e2f22013-05-16 19:44:14 -06007275static void FPT_utilEEWriteOnOff(u32 p_port, unsigned char p_mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007276{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007277 unsigned char ee_value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007278
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007279 ee_value =
7280 (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
7281 (EXT_ARB_ACK | SCSI_TERM_ENA_H));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007282
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007283 if (p_mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007284
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007285 FPT_utilEESendCmdAddr(p_port, EWEN, EWEN_ADDR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007286
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007287 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07007288
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007289 FPT_utilEESendCmdAddr(p_port, EWDS, EWDS_ADDR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007290
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007291 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */
7292 WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /*Turn off Master Select */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007293}
7294
Linus Torvalds1da177e2005-04-16 15:20:36 -07007295/*---------------------------------------------------------------------
7296 *
7297 * Function: Write EEPROM
7298 *
7299 * Description: Write a word to the EEPROM at the specified
7300 * address.
7301 *
7302 *---------------------------------------------------------------------*/
7303
Khalid Aziz391e2f22013-05-16 19:44:14 -06007304static void FPT_utilEEWrite(u32 p_port, unsigned short ee_data,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007305 unsigned short ee_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007306{
7307
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007308 unsigned char ee_value;
7309 unsigned short i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007310
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007311 ee_value =
7312 (unsigned
7313 char)((RD_HARPOON(p_port + hp_ee_ctrl) &
7314 (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007315
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007316 FPT_utilEESendCmdAddr(p_port, EE_WRITE, ee_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007317
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007318 ee_value |= (SEE_MS + SEE_CS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007319
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007320 for (i = 0x8000; i != 0; i >>= 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007321
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007322 if (i & ee_data)
7323 ee_value |= SEE_DO;
7324 else
7325 ee_value &= ~SEE_DO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007326
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007327 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7328 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7329 ee_value |= SEE_CLK; /* Clock data! */
7330 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7331 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7332 ee_value &= ~SEE_CLK;
7333 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7334 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7335 }
7336 ee_value &= (EXT_ARB_ACK | SCSI_TERM_ENA_H);
7337 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007338
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007339 FPT_Wait(p_port, TO_10ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007340
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007341 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS | SEE_CS)); /* Set CS to EEPROM */
7342 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /* Turn off CS */
7343 WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /* Turn off Master Select */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007344}
7345
7346/*---------------------------------------------------------------------
7347 *
7348 * Function: Read EEPROM
7349 *
7350 * Description: Read a word from the EEPROM at the desired
7351 * address.
7352 *
7353 *---------------------------------------------------------------------*/
7354
Khalid Aziz391e2f22013-05-16 19:44:14 -06007355static unsigned short FPT_utilEERead(u32 p_port,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007356 unsigned short ee_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007357{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007358 unsigned short i, ee_data1, ee_data2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007359
7360 i = 0;
James Bottomley 47b5d692005-04-24 02:38:05 -05007361 ee_data1 = FPT_utilEEReadOrg(p_port, ee_addr);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007362 do {
James Bottomley 47b5d692005-04-24 02:38:05 -05007363 ee_data2 = FPT_utilEEReadOrg(p_port, ee_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007364
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007365 if (ee_data1 == ee_data2)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007366 return ee_data1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007367
7368 ee_data1 = ee_data2;
7369 i++;
7370
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007371 } while (i < 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007372
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007373 return ee_data1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007374}
7375
7376/*---------------------------------------------------------------------
7377 *
7378 * Function: Read EEPROM Original
7379 *
7380 * Description: Read a word from the EEPROM at the desired
7381 * address.
7382 *
7383 *---------------------------------------------------------------------*/
7384
Khalid Aziz391e2f22013-05-16 19:44:14 -06007385static unsigned short FPT_utilEEReadOrg(u32 p_port, unsigned short ee_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007386{
7387
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007388 unsigned char ee_value;
7389 unsigned short i, ee_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007390
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007391 ee_value =
7392 (unsigned
7393 char)((RD_HARPOON(p_port + hp_ee_ctrl) &
7394 (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007395
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007396 FPT_utilEESendCmdAddr(p_port, EE_READ, ee_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007397
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007398 ee_value |= (SEE_MS + SEE_CS);
7399 ee_data = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007400
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007401 for (i = 1; i <= 16; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007402
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007403 ee_value |= SEE_CLK; /* Clock data! */
7404 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7405 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7406 ee_value &= ~SEE_CLK;
7407 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7408 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007409
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007410 ee_data <<= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007411
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007412 if (RD_HARPOON(p_port + hp_ee_ctrl) & SEE_DI)
7413 ee_data |= 1;
7414 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007415
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007416 ee_value &= ~(SEE_MS + SEE_CS);
7417 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */
7418 WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /*Turn off Master Select */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007419
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007420 return ee_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007421}
7422
Linus Torvalds1da177e2005-04-16 15:20:36 -07007423/*---------------------------------------------------------------------
7424 *
7425 * Function: Send EE command and Address to the EEPROM
7426 *
7427 * Description: Transfers the correct command and sends the address
7428 * to the eeprom.
7429 *
7430 *---------------------------------------------------------------------*/
7431
Khalid Aziz391e2f22013-05-16 19:44:14 -06007432static void FPT_utilEESendCmdAddr(u32 p_port, unsigned char ee_cmd,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007433 unsigned short ee_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007434{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007435 unsigned char ee_value;
7436 unsigned char narrow_flg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007437
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007438 unsigned short i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007439
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007440 narrow_flg =
7441 (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
7442 NARROW_SCSI_CARD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007443
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007444 ee_value = SEE_MS;
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 ee_value |= SEE_CS; /* Set CS to EEPROM */
7448 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007449
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007450 for (i = 0x04; i != 0; i >>= 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007451
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007452 if (i & ee_cmd)
7453 ee_value |= SEE_DO;
7454 else
7455 ee_value &= ~SEE_DO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007456
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007457 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7458 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7459 ee_value |= SEE_CLK; /* Clock data! */
7460 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7461 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7462 ee_value &= ~SEE_CLK;
7463 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7464 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7465 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007466
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007467 if (narrow_flg)
7468 i = 0x0080;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007469
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007470 else
7471 i = 0x0200;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007472
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007473 while (i != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007474
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007475 if (i & ee_addr)
7476 ee_value |= SEE_DO;
7477 else
7478 ee_value &= ~SEE_DO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007479
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007480 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7481 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7482 ee_value |= SEE_CLK; /* Clock data! */
7483 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7484 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7485 ee_value &= ~SEE_CLK;
7486 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7487 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007488
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007489 i >>= 1;
7490 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007491}
7492
Alexey Dobriyanc823fee2006-03-08 00:14:25 -08007493static unsigned short FPT_CalcCrc16(unsigned char buffer[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07007494{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007495 unsigned short crc = 0;
7496 int i, j;
7497 unsigned short ch;
7498 for (i = 0; i < ID_STRING_LENGTH; i++) {
7499 ch = (unsigned short)buffer[i];
7500 for (j = 0; j < 8; j++) {
7501 if ((crc ^ ch) & 1)
7502 crc = (crc >> 1) ^ CRCMASK;
7503 else
7504 crc >>= 1;
7505 ch >>= 1;
7506 }
7507 }
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007508 return crc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007509}
7510
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08007511static unsigned char FPT_CalcLrc(unsigned char buffer[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07007512{
7513 int i;
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08007514 unsigned char lrc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007515 lrc = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007516 for (i = 0; i < ID_STRING_LENGTH; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007517 lrc ^= buffer[i];
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007518 return lrc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007519}
7520
Linus Torvalds1da177e2005-04-16 15:20:36 -07007521/*
7522 The following inline definitions avoid type conflicts.
7523*/
7524
7525static inline unsigned char
Khalid Aziz839cb992013-05-16 19:44:13 -06007526FlashPoint__ProbeHostAdapter(struct fpoint_info *FlashPointInfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007527{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007528 return FlashPoint_ProbeHostAdapter((struct sccb_mgr_info *)
7529 FlashPointInfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007530}
7531
Khalid Aziz391e2f22013-05-16 19:44:14 -06007532static inline void *
Khalid Aziz839cb992013-05-16 19:44:13 -06007533FlashPoint__HardwareResetHostAdapter(struct fpoint_info *FlashPointInfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007534{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007535 return FlashPoint_HardwareResetHostAdapter((struct sccb_mgr_info *)
7536 FlashPointInfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007537}
7538
7539static inline void
Khalid Aziz391e2f22013-05-16 19:44:14 -06007540FlashPoint__ReleaseHostAdapter(void *CardHandle)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007541{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007542 FlashPoint_ReleaseHostAdapter(CardHandle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007543}
7544
Linus Torvalds1da177e2005-04-16 15:20:36 -07007545static inline void
Khalid Aziz391e2f22013-05-16 19:44:14 -06007546FlashPoint__StartCCB(void *CardHandle, struct blogic_ccb *CCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007547{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007548 FlashPoint_StartCCB(CardHandle, (struct sccb *)CCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007549}
7550
Linus Torvalds1da177e2005-04-16 15:20:36 -07007551static inline void
Khalid Aziz391e2f22013-05-16 19:44:14 -06007552FlashPoint__AbortCCB(void *CardHandle, struct blogic_ccb *CCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007553{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007554 FlashPoint_AbortCCB(CardHandle, (struct sccb *)CCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007555}
7556
Richard Knutsson2065e312007-02-05 16:39:01 -08007557static inline bool
Khalid Aziz391e2f22013-05-16 19:44:14 -06007558FlashPoint__InterruptPending(void *CardHandle)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007559{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007560 return FlashPoint_InterruptPending(CardHandle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007561}
7562
Linus Torvalds1da177e2005-04-16 15:20:36 -07007563static inline int
Khalid Aziz391e2f22013-05-16 19:44:14 -06007564FlashPoint__HandleInterrupt(void *CardHandle)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007565{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007566 return FlashPoint_HandleInterrupt(CardHandle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007567}
7568
Linus Torvalds1da177e2005-04-16 15:20:36 -07007569#define FlashPoint_ProbeHostAdapter FlashPoint__ProbeHostAdapter
7570#define FlashPoint_HardwareResetHostAdapter FlashPoint__HardwareResetHostAdapter
7571#define FlashPoint_ReleaseHostAdapter FlashPoint__ReleaseHostAdapter
7572#define FlashPoint_StartCCB FlashPoint__StartCCB
7573#define FlashPoint_AbortCCB FlashPoint__AbortCCB
7574#define FlashPoint_InterruptPending FlashPoint__InterruptPending
7575#define FlashPoint_HandleInterrupt FlashPoint__HandleInterrupt
7576
Matthew Wilcox78b4b052008-03-13 06:55:08 -06007577#else /* !CONFIG_SCSI_FLASHPOINT */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007578
7579/*
7580 Define prototypes for the FlashPoint SCCB Manager Functions.
7581*/
7582
Khalid Aziz839cb992013-05-16 19:44:13 -06007583extern unsigned char FlashPoint_ProbeHostAdapter(struct fpoint_info *);
Khalid Aziz391e2f22013-05-16 19:44:14 -06007584extern void *FlashPoint_HardwareResetHostAdapter(struct fpoint_info *);
7585extern void FlashPoint_StartCCB(void *, struct blogic_ccb *);
7586extern int FlashPoint_AbortCCB(void *, struct blogic_ccb *);
7587extern bool FlashPoint_InterruptPending(void *);
7588extern int FlashPoint_HandleInterrupt(void *);
7589extern void FlashPoint_ReleaseHostAdapter(void *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007590
Matthew Wilcox78b4b052008-03-13 06:55:08 -06007591#endif /* CONFIG_SCSI_FLASHPOINT */