blob: 90253208a72f5728cdbec61f5f2826a56b2c6a29 [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;
Randy Dunlap4d431152021-05-29 16:48:57 -070043 u16 si_mflags;
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
308#define SMIDENT 0x80
309#define DISC_PRIV 0x40
310
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311#define SM8BIT 0x00
312#define SM16BIT 0x01
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313
314#define SIX_BYTE_CMD 0x06
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315#define TWELVE_BYTE_CMD 0x0C
316
317#define ASYNC 0x00
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800318#define MAX_OFFSET 0x0F /* Maxbyteoffset for Sync Xfers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319
320#define EEPROM_WD_CNT 256
321
322#define EEPROM_CHECK_SUM 0
323#define FW_SIGNATURE 2
324#define MODEL_NUMB_0 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325#define MODEL_NUMB_2 6
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326#define MODEL_NUMB_4 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327#define SYSTEM_CONFIG 16
328#define SCSI_CONFIG 17
329#define BIOS_CONFIG 18
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330#define SCAM_CONFIG 20
331#define ADAPTER_SCSI_ID 24
332
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333#define IGNORE_B_SCAN 32
334#define SEND_START_ENA 34
335#define DEVICE_ENABLE 36
336
337#define SYNC_RATE_TBL 38
338#define SYNC_RATE_TBL01 38
339#define SYNC_RATE_TBL23 40
340#define SYNC_RATE_TBL45 42
341#define SYNC_RATE_TBL67 44
342#define SYNC_RATE_TBL89 46
343#define SYNC_RATE_TBLab 48
344#define SYNC_RATE_TBLcd 50
345#define SYNC_RATE_TBLef 52
346
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800347#define EE_SCAMBASE 256
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800349#define SCAM_ENABLED BIT(2)
350#define SCAM_LEVEL2 BIT(3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351
Jiri Slaby1cafc302007-10-18 23:40:36 -0700352#define RENEGO_ENA BIT(10)
353#define CONNIO_ENA BIT(11)
354#define GREEN_PC_ENA BIT(12)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800356#define AUTO_RATE_00 00
357#define AUTO_RATE_05 01
358#define AUTO_RATE_10 02
359#define AUTO_RATE_20 03
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800361#define WIDE_NEGO_BIT BIT(7)
362#define DISC_ENABLE_BIT BIT(6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800364#define hp_vendor_id_0 0x00 /* LSB */
365#define ORION_VEND_0 0x4B
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800367#define hp_vendor_id_1 0x01 /* MSB */
368#define ORION_VEND_1 0x10
Linus Torvalds1da177e2005-04-16 15:20:36 -0700369
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800370#define hp_device_id_0 0x02 /* LSB */
371#define ORION_DEV_0 0x30
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800373#define hp_device_id_1 0x03 /* MSB */
374#define ORION_DEV_1 0x81
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375
376 /* Sub Vendor ID and Sub Device ID only available in
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800377 Harpoon Version 2 and higher */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800379#define hp_sub_device_id_0 0x06 /* LSB */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800381#define hp_semaphore 0x0C
382#define SCCB_MGR_ACTIVE BIT(0)
383#define TICKLE_ME BIT(1)
384#define SCCB_MGR_PRESENT BIT(3)
385#define BIOS_IN_USE BIT(4)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800387#define hp_sys_ctrl 0x0F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800389#define STOP_CLK BIT(0) /*Turn off BusMaster Clock */
390#define DRVR_RST BIT(1) /*Firmware Reset to 80C15 chip */
391#define HALT_MACH BIT(3) /*Halt State Machine */
392#define HARD_ABORT BIT(4) /*Hard Abort */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800394#define hp_host_blk_cnt 0x13
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800396#define XFER_BLK64 0x06 /* 1 1 0 64 byte per block */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800398#define BM_THRESHOLD 0x40 /* PCI mode can only xfer 16 bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800400#define hp_int_mask 0x17
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800402#define INT_CMD_COMPL BIT(0) /* DMA command complete */
403#define INT_EXT_STATUS BIT(1) /* Extended Status Set */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800405#define hp_xfer_cnt_lo 0x18
406#define hp_xfer_cnt_hi 0x1A
407#define hp_xfer_cmd 0x1B
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800409#define XFER_HOST_DMA 0x00 /* 0 0 0 Transfer Host -> DMA */
410#define XFER_DMA_HOST 0x01 /* 0 0 1 Transfer DMA -> Host */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800412#define XFER_HOST_AUTO 0x00 /* 0 0 Auto Transfer Size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800414#define XFER_DMA_8BIT 0x20 /* 0 1 8 BIT Transfer Size */
Alexey Dobriyan85ae97d82006-03-08 00:14:22 -0800415
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800416#define DISABLE_INT BIT(7) /*Do not interrupt at end of cmd. */
Alexey Dobriyan85ae97d82006-03-08 00:14:22 -0800417
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800418#define HOST_WRT_CMD ((DISABLE_INT + XFER_HOST_DMA + XFER_HOST_AUTO + XFER_DMA_8BIT))
419#define HOST_RD_CMD ((DISABLE_INT + XFER_DMA_HOST + XFER_HOST_AUTO + XFER_DMA_8BIT))
Alexey Dobriyan85ae97d82006-03-08 00:14:22 -0800420
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800421#define hp_host_addr_lo 0x1C
422#define hp_host_addr_hmi 0x1E
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800424#define hp_ee_ctrl 0x22
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800426#define EXT_ARB_ACK BIT(7)
427#define SCSI_TERM_ENA_H BIT(6) /* SCSI high byte terminator */
428#define SEE_MS BIT(5)
429#define SEE_CS BIT(3)
430#define SEE_CLK BIT(2)
431#define SEE_DO BIT(1)
432#define SEE_DI BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800434#define EE_READ 0x06
435#define EE_WRITE 0x05
436#define EWEN 0x04
437#define EWEN_ADDR 0x03C0
438#define EWDS 0x04
439#define EWDS_ADDR 0x0000
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800441#define hp_bm_ctrl 0x26
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800443#define SCSI_TERM_ENA_L BIT(0) /*Enable/Disable external terminators */
444#define FLUSH_XFER_CNTR BIT(1) /*Flush transfer counter */
445#define FORCE1_XFER BIT(5) /*Always xfer one byte in byte mode */
446#define FAST_SINGLE BIT(6) /*?? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800448#define BMCTRL_DEFAULT (FORCE1_XFER|FAST_SINGLE|SCSI_TERM_ENA_L)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800450#define hp_sg_addr 0x28
451#define hp_page_ctrl 0x29
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800453#define SCATTER_EN BIT(0)
454#define SGRAM_ARAM BIT(1)
455#define G_INT_DISABLE BIT(3) /* Enable/Disable all Interrupts */
456#define NARROW_SCSI_CARD BIT(4) /* NARROW/WIDE SCSI config pin */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800458#define hp_pci_stat_cfg 0x2D
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800460#define REC_MASTER_ABORT BIT(5) /*received Master abort */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800462#define hp_rev_num 0x33
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800464#define hp_stack_data 0x34
465#define hp_stack_addr 0x35
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800467#define hp_ext_status 0x36
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800469#define BM_FORCE_OFF BIT(0) /*Bus Master is forced to get off */
470#define PCI_TGT_ABORT BIT(0) /*PCI bus master transaction aborted */
471#define PCI_DEV_TMOUT BIT(1) /*PCI Device Time out */
472#define CMD_ABORTED BIT(4) /*Command aborted */
473#define BM_PARITY_ERR BIT(5) /*parity error on data received */
474#define PIO_OVERRUN BIT(6) /*Slave data overrun */
475#define BM_CMD_BUSY BIT(7) /*Bus master transfer command busy */
476#define BAD_EXT_STATUS (BM_FORCE_OFF | PCI_DEV_TMOUT | CMD_ABORTED | \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 BM_PARITY_ERR | PIO_OVERRUN)
478
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800479#define hp_int_status 0x37
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800481#define EXT_STATUS_ON BIT(1) /*Extended status is valid */
482#define SCSI_INTERRUPT BIT(2) /*Global indication of a SCSI int. */
483#define INT_ASSERTED BIT(5) /* */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800485#define hp_fifo_cnt 0x38
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800487#define hp_intena 0x40
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488
Jiri Slaby1cafc302007-10-18 23:40:36 -0700489#define RESET BIT(7)
490#define PROG_HLT BIT(6)
491#define PARITY BIT(5)
492#define FIFO BIT(4)
493#define SEL BIT(3)
494#define SCAM_SEL BIT(2)
495#define RSEL BIT(1)
496#define TIMEOUT BIT(0)
497#define BUS_FREE BIT(15)
498#define XFER_CNT_0 BIT(14)
499#define PHASE BIT(13)
500#define IUNKWN BIT(12)
501#define ICMD_COMP BIT(11)
502#define ITICKLE BIT(10)
503#define IDO_STRT BIT(9)
504#define ITAR_DISC BIT(8)
505#define AUTO_INT (BIT(12)+BIT(11)+BIT(10)+BIT(9)+BIT(8))
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800506#define CLR_ALL_INT 0xFFFF
507#define CLR_ALL_INT_1 0xFF00
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800509#define hp_intstat 0x42
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800511#define hp_scsisig 0x44
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800513#define SCSI_SEL BIT(7)
514#define SCSI_BSY BIT(6)
515#define SCSI_REQ BIT(5)
516#define SCSI_ACK BIT(4)
517#define SCSI_ATN BIT(3)
518#define SCSI_CD BIT(2)
519#define SCSI_MSG BIT(1)
520#define SCSI_IOBIT BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800522#define S_SCSI_PHZ (BIT(2)+BIT(1)+BIT(0))
523#define S_MSGO_PH (BIT(2)+BIT(1) )
524#define S_MSGI_PH (BIT(2)+BIT(1)+BIT(0))
525#define S_DATAI_PH ( BIT(0))
526#define S_DATAO_PH 0x00
527#define S_ILL_PH ( BIT(1) )
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800529#define hp_scsictrl_0 0x45
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800531#define SEL_TAR BIT(6)
532#define ENA_ATN BIT(4)
533#define ENA_RESEL BIT(2)
534#define SCSI_RST BIT(1)
535#define ENA_SCAM_SEL BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800537#define hp_portctrl_0 0x46
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800539#define SCSI_PORT BIT(7)
540#define SCSI_INBIT BIT(6)
541#define DMA_PORT BIT(5)
542#define DMA_RD BIT(4)
543#define HOST_PORT BIT(3)
544#define HOST_WRT BIT(2)
545#define SCSI_BUS_EN BIT(1)
546#define START_TO BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800548#define hp_scsireset 0x47
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800550#define SCSI_INI BIT(6)
551#define SCAM_EN BIT(5)
552#define DMA_RESET BIT(3)
553#define HPSCSI_RESET BIT(2)
554#define PROG_RESET BIT(1)
555#define FIFO_CLR BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800557#define hp_xfercnt_0 0x48
558#define hp_xfercnt_2 0x4A
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800560#define hp_fifodata_0 0x4C
561#define hp_addstat 0x4E
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800563#define SCAM_TIMER BIT(7)
564#define SCSI_MODE8 BIT(3)
565#define SCSI_PAR_ERR BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800567#define hp_prgmcnt_0 0x4F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800569#define hp_selfid_0 0x50
570#define hp_selfid_1 0x51
571#define hp_arb_id 0x52
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800573#define hp_select_id 0x53
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800575#define hp_synctarg_base 0x54
576#define hp_synctarg_12 0x54
577#define hp_synctarg_13 0x55
578#define hp_synctarg_14 0x56
579#define hp_synctarg_15 0x57
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800581#define hp_synctarg_8 0x58
582#define hp_synctarg_9 0x59
583#define hp_synctarg_10 0x5A
584#define hp_synctarg_11 0x5B
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800586#define hp_synctarg_4 0x5C
587#define hp_synctarg_5 0x5D
588#define hp_synctarg_6 0x5E
589#define hp_synctarg_7 0x5F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800591#define hp_synctarg_0 0x60
592#define hp_synctarg_1 0x61
593#define hp_synctarg_2 0x62
594#define hp_synctarg_3 0x63
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800596#define NARROW_SCSI BIT(4)
597#define DEFAULT_OFFSET 0x0F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800599#define hp_autostart_0 0x64
600#define hp_autostart_1 0x65
601#define hp_autostart_3 0x67
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800603#define AUTO_IMMED BIT(5)
604#define SELECT BIT(6)
605#define END_DATA (BIT(7)+BIT(6))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800607#define hp_gp_reg_0 0x68
608#define hp_gp_reg_1 0x69
609#define hp_gp_reg_3 0x6B
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800611#define hp_seltimeout 0x6C
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800613#define TO_4ms 0x67 /* 3.9959ms */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800615#define TO_5ms 0x03 /* 4.9152ms */
616#define TO_10ms 0x07 /* 11.xxxms */
617#define TO_250ms 0x99 /* 250.68ms */
618#define TO_290ms 0xB1 /* 289.99ms */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800620#define hp_clkctrl_0 0x6D
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800622#define PWR_DWN BIT(6)
623#define ACTdeassert BIT(4)
624#define CLK_40MHZ (BIT(1) + BIT(0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800626#define CLKCTRL_DEFAULT (ACTdeassert | CLK_40MHZ)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800628#define hp_fiforead 0x6E
629#define hp_fifowrite 0x6F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800631#define hp_offsetctr 0x70
632#define hp_xferstat 0x71
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800634#define FIFO_EMPTY BIT(6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800636#define hp_portctrl_1 0x72
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800638#define CHK_SCSI_P BIT(3)
639#define HOST_MODE8 BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800641#define hp_xfer_pad 0x73
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800643#define ID_UNLOCK BIT(3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800645#define hp_scsidata_0 0x74
646#define hp_scsidata_1 0x75
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800648#define hp_aramBase 0x80
649#define BIOS_DATA_OFFSET 0x60
650#define BIOS_RELATIVE_CARD 0x64
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651
Jiri Slaby1cafc302007-10-18 23:40:36 -0700652#define AR3 (BIT(9) + BIT(8))
653#define SDATA BIT(10)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654
Jiri Slaby1cafc302007-10-18 23:40:36 -0700655#define CRD_OP BIT(11) /* Cmp Reg. w/ Data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656
Jiri Slaby1cafc302007-10-18 23:40:36 -0700657#define CRR_OP BIT(12) /* Cmp Reg. w. Reg. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658
Jiri Slaby1cafc302007-10-18 23:40:36 -0700659#define CPE_OP (BIT(14)+BIT(11)) /* Cmp SCSI phs & Branch EQ */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660
Jiri Slaby1cafc302007-10-18 23:40:36 -0700661#define CPN_OP (BIT(14)+BIT(12)) /* Cmp SCSI phs & Branch NOT EQ */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800663#define ADATA_OUT 0x00
Jiri Slaby1cafc302007-10-18 23:40:36 -0700664#define ADATA_IN BIT(8)
665#define ACOMMAND BIT(10)
666#define ASTATUS (BIT(10)+BIT(8))
667#define AMSG_OUT (BIT(10)+BIT(9))
668#define AMSG_IN (BIT(10)+BIT(9)+BIT(8))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669
Jiri Slaby1cafc302007-10-18 23:40:36 -0700670#define BRH_OP BIT(13) /* Branch */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800672#define ALWAYS 0x00
Jiri Slaby1cafc302007-10-18 23:40:36 -0700673#define EQUAL BIT(8)
674#define NOT_EQ BIT(9)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675
Jiri Slaby1cafc302007-10-18 23:40:36 -0700676#define TCB_OP (BIT(13)+BIT(11)) /* Test condition & branch */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677
Jiri Slaby1cafc302007-10-18 23:40:36 -0700678#define FIFO_0 BIT(10)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679
Jiri Slaby1cafc302007-10-18 23:40:36 -0700680#define MPM_OP BIT(15) /* Match phase and move data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681
Jiri Slaby1cafc302007-10-18 23:40:36 -0700682#define MRR_OP BIT(14) /* Move DReg. to Reg. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800684#define S_IDREG (BIT(2)+BIT(1)+BIT(0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800686#define D_AR0 0x00
687#define D_AR1 BIT(0)
688#define D_BUCKET (BIT(2) + BIT(1) + BIT(0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689
Jiri Slaby1cafc302007-10-18 23:40:36 -0700690#define RAT_OP (BIT(14)+BIT(13)+BIT(11))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691
Jiri Slaby1cafc302007-10-18 23:40:36 -0700692#define SSI_OP (BIT(15)+BIT(11))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800694#define SSI_ITAR_DISC (ITAR_DISC >> 8)
695#define SSI_IDO_STRT (IDO_STRT >> 8)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800697#define SSI_ICMD_COMP (ICMD_COMP >> 8)
698#define SSI_ITICKLE (ITICKLE >> 8)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800700#define SSI_IUNKWN (IUNKWN >> 8)
701#define SSI_INO_CC (IUNKWN >> 8)
702#define SSI_IRFAIL (IUNKWN >> 8)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800704#define NP 0x10 /*Next Phase */
705#define NTCMD 0x02 /*Non- Tagged Command start */
706#define CMDPZ 0x04 /*Command phase */
707#define DINT 0x12 /*Data Out/In interrupt */
708#define DI 0x13 /*Data Out */
709#define DC 0x19 /*Disconnect Message */
710#define ST 0x1D /*Status Phase */
711#define UNKNWN 0x24 /*Unknown bus action */
712#define CC 0x25 /*Command Completion failure */
713#define TICK 0x26 /*New target reselected us. */
714#define SELCHK 0x28 /*Select & Check SCSI ID latch reg */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800716#define ID_MSG_STRT hp_aramBase + 0x00
717#define NON_TAG_ID_MSG hp_aramBase + 0x06
718#define CMD_STRT hp_aramBase + 0x08
719#define SYNC_MSGS hp_aramBase + 0x08
Alexey Dobriyan85ae97d82006-03-08 00:14:22 -0800720
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800721#define TAG_STRT 0x00
722#define DISCONNECT_START 0x10/2
723#define END_DATA_START 0x14/2
724#define CMD_ONLY_STRT CMDPZ/2
725#define SELCHK_STRT SELCHK/2
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726
727#define GET_XFER_CNT(port, xfercnt) {RD_HARP32(port,hp_xfercnt_0,xfercnt); xfercnt &= 0xFFFFFF;}
728/* #define GET_XFER_CNT(port, xfercnt) (xfercnt = RD_HARPOON(port+hp_xfercnt_2), \
729 xfercnt <<= 16,\
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800730 xfercnt |= RDW_HARPOON((unsigned short)(port+hp_xfercnt_0)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 */
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800732#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 -0700733 addr >>= 16,\
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800734 WRW_HARPOON((port+hp_host_addr_hmi), (unsigned short)(addr & 0x0000FFFFL)),\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 WR_HARP32(port,hp_xfercnt_0,count),\
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800736 WRW_HARPOON((port+hp_xfer_cnt_lo), (unsigned short)(count & 0x0000FFFFL)),\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 count >>= 16,\
738 WR_HARPOON(port+hp_xfer_cnt_hi, (count & 0xFF)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739
740#define ACCEPT_MSG(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
741 WR_HARPOON(port+hp_scsisig, S_ILL_PH);}
742
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743#define ACCEPT_MSG_ATN(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
744 WR_HARPOON(port+hp_scsisig, (S_ILL_PH|SCSI_ATN));}
745
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746#define DISABLE_AUTO(port) (WR_HARPOON(port+hp_scsireset, PROG_RESET),\
747 WR_HARPOON(port+hp_scsireset, 0x00))
748
749#define ARAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
750 (RD_HARPOON(p_port+hp_page_ctrl) | SGRAM_ARAM)))
751
752#define SGRAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
753 (RD_HARPOON(p_port+hp_page_ctrl) & ~SGRAM_ARAM)))
754
755#define MDISABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
756 (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE)))
757
758#define MENABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
759 (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE)))
760
Khalid Aziz391e2f22013-05-16 19:44:14 -0600761static unsigned char FPT_sisyncn(u32 port, unsigned char p_card,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800762 unsigned char syncFlag);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600763static void FPT_ssel(u32 port, unsigned char p_card);
764static void FPT_sres(u32 port, unsigned char p_card,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800765 struct sccb_card *pCurrCard);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600766static void FPT_shandem(u32 port, unsigned char p_card,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800767 struct sccb *pCurrSCCB);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600768static void FPT_stsyncn(u32 port, unsigned char p_card);
769static void FPT_sisyncr(u32 port, unsigned char sync_pulse,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800770 unsigned char offset);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600771static void FPT_sssyncv(u32 p_port, unsigned char p_id,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800772 unsigned char p_sync_value,
773 struct sccb_mgr_tar_info *currTar_Info);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600774static void FPT_sresb(u32 port, unsigned char p_card);
775static void FPT_sxfrp(u32 p_port, unsigned char p_card);
776static void FPT_schkdd(u32 port, unsigned char p_card);
777static unsigned char FPT_RdStack(u32 port, unsigned char index);
778static void FPT_WrStack(u32 portBase, unsigned char index,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800779 unsigned char data);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600780static unsigned char FPT_ChkIfChipInitialized(u32 ioPort);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781
Khalid Aziz391e2f22013-05-16 19:44:14 -0600782static void FPT_SendMsg(u32 port, unsigned char message);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800783static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
784 unsigned char error_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800786static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card);
787static void FPT_RNVRamData(struct nvram_info *pNvRamInfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788
Khalid Aziz391e2f22013-05-16 19:44:14 -0600789static unsigned char FPT_siwidn(u32 port, unsigned char p_card);
790static void FPT_stwidn(u32 port, unsigned char p_card);
791static void FPT_siwidr(u32 port, unsigned char width);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800793static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
794 unsigned char p_card);
795static void FPT_queueDisconnect(struct sccb *p_SCCB, unsigned char p_card);
796static void FPT_queueCmdComplete(struct sccb_card *pCurrCard,
797 struct sccb *p_SCCB, unsigned char p_card);
798static void FPT_queueSearchSelect(struct sccb_card *pCurrCard,
Alexey Dobriyandb038cf82006-03-08 00:14:24 -0800799 unsigned char p_card);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800800static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code);
801static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char card);
802static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB,
803 unsigned char p_card);
804static void FPT_utilUpdateResidual(struct sccb *p_SCCB);
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800805static unsigned short FPT_CalcCrc16(unsigned char buffer[]);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800806static unsigned char FPT_CalcLrc(unsigned char buffer[]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807
Khalid Aziz391e2f22013-05-16 19:44:14 -0600808static void FPT_Wait1Second(u32 p_port);
809static void FPT_Wait(u32 p_port, unsigned char p_delay);
810static void FPT_utilEEWriteOnOff(u32 p_port, unsigned char p_mode);
811static void FPT_utilEEWrite(u32 p_port, unsigned short ee_data,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800812 unsigned short ee_addr);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600813static unsigned short FPT_utilEERead(u32 p_port,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800814 unsigned short ee_addr);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600815static unsigned short FPT_utilEEReadOrg(u32 p_port,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800816 unsigned short ee_addr);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600817static void FPT_utilEESendCmdAddr(u32 p_port, unsigned char ee_cmd,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800818 unsigned short ee_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819
Khalid Aziz391e2f22013-05-16 19:44:14 -0600820static void FPT_phaseDataOut(u32 port, unsigned char p_card);
821static void FPT_phaseDataIn(u32 port, unsigned char p_card);
822static void FPT_phaseCommand(u32 port, unsigned char p_card);
823static void FPT_phaseStatus(u32 port, unsigned char p_card);
824static void FPT_phaseMsgOut(u32 port, unsigned char p_card);
825static void FPT_phaseMsgIn(u32 port, unsigned char p_card);
826static void FPT_phaseIllegal(u32 port, unsigned char p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827
Khalid Aziz391e2f22013-05-16 19:44:14 -0600828static void FPT_phaseDecode(u32 port, unsigned char p_card);
829static void FPT_phaseChkFifo(u32 port, unsigned char p_card);
830static void FPT_phaseBusFree(u32 p_port, unsigned char p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831
Khalid Aziz391e2f22013-05-16 19:44:14 -0600832static void FPT_XbowInit(u32 port, unsigned char scamFlg);
833static void FPT_BusMasterInit(u32 p_port);
834static void FPT_DiagEEPROM(u32 p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835
Khalid Aziz391e2f22013-05-16 19:44:14 -0600836static void FPT_dataXferProcessor(u32 port,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800837 struct sccb_card *pCurrCard);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600838static void FPT_busMstrSGDataXferStart(u32 port,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800839 struct sccb *pCurrSCCB);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600840static void FPT_busMstrDataXferStart(u32 port,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800841 struct sccb *pCurrSCCB);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600842static void FPT_hostDataXferAbort(u32 port, unsigned char p_card,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800843 struct sccb *pCurrSCCB);
844static void FPT_hostDataXferRestart(struct sccb *currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845
Khalid Aziz391e2f22013-05-16 19:44:14 -0600846static unsigned char FPT_SccbMgr_bad_isr(u32 p_port,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800847 unsigned char p_card,
848 struct sccb_card *pCurrCard,
849 unsigned short p_int);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800851static void FPT_SccbMgrTableInitAll(void);
852static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard,
853 unsigned char p_card);
854static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
855 unsigned char target);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800857static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
858 unsigned char p_power_up);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700859
Khalid Aziz391e2f22013-05-16 19:44:14 -0600860static int FPT_scarb(u32 p_port, unsigned char p_sel_type);
861static void FPT_scbusf(u32 p_port);
862static void FPT_scsel(u32 p_port);
863static void FPT_scasid(unsigned char p_card, u32 p_port);
864static unsigned char FPT_scxferc(u32 p_port, unsigned char p_data);
865static unsigned char FPT_scsendi(u32 p_port,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800866 unsigned char p_id_string[]);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600867static unsigned char FPT_sciso(u32 p_port,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800868 unsigned char p_id_string[]);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600869static void FPT_scwirod(u32 p_port, unsigned char p_data_bit);
870static void FPT_scwiros(u32 p_port, unsigned char p_data_bit);
Alexey Dobriyandb038cf82006-03-08 00:14:24 -0800871static unsigned char FPT_scvalq(unsigned char p_quintet);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600872static unsigned char FPT_scsell(u32 p_port, unsigned char targ_id);
873static void FPT_scwtsel(u32 p_port);
874static void FPT_inisci(unsigned char p_card, u32 p_port,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800875 unsigned char p_our_id);
Khalid Aziz391e2f22013-05-16 19:44:14 -0600876static void FPT_scsavdi(unsigned char p_card, u32 p_port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800877static unsigned char FPT_scmachid(unsigned char p_card,
878 unsigned char p_id_string[]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879
Khalid Aziz391e2f22013-05-16 19:44:14 -0600880static void FPT_autoCmdCmplt(u32 p_port, unsigned char p_card);
881static void FPT_autoLoadDefaultMap(u32 p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800883static struct sccb_mgr_tar_info FPT_sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] =
884 { {{0}} };
885static struct sccb_card FPT_BL_Card[MAX_CARDS] = { {0} };
886static SCCBSCAM_INFO FPT_scamInfo[MAX_SCSI_TAR] = { {{0}} };
887static struct nvram_info FPT_nvRamInfo[MAX_MB_CARDS] = { {0} };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888
Alexey Dobriyandb038cf82006-03-08 00:14:24 -0800889static unsigned char FPT_mbCards = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800890static unsigned char FPT_scamHAString[] =
891 { 0x63, 0x07, 'B', 'U', 'S', 'L', 'O', 'G', 'I', 'C',
892 ' ', 'B', 'T', '-', '9', '3', '0',
893 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
894 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
895};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800897static unsigned short FPT_default_intena = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898
Khalid Aziz391e2f22013-05-16 19:44:14 -0600899static void (*FPT_s_PhaseTbl[8]) (u32, unsigned char) = {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08009000};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901
902/*---------------------------------------------------------------------
903 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -0800904 * Function: FlashPoint_ProbeHostAdapter
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 *
906 * Description: Setup and/or Search for cards and return info to caller.
907 *
908 *---------------------------------------------------------------------*/
909
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800910static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800912 static unsigned char first_time = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800914 unsigned char i, j, id, ScamFlg;
915 unsigned short temp, temp2, temp3, temp4, temp5, temp6;
Khalid Aziz391e2f22013-05-16 19:44:14 -0600916 u32 ioport;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800917 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800919 ioport = pCardInfo->si_baseaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800921 if (RD_HARPOON(ioport + hp_vendor_id_0) != ORION_VEND_0)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800922 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800924 if ((RD_HARPOON(ioport + hp_vendor_id_1) != ORION_VEND_1))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800925 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800927 if ((RD_HARPOON(ioport + hp_device_id_0) != ORION_DEV_0))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800928 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800930 if ((RD_HARPOON(ioport + hp_device_id_1) != ORION_DEV_1))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800931 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800933 if (RD_HARPOON(ioport + hp_rev_num) != 0x0f) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934
935/* For new Harpoon then check for sub_device ID LSB
936 the bits(0-3) must be all ZERO for compatible with
937 current version of SCCBMgr, else skip this Harpoon
938 device. */
939
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800940 if (RD_HARPOON(ioport + hp_sub_device_id_0) & 0x0f)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800941 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 }
943
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800944 if (first_time) {
945 FPT_SccbMgrTableInitAll();
946 first_time = 0;
James Bottomley 47b5d692005-04-24 02:38:05 -0500947 FPT_mbCards = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800948 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800950 if (FPT_RdStack(ioport, 0) != 0x00) {
951 if (FPT_ChkIfChipInitialized(ioport) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 pCurrNvRam = NULL;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800953 WR_HARPOON(ioport + hp_semaphore, 0x00);
954 FPT_XbowInit(ioport, 0); /*Must Init the SCSI before attempting */
James Bottomley 47b5d692005-04-24 02:38:05 -0500955 FPT_DiagEEPROM(ioport);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800956 } else {
957 if (FPT_mbCards < MAX_MB_CARDS) {
James Bottomley 47b5d692005-04-24 02:38:05 -0500958 pCurrNvRam = &FPT_nvRamInfo[FPT_mbCards];
959 FPT_mbCards++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 pCurrNvRam->niBaseAddr = ioport;
James Bottomley 47b5d692005-04-24 02:38:05 -0500961 FPT_RNVRamData(pCurrNvRam);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800962 } else
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800963 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800965 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 pCurrNvRam = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800968 WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT);
969 WR_HARPOON(ioport + hp_sys_ctrl, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800971 if (pCurrNvRam)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 pCardInfo->si_id = pCurrNvRam->niAdapId;
973 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800974 pCardInfo->si_id =
975 (unsigned
976 char)(FPT_utilEERead(ioport,
977 (ADAPTER_SCSI_ID /
978 2)) & (unsigned char)0x0FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800980 pCardInfo->si_lun = 0x00;
981 pCardInfo->si_fw_revision = ORION_FW_REV;
982 temp2 = 0x0000;
983 temp3 = 0x0000;
984 temp4 = 0x0000;
985 temp5 = 0x0000;
986 temp6 = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800988 for (id = 0; id < (16 / 2); id++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800990 if (pCurrNvRam) {
991 temp = (unsigned short)pCurrNvRam->niSyncTbl[id];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800993 (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
994 } else
995 temp =
996 FPT_utilEERead(ioport,
997 (unsigned short)((SYNC_RATE_TBL / 2)
998 + id));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001000 for (i = 0; i < 2; temp >>= 8, i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001002 temp2 >>= 1;
1003 temp3 >>= 1;
1004 temp4 >>= 1;
1005 temp5 >>= 1;
1006 temp6 >>= 1;
1007 switch (temp & 0x3) {
1008 case AUTO_RATE_20: /* Synchronous, 20 mega-transfers/second */
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001009 temp6 |= 0x8000;
1010 fallthrough;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001011 case AUTO_RATE_10: /* Synchronous, 10 mega-transfers/second */
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001012 temp5 |= 0x8000;
1013 fallthrough;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001014 case AUTO_RATE_05: /* Synchronous, 5 mega-transfers/second */
Gustavo A. R. Silvadf561f662020-08-23 17:36:59 -05001015 temp2 |= 0x8000;
1016 fallthrough;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001017 case AUTO_RATE_00: /* Asynchronous */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 break;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001019 }
1020
1021 if (temp & DISC_ENABLE_BIT)
1022 temp3 |= 0x8000;
1023
1024 if (temp & WIDE_NEGO_BIT)
1025 temp4 |= 0x8000;
1026
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 }
1029
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001030 pCardInfo->si_per_targ_init_sync = temp2;
1031 pCardInfo->si_per_targ_no_disc = temp3;
1032 pCardInfo->si_per_targ_wide_nego = temp4;
1033 pCardInfo->si_per_targ_fast_nego = temp5;
1034 pCardInfo->si_per_targ_ultra_nego = temp6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001036 if (pCurrNvRam)
1037 i = pCurrNvRam->niSysConf;
1038 else
1039 i = (unsigned
1040 char)(FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001042 if (pCurrNvRam)
1043 ScamFlg = pCurrNvRam->niScamConf;
1044 else
1045 ScamFlg =
1046 (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047
Randy Dunlap4d431152021-05-29 16:48:57 -07001048 pCardInfo->si_mflags = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001050 if (i & 0x01)
Randy Dunlap4d431152021-05-29 16:48:57 -07001051 pCardInfo->si_mflags |= SCSI_PARITY_ENA;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001052
1053 if (!(i & 0x02))
Randy Dunlap4d431152021-05-29 16:48:57 -07001054 pCardInfo->si_mflags |= SOFT_RESET;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001055
1056 if (i & 0x10)
Randy Dunlap4d431152021-05-29 16:48:57 -07001057 pCardInfo->si_mflags |= EXTENDED_TRANSLATION;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001058
1059 if (ScamFlg & SCAM_ENABLED)
Randy Dunlap4d431152021-05-29 16:48:57 -07001060 pCardInfo->si_mflags |= FLAG_SCAM_ENABLED;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001061
1062 if (ScamFlg & SCAM_LEVEL2)
Randy Dunlap4d431152021-05-29 16:48:57 -07001063 pCardInfo->si_mflags |= FLAG_SCAM_LEVEL2;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001064
1065 j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
1066 if (i & 0x04) {
1067 j |= SCSI_TERM_ENA_L;
1068 }
1069 WR_HARPOON(ioport + hp_bm_ctrl, j);
1070
1071 j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
1072 if (i & 0x08) {
1073 j |= SCSI_TERM_ENA_H;
1074 }
1075 WR_HARPOON(ioport + hp_ee_ctrl, j);
1076
1077 if (!(RD_HARPOON(ioport + hp_page_ctrl) & NARROW_SCSI_CARD))
1078
Randy Dunlap4d431152021-05-29 16:48:57 -07001079 pCardInfo->si_mflags |= SUPPORT_16TAR_32LUN;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001080
1081 pCardInfo->si_card_family = HARPOON_FAMILY;
1082 pCardInfo->si_bustype = BUSTYPE_PCI;
1083
1084 if (pCurrNvRam) {
1085 pCardInfo->si_card_model[0] = '9';
1086 switch (pCurrNvRam->niModel & 0x0f) {
1087 case MODEL_LT:
1088 pCardInfo->si_card_model[1] = '3';
1089 pCardInfo->si_card_model[2] = '0';
1090 break;
1091 case MODEL_LW:
1092 pCardInfo->si_card_model[1] = '5';
1093 pCardInfo->si_card_model[2] = '0';
1094 break;
1095 case MODEL_DL:
1096 pCardInfo->si_card_model[1] = '3';
1097 pCardInfo->si_card_model[2] = '2';
1098 break;
1099 case MODEL_DW:
1100 pCardInfo->si_card_model[1] = '5';
1101 pCardInfo->si_card_model[2] = '2';
1102 break;
1103 }
1104 } else {
1105 temp = FPT_utilEERead(ioport, (MODEL_NUMB_0 / 2));
1106 pCardInfo->si_card_model[0] = (unsigned char)(temp >> 8);
1107 temp = FPT_utilEERead(ioport, (MODEL_NUMB_2 / 2));
1108
1109 pCardInfo->si_card_model[1] = (unsigned char)(temp & 0x00FF);
1110 pCardInfo->si_card_model[2] = (unsigned char)(temp >> 8);
1111 }
1112
1113 if (pCardInfo->si_card_model[1] == '3') {
1114 if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
Randy Dunlap4d431152021-05-29 16:48:57 -07001115 pCardInfo->si_mflags |= LOW_BYTE_TERM;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001116 } else if (pCardInfo->si_card_model[2] == '0') {
1117 temp = RD_HARPOON(ioport + hp_xfer_pad);
1118 WR_HARPOON(ioport + hp_xfer_pad, (temp & ~BIT(4)));
1119 if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
Randy Dunlap4d431152021-05-29 16:48:57 -07001120 pCardInfo->si_mflags |= LOW_BYTE_TERM;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001121 WR_HARPOON(ioport + hp_xfer_pad, (temp | BIT(4)));
1122 if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
Randy Dunlap4d431152021-05-29 16:48:57 -07001123 pCardInfo->si_mflags |= HIGH_BYTE_TERM;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001124 WR_HARPOON(ioport + hp_xfer_pad, temp);
1125 } else {
1126 temp = RD_HARPOON(ioport + hp_ee_ctrl);
1127 temp2 = RD_HARPOON(ioport + hp_xfer_pad);
1128 WR_HARPOON(ioport + hp_ee_ctrl, (temp | SEE_CS));
1129 WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4)));
1130 temp3 = 0;
1131 for (i = 0; i < 8; i++) {
1132 temp3 <<= 1;
1133 if (!(RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7)))
1134 temp3 |= 1;
1135 WR_HARPOON(ioport + hp_xfer_pad, (temp2 & ~BIT(4)));
1136 WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4)));
1137 }
1138 WR_HARPOON(ioport + hp_ee_ctrl, temp);
1139 WR_HARPOON(ioport + hp_xfer_pad, temp2);
1140 if (!(temp3 & BIT(7)))
Randy Dunlap4d431152021-05-29 16:48:57 -07001141 pCardInfo->si_mflags |= LOW_BYTE_TERM;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001142 if (!(temp3 & BIT(6)))
Randy Dunlap4d431152021-05-29 16:48:57 -07001143 pCardInfo->si_mflags |= HIGH_BYTE_TERM;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001144 }
1145
1146 ARAM_ACCESS(ioport);
1147
1148 for (i = 0; i < 4; i++) {
1149
1150 pCardInfo->si_XlatInfo[i] =
1151 RD_HARPOON(ioport + hp_aramBase + BIOS_DATA_OFFSET + i);
1152 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153
1154 /* return with -1 if no sort, else return with
1155 logical card number sorted by BIOS (zero-based) */
1156
1157 pCardInfo->si_relative_cardnum =
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001158 (unsigned
1159 char)(RD_HARPOON(ioport + hp_aramBase + BIOS_RELATIVE_CARD) - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001161 SGRAM_ACCESS(ioport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001163 FPT_s_PhaseTbl[0] = FPT_phaseDataOut;
1164 FPT_s_PhaseTbl[1] = FPT_phaseDataIn;
1165 FPT_s_PhaseTbl[2] = FPT_phaseIllegal;
1166 FPT_s_PhaseTbl[3] = FPT_phaseIllegal;
1167 FPT_s_PhaseTbl[4] = FPT_phaseCommand;
1168 FPT_s_PhaseTbl[5] = FPT_phaseStatus;
1169 FPT_s_PhaseTbl[6] = FPT_phaseMsgOut;
1170 FPT_s_PhaseTbl[7] = FPT_phaseMsgIn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001172 pCardInfo->si_present = 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001174 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175}
1176
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177/*---------------------------------------------------------------------
1178 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001179 * Function: FlashPoint_HardwareResetHostAdapter
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 *
1181 * Description: Setup adapter for normal operation (hard reset).
1182 *
1183 *---------------------------------------------------------------------*/
1184
Khalid Aziz391e2f22013-05-16 19:44:14 -06001185static void *FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001186 *pCardInfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001188 struct sccb_card *CurrCard = NULL;
1189 struct nvram_info *pCurrNvRam;
1190 unsigned char i, j, thisCard, ScamFlg;
1191 unsigned short temp, sync_bit_map, id;
Khalid Aziz391e2f22013-05-16 19:44:14 -06001192 u32 ioport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001194 ioport = pCardInfo->si_baseaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001196 for (thisCard = 0; thisCard <= MAX_CARDS; thisCard++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197
Khalid Aziz391e2f22013-05-16 19:44:14 -06001198 if (thisCard == MAX_CARDS)
1199 return (void *)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001201 if (FPT_BL_Card[thisCard].ioPort == ioport) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001203 CurrCard = &FPT_BL_Card[thisCard];
1204 FPT_SccbMgrTableInitCard(CurrCard, thisCard);
1205 break;
1206 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001208 else if (FPT_BL_Card[thisCard].ioPort == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001210 FPT_BL_Card[thisCard].ioPort = ioport;
1211 CurrCard = &FPT_BL_Card[thisCard];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001213 if (FPT_mbCards)
1214 for (i = 0; i < FPT_mbCards; i++) {
1215 if (CurrCard->ioPort ==
1216 FPT_nvRamInfo[i].niBaseAddr)
1217 CurrCard->pNvRamInfo =
1218 &FPT_nvRamInfo[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001220 FPT_SccbMgrTableInitCard(CurrCard, thisCard);
1221 CurrCard->cardIndex = thisCard;
1222 CurrCard->cardInfo = pCardInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001224 break;
1225 }
1226 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227
1228 pCurrNvRam = CurrCard->pNvRamInfo;
1229
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001230 if (pCurrNvRam) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 ScamFlg = pCurrNvRam->niScamConf;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001232 } else {
1233 ScamFlg =
1234 (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 }
1236
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001237 FPT_BusMasterInit(ioport);
1238 FPT_XbowInit(ioport, ScamFlg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001240 FPT_autoLoadDefaultMap(ioport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001242 for (i = 0, id = 0x01; i != pCardInfo->si_id; i++, id <<= 1) {
1243 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001245 WR_HARPOON(ioport + hp_selfid_0, id);
1246 WR_HARPOON(ioport + hp_selfid_1, 0x00);
1247 WR_HARPOON(ioport + hp_arb_id, pCardInfo->si_id);
1248 CurrCard->ourId = pCardInfo->si_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249
Randy Dunlap4d431152021-05-29 16:48:57 -07001250 i = (unsigned char)pCardInfo->si_mflags;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001251 if (i & SCSI_PARITY_ENA)
1252 WR_HARPOON(ioport + hp_portctrl_1, (HOST_MODE8 | CHK_SCSI_P));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001254 j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
1255 if (i & LOW_BYTE_TERM)
1256 j |= SCSI_TERM_ENA_L;
1257 WR_HARPOON(ioport + hp_bm_ctrl, j);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001259 j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
1260 if (i & HIGH_BYTE_TERM)
1261 j |= SCSI_TERM_ENA_H;
1262 WR_HARPOON(ioport + hp_ee_ctrl, j);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263
Randy Dunlap4d431152021-05-29 16:48:57 -07001264 if (!(pCardInfo->si_mflags & SOFT_RESET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001266 FPT_sresb(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001268 FPT_scini(thisCard, pCardInfo->si_id, 0);
1269 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270
Randy Dunlap4d431152021-05-29 16:48:57 -07001271 if (pCardInfo->si_mflags & POST_ALL_UNDERRRUNS)
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001272 CurrCard->globalFlags |= F_NO_FILTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001274 if (pCurrNvRam) {
1275 if (pCurrNvRam->niSysConf & 0x10)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 CurrCard->globalFlags |= F_GREEN_PC;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001277 } else {
1278 if (FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)) & GREEN_PC_ENA)
1279 CurrCard->globalFlags |= F_GREEN_PC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 }
1281
1282 /* Set global flag to indicate Re-Negotiation to be done on all
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001283 ckeck condition */
1284 if (pCurrNvRam) {
1285 if (pCurrNvRam->niScsiConf & 0x04)
1286 CurrCard->globalFlags |= F_DO_RENEGO;
1287 } else {
1288 if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & RENEGO_ENA)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289 CurrCard->globalFlags |= F_DO_RENEGO;
1290 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001292 if (pCurrNvRam) {
1293 if (pCurrNvRam->niScsiConf & 0x08)
1294 CurrCard->globalFlags |= F_CONLUN_IO;
1295 } else {
1296 if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & CONNIO_ENA)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 CurrCard->globalFlags |= F_CONLUN_IO;
1298 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001299
1300 temp = pCardInfo->si_per_targ_no_disc;
1301
1302 for (i = 0, id = 1; i < MAX_SCSI_TAR; i++, id <<= 1) {
1303
1304 if (temp & id)
1305 FPT_sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 }
1307
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001308 sync_bit_map = 0x0001;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001310 for (id = 0; id < (MAX_SCSI_TAR / 2); id++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001312 if (pCurrNvRam) {
1313 temp = (unsigned short)pCurrNvRam->niSyncTbl[id];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001315 (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
1316 } else
1317 temp =
1318 FPT_utilEERead(ioport,
1319 (unsigned short)((SYNC_RATE_TBL / 2)
1320 + id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001322 for (i = 0; i < 2; temp >>= 8, i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001324 if (pCardInfo->si_per_targ_init_sync & sync_bit_map) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001326 FPT_sccbMgrTbl[thisCard][id * 2 +
1327 i].TarEEValue =
1328 (unsigned char)temp;
1329 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001331 else {
1332 FPT_sccbMgrTbl[thisCard][id * 2 +
1333 i].TarStatus |=
1334 SYNC_SUPPORTED;
1335 FPT_sccbMgrTbl[thisCard][id * 2 +
1336 i].TarEEValue =
1337 (unsigned char)(temp & ~EE_SYNC_MASK);
1338 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340/* if ((pCardInfo->si_per_targ_wide_nego & sync_bit_map) ||
1341 (id*2+i >= 8)){
1342*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001343 if (pCardInfo->si_per_targ_wide_nego & sync_bit_map) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001345 FPT_sccbMgrTbl[thisCard][id * 2 +
1346 i].TarEEValue |=
1347 EE_WIDE_SCSI;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001349 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001351 else { /* NARROW SCSI */
1352 FPT_sccbMgrTbl[thisCard][id * 2 +
1353 i].TarStatus |=
1354 WIDE_NEGOCIATED;
1355 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001357 sync_bit_map <<= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001359 }
1360 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001362 WR_HARPOON((ioport + hp_semaphore),
1363 (unsigned char)(RD_HARPOON((ioport + hp_semaphore)) |
1364 SCCB_MGR_PRESENT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365
Khalid Aziz391e2f22013-05-16 19:44:14 -06001366 return (void *)CurrCard;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367}
1368
Khalid Aziz391e2f22013-05-16 19:44:14 -06001369static void FlashPoint_ReleaseHostAdapter(void *pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370{
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08001371 unsigned char i;
Khalid Aziz391e2f22013-05-16 19:44:14 -06001372 u32 portBase;
1373 u32 regOffset;
1374 u32 scamData;
1375 u32 *pScamTbl;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001376 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001378 pCurrNvRam = ((struct sccb_card *)pCurrCard)->pNvRamInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001380 if (pCurrNvRam) {
James Bottomley 47b5d692005-04-24 02:38:05 -05001381 FPT_WrStack(pCurrNvRam->niBaseAddr, 0, pCurrNvRam->niModel);
1382 FPT_WrStack(pCurrNvRam->niBaseAddr, 1, pCurrNvRam->niSysConf);
1383 FPT_WrStack(pCurrNvRam->niBaseAddr, 2, pCurrNvRam->niScsiConf);
1384 FPT_WrStack(pCurrNvRam->niBaseAddr, 3, pCurrNvRam->niScamConf);
1385 FPT_WrStack(pCurrNvRam->niBaseAddr, 4, pCurrNvRam->niAdapId);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001387 for (i = 0; i < MAX_SCSI_TAR / 2; i++)
1388 FPT_WrStack(pCurrNvRam->niBaseAddr,
1389 (unsigned char)(i + 5),
1390 pCurrNvRam->niSyncTbl[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391
1392 portBase = pCurrNvRam->niBaseAddr;
1393
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001394 for (i = 0; i < MAX_SCSI_TAR; i++) {
1395 regOffset = hp_aramBase + 64 + i * 4;
Khalid Aziz391e2f22013-05-16 19:44:14 -06001396 pScamTbl = (u32 *)&pCurrNvRam->niScamTbl[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 scamData = *pScamTbl;
1398 WR_HARP32(portBase, regOffset, scamData);
1399 }
1400
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001401 } else {
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001402 FPT_WrStack(((struct sccb_card *)pCurrCard)->ioPort, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 }
1404}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001406static void FPT_RNVRamData(struct nvram_info *pNvRamInfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407{
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08001408 unsigned char i;
Khalid Aziz391e2f22013-05-16 19:44:14 -06001409 u32 portBase;
1410 u32 regOffset;
1411 u32 scamData;
1412 u32 *pScamTbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001414 pNvRamInfo->niModel = FPT_RdStack(pNvRamInfo->niBaseAddr, 0);
1415 pNvRamInfo->niSysConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 1);
James Bottomley 47b5d692005-04-24 02:38:05 -05001416 pNvRamInfo->niScsiConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 2);
1417 pNvRamInfo->niScamConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 3);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001418 pNvRamInfo->niAdapId = FPT_RdStack(pNvRamInfo->niBaseAddr, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001420 for (i = 0; i < MAX_SCSI_TAR / 2; i++)
1421 pNvRamInfo->niSyncTbl[i] =
1422 FPT_RdStack(pNvRamInfo->niBaseAddr, (unsigned char)(i + 5));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423
1424 portBase = pNvRamInfo->niBaseAddr;
1425
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001426 for (i = 0; i < MAX_SCSI_TAR; i++) {
1427 regOffset = hp_aramBase + 64 + i * 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 RD_HARP32(portBase, regOffset, scamData);
Khalid Aziz391e2f22013-05-16 19:44:14 -06001429 pScamTbl = (u32 *)&pNvRamInfo->niScamTbl[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430 *pScamTbl = scamData;
1431 }
1432
1433}
1434
Khalid Aziz391e2f22013-05-16 19:44:14 -06001435static unsigned char FPT_RdStack(u32 portBase, unsigned char index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436{
1437 WR_HARPOON(portBase + hp_stack_addr, index);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001438 return RD_HARPOON(portBase + hp_stack_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439}
1440
Khalid Aziz391e2f22013-05-16 19:44:14 -06001441static void FPT_WrStack(u32 portBase, unsigned char index, unsigned char data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442{
1443 WR_HARPOON(portBase + hp_stack_addr, index);
1444 WR_HARPOON(portBase + hp_stack_data, data);
1445}
1446
Khalid Aziz391e2f22013-05-16 19:44:14 -06001447static unsigned char FPT_ChkIfChipInitialized(u32 ioPort)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001449 if ((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != FPT_RdStack(ioPort, 4))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001450 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001451 if ((RD_HARPOON(ioPort + hp_clkctrl_0) & CLKCTRL_DEFAULT)
1452 != CLKCTRL_DEFAULT)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001453 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001454 if ((RD_HARPOON(ioPort + hp_seltimeout) == TO_250ms) ||
1455 (RD_HARPOON(ioPort + hp_seltimeout) == TO_290ms))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001456 return 1;
1457 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458
1459}
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001460
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461/*---------------------------------------------------------------------
1462 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001463 * Function: FlashPoint_StartCCB
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464 *
1465 * Description: Start a command pointed to by p_Sccb. When the
1466 * command is completed it will be returned via the
1467 * callback function.
1468 *
1469 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06001470static void FlashPoint_StartCCB(void *curr_card, struct sccb *p_Sccb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471{
Khalid Aziz391e2f22013-05-16 19:44:14 -06001472 u32 ioport;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001473 unsigned char thisCard, lun;
1474 struct sccb *pSaveSccb;
1475 CALL_BK_FN callback;
Khalid Aziz391e2f22013-05-16 19:44:14 -06001476 struct sccb_card *pCurrCard = curr_card;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477
Khalid Aziz391e2f22013-05-16 19:44:14 -06001478 thisCard = pCurrCard->cardIndex;
1479 ioport = pCurrCard->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480
Adrian Bunk1377d8d2008-04-23 12:51:10 +03001481 if ((p_Sccb->TargID >= MAX_SCSI_TAR) || (p_Sccb->Lun >= MAX_LUN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 p_Sccb->HostStatus = SCCB_COMPLETE;
1484 p_Sccb->SccbStatus = SCCB_ERROR;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001485 callback = (CALL_BK_FN) p_Sccb->SccbCallback;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486 if (callback)
1487 callback(p_Sccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 return;
1490 }
1491
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001492 FPT_sinits(p_Sccb, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493
Khalid Aziz391e2f22013-05-16 19:44:14 -06001494 if (!pCurrCard->cmdCounter) {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001495 WR_HARPOON(ioport + hp_semaphore,
1496 (RD_HARPOON(ioport + hp_semaphore)
1497 | SCCB_MGR_ACTIVE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498
Khalid Aziz391e2f22013-05-16 19:44:14 -06001499 if (pCurrCard->globalFlags & F_GREEN_PC) {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001500 WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT);
1501 WR_HARPOON(ioport + hp_sys_ctrl, 0x00);
1502 }
1503 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504
Khalid Aziz391e2f22013-05-16 19:44:14 -06001505 pCurrCard->cmdCounter++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001507 if (RD_HARPOON(ioport + hp_semaphore) & BIOS_IN_USE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001509 WR_HARPOON(ioport + hp_semaphore,
1510 (RD_HARPOON(ioport + hp_semaphore)
1511 | TICKLE_ME));
1512 if (p_Sccb->OperationCode == RESET_COMMAND) {
1513 pSaveSccb =
Khalid Aziz391e2f22013-05-16 19:44:14 -06001514 pCurrCard->currentSCCB;
1515 pCurrCard->currentSCCB = p_Sccb;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001516 FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
Khalid Aziz391e2f22013-05-16 19:44:14 -06001517 pCurrCard->currentSCCB =
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001518 pSaveSccb;
1519 } else {
1520 FPT_queueAddSccb(p_Sccb, thisCard);
1521 }
1522 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001524 else if ((RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001526 if (p_Sccb->OperationCode == RESET_COMMAND) {
1527 pSaveSccb =
Khalid Aziz391e2f22013-05-16 19:44:14 -06001528 pCurrCard->currentSCCB;
1529 pCurrCard->currentSCCB = p_Sccb;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001530 FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
Khalid Aziz391e2f22013-05-16 19:44:14 -06001531 pCurrCard->currentSCCB =
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001532 pSaveSccb;
1533 } else {
1534 FPT_queueAddSccb(p_Sccb, thisCard);
1535 }
1536 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001538 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001540 MDISABLE_INT(ioport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541
Khalid Aziz391e2f22013-05-16 19:44:14 -06001542 if ((pCurrCard->globalFlags & F_CONLUN_IO) &&
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001543 ((FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].
1544 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545 lun = p_Sccb->Lun;
1546 else
1547 lun = 0;
Khalid Aziz391e2f22013-05-16 19:44:14 -06001548 if ((pCurrCard->currentSCCB == NULL) &&
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001549 (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarSelQ_Cnt == 0)
1550 && (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarLUNBusy[lun]
1551 == 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552
Khalid Aziz391e2f22013-05-16 19:44:14 -06001553 pCurrCard->currentSCCB = p_Sccb;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001554 FPT_ssel(p_Sccb->SccbIOPort, thisCard);
1555 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001557 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001559 if (p_Sccb->OperationCode == RESET_COMMAND) {
Khalid Aziz391e2f22013-05-16 19:44:14 -06001560 pSaveSccb = pCurrCard->currentSCCB;
1561 pCurrCard->currentSCCB = p_Sccb;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001562 FPT_queueSelectFail(&FPT_BL_Card[thisCard],
1563 thisCard);
Khalid Aziz391e2f22013-05-16 19:44:14 -06001564 pCurrCard->currentSCCB = pSaveSccb;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001565 } else {
1566 FPT_queueAddSccb(p_Sccb, thisCard);
1567 }
1568 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001570 MENABLE_INT(ioport);
1571 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573}
1574
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575/*---------------------------------------------------------------------
1576 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001577 * Function: FlashPoint_AbortCCB
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578 *
1579 * Description: Abort the command pointed to by p_Sccb. When the
1580 * command is completed it will be returned via the
1581 * callback function.
1582 *
1583 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06001584static int FlashPoint_AbortCCB(void *pCurrCard, struct sccb *p_Sccb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585{
Khalid Aziz391e2f22013-05-16 19:44:14 -06001586 u32 ioport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08001588 unsigned char thisCard;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589 CALL_BK_FN callback;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001590 struct sccb *pSaveSCCB;
1591 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001593 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001595 thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001597 if (!(RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001599 if (FPT_queueFindSccb(p_Sccb, thisCard)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001601 ((struct sccb_card *)pCurrCard)->cmdCounter--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001603 if (!((struct sccb_card *)pCurrCard)->cmdCounter)
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001604 WR_HARPOON(ioport + hp_semaphore,
1605 (RD_HARPOON(ioport + hp_semaphore)
1606 & (unsigned
1607 char)(~(SCCB_MGR_ACTIVE |
1608 TICKLE_ME))));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 p_Sccb->SccbStatus = SCCB_ABORT;
1611 callback = p_Sccb->SccbCallback;
1612 callback(p_Sccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001614 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 }
1616
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001617 else {
1618 if (((struct sccb_card *)pCurrCard)->currentSCCB ==
1619 p_Sccb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620 p_Sccb->SccbStatus = SCCB_ABORT;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001621 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622
1623 }
1624
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001625 else {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001626 if (p_Sccb->Sccb_tag) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627 MDISABLE_INT(ioport);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001628 if (((struct sccb_card *)pCurrCard)->
1629 discQ_Tbl[p_Sccb->Sccb_tag] ==
1630 p_Sccb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 p_Sccb->SccbStatus = SCCB_ABORT;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001632 p_Sccb->Sccb_scsistat =
1633 ABORT_ST;
1634 p_Sccb->Sccb_scsimsg =
Hannes Reineckea87afe22021-04-27 10:30:40 +02001635 ABORT_TASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001637 if (((struct sccb_card *)
1638 pCurrCard)->currentSCCB ==
1639 NULL) {
1640 ((struct sccb_card *)
1641 pCurrCard)->
1642 currentSCCB = p_Sccb;
1643 FPT_ssel(ioport,
1644 thisCard);
1645 } else {
1646 pSaveSCCB =
1647 ((struct sccb_card
1648 *)pCurrCard)->
1649 currentSCCB;
1650 ((struct sccb_card *)
1651 pCurrCard)->
1652 currentSCCB = p_Sccb;
1653 FPT_queueSelectFail((struct sccb_card *)pCurrCard, thisCard);
1654 ((struct sccb_card *)
1655 pCurrCard)->
1656 currentSCCB = pSaveSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 }
1658 }
1659 MENABLE_INT(ioport);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001660 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001661 } else {
1662 currTar_Info =
1663 &FPT_sccbMgrTbl[thisCard][p_Sccb->
1664 TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001666 if (FPT_BL_Card[thisCard].
1667 discQ_Tbl[currTar_Info->
1668 LunDiscQ_Idx[p_Sccb->Lun]]
1669 == p_Sccb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670 p_Sccb->SccbStatus = SCCB_ABORT;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001671 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 }
1673 }
1674 }
1675 }
1676 }
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001677 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678}
1679
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680/*---------------------------------------------------------------------
1681 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001682 * Function: FlashPoint_InterruptPending
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683 *
1684 * Description: Do a quick check to determine if there is a pending
1685 * interrupt for this card and disable the IRQ Pin if so.
1686 *
1687 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06001688static unsigned char FlashPoint_InterruptPending(void *pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689{
Khalid Aziz391e2f22013-05-16 19:44:14 -06001690 u32 ioport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001692 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001694 if (RD_HARPOON(ioport + hp_int_status) & INT_ASSERTED) {
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001695 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001696 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001698 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001700 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701}
1702
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703/*---------------------------------------------------------------------
1704 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001705 * Function: FlashPoint_HandleInterrupt
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 *
1707 * Description: This is our entry point when an interrupt is generated
1708 * by the card and the upper level driver passes it on to
1709 * us.
1710 *
1711 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06001712static int FlashPoint_HandleInterrupt(void *pcard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001714 struct sccb *currSCCB;
1715 unsigned char thisCard, result, bm_status, bm_int_st;
1716 unsigned short hp_int;
1717 unsigned char i, target;
Khalid Aziz391e2f22013-05-16 19:44:14 -06001718 struct sccb_card *pCurrCard = pcard;
1719 u32 ioport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720
Khalid Aziz391e2f22013-05-16 19:44:14 -06001721 thisCard = pCurrCard->cardIndex;
1722 ioport = pCurrCard->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001724 MDISABLE_INT(ioport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001726 if ((bm_int_st = RD_HARPOON(ioport + hp_int_status)) & EXT_STATUS_ON)
Khalid Aziz391e2f22013-05-16 19:44:14 -06001727 bm_status = RD_HARPOON(ioport + hp_ext_status) &
1728 (unsigned char)BAD_EXT_STATUS;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001729 else
1730 bm_status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001732 WR_HARPOON(ioport + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733
Khalid Aziz391e2f22013-05-16 19:44:14 -06001734 while ((hp_int = RDW_HARPOON((ioport + hp_intstat)) &
1735 FPT_default_intena) | bm_status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736
Khalid Aziz391e2f22013-05-16 19:44:14 -06001737 currSCCB = pCurrCard->currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001739 if (hp_int & (FIFO | TIMEOUT | RESET | SCAM_SEL) || bm_status) {
1740 result =
Khalid Aziz391e2f22013-05-16 19:44:14 -06001741 FPT_SccbMgr_bad_isr(ioport, thisCard, pCurrCard,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001742 hp_int);
1743 WRW_HARPOON((ioport + hp_intstat),
1744 (FIFO | TIMEOUT | RESET | SCAM_SEL));
1745 bm_status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001747 if (result) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001749 MENABLE_INT(ioport);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001750 return result;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001751 }
1752 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001754 else if (hp_int & ICMD_COMP) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001756 if (!(hp_int & BUS_FREE)) {
1757 /* Wait for the BusFree before starting a new command. We
1758 must also check for being reselected since the BusFree
1759 may not show up if another device reselects us in 1.5us or
1760 less. SRR Wednesday, 3/8/1995.
1761 */
1762 while (!
1763 (RDW_HARPOON((ioport + hp_intstat)) &
1764 (BUS_FREE | RSEL))) ;
1765 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766
Khalid Aziz391e2f22013-05-16 19:44:14 -06001767 if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001769 FPT_phaseChkFifo(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770
1771/* WRW_HARPOON((ioport+hp_intstat),
1772 (BUS_FREE | ICMD_COMP | ITAR_DISC | XFER_CNT_0));
1773 */
1774
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001775 WRW_HARPOON((ioport + hp_intstat), CLR_ALL_INT_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001776
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001777 FPT_autoCmdCmplt(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001779 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001781 else if (hp_int & ITAR_DISC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782
Khalid Aziz391e2f22013-05-16 19:44:14 -06001783 if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001784 FPT_phaseChkFifo(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785
Khalid Aziz391e2f22013-05-16 19:44:14 -06001786 if (RD_HARPOON(ioport + hp_gp_reg_1) ==
Hannes Reineckea87afe22021-04-27 10:30:40 +02001787 SAVE_POINTERS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001789 WR_HARPOON(ioport + hp_gp_reg_1, 0x00);
1790 currSCCB->Sccb_XferState |= F_NO_DATA_YET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001792 currSCCB->Sccb_savedATC = currSCCB->Sccb_ATC;
1793 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001795 currSCCB->Sccb_scsistat = DISCONNECT_ST;
1796 FPT_queueDisconnect(currSCCB, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001798 /* Wait for the BusFree before starting a new command. We
1799 must also check for being reselected since the BusFree
1800 may not show up if another device reselects us in 1.5us or
1801 less. SRR Wednesday, 3/8/1995.
1802 */
1803 while (!
1804 (RDW_HARPOON((ioport + hp_intstat)) &
1805 (BUS_FREE | RSEL))
1806 && !((RDW_HARPOON((ioport + hp_intstat)) & PHASE)
1807 && RD_HARPOON((ioport + hp_scsisig)) ==
1808 (SCSI_BSY | SCSI_REQ | SCSI_CD | SCSI_MSG |
1809 SCSI_IOBIT))) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001811 /*
1812 The additional loop exit condition above detects a timing problem
1813 with the revision D/E harpoon chips. The caller should reset the
1814 host adapter to recover when 0xFE is returned.
1815 */
1816 if (!
1817 (RDW_HARPOON((ioport + hp_intstat)) &
1818 (BUS_FREE | RSEL))) {
1819 MENABLE_INT(ioport);
1820 return 0xFE;
1821 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001823 WRW_HARPOON((ioport + hp_intstat),
1824 (BUS_FREE | ITAR_DISC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825
Khalid Aziz391e2f22013-05-16 19:44:14 -06001826 pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001828 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001829
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001830 else if (hp_int & RSEL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001832 WRW_HARPOON((ioport + hp_intstat),
1833 (PROG_HLT | RSEL | PHASE | BUS_FREE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001835 if (RDW_HARPOON((ioport + hp_intstat)) & ITAR_DISC) {
Khalid Aziz391e2f22013-05-16 19:44:14 -06001836 if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001837 FPT_phaseChkFifo(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001839 if (RD_HARPOON(ioport + hp_gp_reg_1) ==
Hannes Reineckea87afe22021-04-27 10:30:40 +02001840 SAVE_POINTERS) {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001841 WR_HARPOON(ioport + hp_gp_reg_1, 0x00);
1842 currSCCB->Sccb_XferState |=
1843 F_NO_DATA_YET;
1844 currSCCB->Sccb_savedATC =
1845 currSCCB->Sccb_ATC;
1846 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001847
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001848 WRW_HARPOON((ioport + hp_intstat),
1849 (BUS_FREE | ITAR_DISC));
1850 currSCCB->Sccb_scsistat = DISCONNECT_ST;
1851 FPT_queueDisconnect(currSCCB, thisCard);
1852 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001853
Khalid Aziz391e2f22013-05-16 19:44:14 -06001854 FPT_sres(ioport, thisCard, pCurrCard);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001855 FPT_phaseDecode(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001856
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001857 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001859 else if ((hp_int & IDO_STRT) && (!(hp_int & BUS_FREE))) {
1860
1861 WRW_HARPOON((ioport + hp_intstat),
1862 (IDO_STRT | XFER_CNT_0));
1863 FPT_phaseDecode(ioport, thisCard);
1864
1865 }
1866
1867 else if ((hp_int & IUNKWN) || (hp_int & PROG_HLT)) {
1868 WRW_HARPOON((ioport + hp_intstat),
1869 (PHASE | IUNKWN | PROG_HLT));
1870 if ((RD_HARPOON(ioport + hp_prgmcnt_0) & (unsigned char)
1871 0x3f) < (unsigned char)SELCHK) {
1872 FPT_phaseDecode(ioport, thisCard);
1873 } else {
1874 /* Harpoon problem some SCSI target device respond to selection
1875 with short BUSY pulse (<400ns) this will make the Harpoon is not able
1876 to latch the correct Target ID into reg. x53.
1877 The work around require to correct this reg. But when write to this
1878 reg. (0x53) also increment the FIFO write addr reg (0x6f), thus we
1879 need to read this reg first then restore it later. After update to 0x53 */
1880
1881 i = (unsigned
1882 char)(RD_HARPOON(ioport + hp_fifowrite));
1883 target =
1884 (unsigned
1885 char)(RD_HARPOON(ioport + hp_gp_reg_3));
1886 WR_HARPOON(ioport + hp_xfer_pad,
1887 (unsigned char)ID_UNLOCK);
1888 WR_HARPOON(ioport + hp_select_id,
1889 (unsigned char)(target | target <<
1890 4));
1891 WR_HARPOON(ioport + hp_xfer_pad,
1892 (unsigned char)0x00);
1893 WR_HARPOON(ioport + hp_fifowrite, i);
1894 WR_HARPOON(ioport + hp_autostart_3,
1895 (AUTO_IMMED + TAG_STRT));
1896 }
1897 }
1898
1899 else if (hp_int & XFER_CNT_0) {
1900
1901 WRW_HARPOON((ioport + hp_intstat), XFER_CNT_0);
1902
1903 FPT_schkdd(ioport, thisCard);
1904
1905 }
1906
1907 else if (hp_int & BUS_FREE) {
1908
1909 WRW_HARPOON((ioport + hp_intstat), BUS_FREE);
1910
Khalid Aziz391e2f22013-05-16 19:44:14 -06001911 if (pCurrCard->globalFlags & F_HOST_XFER_ACT) {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001912
1913 FPT_hostDataXferAbort(ioport, thisCard,
1914 currSCCB);
1915 }
1916
1917 FPT_phaseBusFree(ioport, thisCard);
1918 }
1919
1920 else if (hp_int & ITICKLE) {
1921
1922 WRW_HARPOON((ioport + hp_intstat), ITICKLE);
Khalid Aziz391e2f22013-05-16 19:44:14 -06001923 pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001924 }
1925
1926 if (((struct sccb_card *)pCurrCard)->
1927 globalFlags & F_NEW_SCCB_CMD) {
1928
Khalid Aziz391e2f22013-05-16 19:44:14 -06001929 pCurrCard->globalFlags &= ~F_NEW_SCCB_CMD;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001930
Khalid Aziz391e2f22013-05-16 19:44:14 -06001931 if (pCurrCard->currentSCCB == NULL)
1932 FPT_queueSearchSelect(pCurrCard, thisCard);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001933
Khalid Aziz391e2f22013-05-16 19:44:14 -06001934 if (pCurrCard->currentSCCB != NULL) {
1935 pCurrCard->globalFlags &= ~F_NEW_SCCB_CMD;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001936 FPT_ssel(ioport, thisCard);
1937 }
1938
1939 break;
1940
1941 }
1942
1943 } /*end while */
1944
1945 MENABLE_INT(ioport);
1946
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001947 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948}
1949
1950/*---------------------------------------------------------------------
1951 *
1952 * Function: Sccb_bad_isr
1953 *
1954 * Description: Some type of interrupt has occurred which is slightly
1955 * out of the ordinary. We will now decode it fully, in
1956 * this routine. This is broken up in an attempt to save
1957 * processing time.
1958 *
1959 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06001960static unsigned char FPT_SccbMgr_bad_isr(u32 p_port, unsigned char p_card,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001961 struct sccb_card *pCurrCard,
1962 unsigned short p_int)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001964 unsigned char temp, ScamFlg;
1965 struct sccb_mgr_tar_info *currTar_Info;
1966 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001968 if (RD_HARPOON(p_port + hp_ext_status) &
1969 (BM_FORCE_OFF | PCI_DEV_TMOUT | BM_PARITY_ERR | PIO_OVERRUN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001970
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001971 if (pCurrCard->globalFlags & F_HOST_XFER_ACT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001973 FPT_hostDataXferAbort(p_port, p_card,
1974 pCurrCard->currentSCCB);
1975 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001977 if (RD_HARPOON(p_port + hp_pci_stat_cfg) & REC_MASTER_ABORT)
1978 {
1979 WR_HARPOON(p_port + hp_pci_stat_cfg,
1980 (RD_HARPOON(p_port + hp_pci_stat_cfg) &
1981 ~REC_MASTER_ABORT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001982
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001983 WR_HARPOON(p_port + hp_host_blk_cnt, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001984
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001985 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001987 if (pCurrCard->currentSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001989 if (!pCurrCard->currentSCCB->HostStatus)
1990 pCurrCard->currentSCCB->HostStatus =
1991 SCCB_BM_ERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001993 FPT_sxfrp(p_port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001995 temp = (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
1996 (EXT_ARB_ACK | SCSI_TERM_ENA_H));
1997 WR_HARPOON(p_port + hp_ee_ctrl,
1998 ((unsigned char)temp | SEE_MS | SEE_CS));
1999 WR_HARPOON(p_port + hp_ee_ctrl, temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002001 if (!
2002 (RDW_HARPOON((p_port + hp_intstat)) &
2003 (BUS_FREE | RESET))) {
2004 FPT_phaseDecode(p_port, p_card);
2005 }
2006 }
2007 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002008
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002009 else if (p_int & RESET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002010
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002011 WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
2012 WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
2013 if (pCurrCard->currentSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002015 if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002017 FPT_hostDataXferAbort(p_port, p_card,
2018 pCurrCard->currentSCCB);
2019 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002021 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002023 FPT_sresb(p_port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002025 while (RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST) {
2026 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002028 pCurrNvRam = pCurrCard->pNvRamInfo;
2029 if (pCurrNvRam) {
2030 ScamFlg = pCurrNvRam->niScamConf;
2031 } else {
2032 ScamFlg =
2033 (unsigned char)FPT_utilEERead(p_port,
2034 SCAM_CONFIG / 2);
2035 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002037 FPT_XbowInit(p_port, ScamFlg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002039 FPT_scini(p_card, pCurrCard->ourId, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002041 return 0xFF;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002042 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002043
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002044 else if (p_int & FIFO) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002046 WRW_HARPOON((p_port + hp_intstat), FIFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002048 if (pCurrCard->currentSCCB != NULL)
2049 FPT_sxfrp(p_port, p_card);
2050 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002051
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002052 else if (p_int & TIMEOUT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002054 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002055
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002056 WRW_HARPOON((p_port + hp_intstat),
2057 (PROG_HLT | TIMEOUT | SEL | BUS_FREE | PHASE |
2058 IUNKWN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002060 pCurrCard->currentSCCB->HostStatus = SCCB_SELECTION_TIMEOUT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002062 currTar_Info =
2063 &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
2064 if ((pCurrCard->globalFlags & F_CONLUN_IO)
2065 && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
2066 TAG_Q_TRYING))
2067 currTar_Info->TarLUNBusy[pCurrCard->currentSCCB->Lun] =
2068 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002070 currTar_Info->TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002072 if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
2073 currTar_Info->TarSyncCtrl = 0;
2074 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2075 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002077 if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
2078 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2079 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002081 FPT_sssyncv(p_port, pCurrCard->currentSCCB->TargID, NARROW_SCSI,
2082 currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002083
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002084 FPT_queueCmdComplete(pCurrCard, pCurrCard->currentSCCB, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002086 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002088 else if (p_int & SCAM_SEL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002090 FPT_scarb(p_port, LEVEL2_TAR);
2091 FPT_scsel(p_port);
2092 FPT_scasid(p_card, p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002094 FPT_scbusf(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002096 WRW_HARPOON((p_port + hp_intstat), SCAM_SEL);
2097 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002099 return 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100}
2101
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102/*---------------------------------------------------------------------
2103 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104 * Function: SccbMgrTableInit
2105 *
2106 * Description: Initialize all Sccb manager data structures.
2107 *
2108 *---------------------------------------------------------------------*/
2109
Sudip Mukherjeecd9d7152015-09-16 19:36:20 +05302110static void FPT_SccbMgrTableInitAll(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002112 unsigned char thisCard;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002114 for (thisCard = 0; thisCard < MAX_CARDS; thisCard++) {
2115 FPT_SccbMgrTableInitCard(&FPT_BL_Card[thisCard], thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002117 FPT_BL_Card[thisCard].ioPort = 0x00;
2118 FPT_BL_Card[thisCard].cardInfo = NULL;
2119 FPT_BL_Card[thisCard].cardIndex = 0xFF;
2120 FPT_BL_Card[thisCard].ourId = 0x00;
2121 FPT_BL_Card[thisCard].pNvRamInfo = NULL;
2122 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123}
2124
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125/*---------------------------------------------------------------------
2126 *
2127 * Function: SccbMgrTableInit
2128 *
2129 * Description: Initialize all Sccb manager data structures.
2130 *
2131 *---------------------------------------------------------------------*/
2132
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002133static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard,
2134 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002136 unsigned char scsiID, qtag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002138 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002139 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140 }
2141
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002142 for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
2143 FPT_sccbMgrTbl[p_card][scsiID].TarStatus = 0;
2144 FPT_sccbMgrTbl[p_card][scsiID].TarEEValue = 0;
2145 FPT_SccbMgrTableInitTarget(p_card, scsiID);
2146 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002148 pCurrCard->scanIndex = 0x00;
2149 pCurrCard->currentSCCB = NULL;
2150 pCurrCard->globalFlags = 0x00;
2151 pCurrCard->cmdCounter = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 pCurrCard->tagQ_Lst = 0x01;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002153 pCurrCard->discQCount = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154
2155}
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_SccbMgrTableInitTarget(unsigned char p_card,
2166 unsigned char target)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167{
2168
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08002169 unsigned char lun, qtag;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002170 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171
James Bottomley 47b5d692005-04-24 02:38:05 -05002172 currTar_Info = &FPT_sccbMgrTbl[p_card][target];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173
2174 currTar_Info->TarSelQ_Cnt = 0;
2175 currTar_Info->TarSyncCtrl = 0;
2176
2177 currTar_Info->TarSelQ_Head = NULL;
2178 currTar_Info->TarSelQ_Tail = NULL;
2179 currTar_Info->TarTagQ_Cnt = 0;
James Bottomley 47b5d692005-04-24 02:38:05 -05002180 currTar_Info->TarLUN_CA = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002182 for (lun = 0; lun < MAX_LUN; lun++) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002183 currTar_Info->TarLUNBusy[lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184 currTar_Info->LunDiscQ_Idx[lun] = 0;
2185 }
2186
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002187 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
2188 if (FPT_BL_Card[p_card].discQ_Tbl[qtag] != NULL) {
2189 if (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
2190 target) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002191 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
2192 FPT_BL_Card[p_card].discQCount--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 }
2194 }
2195 }
2196}
2197
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198/*---------------------------------------------------------------------
2199 *
2200 * Function: sfetm
2201 *
2202 * Description: Read in a message byte from the SCSI bus, and check
2203 * for a parity error.
2204 *
2205 *---------------------------------------------------------------------*/
2206
Khalid Aziz391e2f22013-05-16 19:44:14 -06002207static unsigned char FPT_sfm(u32 port, struct sccb *pCurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208{
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08002209 unsigned char message;
Alexey Dobriyanc823fee2006-03-08 00:14:25 -08002210 unsigned short TimeOutLoop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211
2212 TimeOutLoop = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002213 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2214 (TimeOutLoop++ < 20000)) {
2215 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002217 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002219 message = RD_HARPOON(port + hp_scsidata_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002221 WR_HARPOON(port + hp_scsisig, SCSI_ACK + S_MSGI_PH);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222
2223 if (TimeOutLoop > 20000)
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002224 message = 0x00; /* force message byte = 0 if Time Out on Req */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002226 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
2227 (RD_HARPOON(port + hp_addstat) & SCSI_PAR_ERR)) {
2228 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2229 WR_HARPOON(port + hp_xferstat, 0);
2230 WR_HARPOON(port + hp_fiforead, 0);
2231 WR_HARPOON(port + hp_fifowrite, 0);
2232 if (pCurrSCCB != NULL) {
Hannes Reineckea87afe22021-04-27 10:30:40 +02002233 pCurrSCCB->Sccb_scsimsg = MSG_PARITY_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234 }
2235 message = 0x00;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002236 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237 ACCEPT_MSG_ATN(port);
2238 TimeOutLoop = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002239 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2240 (TimeOutLoop++ < 20000)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002242 if (TimeOutLoop > 20000) {
2243 WRW_HARPOON((port + hp_intstat), PARITY);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002244 return message;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002246 if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) !=
2247 S_MSGI_PH) {
2248 WRW_HARPOON((port + hp_intstat), PARITY);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002249 return message;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002250 }
2251 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002252
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002253 RD_HARPOON(port + hp_scsidata_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002255 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002257 } while (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258
2259 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002260 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);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002264 return message;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265}
2266
Linus Torvalds1da177e2005-04-16 15:20:36 -07002267/*---------------------------------------------------------------------
2268 *
James Bottomley 47b5d692005-04-24 02:38:05 -05002269 * Function: FPT_ssel
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270 *
2271 * Description: Load up automation and select target device.
2272 *
2273 *---------------------------------------------------------------------*/
2274
Khalid Aziz391e2f22013-05-16 19:44:14 -06002275static void FPT_ssel(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276{
2277
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002278 unsigned char auto_loaded, i, target, *theCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279
Khalid Aziz391e2f22013-05-16 19:44:14 -06002280 u32 cdb_reg;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002281 struct sccb_card *CurrCard;
2282 struct sccb *currSCCB;
2283 struct sccb_mgr_tar_info *currTar_Info;
2284 unsigned char lastTag, lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002286 CurrCard = &FPT_BL_Card[p_card];
2287 currSCCB = CurrCard->currentSCCB;
2288 target = currSCCB->TargID;
2289 currTar_Info = &FPT_sccbMgrTbl[p_card][target];
2290 lastTag = CurrCard->tagQ_Lst;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002292 ARAM_ACCESS(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293
2294 if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
2295 currSCCB->ControlByte &= ~F_USE_CMD_Q;
2296
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002297 if (((CurrCard->globalFlags & F_CONLUN_IO) &&
2298 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002300 lun = currSCCB->Lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301 else
2302 lun = 0;
2303
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002304 if (CurrCard->globalFlags & F_TAG_STARTED) {
2305 if (!(currSCCB->ControlByte & F_USE_CMD_Q)) {
2306 if ((currTar_Info->TarLUN_CA == 0)
2307 && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
2308 == TAG_Q_TRYING)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002310 if (currTar_Info->TarTagQ_Cnt != 0) {
2311 currTar_Info->TarLUNBusy[lun] = 1;
2312 FPT_queueSelectFail(CurrCard, p_card);
2313 SGRAM_ACCESS(port);
2314 return;
2315 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002317 else {
2318 currTar_Info->TarLUNBusy[lun] = 1;
2319 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002321 }
2322 /*End non-tagged */
2323 else {
2324 currTar_Info->TarLUNBusy[lun] = 1;
2325 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002327 }
2328 /*!Use cmd Q Tagged */
2329 else {
2330 if (currTar_Info->TarLUN_CA == 1) {
2331 FPT_queueSelectFail(CurrCard, p_card);
2332 SGRAM_ACCESS(port);
2333 return;
2334 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335
James Bottomley 47b5d692005-04-24 02:38:05 -05002336 currTar_Info->TarLUNBusy[lun] = 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002337
2338 } /*else use cmd Q tagged */
2339
2340 }
2341 /*if glob tagged started */
2342 else {
2343 currTar_Info->TarLUNBusy[lun] = 1;
2344 }
2345
2346 if ((((CurrCard->globalFlags & F_CONLUN_IO) &&
2347 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
2348 || (!(currSCCB->ControlByte & F_USE_CMD_Q)))) {
2349 if (CurrCard->discQCount >= QUEUE_DEPTH) {
2350 currTar_Info->TarLUNBusy[lun] = 1;
2351 FPT_queueSelectFail(CurrCard, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352 SGRAM_ACCESS(port);
2353 return;
2354 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002355 for (i = 1; i < QUEUE_DEPTH; i++) {
2356 if (++lastTag >= QUEUE_DEPTH)
2357 lastTag = 1;
2358 if (CurrCard->discQ_Tbl[lastTag] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359 CurrCard->tagQ_Lst = lastTag;
2360 currTar_Info->LunDiscQ_Idx[lun] = lastTag;
2361 CurrCard->discQ_Tbl[lastTag] = currSCCB;
2362 CurrCard->discQCount++;
2363 break;
2364 }
2365 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002366 if (i == QUEUE_DEPTH) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002367 currTar_Info->TarLUNBusy[lun] = 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002368 FPT_queueSelectFail(CurrCard, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369 SGRAM_ACCESS(port);
2370 return;
2371 }
2372 }
2373
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002374 auto_loaded = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002376 WR_HARPOON(port + hp_select_id, target);
2377 WR_HARPOON(port + hp_gp_reg_3, target); /* Use by new automation logic */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002379 if (currSCCB->OperationCode == RESET_COMMAND) {
2380 WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
2381 (currSCCB->
2382 Sccb_idmsg & ~DISC_PRIV)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002384 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + NP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385
Hannes Reineckea87afe22021-04-27 10:30:40 +02002386 currSCCB->Sccb_scsimsg = TARGET_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002388 WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
2389 auto_loaded = 1;
2390 currSCCB->Sccb_scsistat = SELECT_BDR_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002392 if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
2393 currTar_Info->TarSyncCtrl = 0;
2394 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395 }
2396
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002397 if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
2398 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2399 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002401 FPT_sssyncv(port, target, NARROW_SCSI, currTar_Info);
2402 FPT_SccbMgrTableInitTarget(p_card, target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002404 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002406 else if (currSCCB->Sccb_scsistat == ABORT_ST) {
2407 WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
2408 (currSCCB->
2409 Sccb_idmsg & ~DISC_PRIV)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002411 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002413 WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT +
2414 (((unsigned
2415 char)(currSCCB->
2416 ControlByte &
2417 TAG_TYPE_MASK)
2418 >> 6) | (unsigned char)
2419 0x20)));
2420 WRW_HARPOON((port + SYNC_MSGS + 2),
2421 (MPM_OP + AMSG_OUT + currSCCB->Sccb_tag));
2422 WRW_HARPOON((port + SYNC_MSGS + 4), (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002424 WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
2425 auto_loaded = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002427 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002429 else if (!(currTar_Info->TarStatus & WIDE_NEGOCIATED)) {
2430 auto_loaded = FPT_siwidn(port, p_card);
2431 currSCCB->Sccb_scsistat = SELECT_WN_ST;
2432 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002434 else if (!((currTar_Info->TarStatus & TAR_SYNC_MASK)
2435 == SYNC_SUPPORTED)) {
2436 auto_loaded = FPT_sisyncn(port, p_card, 0);
2437 currSCCB->Sccb_scsistat = SELECT_SN_ST;
2438 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002440 if (!auto_loaded) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002442 if (currSCCB->ControlByte & F_USE_CMD_Q) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002444 CurrCard->globalFlags |= F_TAG_STARTED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002446 if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
2447 == TAG_Q_REJECT) {
2448 currSCCB->ControlByte &= ~F_USE_CMD_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002449
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002450 /* Fix up the start instruction with a jump to
2451 Non-Tag-CMD handling */
2452 WRW_HARPOON((port + ID_MSG_STRT),
2453 BRH_OP + ALWAYS + NTCMD);
2454
2455 WRW_HARPOON((port + NON_TAG_ID_MSG),
2456 (MPM_OP + AMSG_OUT +
2457 currSCCB->Sccb_idmsg));
2458
2459 WR_HARPOON(port + hp_autostart_3,
2460 (SELECT + SELCHK_STRT));
2461
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002462 /* Setup our STATE so we know what happened when
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002463 the wheels fall off. */
2464 currSCCB->Sccb_scsistat = SELECT_ST;
2465
2466 currTar_Info->TarLUNBusy[lun] = 1;
2467 }
2468
2469 else {
2470 WRW_HARPOON((port + ID_MSG_STRT),
2471 (MPM_OP + AMSG_OUT +
2472 currSCCB->Sccb_idmsg));
2473
2474 WRW_HARPOON((port + ID_MSG_STRT + 2),
2475 (MPM_OP + AMSG_OUT +
2476 (((unsigned char)(currSCCB->
2477 ControlByte &
2478 TAG_TYPE_MASK)
2479 >> 6) | (unsigned char)0x20)));
2480
2481 for (i = 1; i < QUEUE_DEPTH; i++) {
2482 if (++lastTag >= QUEUE_DEPTH)
2483 lastTag = 1;
2484 if (CurrCard->discQ_Tbl[lastTag] ==
2485 NULL) {
2486 WRW_HARPOON((port +
2487 ID_MSG_STRT + 6),
2488 (MPM_OP + AMSG_OUT +
2489 lastTag));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490 CurrCard->tagQ_Lst = lastTag;
2491 currSCCB->Sccb_tag = lastTag;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002492 CurrCard->discQ_Tbl[lastTag] =
2493 currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494 CurrCard->discQCount++;
2495 break;
2496 }
2497 }
2498
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002499 if (i == QUEUE_DEPTH) {
2500 currTar_Info->TarLUNBusy[lun] = 1;
2501 FPT_queueSelectFail(CurrCard, p_card);
2502 SGRAM_ACCESS(port);
2503 return;
2504 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002506 currSCCB->Sccb_scsistat = SELECT_Q_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002508 WR_HARPOON(port + hp_autostart_3,
2509 (SELECT + SELCHK_STRT));
2510 }
2511 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002513 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002515 WRW_HARPOON((port + ID_MSG_STRT),
2516 BRH_OP + ALWAYS + NTCMD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002518 WRW_HARPOON((port + NON_TAG_ID_MSG),
2519 (MPM_OP + AMSG_OUT + currSCCB->Sccb_idmsg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002521 currSCCB->Sccb_scsistat = SELECT_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002523 WR_HARPOON(port + hp_autostart_3,
2524 (SELECT + SELCHK_STRT));
2525 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002527 theCCB = (unsigned char *)&currSCCB->Cdb[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002529 cdb_reg = port + CMD_STRT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002531 for (i = 0; i < currSCCB->CdbLength; i++) {
2532 WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + *theCCB));
2533 cdb_reg += 2;
2534 theCCB++;
2535 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002537 if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
2538 WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002539
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002540 }
2541 /* auto_loaded */
2542 WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
2543 WR_HARPOON(port + hp_xferstat, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002545 WRW_HARPOON((port + hp_intstat), (PROG_HLT | TIMEOUT | SEL | BUS_FREE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002547 WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002549 if (!(currSCCB->Sccb_MGRFlags & F_DEV_SELECTED)) {
2550 WR_HARPOON(port + hp_scsictrl_0,
2551 (SEL_TAR | ENA_ATN | ENA_RESEL | ENA_SCAM_SEL));
2552 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08002554/* auto_loaded = (RD_HARPOON(port+hp_autostart_3) & (unsigned char)0x1F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555 auto_loaded |= AUTO_IMMED; */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002556 auto_loaded = AUTO_IMMED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002558 DISABLE_AUTO(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002560 WR_HARPOON(port + hp_autostart_3, auto_loaded);
2561 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002562
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002563 SGRAM_ACCESS(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564}
2565
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566/*---------------------------------------------------------------------
2567 *
James Bottomley 47b5d692005-04-24 02:38:05 -05002568 * Function: FPT_sres
Linus Torvalds1da177e2005-04-16 15:20:36 -07002569 *
2570 * Description: Hookup the correct CCB and handle the incoming messages.
2571 *
2572 *---------------------------------------------------------------------*/
2573
Khalid Aziz391e2f22013-05-16 19:44:14 -06002574static void FPT_sres(u32 port, unsigned char p_card,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002575 struct sccb_card *pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576{
2577
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002578 unsigned char our_target, message, lun = 0, tag, msgRetryCount;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002580 struct sccb_mgr_tar_info *currTar_Info;
2581 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002583 if (pCurrCard->currentSCCB != NULL) {
2584 currTar_Info =
2585 &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586 DISABLE_AUTO(port);
2587
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002588 WR_HARPOON((port + hp_scsictrl_0), (ENA_RESEL | ENA_SCAM_SEL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589
2590 currSCCB = pCurrCard->currentSCCB;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002591 if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2593 currSCCB->Sccb_scsistat = BUS_FREE_ST;
2594 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002595 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2597 currSCCB->Sccb_scsistat = BUS_FREE_ST;
2598 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002599 if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
2600 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
2601 TAG_Q_TRYING))) {
2602 currTar_Info->TarLUNBusy[currSCCB->Lun] = 0;
2603 if (currSCCB->Sccb_scsistat != ABORT_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002604 pCurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002605 pCurrCard->discQ_Tbl[currTar_Info->
2606 LunDiscQ_Idx[currSCCB->
2607 Lun]]
2608 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002609 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002610 } else {
2611 currTar_Info->TarLUNBusy[0] = 0;
2612 if (currSCCB->Sccb_tag) {
2613 if (currSCCB->Sccb_scsistat != ABORT_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614 pCurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002615 pCurrCard->discQ_Tbl[currSCCB->
2616 Sccb_tag] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002618 } else {
2619 if (currSCCB->Sccb_scsistat != ABORT_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620 pCurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002621 pCurrCard->discQ_Tbl[currTar_Info->
2622 LunDiscQ_Idx[0]] =
2623 NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624 }
2625 }
2626 }
2627
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002628 FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629 }
2630
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002631 WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002633 our_target = (unsigned char)(RD_HARPOON(port + hp_select_id) >> 4);
James Bottomley 47b5d692005-04-24 02:38:05 -05002634 currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636 msgRetryCount = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002637 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638
James Bottomley 47b5d692005-04-24 02:38:05 -05002639 currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640 tag = 0;
2641
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002642 while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
2643 if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002645 WRW_HARPOON((port + hp_intstat), PHASE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646 return;
2647 }
2648 }
2649
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002650 WRW_HARPOON((port + hp_intstat), PHASE);
2651 if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002652
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002653 message = FPT_sfm(port, pCurrCard->currentSCCB);
2654 if (message) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002656 if (message <= (0x80 | LUN_MASK)) {
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08002657 lun = message & (unsigned char)LUN_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002659 if ((currTar_Info->
2660 TarStatus & TAR_TAG_Q_MASK) ==
2661 TAG_Q_TRYING) {
2662 if (currTar_Info->TarTagQ_Cnt !=
2663 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002665 if (!
2666 (currTar_Info->
2667 TarLUN_CA)) {
2668 ACCEPT_MSG(port); /*Release the ACK for ID msg. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002670 message =
2671 FPT_sfm
2672 (port,
2673 pCurrCard->
2674 currentSCCB);
2675 if (message) {
2676 ACCEPT_MSG
2677 (port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002678 }
2679
2680 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002681 message
2682 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002684 if (message !=
2685 0) {
2686 tag =
2687 FPT_sfm
2688 (port,
2689 pCurrCard->
2690 currentSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002692 if (!
2693 (tag))
2694 message
2695 =
2696 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697 }
2698
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002699 }
2700 /*C.A. exists! */
2701 }
2702 /*End Q cnt != 0 */
2703 }
2704 /*End Tag cmds supported! */
2705 }
2706 /*End valid ID message. */
2707 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708
2709 ACCEPT_MSG_ATN(port);
2710 }
2711
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002712 }
2713 /* End good id message. */
2714 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715
James Bottomley 47b5d692005-04-24 02:38:05 -05002716 message = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002718 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719 ACCEPT_MSG_ATN(port);
2720
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002721 while (!
2722 (RDW_HARPOON((port + hp_intstat)) &
2723 (PHASE | RESET))
2724 && !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
2725 && (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726
2727 return;
2728 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002730 if (message == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731 msgRetryCount++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002732 if (msgRetryCount == 1) {
Hannes Reineckea87afe22021-04-27 10:30:40 +02002733 FPT_SendMsg(port, MSG_PARITY_ERROR);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002734 } else {
Hannes Reineckea87afe22021-04-27 10:30:40 +02002735 FPT_SendMsg(port, TARGET_RESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002737 FPT_sssyncv(port, our_target, NARROW_SCSI,
2738 currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002740 if (FPT_sccbMgrTbl[p_card][our_target].
2741 TarEEValue & EE_SYNC_MASK) {
2742
2743 FPT_sccbMgrTbl[p_card][our_target].
2744 TarStatus &= ~TAR_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745
2746 }
2747
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002748 if (FPT_sccbMgrTbl[p_card][our_target].
2749 TarEEValue & EE_WIDE_SCSI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002751 FPT_sccbMgrTbl[p_card][our_target].
2752 TarStatus &= ~TAR_WIDE_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753 }
2754
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002755 FPT_queueFlushTargSccb(p_card, our_target,
2756 SCCB_COMPLETE);
2757 FPT_SccbMgrTableInitTarget(p_card, our_target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758 return;
2759 }
2760 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002761 } while (message == 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002763 if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
2764 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002765 currTar_Info->TarLUNBusy[lun] = 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002766 pCurrCard->currentSCCB =
2767 pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[lun]];
2768 if (pCurrCard->currentSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002770 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771 ACCEPT_MSG_ATN(port);
2772 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002773 } else {
James Bottomley 47b5d692005-04-24 02:38:05 -05002774 currTar_Info->TarLUNBusy[0] = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002776 if (tag) {
2777 if (pCurrCard->discQ_Tbl[tag] != NULL) {
2778 pCurrCard->currentSCCB =
2779 pCurrCard->discQ_Tbl[tag];
2780 currTar_Info->TarTagQ_Cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002782 } else {
2783 ACCEPT_MSG_ATN(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002784 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002785 } else {
2786 pCurrCard->currentSCCB =
2787 pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]];
2788 if (pCurrCard->currentSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002790 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791 ACCEPT_MSG_ATN(port);
2792 }
2793 }
2794 }
2795
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002796 if (pCurrCard->currentSCCB != NULL) {
2797 if (pCurrCard->currentSCCB->Sccb_scsistat == ABORT_ST) {
2798 /* During Abort Tag command, the target could have got re-selected
2799 and completed the command. Check the select Q and remove the CCB
2800 if it is in the Select Q */
James Bottomley 47b5d692005-04-24 02:38:05 -05002801 FPT_queueFindSccb(pCurrCard->currentSCCB, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802 }
2803 }
2804
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002805 while (!(RDW_HARPOON((port + hp_intstat)) & (PHASE | RESET)) &&
2806 !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ) &&
2807 (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808}
2809
Khalid Aziz391e2f22013-05-16 19:44:14 -06002810static void FPT_SendMsg(u32 port, unsigned char message)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002812 while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
2813 if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002815 WRW_HARPOON((port + hp_intstat), PHASE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816 return;
2817 }
2818 }
2819
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002820 WRW_HARPOON((port + hp_intstat), PHASE);
2821 if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGO_PH) {
2822 WRW_HARPOON((port + hp_intstat),
2823 (BUS_FREE | PHASE | XFER_CNT_0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002825 WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002827 WR_HARPOON(port + hp_scsidata_0, message);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002828
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002829 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830
2831 ACCEPT_MSG(port);
2832
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002833 WR_HARPOON(port + hp_portctrl_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834
Hannes Reineckea87afe22021-04-27 10:30:40 +02002835 if ((message == ABORT_TASK_SET) || (message == TARGET_RESET) ||
2836 (message == ABORT_TASK)) {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002837 while (!
2838 (RDW_HARPOON((port + hp_intstat)) &
2839 (BUS_FREE | PHASE))) {
2840 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002842 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
2843 WRW_HARPOON((port + hp_intstat), BUS_FREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002844 }
2845 }
2846 }
2847}
2848
2849/*---------------------------------------------------------------------
2850 *
James Bottomley 47b5d692005-04-24 02:38:05 -05002851 * Function: FPT_sdecm
Linus Torvalds1da177e2005-04-16 15:20:36 -07002852 *
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002853 * Description: Determine the proper response to the message from the
Linus Torvalds1da177e2005-04-16 15:20:36 -07002854 * target device.
2855 *
2856 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06002857static void FPT_sdecm(unsigned char message, u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002858{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002859 struct sccb *currSCCB;
2860 struct sccb_card *CurrCard;
2861 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862
James Bottomley 47b5d692005-04-24 02:38:05 -05002863 CurrCard = &FPT_BL_Card[p_card];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002864 currSCCB = CurrCard->currentSCCB;
2865
James Bottomley 47b5d692005-04-24 02:38:05 -05002866 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867
Hannes Reineckea87afe22021-04-27 10:30:40 +02002868 if (message == RESTORE_POINTERS) {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002869 if (!(currSCCB->Sccb_XferState & F_NO_DATA_YET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870 currSCCB->Sccb_ATC = currSCCB->Sccb_savedATC;
2871
James Bottomley 47b5d692005-04-24 02:38:05 -05002872 FPT_hostDataXferRestart(currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002873 }
2874
2875 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002876 WR_HARPOON(port + hp_autostart_1,
2877 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002878 }
2879
Hannes Reineckea87afe22021-04-27 10:30:40 +02002880 else if (message == COMMAND_COMPLETE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002882 if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
2883 currTar_Info->TarStatus &=
2884 ~(unsigned char)TAR_TAG_Q_MASK;
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08002885 currTar_Info->TarStatus |= (unsigned char)TAG_Q_REJECT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002886 }
2887
2888 ACCEPT_MSG(port);
2889
2890 }
2891
Hannes Reineckea87afe22021-04-27 10:30:40 +02002892 else if ((message == NOP) || (message >= IDENTIFY_BASE) ||
2893 (message == INITIATE_RECOVERY) ||
2894 (message == RELEASE_RECOVERY)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002895
2896 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002897 WR_HARPOON(port + hp_autostart_1,
2898 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002899 }
2900
Hannes Reineckea87afe22021-04-27 10:30:40 +02002901 else if (message == MESSAGE_REJECT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902
2903 if ((currSCCB->Sccb_scsistat == SELECT_SN_ST) ||
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002904 (currSCCB->Sccb_scsistat == SELECT_WN_ST) ||
2905 ((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)
2906 || ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) ==
2907 TAG_Q_TRYING))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002908 {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002909 WRW_HARPOON((port + hp_intstat), BUS_FREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910
2911 ACCEPT_MSG(port);
2912
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002913 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2914 (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915 {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002916 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002917
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002918 if (currSCCB->Lun == 0x00) {
Nathan Chancelloradb11022018-09-20 14:10:32 -07002919 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002920
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002921 currTar_Info->TarStatus |=
2922 (unsigned char)SYNC_SUPPORTED;
2923
2924 currTar_Info->TarEEValue &=
2925 ~EE_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002926 }
2927
Nathan Chancelloradb11022018-09-20 14:10:32 -07002928 else if (currSCCB->Sccb_scsistat ==
2929 SELECT_WN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002931 currTar_Info->TarStatus =
2932 (currTar_Info->
2933 TarStatus & ~WIDE_ENABLED) |
2934 WIDE_NEGOCIATED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002935
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002936 currTar_Info->TarEEValue &=
2937 ~EE_WIDE_SCSI;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002938
2939 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002941 else if ((currTar_Info->
2942 TarStatus & TAR_TAG_Q_MASK) ==
2943 TAG_Q_TRYING) {
2944 currTar_Info->TarStatus =
2945 (currTar_Info->
2946 TarStatus & ~(unsigned char)
2947 TAR_TAG_Q_MASK) | TAG_Q_REJECT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002948
2949 currSCCB->ControlByte &= ~F_USE_CMD_Q;
2950 CurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002951 CurrCard->discQ_Tbl[currSCCB->
2952 Sccb_tag] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953 currSCCB->Sccb_tag = 0x00;
2954
2955 }
2956 }
2957
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002958 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002959
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002960 if (currSCCB->Lun == 0x00) {
2961 WRW_HARPOON((port + hp_intstat),
2962 BUS_FREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002963 CurrCard->globalFlags |= F_NEW_SCCB_CMD;
2964 }
2965 }
2966
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002967 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002968
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002969 if ((CurrCard->globalFlags & F_CONLUN_IO) &&
2970 ((currTar_Info->
2971 TarStatus & TAR_TAG_Q_MASK) !=
2972 TAG_Q_TRYING))
2973 currTar_Info->TarLUNBusy[currSCCB->
2974 Lun] = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002975 else
James Bottomley 47b5d692005-04-24 02:38:05 -05002976 currTar_Info->TarLUNBusy[0] = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002978 currSCCB->ControlByte &=
2979 ~(unsigned char)F_USE_CMD_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002980
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002981 WR_HARPOON(port + hp_autostart_1,
2982 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983
2984 }
2985 }
2986
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002987 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002988 ACCEPT_MSG(port);
2989
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002990 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2991 (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002992 {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002993 }
2994
2995 if (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)) {
2996 WR_HARPOON(port + hp_autostart_1,
2997 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002998 }
2999 }
3000 }
3001
Hannes Reineckea87afe22021-04-27 10:30:40 +02003002 else if (message == EXTENDED_MESSAGE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003
3004 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003005 FPT_shandem(port, p_card, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006 }
3007
Hannes Reineckea87afe22021-04-27 10:30:40 +02003008 else if (message == IGNORE_WIDE_RESIDUE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003010 ACCEPT_MSG(port); /* ACK the RESIDUE MSG */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003011
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003012 message = FPT_sfm(port, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013
Hannes Reineckea87afe22021-04-27 10:30:40 +02003014 if (currSCCB->Sccb_scsimsg != MSG_PARITY_ERROR)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003016 WR_HARPOON(port + hp_autostart_1,
3017 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003018 }
3019
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003020 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003021
3022 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
Hannes Reineckea87afe22021-04-27 10:30:40 +02003023 currSCCB->Sccb_scsimsg = MESSAGE_REJECT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024
3025 ACCEPT_MSG_ATN(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003026 WR_HARPOON(port + hp_autostart_1,
3027 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028 }
3029}
3030
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031/*---------------------------------------------------------------------
3032 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003033 * Function: FPT_shandem
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034 *
3035 * Description: Decide what to do with the extended message.
3036 *
3037 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06003038static void FPT_shandem(u32 port, unsigned char p_card, struct sccb *pCurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003040 unsigned char length, message;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003042 length = FPT_sfm(port, pCurrSCCB);
3043 if (length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003044
3045 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003046 message = FPT_sfm(port, pCurrSCCB);
3047 if (message) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003048
Hannes Reineckea87afe22021-04-27 10:30:40 +02003049 if (message == EXTENDED_SDTR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003050
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003051 if (length == 0x03) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003052
3053 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003054 FPT_stsyncn(port, p_card);
3055 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003056
Hannes Reineckea87afe22021-04-27 10:30:40 +02003057 pCurrSCCB->Sccb_scsimsg = MESSAGE_REJECT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003058 ACCEPT_MSG_ATN(port);
3059 }
Hannes Reineckea87afe22021-04-27 10:30:40 +02003060 } else if (message == EXTENDED_WDTR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003061
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003062 if (length == 0x02) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063
3064 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003065 FPT_stwidn(port, p_card);
3066 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003067
Hannes Reineckea87afe22021-04-27 10:30:40 +02003068 pCurrSCCB->Sccb_scsimsg = MESSAGE_REJECT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069 ACCEPT_MSG_ATN(port);
3070
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003071 WR_HARPOON(port + hp_autostart_1,
3072 (AUTO_IMMED +
3073 DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003074 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003075 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003076
Hannes Reineckea87afe22021-04-27 10:30:40 +02003077 pCurrSCCB->Sccb_scsimsg = MESSAGE_REJECT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078 ACCEPT_MSG_ATN(port);
3079
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003080 WR_HARPOON(port + hp_autostart_1,
3081 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003082 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003083 } else {
Hannes Reineckea87afe22021-04-27 10:30:40 +02003084 if (pCurrSCCB->Sccb_scsimsg != MSG_PARITY_ERROR)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003086 WR_HARPOON(port + hp_autostart_1,
3087 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003088 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003089 } else {
Hannes Reineckea87afe22021-04-27 10:30:40 +02003090 if (pCurrSCCB->Sccb_scsimsg == MSG_PARITY_ERROR)
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003091 WR_HARPOON(port + hp_autostart_1,
3092 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003093 }
3094}
3095
Linus Torvalds1da177e2005-04-16 15:20:36 -07003096/*---------------------------------------------------------------------
3097 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003098 * Function: FPT_sisyncn
Linus Torvalds1da177e2005-04-16 15:20:36 -07003099 *
3100 * Description: Read in a message byte from the SCSI bus, and check
3101 * for a parity error.
3102 *
3103 *---------------------------------------------------------------------*/
3104
Khalid Aziz391e2f22013-05-16 19:44:14 -06003105static unsigned char FPT_sisyncn(u32 port, unsigned char p_card,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003106 unsigned char syncFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003108 struct sccb *currSCCB;
3109 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003111 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3112 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003113
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003114 if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003115
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003116 WRW_HARPOON((port + ID_MSG_STRT),
3117 (MPM_OP + AMSG_OUT +
3118 (currSCCB->
3119 Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003120
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003121 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003122
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003123 WRW_HARPOON((port + SYNC_MSGS + 0),
Hannes Reineckea87afe22021-04-27 10:30:40 +02003124 (MPM_OP + AMSG_OUT + EXTENDED_MESSAGE));
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003125 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
3126 WRW_HARPOON((port + SYNC_MSGS + 4),
Hannes Reineckea87afe22021-04-27 10:30:40 +02003127 (MPM_OP + AMSG_OUT + EXTENDED_SDTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003129 if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003131 WRW_HARPOON((port + SYNC_MSGS + 6),
3132 (MPM_OP + AMSG_OUT + 12));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003134 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
3135 EE_SYNC_10MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003137 WRW_HARPOON((port + SYNC_MSGS + 6),
3138 (MPM_OP + AMSG_OUT + 25));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003140 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
3141 EE_SYNC_5MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003142
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003143 WRW_HARPOON((port + SYNC_MSGS + 6),
3144 (MPM_OP + AMSG_OUT + 50));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003145
Linus Torvalds1da177e2005-04-16 15:20:36 -07003146 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003147 WRW_HARPOON((port + SYNC_MSGS + 6),
3148 (MPM_OP + AMSG_OUT + 00));
3149
3150 WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
3151 WRW_HARPOON((port + SYNC_MSGS + 10),
3152 (MPM_OP + AMSG_OUT + DEFAULT_OFFSET));
3153 WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
3154
3155 if (syncFlag == 0) {
3156 WR_HARPOON(port + hp_autostart_3,
3157 (SELECT + SELCHK_STRT));
3158 currTar_Info->TarStatus =
3159 ((currTar_Info->
3160 TarStatus & ~(unsigned char)TAR_SYNC_MASK) |
3161 (unsigned char)SYNC_TRYING);
3162 } else {
3163 WR_HARPOON(port + hp_autostart_3,
3164 (AUTO_IMMED + CMD_ONLY_STRT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003165 }
3166
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08003167 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003168 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003169
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003170 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003171
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003172 currTar_Info->TarStatus |= (unsigned char)SYNC_SUPPORTED;
3173 currTar_Info->TarEEValue &= ~EE_SYNC_MASK;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08003174 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003175 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176}
3177
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178/*---------------------------------------------------------------------
3179 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003180 * Function: FPT_stsyncn
Linus Torvalds1da177e2005-04-16 15:20:36 -07003181 *
3182 * Description: The has sent us a Sync Nego message so handle it as
3183 * necessary.
3184 *
3185 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06003186static void FPT_stsyncn(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003188 unsigned char sync_msg, offset, sync_reg, our_sync_msg;
3189 struct sccb *currSCCB;
3190 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003192 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3193 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003195 sync_msg = FPT_sfm(port, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003196
Hannes Reineckea87afe22021-04-27 10:30:40 +02003197 if ((sync_msg == 0x00) && (currSCCB->Sccb_scsimsg == MSG_PARITY_ERROR)) {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003198 WR_HARPOON(port + hp_autostart_1,
3199 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003200 return;
3201 }
3202
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003203 ACCEPT_MSG(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003204
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003205 offset = FPT_sfm(port, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003206
Hannes Reineckea87afe22021-04-27 10:30:40 +02003207 if ((offset == 0x00) && (currSCCB->Sccb_scsimsg == MSG_PARITY_ERROR)) {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003208 WR_HARPOON(port + hp_autostart_1,
3209 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003210 return;
3211 }
3212
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003213 if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003214
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003215 our_sync_msg = 12; /* Setup our Message to 20mb/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003216
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003217 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_10MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003218
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003219 our_sync_msg = 25; /* Setup our Message to 10mb/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003220
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003221 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_5MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003222
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003223 our_sync_msg = 50; /* Setup our Message to 5mb/s */
3224 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003225
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003226 our_sync_msg = 0; /* Message = Async */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003228 if (sync_msg < our_sync_msg) {
3229 sync_msg = our_sync_msg; /*if faster, then set to max. */
3230 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003232 if (offset == ASYNC)
3233 sync_msg = ASYNC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003234
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003235 if (offset > MAX_OFFSET)
3236 offset = MAX_OFFSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003237
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003238 sync_reg = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003239
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003240 if (sync_msg > 12)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003241
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003242 sync_reg = 0x20; /* Use 10MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003243
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003244 if (sync_msg > 25)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003245
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003246 sync_reg = 0x40; /* Use 6.6MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003247
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003248 if (sync_msg > 38)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003249
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003250 sync_reg = 0x60; /* Use 5MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003251
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003252 if (sync_msg > 50)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003253
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003254 sync_reg = 0x80; /* Use 4MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003255
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003256 if (sync_msg > 62)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003257
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003258 sync_reg = 0xA0; /* Use 3.33MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003260 if (sync_msg > 75)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003261
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003262 sync_reg = 0xC0; /* Use 2.85MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003263
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003264 if (sync_msg > 87)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003265
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003266 sync_reg = 0xE0; /* Use 2.5MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003267
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003268 if (sync_msg > 100) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003270 sync_reg = 0x00; /* Use ASYNC */
3271 offset = 0x00;
3272 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003274 if (currTar_Info->TarStatus & WIDE_ENABLED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003275
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003276 sync_reg |= offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003277
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003278 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003279
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003280 sync_reg |= (offset | NARROW_SCSI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003281
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003282 FPT_sssyncv(port, currSCCB->TargID, sync_reg, currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003283
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003284 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003285
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003286 ACCEPT_MSG(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003287
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003288 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3289 ~(unsigned char)TAR_SYNC_MASK) |
3290 (unsigned char)SYNC_SUPPORTED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003291
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003292 WR_HARPOON(port + hp_autostart_1,
3293 (AUTO_IMMED + DISCONNECT_START));
3294 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003295
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003296 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003297
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003298 ACCEPT_MSG_ATN(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003300 FPT_sisyncr(port, sync_msg, offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003301
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003302 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3303 ~(unsigned char)TAR_SYNC_MASK) |
3304 (unsigned char)SYNC_SUPPORTED);
3305 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003306}
3307
Linus Torvalds1da177e2005-04-16 15:20:36 -07003308/*---------------------------------------------------------------------
3309 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003310 * Function: FPT_sisyncr
Linus Torvalds1da177e2005-04-16 15:20:36 -07003311 *
3312 * Description: Answer the targets sync message.
3313 *
3314 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06003315static void FPT_sisyncr(u32 port, unsigned char sync_pulse,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003316 unsigned char offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003317{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003318 ARAM_ACCESS(port);
Hannes Reineckea87afe22021-04-27 10:30:40 +02003319 WRW_HARPOON((port + SYNC_MSGS + 0),
3320 (MPM_OP + AMSG_OUT + EXTENDED_MESSAGE));
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003321 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
Hannes Reineckea87afe22021-04-27 10:30:40 +02003322 WRW_HARPOON((port + SYNC_MSGS + 4),
3323 (MPM_OP + AMSG_OUT + EXTENDED_SDTR));
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003324 WRW_HARPOON((port + SYNC_MSGS + 6), (MPM_OP + AMSG_OUT + sync_pulse));
3325 WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
3326 WRW_HARPOON((port + SYNC_MSGS + 10), (MPM_OP + AMSG_OUT + offset));
3327 WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
3328 SGRAM_ACCESS(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003329
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003330 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3331 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003332
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003333 WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003334
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003335 while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
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_siwidn
Linus Torvalds1da177e2005-04-16 15:20:36 -07003342 *
3343 * Description: Read in a message byte from the SCSI bus, and check
3344 * for a parity error.
3345 *
3346 *---------------------------------------------------------------------*/
3347
Khalid Aziz391e2f22013-05-16 19:44:14 -06003348static unsigned char FPT_siwidn(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003349{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003350 struct sccb *currSCCB;
3351 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003352
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003353 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3354 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003355
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003356 if (!((currTar_Info->TarStatus & TAR_WIDE_MASK) == WIDE_NEGOCIATED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003357
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003358 WRW_HARPOON((port + ID_MSG_STRT),
3359 (MPM_OP + AMSG_OUT +
3360 (currSCCB->
3361 Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003362
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003363 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003364
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003365 WRW_HARPOON((port + SYNC_MSGS + 0),
Hannes Reineckea87afe22021-04-27 10:30:40 +02003366 (MPM_OP + AMSG_OUT + EXTENDED_MESSAGE));
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003367 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
3368 WRW_HARPOON((port + SYNC_MSGS + 4),
Hannes Reineckea87afe22021-04-27 10:30:40 +02003369 (MPM_OP + AMSG_OUT + EXTENDED_WDTR));
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003370 WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
3371 WRW_HARPOON((port + SYNC_MSGS + 8),
3372 (MPM_OP + AMSG_OUT + SM16BIT));
3373 WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003375 WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003376
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003377 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3378 ~(unsigned char)TAR_WIDE_MASK) |
3379 (unsigned char)WIDE_ENABLED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003380
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08003381 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003382 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003383
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003384 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003385
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003386 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3387 ~(unsigned char)TAR_WIDE_MASK) |
3388 WIDE_NEGOCIATED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003389
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003390 currTar_Info->TarEEValue &= ~EE_WIDE_SCSI;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08003391 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003392 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003393}
3394
Linus Torvalds1da177e2005-04-16 15:20:36 -07003395/*---------------------------------------------------------------------
3396 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003397 * Function: FPT_stwidn
Linus Torvalds1da177e2005-04-16 15:20:36 -07003398 *
3399 * Description: The has sent us a Wide Nego message so handle it as
3400 * necessary.
3401 *
3402 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06003403static void FPT_stwidn(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003404{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003405 unsigned char width;
3406 struct sccb *currSCCB;
3407 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003408
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003409 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3410 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003411
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003412 width = FPT_sfm(port, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003413
Hannes Reineckea87afe22021-04-27 10:30:40 +02003414 if ((width == 0x00) && (currSCCB->Sccb_scsimsg == MSG_PARITY_ERROR)) {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003415 WR_HARPOON(port + hp_autostart_1,
3416 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003417 return;
3418 }
3419
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003420 if (!(currTar_Info->TarEEValue & EE_WIDE_SCSI))
3421 width = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003422
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003423 if (width) {
3424 currTar_Info->TarStatus |= WIDE_ENABLED;
3425 width = 0;
3426 } else {
3427 width = NARROW_SCSI;
3428 currTar_Info->TarStatus &= ~WIDE_ENABLED;
3429 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003430
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003431 FPT_sssyncv(port, currSCCB->TargID, width, currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003432
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003433 if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003434
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003435 currTar_Info->TarStatus |= WIDE_NEGOCIATED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003436
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003437 if (!
3438 ((currTar_Info->TarStatus & TAR_SYNC_MASK) ==
3439 SYNC_SUPPORTED)) {
3440 ACCEPT_MSG_ATN(port);
3441 ARAM_ACCESS(port);
3442 FPT_sisyncn(port, p_card, 1);
3443 currSCCB->Sccb_scsistat = SELECT_SN_ST;
3444 SGRAM_ACCESS(port);
3445 } else {
3446 ACCEPT_MSG(port);
3447 WR_HARPOON(port + hp_autostart_1,
3448 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003450 }
3451
3452 else {
3453
3454 ACCEPT_MSG_ATN(port);
3455
3456 if (currTar_Info->TarEEValue & EE_WIDE_SCSI)
3457 width = SM16BIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003458 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003459 width = SM8BIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003461 FPT_siwidr(port, width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003462
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003463 currTar_Info->TarStatus |= (WIDE_NEGOCIATED | WIDE_ENABLED);
3464 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003465}
3466
Linus Torvalds1da177e2005-04-16 15:20:36 -07003467/*---------------------------------------------------------------------
3468 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003469 * Function: FPT_siwidr
Linus Torvalds1da177e2005-04-16 15:20:36 -07003470 *
3471 * Description: Answer the targets Wide nego message.
3472 *
3473 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06003474static void FPT_siwidr(u32 port, unsigned char width)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003475{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003476 ARAM_ACCESS(port);
Hannes Reineckea87afe22021-04-27 10:30:40 +02003477 WRW_HARPOON((port + SYNC_MSGS + 0),
3478 (MPM_OP + AMSG_OUT + EXTENDED_MESSAGE));
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003479 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
Hannes Reineckea87afe22021-04-27 10:30:40 +02003480 WRW_HARPOON((port + SYNC_MSGS + 4),
3481 (MPM_OP + AMSG_OUT + EXTENDED_WDTR));
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003482 WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
3483 WRW_HARPOON((port + SYNC_MSGS + 8), (MPM_OP + AMSG_OUT + width));
3484 WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
3485 SGRAM_ACCESS(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003486
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003487 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3488 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003490 WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003491
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003492 while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
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_sssyncv
Linus Torvalds1da177e2005-04-16 15:20:36 -07003499 *
3500 * Description: Write the desired value to the Sync Register for the
3501 * ID specified.
3502 *
3503 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06003504static void FPT_sssyncv(u32 p_port, unsigned char p_id,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003505 unsigned char p_sync_value,
3506 struct sccb_mgr_tar_info *currTar_Info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003507{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003508 unsigned char index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003509
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003510 index = p_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003511
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003512 switch (index) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003513
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003514 case 0:
3515 index = 12; /* hp_synctarg_0 */
3516 break;
3517 case 1:
3518 index = 13; /* hp_synctarg_1 */
3519 break;
3520 case 2:
3521 index = 14; /* hp_synctarg_2 */
3522 break;
3523 case 3:
3524 index = 15; /* hp_synctarg_3 */
3525 break;
3526 case 4:
3527 index = 8; /* hp_synctarg_4 */
3528 break;
3529 case 5:
3530 index = 9; /* hp_synctarg_5 */
3531 break;
3532 case 6:
3533 index = 10; /* hp_synctarg_6 */
3534 break;
3535 case 7:
3536 index = 11; /* hp_synctarg_7 */
3537 break;
3538 case 8:
3539 index = 4; /* hp_synctarg_8 */
3540 break;
3541 case 9:
3542 index = 5; /* hp_synctarg_9 */
3543 break;
3544 case 10:
3545 index = 6; /* hp_synctarg_10 */
3546 break;
3547 case 11:
3548 index = 7; /* hp_synctarg_11 */
3549 break;
3550 case 12:
3551 index = 0; /* hp_synctarg_12 */
3552 break;
3553 case 13:
3554 index = 1; /* hp_synctarg_13 */
3555 break;
3556 case 14:
3557 index = 2; /* hp_synctarg_14 */
3558 break;
3559 case 15:
3560 index = 3; /* hp_synctarg_15 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003561
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003562 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003563
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003564 WR_HARPOON(p_port + hp_synctarg_base + index, p_sync_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003565
3566 currTar_Info->TarSyncCtrl = p_sync_value;
3567}
3568
Linus Torvalds1da177e2005-04-16 15:20:36 -07003569/*---------------------------------------------------------------------
3570 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003571 * Function: FPT_sresb
Linus Torvalds1da177e2005-04-16 15:20:36 -07003572 *
3573 * Description: Reset the desired card's SCSI bus.
3574 *
3575 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06003576static void FPT_sresb(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003577{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003578 unsigned char scsiID, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003579
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003580 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003581
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003582 WR_HARPOON(port + hp_page_ctrl,
3583 (RD_HARPOON(port + hp_page_ctrl) | G_INT_DISABLE));
3584 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003585
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003586 WR_HARPOON(port + hp_scsictrl_0, SCSI_RST);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003587
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003588 scsiID = RD_HARPOON(port + hp_seltimeout);
3589 WR_HARPOON(port + hp_seltimeout, TO_5ms);
3590 WRW_HARPOON((port + hp_intstat), TIMEOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003591
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003592 WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT | START_TO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003593
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003594 while (!(RDW_HARPOON((port + hp_intstat)) & TIMEOUT)) {
3595 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003596
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003597 WR_HARPOON(port + hp_seltimeout, scsiID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003598
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003599 WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003600
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003601 FPT_Wait(port, TO_5ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003602
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003603 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003604
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003605 WR_HARPOON(port + hp_int_mask, (RD_HARPOON(port + hp_int_mask) | 0x00));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003606
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003607 for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
3608 currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003610 if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
3611 currTar_Info->TarSyncCtrl = 0;
3612 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
3613 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003615 if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
3616 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
3617 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003618
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003619 FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003620
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003621 FPT_SccbMgrTableInitTarget(p_card, scsiID);
3622 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003623
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003624 FPT_BL_Card[p_card].scanIndex = 0x00;
3625 FPT_BL_Card[p_card].currentSCCB = NULL;
3626 FPT_BL_Card[p_card].globalFlags &= ~(F_TAG_STARTED | F_HOST_XFER_ACT
3627 | F_NEW_SCCB_CMD);
3628 FPT_BL_Card[p_card].cmdCounter = 0x00;
James Bottomley 47b5d692005-04-24 02:38:05 -05003629 FPT_BL_Card[p_card].discQCount = 0x00;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003630 FPT_BL_Card[p_card].tagQ_Lst = 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003632 for (i = 0; i < QUEUE_DEPTH; i++)
James Bottomley 47b5d692005-04-24 02:38:05 -05003633 FPT_BL_Card[p_card].discQ_Tbl[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003634
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003635 WR_HARPOON(port + hp_page_ctrl,
3636 (RD_HARPOON(port + hp_page_ctrl) & ~G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003637
3638}
3639
3640/*---------------------------------------------------------------------
3641 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003642 * Function: FPT_ssenss
Linus Torvalds1da177e2005-04-16 15:20:36 -07003643 *
3644 * Description: Setup for the Auto Sense command.
3645 *
3646 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003647static void FPT_ssenss(struct sccb_card *pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003648{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003649 unsigned char i;
3650 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003652 currSCCB = pCurrCard->currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003654 currSCCB->Save_CdbLen = currSCCB->CdbLength;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003655
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003656 for (i = 0; i < 6; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003657
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003658 currSCCB->Save_Cdb[i] = currSCCB->Cdb[i];
3659 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003660
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003661 currSCCB->CdbLength = SIX_BYTE_CMD;
Hannes Reineckea87afe22021-04-27 10:30:40 +02003662 currSCCB->Cdb[0] = REQUEST_SENSE;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003663 currSCCB->Cdb[1] = currSCCB->Cdb[1] & (unsigned char)0xE0; /*Keep LUN. */
3664 currSCCB->Cdb[2] = 0x00;
3665 currSCCB->Cdb[3] = 0x00;
3666 currSCCB->Cdb[4] = currSCCB->RequestSenseLength;
3667 currSCCB->Cdb[5] = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003668
Khalid Aziz391e2f22013-05-16 19:44:14 -06003669 currSCCB->Sccb_XferCnt = (u32)currSCCB->RequestSenseLength;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003670
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003671 currSCCB->Sccb_ATC = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003672
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003673 currSCCB->Sccb_XferState |= F_AUTO_SENSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003674
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003675 currSCCB->Sccb_XferState &= ~F_SG_XFER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003676
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003677 currSCCB->Sccb_idmsg = currSCCB->Sccb_idmsg & ~(unsigned char)DISC_PRIV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003678
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003679 currSCCB->ControlByte = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003680
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003681 currSCCB->Sccb_MGRFlags &= F_STATUSLOADED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682}
3683
Linus Torvalds1da177e2005-04-16 15:20:36 -07003684/*---------------------------------------------------------------------
3685 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003686 * Function: FPT_sxfrp
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687 *
3688 * Description: Transfer data into the bit bucket until the device
3689 * decides to switch phase.
3690 *
3691 *---------------------------------------------------------------------*/
3692
Khalid Aziz391e2f22013-05-16 19:44:14 -06003693static void FPT_sxfrp(u32 p_port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003695 unsigned char curr_phz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003697 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003698
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003699 if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003700
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003701 FPT_hostDataXferAbort(p_port, p_card,
3702 FPT_BL_Card[p_card].currentSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003703
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003704 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003705
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003706 /* If the Automation handled the end of the transfer then do not
3707 match the phase or we will get out of sync with the ISR. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003709 if (RDW_HARPOON((p_port + hp_intstat)) &
3710 (BUS_FREE | XFER_CNT_0 | AUTO_INT))
3711 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003712
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003713 WR_HARPOON(p_port + hp_xfercnt_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003715 curr_phz = RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003716
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003717 WRW_HARPOON((p_port + hp_intstat), XFER_CNT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003718
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003719 WR_HARPOON(p_port + hp_scsisig, curr_phz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003721 while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET)) &&
3722 (curr_phz ==
3723 (RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ)))
3724 {
3725 if (curr_phz & (unsigned char)SCSI_IOBIT) {
3726 WR_HARPOON(p_port + hp_portctrl_0,
3727 (SCSI_PORT | HOST_PORT | SCSI_INBIT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003728
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003729 if (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
3730 RD_HARPOON(p_port + hp_fifodata_0);
3731 }
3732 } else {
3733 WR_HARPOON(p_port + hp_portctrl_0,
3734 (SCSI_PORT | HOST_PORT | HOST_WRT));
3735 if (RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY) {
3736 WR_HARPOON(p_port + hp_fifodata_0, 0xFA);
3737 }
3738 }
3739 } /* End of While loop for padding data I/O phase */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003740
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003741 while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
3742 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ)
3743 break;
3744 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003745
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003746 WR_HARPOON(p_port + hp_portctrl_0,
3747 (SCSI_PORT | HOST_PORT | SCSI_INBIT));
3748 while (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
3749 RD_HARPOON(p_port + hp_fifodata_0);
3750 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003751
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003752 if (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
3753 WR_HARPOON(p_port + hp_autostart_0,
3754 (AUTO_IMMED + DISCONNECT_START));
3755 while (!(RDW_HARPOON((p_port + hp_intstat)) & AUTO_INT)) {
3756 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003757
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003758 if (RDW_HARPOON((p_port + hp_intstat)) &
3759 (ICMD_COMP | ITAR_DISC))
3760 while (!
3761 (RDW_HARPOON((p_port + hp_intstat)) &
3762 (BUS_FREE | RSEL))) ;
3763 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003764}
3765
Linus Torvalds1da177e2005-04-16 15:20:36 -07003766/*---------------------------------------------------------------------
3767 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003768 * Function: FPT_schkdd
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769 *
3770 * Description: Make sure data has been flushed from both FIFOs and abort
3771 * the operations if necessary.
3772 *
3773 *---------------------------------------------------------------------*/
3774
Khalid Aziz391e2f22013-05-16 19:44:14 -06003775static void FPT_schkdd(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003776{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003777 unsigned short TimeOutLoop;
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08003778 unsigned char sPhase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003780 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003782 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003783
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003784 if ((currSCCB->Sccb_scsistat != DATA_OUT_ST) &&
3785 (currSCCB->Sccb_scsistat != DATA_IN_ST)) {
3786 return;
3787 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003788
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003789 if (currSCCB->Sccb_XferState & F_ODD_BALL_CNT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003790
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003791 currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003792
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003793 currSCCB->Sccb_XferCnt = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003794
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003795 currSCCB->Sccb_XferState &= ~F_ODD_BALL_CNT;
3796 WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
3797 WR_HARPOON(port + hp_xferstat, 0x00);
3798 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003799
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003800 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003802 currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003803
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003804 currSCCB->Sccb_XferCnt = 0;
3805 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003806
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003807 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
3808 (currSCCB->HostStatus == SCCB_COMPLETE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003809
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003810 currSCCB->HostStatus = SCCB_PARITY_ERR;
3811 WRW_HARPOON((port + hp_intstat), PARITY);
3812 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003814 FPT_hostDataXferAbort(port, p_card, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003815
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003816 while (RD_HARPOON(port + hp_scsisig) & SCSI_ACK) {
3817 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003818
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003819 TimeOutLoop = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003820
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003821 while (RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY) {
3822 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
3823 return;
3824 }
3825 if (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) {
3826 break;
3827 }
3828 if (RDW_HARPOON((port + hp_intstat)) & RESET) {
3829 return;
3830 }
3831 if ((RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
3832 || (TimeOutLoop++ > 0x3000))
3833 break;
3834 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003836 sPhase = RD_HARPOON(port + hp_scsisig) & (SCSI_BSY | S_SCSI_PHZ);
3837 if ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) ||
3838 (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) ||
3839 (sPhase == (SCSI_BSY | S_DATAO_PH)) ||
3840 (sPhase == (SCSI_BSY | S_DATAI_PH))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003842 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003843
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003844 if (!(currSCCB->Sccb_XferState & F_ALL_XFERRED)) {
3845 if (currSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
3846 FPT_phaseDataIn(port, p_card);
3847 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003848
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003849 else {
3850 FPT_phaseDataOut(port, p_card);
3851 }
3852 } else {
3853 FPT_sxfrp(port, p_card);
3854 if (!(RDW_HARPOON((port + hp_intstat)) &
3855 (BUS_FREE | ICMD_COMP | ITAR_DISC | RESET))) {
3856 WRW_HARPOON((port + hp_intstat), AUTO_INT);
3857 FPT_phaseDecode(port, p_card);
3858 }
3859 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003860
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003861 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003863 else {
3864 WR_HARPOON(port + hp_portctrl_0, 0x00);
3865 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003866}
3867
Linus Torvalds1da177e2005-04-16 15:20:36 -07003868/*---------------------------------------------------------------------
3869 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003870 * Function: FPT_sinits
Linus Torvalds1da177e2005-04-16 15:20:36 -07003871 *
3872 * Description: Setup SCCB manager fields in this SCCB.
3873 *
3874 *---------------------------------------------------------------------*/
3875
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003876static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003877{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003878 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003879
Dan Carpenter5d7ebb92009-12-28 20:08:39 +02003880 if ((p_sccb->TargID >= MAX_SCSI_TAR) || (p_sccb->Lun >= MAX_LUN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003881 return;
3882 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003883 currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003884
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003885 p_sccb->Sccb_XferState = 0x00;
3886 p_sccb->Sccb_XferCnt = p_sccb->DataLength;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003887
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003888 if ((p_sccb->OperationCode == SCATTER_GATHER_COMMAND) ||
3889 (p_sccb->OperationCode == RESIDUAL_SG_COMMAND)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003890
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003891 p_sccb->Sccb_SGoffset = 0;
3892 p_sccb->Sccb_XferState = F_SG_XFER;
3893 p_sccb->Sccb_XferCnt = 0x00;
3894 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003896 if (p_sccb->DataLength == 0x00)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003897
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003898 p_sccb->Sccb_XferState |= F_ALL_XFERRED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003900 if (p_sccb->ControlByte & F_USE_CMD_Q) {
3901 if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
3902 p_sccb->ControlByte &= ~F_USE_CMD_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003903
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003904 else
3905 currTar_Info->TarStatus |= TAG_Q_TRYING;
3906 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907
3908/* For !single SCSI device in system & device allow Disconnect
3909 or command is tag_q type then send Cmd with Disconnect Enable
3910 else send Cmd with Disconnect Disable */
3911
3912/*
James Bottomley 47b5d692005-04-24 02:38:05 -05003913 if (((!(FPT_BL_Card[p_card].globalFlags & F_SINGLE_DEVICE)) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07003914 (currTar_Info->TarStatus & TAR_ALLOW_DISC)) ||
3915 (currTar_Info->TarStatus & TAG_Q_TRYING)) {
3916*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003917 if ((currTar_Info->TarStatus & TAR_ALLOW_DISC) ||
3918 (currTar_Info->TarStatus & TAG_Q_TRYING)) {
Hannes Reineckea87afe22021-04-27 10:30:40 +02003919 p_sccb->Sccb_idmsg = IDENTIFY(true, p_sccb->Lun);
3920 } else {
3921 p_sccb->Sccb_idmsg = IDENTIFY(false, p_sccb->Lun);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003922 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003923
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003924 p_sccb->HostStatus = 0x00;
3925 p_sccb->TargetStatus = 0x00;
3926 p_sccb->Sccb_tag = 0x00;
3927 p_sccb->Sccb_MGRFlags = 0x00;
3928 p_sccb->Sccb_sgseg = 0x00;
3929 p_sccb->Sccb_ATC = 0x00;
3930 p_sccb->Sccb_savedATC = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003931/*
3932 p_sccb->SccbVirtDataPtr = 0x00;
3933 p_sccb->Sccb_forwardlink = NULL;
3934 p_sccb->Sccb_backlink = NULL;
3935 */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003936 p_sccb->Sccb_scsistat = BUS_FREE_ST;
3937 p_sccb->SccbStatus = SCCB_IN_PROCESS;
Hannes Reineckea87afe22021-04-27 10:30:40 +02003938 p_sccb->Sccb_scsimsg = NOP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939
3940}
3941
Linus Torvalds1da177e2005-04-16 15:20:36 -07003942/*---------------------------------------------------------------------
3943 *
3944 * Function: Phase Decode
3945 *
3946 * Description: Determine the phase and call the appropriate function.
3947 *
3948 *---------------------------------------------------------------------*/
3949
Khalid Aziz391e2f22013-05-16 19:44:14 -06003950static void FPT_phaseDecode(u32 p_port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003951{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003952 unsigned char phase_ref;
Khalid Aziz391e2f22013-05-16 19:44:14 -06003953 void (*phase) (u32, unsigned char);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003955 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003957 phase_ref =
3958 (unsigned char)(RD_HARPOON(p_port + hp_scsisig) & S_SCSI_PHZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003959
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003960 phase = FPT_s_PhaseTbl[phase_ref];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003962 (*phase) (p_port, p_card); /* Call the correct phase func */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963}
3964
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965/*---------------------------------------------------------------------
3966 *
3967 * Function: Data Out Phase
3968 *
3969 * Description: Start up both the BusMaster and Xbow.
3970 *
3971 *---------------------------------------------------------------------*/
3972
Khalid Aziz391e2f22013-05-16 19:44:14 -06003973static void FPT_phaseDataOut(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974{
3975
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003976 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003977
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003978 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3979 if (currSCCB == NULL) {
3980 return; /* Exit if No SCCB record */
3981 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003983 currSCCB->Sccb_scsistat = DATA_OUT_ST;
3984 currSCCB->Sccb_XferState &= ~(F_HOST_XFER_DIR | F_NO_DATA_YET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003986 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003987
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003988 WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003989
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003990 WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003992 FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003993
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003994 if (currSCCB->Sccb_XferCnt == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003995
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003996 if ((currSCCB->ControlByte & SCCB_DATA_XFER_OUT) &&
3997 (currSCCB->HostStatus == SCCB_COMPLETE))
3998 currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003999
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004000 FPT_sxfrp(port, p_card);
4001 if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
4002 FPT_phaseDecode(port, p_card);
4003 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004004}
4005
Linus Torvalds1da177e2005-04-16 15:20:36 -07004006/*---------------------------------------------------------------------
4007 *
4008 * Function: Data In Phase
4009 *
4010 * Description: Startup the BusMaster and the XBOW.
4011 *
4012 *---------------------------------------------------------------------*/
4013
Khalid Aziz391e2f22013-05-16 19:44:14 -06004014static void FPT_phaseDataIn(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004015{
4016
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004017 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004018
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004019 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004020
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004021 if (currSCCB == NULL) {
4022 return; /* Exit if No SCCB record */
4023 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004024
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004025 currSCCB->Sccb_scsistat = DATA_IN_ST;
4026 currSCCB->Sccb_XferState |= F_HOST_XFER_DIR;
4027 currSCCB->Sccb_XferState &= ~F_NO_DATA_YET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004029 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004030
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004031 WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004033 WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004034
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004035 FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004036
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004037 if (currSCCB->Sccb_XferCnt == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004038
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004039 if ((currSCCB->ControlByte & SCCB_DATA_XFER_IN) &&
4040 (currSCCB->HostStatus == SCCB_COMPLETE))
4041 currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004043 FPT_sxfrp(port, p_card);
4044 if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
4045 FPT_phaseDecode(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004047 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004048}
4049
4050/*---------------------------------------------------------------------
4051 *
4052 * Function: Command Phase
4053 *
4054 * Description: Load the CDB into the automation and start it up.
4055 *
4056 *---------------------------------------------------------------------*/
4057
Khalid Aziz391e2f22013-05-16 19:44:14 -06004058static void FPT_phaseCommand(u32 p_port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004059{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004060 struct sccb *currSCCB;
Khalid Aziz391e2f22013-05-16 19:44:14 -06004061 u32 cdb_reg;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004062 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004063
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004064 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004065
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004066 if (currSCCB->OperationCode == RESET_COMMAND) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004067
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004068 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4069 currSCCB->CdbLength = SIX_BYTE_CMD;
4070 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004072 WR_HARPOON(p_port + hp_scsisig, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004073
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004074 ARAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004076 cdb_reg = p_port + CMD_STRT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004077
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004078 for (i = 0; i < currSCCB->CdbLength; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004080 if (currSCCB->OperationCode == RESET_COMMAND)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004082 WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + 0x00));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004084 else
4085 WRW_HARPOON(cdb_reg,
4086 (MPM_OP + ACOMMAND + currSCCB->Cdb[i]));
4087 cdb_reg += 2;
4088 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004090 if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
4091 WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004092
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004093 WR_HARPOON(p_port + hp_portctrl_0, (SCSI_PORT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004094
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004095 currSCCB->Sccb_scsistat = COMMAND_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004096
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004097 WR_HARPOON(p_port + hp_autostart_3, (AUTO_IMMED | CMD_ONLY_STRT));
4098 SGRAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099}
4100
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101/*---------------------------------------------------------------------
4102 *
4103 * Function: Status phase
4104 *
4105 * Description: Bring in the status and command complete message bytes
4106 *
4107 *---------------------------------------------------------------------*/
4108
Khalid Aziz391e2f22013-05-16 19:44:14 -06004109static void FPT_phaseStatus(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004111 /* Start-up the automation to finish off this command and let the
4112 isr handle the interrupt for command complete when it comes in.
4113 We could wait here for the interrupt to be generated?
4114 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004115
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004116 WR_HARPOON(port + hp_scsisig, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004117
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004118 WR_HARPOON(port + hp_autostart_0, (AUTO_IMMED + END_DATA_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119}
4120
Linus Torvalds1da177e2005-04-16 15:20:36 -07004121/*---------------------------------------------------------------------
4122 *
4123 * Function: Phase Message Out
4124 *
4125 * Description: Send out our message (if we have one) and handle whatever
4126 * else is involed.
4127 *
4128 *---------------------------------------------------------------------*/
4129
Khalid Aziz391e2f22013-05-16 19:44:14 -06004130static void FPT_phaseMsgOut(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004131{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004132 unsigned char message, scsiID;
4133 struct sccb *currSCCB;
4134 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004135
James Bottomley 47b5d692005-04-24 02:38:05 -05004136 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137
4138 if (currSCCB != NULL) {
4139
4140 message = currSCCB->Sccb_scsimsg;
4141 scsiID = currSCCB->TargID;
4142
Hannes Reineckea87afe22021-04-27 10:30:40 +02004143 if (message == TARGET_RESET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144
James Bottomley 47b5d692005-04-24 02:38:05 -05004145 currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146 currTar_Info->TarSyncCtrl = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004147 FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004149 if (FPT_sccbMgrTbl[p_card][scsiID].
4150 TarEEValue & EE_SYNC_MASK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004152 FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
4153 ~TAR_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004154
4155 }
4156
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004157 if (FPT_sccbMgrTbl[p_card][scsiID].
4158 TarEEValue & EE_WIDE_SCSI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004159
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004160 FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
4161 ~TAR_WIDE_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004162 }
4163
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004164 FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
4165 FPT_SccbMgrTableInitTarget(p_card, scsiID);
4166 } else if (currSCCB->Sccb_scsistat == ABORT_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004167 currSCCB->HostStatus = SCCB_COMPLETE;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004168 if (FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] !=
4169 NULL) {
4170 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4171 Sccb_tag] = NULL;
James Bottomley 47b5d692005-04-24 02:38:05 -05004172 FPT_sccbMgrTbl[p_card][scsiID].TarTagQ_Cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004174
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175 }
4176
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004177 else if (currSCCB->Sccb_scsistat < COMMAND_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004178
Hannes Reineckea87afe22021-04-27 10:30:40 +02004179 if (message == NOP) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004180 currSCCB->Sccb_MGRFlags |= F_DEV_SELECTED;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004181
4182 FPT_ssel(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004183 return;
4184 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004185 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004186
Hannes Reineckea87afe22021-04-27 10:30:40 +02004187 if (message == ABORT_TASK_SET)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004188
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004189 FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004190 }
4191
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004192 } else {
Hannes Reineckea87afe22021-04-27 10:30:40 +02004193 message = ABORT_TASK_SET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004194 }
4195
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004196 WRW_HARPOON((port + hp_intstat), (BUS_FREE | PHASE | XFER_CNT_0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004197
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004198 WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004199
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004200 WR_HARPOON(port + hp_scsidata_0, message);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004201
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004202 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004203
4204 ACCEPT_MSG(port);
4205
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004206 WR_HARPOON(port + hp_portctrl_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004207
Hannes Reineckea87afe22021-04-27 10:30:40 +02004208 if ((message == ABORT_TASK_SET) || (message == TARGET_RESET) ||
4209 (message == ABORT_TASK)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004210
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004211 while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | PHASE))) {
4212 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004213
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004214 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
4215 WRW_HARPOON((port + hp_intstat), BUS_FREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004216
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004217 if (currSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004218
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004219 if ((FPT_BL_Card[p_card].
4220 globalFlags & F_CONLUN_IO)
4221 &&
4222 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4223 TarStatus & TAR_TAG_Q_MASK) !=
4224 TAG_Q_TRYING))
4225 FPT_sccbMgrTbl[p_card][currSCCB->
4226 TargID].
4227 TarLUNBusy[currSCCB->Lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004228 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004229 FPT_sccbMgrTbl[p_card][currSCCB->
4230 TargID].
4231 TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004232
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004233 FPT_queueCmdComplete(&FPT_BL_Card[p_card],
4234 currSCCB, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004235 }
4236
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004237 else {
4238 FPT_BL_Card[p_card].globalFlags |=
4239 F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004240 }
4241 }
4242
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004243 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004244
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004245 FPT_sxfrp(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004246 }
4247 }
4248
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004249 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004250
Hannes Reineckea87afe22021-04-27 10:30:40 +02004251 if (message == MSG_PARITY_ERROR) {
4252 currSCCB->Sccb_scsimsg = NOP;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004253 WR_HARPOON(port + hp_autostart_1,
4254 (AUTO_IMMED + DISCONNECT_START));
4255 } else {
4256 FPT_sxfrp(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004257 }
4258 }
4259}
4260
Linus Torvalds1da177e2005-04-16 15:20:36 -07004261/*---------------------------------------------------------------------
4262 *
4263 * Function: Message In phase
4264 *
4265 * Description: Bring in the message and determine what to do with it.
4266 *
4267 *---------------------------------------------------------------------*/
4268
Khalid Aziz391e2f22013-05-16 19:44:14 -06004269static void FPT_phaseMsgIn(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004270{
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08004271 unsigned char message;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004272 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004273
James Bottomley 47b5d692005-04-24 02:38:05 -05004274 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004275
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004276 if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004277
James Bottomley 47b5d692005-04-24 02:38:05 -05004278 FPT_phaseChkFifo(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004279 }
4280
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004281 message = RD_HARPOON(port + hp_scsidata_0);
Hannes Reineckea87afe22021-04-27 10:30:40 +02004282 if ((message == DISCONNECT) || (message == SAVE_POINTERS)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004284 WR_HARPOON(port + hp_autostart_1,
4285 (AUTO_IMMED + END_DATA_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004286
4287 }
4288
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004289 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004290
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004291 message = FPT_sfm(port, currSCCB);
4292 if (message) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004293
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004294 FPT_sdecm(message, port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004295
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004296 } else {
Hannes Reineckea87afe22021-04-27 10:30:40 +02004297 if (currSCCB->Sccb_scsimsg != MSG_PARITY_ERROR)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004298 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004299 WR_HARPOON(port + hp_autostart_1,
4300 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004301 }
4302 }
4303
4304}
4305
Linus Torvalds1da177e2005-04-16 15:20:36 -07004306/*---------------------------------------------------------------------
4307 *
4308 * Function: Illegal phase
4309 *
4310 * Description: Target switched to some illegal phase, so all we can do
4311 * is report an error back to the host (if that is possible)
4312 * and send an ABORT message to the misbehaving target.
4313 *
4314 *---------------------------------------------------------------------*/
4315
Khalid Aziz391e2f22013-05-16 19:44:14 -06004316static void FPT_phaseIllegal(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004318 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004319
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004320 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004321
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004322 WR_HARPOON(port + hp_scsisig, RD_HARPOON(port + hp_scsisig));
4323 if (currSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004324
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004325 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4326 currSCCB->Sccb_scsistat = ABORT_ST;
Hannes Reineckea87afe22021-04-27 10:30:40 +02004327 currSCCB->Sccb_scsimsg = ABORT_TASK_SET;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004328 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004329
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004330 ACCEPT_MSG_ATN(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004331}
4332
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333/*---------------------------------------------------------------------
4334 *
4335 * Function: Phase Check FIFO
4336 *
4337 * Description: Make sure data has been flushed from both FIFOs and abort
4338 * the operations if necessary.
4339 *
4340 *---------------------------------------------------------------------*/
4341
Khalid Aziz391e2f22013-05-16 19:44:14 -06004342static void FPT_phaseChkFifo(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004343{
Khalid Aziz391e2f22013-05-16 19:44:14 -06004344 u32 xfercnt;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004345 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004346
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004347 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004348
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004349 if (currSCCB->Sccb_scsistat == DATA_IN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004351 while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) &&
4352 (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)) {
4353 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004354
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004355 if (!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) {
4356 currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004357
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004358 currSCCB->Sccb_XferCnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004359
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004360 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
4361 (currSCCB->HostStatus == SCCB_COMPLETE)) {
4362 currSCCB->HostStatus = SCCB_PARITY_ERR;
4363 WRW_HARPOON((port + hp_intstat), PARITY);
4364 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004365
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004366 FPT_hostDataXferAbort(port, p_card, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004367
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004368 FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004369
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004370 while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY))
4371 && (RD_HARPOON(port + hp_ext_status) &
4372 BM_CMD_BUSY)) {
4373 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004374
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004375 }
4376 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004377
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004378 /*End Data In specific code. */
4379 GET_XFER_CNT(port, xfercnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004380
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004381 WR_HARPOON(port + hp_xfercnt_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004382
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004383 WR_HARPOON(port + hp_portctrl_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004384
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004385 currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - xfercnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004386
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004387 currSCCB->Sccb_XferCnt = xfercnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004388
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004389 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
4390 (currSCCB->HostStatus == SCCB_COMPLETE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004391
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004392 currSCCB->HostStatus = SCCB_PARITY_ERR;
4393 WRW_HARPOON((port + hp_intstat), PARITY);
4394 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004395
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004396 FPT_hostDataXferAbort(port, p_card, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004397
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004398 WR_HARPOON(port + hp_fifowrite, 0x00);
4399 WR_HARPOON(port + hp_fiforead, 0x00);
4400 WR_HARPOON(port + hp_xferstat, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004401
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004402 WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004403}
4404
Linus Torvalds1da177e2005-04-16 15:20:36 -07004405/*---------------------------------------------------------------------
4406 *
4407 * Function: Phase Bus Free
4408 *
4409 * Description: We just went bus free so figure out if it was
4410 * because of command complete or from a disconnect.
4411 *
4412 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06004413static void FPT_phaseBusFree(u32 port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004414{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004415 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004416
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004417 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004419 if (currSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004420
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004421 DISABLE_AUTO(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004422
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004423 if (currSCCB->OperationCode == RESET_COMMAND) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004424
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004425 if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4426 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4427 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4428 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4429 TarLUNBusy[currSCCB->Lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004430 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004431 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4432 TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004433
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004434 FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
4435 p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004436
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004437 FPT_queueSearchSelect(&FPT_BL_Card[p_card], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004438
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004439 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004440
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004441 else if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
4442 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4443 (unsigned char)SYNC_SUPPORTED;
4444 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4445 ~EE_SYNC_MASK;
4446 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004447
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004448 else if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
4449 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
4450 (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4451 TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004452
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004453 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4454 ~EE_WIDE_SCSI;
4455 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004457 else if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
4458 /* Make sure this is not a phony BUS_FREE. If we were
4459 reselected or if BUSY is NOT on then this is a
4460 valid BUS FREE. SRR Wednesday, 5/10/1995. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004461
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004462 if ((!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ||
4463 (RDW_HARPOON((port + hp_intstat)) & RSEL)) {
4464 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4465 TarStatus &= ~TAR_TAG_Q_MASK;
4466 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4467 TarStatus |= TAG_Q_REJECT;
4468 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004469
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004470 else {
4471 return;
4472 }
4473 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004474
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004475 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004476
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004477 currSCCB->Sccb_scsistat = BUS_FREE_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004478
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004479 if (!currSCCB->HostStatus) {
4480 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4481 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004482
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004483 if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4484 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4485 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4486 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4487 TarLUNBusy[currSCCB->Lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004488 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004489 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4490 TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004491
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004492 FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
4493 p_card);
4494 return;
4495 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004496
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004497 FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004498
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004499 } /*end if !=null */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004500}
4501
Linus Torvalds1da177e2005-04-16 15:20:36 -07004502/*---------------------------------------------------------------------
4503 *
4504 * Function: Auto Load Default Map
4505 *
zuoqilin083d2482021-03-04 13:51:20 +08004506 * Description: Load the Automation RAM with the default map values.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004507 *
4508 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06004509static void FPT_autoLoadDefaultMap(u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004510{
Khalid Aziz391e2f22013-05-16 19:44:14 -06004511 u32 map_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004512
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004513 ARAM_ACCESS(p_port);
4514 map_addr = p_port + hp_aramBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004515
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004516 WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0xC0)); /*ID MESSAGE */
4517 map_addr += 2;
4518 WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x20)); /*SIMPLE TAG QUEUEING MSG */
4519 map_addr += 2;
4520 WRW_HARPOON(map_addr, RAT_OP); /*RESET ATTENTION */
4521 map_addr += 2;
4522 WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x00)); /*TAG ID MSG */
4523 map_addr += 2;
4524 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 0 */
4525 map_addr += 2;
4526 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 1 */
4527 map_addr += 2;
4528 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 2 */
4529 map_addr += 2;
4530 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 3 */
4531 map_addr += 2;
4532 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 4 */
4533 map_addr += 2;
4534 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 5 */
4535 map_addr += 2;
4536 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 6 */
4537 map_addr += 2;
4538 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 7 */
4539 map_addr += 2;
4540 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 8 */
4541 map_addr += 2;
4542 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 9 */
4543 map_addr += 2;
4544 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 10 */
4545 map_addr += 2;
4546 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 11 */
4547 map_addr += 2;
4548 WRW_HARPOON(map_addr, (CPE_OP + ADATA_OUT + DINT)); /*JUMP IF DATA OUT */
4549 map_addr += 2;
4550 WRW_HARPOON(map_addr, (TCB_OP + FIFO_0 + DI)); /*JUMP IF NO DATA IN FIFO */
4551 map_addr += 2; /*This means AYNC DATA IN */
4552 WRW_HARPOON(map_addr, (SSI_OP + SSI_IDO_STRT)); /*STOP AND INTERRUPT */
4553 map_addr += 2;
4554 WRW_HARPOON(map_addr, (CPE_OP + ADATA_IN + DINT)); /*JUMP IF NOT DATA IN PHZ */
4555 map_addr += 2;
4556 WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST)); /*IF NOT MSG IN CHECK 4 DATA IN */
4557 map_addr += 2;
4558 WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x02)); /*SAVE DATA PTR MSG? */
4559 map_addr += 2;
4560 WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + DC)); /*GO CHECK FOR DISCONNECT MSG */
4561 map_addr += 2;
4562 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR1)); /*SAVE DATA PTRS MSG */
4563 map_addr += 2;
4564 WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST)); /*IF NOT MSG IN CHECK DATA IN */
4565 map_addr += 2;
4566 WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x04)); /*DISCONNECT MSG? */
4567 map_addr += 2;
4568 WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + UNKNWN)); /*UKNKNOWN MSG */
4569 map_addr += 2;
4570 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET)); /*XFER DISCONNECT MSG */
4571 map_addr += 2;
4572 WRW_HARPOON(map_addr, (SSI_OP + SSI_ITAR_DISC)); /*STOP AND INTERRUPT */
4573 map_addr += 2;
4574 WRW_HARPOON(map_addr, (CPN_OP + ASTATUS + UNKNWN)); /*JUMP IF NOT STATUS PHZ. */
4575 map_addr += 2;
4576 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR0)); /*GET STATUS BYTE */
4577 map_addr += 2;
4578 WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + CC)); /*ERROR IF NOT MSG IN PHZ */
4579 map_addr += 2;
4580 WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x00)); /*CHECK FOR CMD COMPLETE MSG. */
4581 map_addr += 2;
4582 WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + CC)); /*ERROR IF NOT CMD COMPLETE MSG. */
4583 map_addr += 2;
4584 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET)); /*GET CMD COMPLETE MSG */
4585 map_addr += 2;
4586 WRW_HARPOON(map_addr, (SSI_OP + SSI_ICMD_COMP)); /*END OF COMMAND */
4587 map_addr += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004588
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004589 WRW_HARPOON(map_addr, (SSI_OP + SSI_IUNKWN)); /*RECEIVED UNKNOWN MSG BYTE */
4590 map_addr += 2;
4591 WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */
4592 map_addr += 2;
4593 WRW_HARPOON(map_addr, (SSI_OP + SSI_ITICKLE)); /*BIOS Tickled the Mgr */
4594 map_addr += 2;
4595 WRW_HARPOON(map_addr, (SSI_OP + SSI_IRFAIL)); /*EXPECTED ID/TAG MESSAGES AND */
4596 map_addr += 2; /* DIDN'T GET ONE */
4597 WRW_HARPOON(map_addr, (CRR_OP + AR3 + S_IDREG)); /* comp SCSI SEL ID & AR3 */
4598 map_addr += 2;
4599 WRW_HARPOON(map_addr, (BRH_OP + EQUAL + 0x00)); /*SEL ID OK then Conti. */
4600 map_addr += 2;
4601 WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004602
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004603 SGRAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004604}
4605
4606/*---------------------------------------------------------------------
4607 *
4608 * Function: Auto Command Complete
4609 *
4610 * Description: Post command back to host and find another command
4611 * to execute.
4612 *
4613 *---------------------------------------------------------------------*/
4614
Khalid Aziz391e2f22013-05-16 19:44:14 -06004615static void FPT_autoCmdCmplt(u32 p_port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004616{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004617 struct sccb *currSCCB;
4618 unsigned char status_byte;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004619
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004620 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004621
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004622 status_byte = RD_HARPOON(p_port + hp_gp_reg_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004623
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004624 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004625
Hannes Reineckea87afe22021-04-27 10:30:40 +02004626 if (status_byte != SAM_STAT_GOOD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004627
Hannes Reineckea87afe22021-04-27 10:30:40 +02004628 if (status_byte == SAM_STAT_TASK_SET_FULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004629
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004630 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4631 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4632 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4633 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4634 TarLUNBusy[currSCCB->Lun] = 1;
4635 if (FPT_BL_Card[p_card].discQCount != 0)
James Bottomley 47b5d692005-04-24 02:38:05 -05004636 FPT_BL_Card[p_card].discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004637 FPT_BL_Card[p_card].
4638 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4639 [currSCCB->TargID].
4640 LunDiscQ_Idx[currSCCB->Lun]] =
4641 NULL;
4642 } else {
4643 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4644 TarLUNBusy[0] = 1;
4645 if (currSCCB->Sccb_tag) {
4646 if (FPT_BL_Card[p_card].discQCount != 0)
4647 FPT_BL_Card[p_card].
4648 discQCount--;
4649 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4650 Sccb_tag]
4651 = NULL;
4652 } else {
4653 if (FPT_BL_Card[p_card].discQCount != 0)
4654 FPT_BL_Card[p_card].
4655 discQCount--;
4656 FPT_BL_Card[p_card].
4657 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4658 [currSCCB->TargID].
4659 LunDiscQ_Idx[0]] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004660 }
4661 }
4662
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004663 currSCCB->Sccb_MGRFlags |= F_STATUSLOADED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004664
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004665 FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004666
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004667 return;
4668 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004669
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004670 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
4671 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4672 (unsigned char)SYNC_SUPPORTED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004673
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004674 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4675 ~EE_SYNC_MASK;
4676 FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004677
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004678 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4679 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4680 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4681 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4682 TarLUNBusy[currSCCB->Lun] = 1;
4683 if (FPT_BL_Card[p_card].discQCount != 0)
James Bottomley 47b5d692005-04-24 02:38:05 -05004684 FPT_BL_Card[p_card].discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004685 FPT_BL_Card[p_card].
4686 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4687 [currSCCB->TargID].
4688 LunDiscQ_Idx[currSCCB->Lun]] =
4689 NULL;
4690 } else {
4691 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4692 TarLUNBusy[0] = 1;
4693 if (currSCCB->Sccb_tag) {
4694 if (FPT_BL_Card[p_card].discQCount != 0)
4695 FPT_BL_Card[p_card].
4696 discQCount--;
4697 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4698 Sccb_tag]
4699 = NULL;
4700 } else {
4701 if (FPT_BL_Card[p_card].discQCount != 0)
4702 FPT_BL_Card[p_card].
4703 discQCount--;
4704 FPT_BL_Card[p_card].
4705 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4706 [currSCCB->TargID].
4707 LunDiscQ_Idx[0]] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004708 }
4709 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004710 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004711
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004712 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004713
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004714 if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004715
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004716 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
4717 (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4718 TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004719
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004720 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4721 ~EE_WIDE_SCSI;
4722 FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004723
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004724 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4725 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4726 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4727 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4728 TarLUNBusy[currSCCB->Lun] = 1;
4729 if (FPT_BL_Card[p_card].discQCount != 0)
James Bottomley 47b5d692005-04-24 02:38:05 -05004730 FPT_BL_Card[p_card].discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004731 FPT_BL_Card[p_card].
4732 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4733 [currSCCB->TargID].
4734 LunDiscQ_Idx[currSCCB->Lun]] =
4735 NULL;
4736 } else {
4737 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4738 TarLUNBusy[0] = 1;
4739 if (currSCCB->Sccb_tag) {
4740 if (FPT_BL_Card[p_card].discQCount != 0)
4741 FPT_BL_Card[p_card].
4742 discQCount--;
4743 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4744 Sccb_tag]
4745 = NULL;
4746 } else {
4747 if (FPT_BL_Card[p_card].discQCount != 0)
4748 FPT_BL_Card[p_card].
4749 discQCount--;
4750 FPT_BL_Card[p_card].
4751 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4752 [currSCCB->TargID].
4753 LunDiscQ_Idx[0]] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004754 }
4755 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004756 return;
4757
4758 }
4759
Hannes Reineckea87afe22021-04-27 10:30:40 +02004760 if (status_byte == SAM_STAT_CHECK_CONDITION) {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004761 if (FPT_BL_Card[p_card].globalFlags & F_DO_RENEGO) {
4762 if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4763 TarEEValue & EE_SYNC_MASK) {
4764 FPT_sccbMgrTbl[p_card][currSCCB->
4765 TargID].
4766 TarStatus &= ~TAR_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004767 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004768 if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4769 TarEEValue & EE_WIDE_SCSI) {
4770 FPT_sccbMgrTbl[p_card][currSCCB->
4771 TargID].
4772 TarStatus &= ~TAR_WIDE_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004773 }
4774 }
4775 }
4776
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004777 if (!(currSCCB->Sccb_XferState & F_AUTO_SENSE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004778
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004779 currSCCB->SccbStatus = SCCB_ERROR;
4780 currSCCB->TargetStatus = status_byte;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004781
Hannes Reineckea87afe22021-04-27 10:30:40 +02004782 if (status_byte == SAM_STAT_CHECK_CONDITION) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004783
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004784 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4785 TarLUN_CA = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004786
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004787 if (currSCCB->RequestSenseLength !=
4788 NO_AUTO_REQUEST_SENSE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004789
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004790 if (currSCCB->RequestSenseLength == 0)
4791 currSCCB->RequestSenseLength =
4792 14;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004793
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004794 FPT_ssenss(&FPT_BL_Card[p_card]);
4795 FPT_BL_Card[p_card].globalFlags |=
4796 F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004797
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004798 if (((FPT_BL_Card[p_card].
4799 globalFlags & F_CONLUN_IO)
4800 &&
4801 ((FPT_sccbMgrTbl[p_card]
4802 [currSCCB->TargID].
4803 TarStatus & TAR_TAG_Q_MASK) !=
4804 TAG_Q_TRYING))) {
4805 FPT_sccbMgrTbl[p_card]
4806 [currSCCB->TargID].
4807 TarLUNBusy[currSCCB->Lun] =
4808 1;
4809 if (FPT_BL_Card[p_card].
4810 discQCount != 0)
4811 FPT_BL_Card[p_card].
4812 discQCount--;
4813 FPT_BL_Card[p_card].
4814 discQ_Tbl[FPT_sccbMgrTbl
4815 [p_card]
4816 [currSCCB->
4817 TargID].
4818 LunDiscQ_Idx
4819 [currSCCB->Lun]] =
4820 NULL;
4821 } else {
4822 FPT_sccbMgrTbl[p_card]
4823 [currSCCB->TargID].
4824 TarLUNBusy[0] = 1;
4825 if (currSCCB->Sccb_tag) {
4826 if (FPT_BL_Card[p_card].
4827 discQCount != 0)
4828 FPT_BL_Card
4829 [p_card].
4830 discQCount--;
4831 FPT_BL_Card[p_card].
4832 discQ_Tbl[currSCCB->
4833 Sccb_tag]
4834 = NULL;
4835 } else {
4836 if (FPT_BL_Card[p_card].
4837 discQCount != 0)
4838 FPT_BL_Card
4839 [p_card].
4840 discQCount--;
4841 FPT_BL_Card[p_card].
4842 discQ_Tbl
4843 [FPT_sccbMgrTbl
4844 [p_card][currSCCB->
4845 TargID].
4846 LunDiscQ_Idx[0]] =
4847 NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004848 }
4849 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004850 return;
4851 }
4852 }
4853 }
4854 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004855
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004856 if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4857 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4858 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4859 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->
4860 Lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004861 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004862 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004863
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004864 FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004865}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004866
4867#define SHORT_WAIT 0x0000000F
4868#define LONG_WAIT 0x0000FFFFL
4869
Linus Torvalds1da177e2005-04-16 15:20:36 -07004870/*---------------------------------------------------------------------
4871 *
4872 * Function: Data Transfer Processor
4873 *
4874 * Description: This routine performs two tasks.
4875 * (1) Start data transfer by calling HOST_DATA_XFER_START
4876 * function. Once data transfer is started, (2) Depends
4877 * on the type of data transfer mode Scatter/Gather mode
4878 * or NON Scatter/Gather mode. In NON Scatter/Gather mode,
4879 * this routine checks Sccb_MGRFlag (F_HOST_XFER_ACT bit) for
4880 * data transfer done. In Scatter/Gather mode, this routine
4881 * checks bus master command complete and dual rank busy
4882 * bit to keep chaining SC transfer command. Similarly,
4883 * in Scatter/Gather mode, it checks Sccb_MGRFlag
4884 * (F_HOST_XFER_ACT bit) for data transfer done.
4885 *
4886 *---------------------------------------------------------------------*/
4887
Khalid Aziz391e2f22013-05-16 19:44:14 -06004888static void FPT_dataXferProcessor(u32 port, struct sccb_card *pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004889{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004890 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004891
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004892 currSCCB = pCurrCard->currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004893
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004894 if (currSCCB->Sccb_XferState & F_SG_XFER) {
4895 if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
4896 {
4897 currSCCB->Sccb_sgseg += (unsigned char)SG_BUF_CNT;
4898 currSCCB->Sccb_SGoffset = 0x00;
4899 }
4900 pCurrCard->globalFlags |= F_HOST_XFER_ACT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004901
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004902 FPT_busMstrSGDataXferStart(port, currSCCB);
4903 }
4904
4905 else {
4906 if (!(pCurrCard->globalFlags & F_HOST_XFER_ACT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004907 pCurrCard->globalFlags |= F_HOST_XFER_ACT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004908
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004909 FPT_busMstrDataXferStart(port, currSCCB);
4910 }
4911 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004912}
4913
Linus Torvalds1da177e2005-04-16 15:20:36 -07004914/*---------------------------------------------------------------------
4915 *
4916 * Function: BusMaster Scatter Gather Data Transfer Start
4917 *
4918 * Description:
4919 *
4920 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06004921static void FPT_busMstrSGDataXferStart(u32 p_port, struct sccb *pcurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004922{
Khalid Aziz391e2f22013-05-16 19:44:14 -06004923 u32 count, addr, tmpSGCnt;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004924 unsigned int sg_index;
4925 unsigned char sg_count, i;
Khalid Aziz391e2f22013-05-16 19:44:14 -06004926 u32 reg_offset;
4927 struct blogic_sg_seg *segp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004928
Khalid Aziz391e2f22013-05-16 19:44:14 -06004929 if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)
4930 count = ((u32)HOST_RD_CMD) << 24;
4931 else
4932 count = ((u32)HOST_WRT_CMD) << 24;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004933
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004934 sg_count = 0;
4935 tmpSGCnt = 0;
4936 sg_index = pcurrSCCB->Sccb_sgseg;
4937 reg_offset = hp_aramBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004938
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004939 i = (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
4940 ~(SGRAM_ARAM | SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004941
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004942 WR_HARPOON(p_port + hp_page_ctrl, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004943
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004944 while ((sg_count < (unsigned char)SG_BUF_CNT) &&
Khalid Aziz391e2f22013-05-16 19:44:14 -06004945 ((sg_index * (unsigned int)SG_ELEMENT_SIZE) <
4946 pcurrSCCB->DataLength)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004947
Khalid Aziz391e2f22013-05-16 19:44:14 -06004948 segp = (struct blogic_sg_seg *)(pcurrSCCB->DataPointer) +
4949 sg_index;
4950 tmpSGCnt += segp->segbytes;
4951 count |= segp->segbytes;
4952 addr = segp->segdata;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004953
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004954 if ((!sg_count) && (pcurrSCCB->Sccb_SGoffset)) {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004955 addr +=
4956 ((count & 0x00FFFFFFL) - pcurrSCCB->Sccb_SGoffset);
4957 count =
4958 (count & 0xFF000000L) | pcurrSCCB->Sccb_SGoffset;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004959 tmpSGCnt = count & 0x00FFFFFFL;
4960 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004961
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004962 WR_HARP32(p_port, reg_offset, addr);
4963 reg_offset += 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004964
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004965 WR_HARP32(p_port, reg_offset, count);
4966 reg_offset += 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004967
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004968 count &= 0xFF000000L;
4969 sg_index++;
4970 sg_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004971
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004972 } /*End While */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004973
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004974 pcurrSCCB->Sccb_XferCnt = tmpSGCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004975
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004976 WR_HARPOON(p_port + hp_sg_addr, (sg_count << 4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004977
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004978 if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004979
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004980 WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004981
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004982 WR_HARPOON(p_port + hp_portctrl_0,
4983 (DMA_PORT | SCSI_PORT | SCSI_INBIT));
4984 WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
4985 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004986
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004987 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004988
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004989 if ((!(RD_HARPOON(p_port + hp_synctarg_0) & NARROW_SCSI)) &&
4990 (tmpSGCnt & 0x000000001)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004991
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004992 pcurrSCCB->Sccb_XferState |= F_ODD_BALL_CNT;
4993 tmpSGCnt--;
4994 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004995
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004996 WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004997
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004998 WR_HARPOON(p_port + hp_portctrl_0,
4999 (SCSI_PORT | DMA_PORT | DMA_RD));
5000 WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
5001 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005002
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005003 WR_HARPOON(p_port + hp_page_ctrl, (unsigned char)(i | SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005004
5005}
5006
Linus Torvalds1da177e2005-04-16 15:20:36 -07005007/*---------------------------------------------------------------------
5008 *
5009 * Function: BusMaster Data Transfer Start
5010 *
5011 * Description:
5012 *
5013 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06005014static void FPT_busMstrDataXferStart(u32 p_port, struct sccb *pcurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005015{
Khalid Aziz391e2f22013-05-16 19:44:14 -06005016 u32 addr, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005017
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005018 if (!(pcurrSCCB->Sccb_XferState & F_AUTO_SENSE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005019
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005020 count = pcurrSCCB->Sccb_XferCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005021
Khalid Aziz391e2f22013-05-16 19:44:14 -06005022 addr = (u32)(unsigned long)pcurrSCCB->DataPointer + pcurrSCCB->Sccb_ATC;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005023 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005024
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005025 else {
5026 addr = pcurrSCCB->SensePointer;
5027 count = pcurrSCCB->RequestSenseLength;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005028
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005029 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005030
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005031 HP_SETUP_ADDR_CNT(p_port, addr, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005032
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005033 if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005034
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005035 WR_HARPOON(p_port + hp_portctrl_0,
5036 (DMA_PORT | SCSI_PORT | SCSI_INBIT));
5037 WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005038
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005039 WR_HARPOON(p_port + hp_xfer_cmd,
5040 (XFER_DMA_HOST | XFER_HOST_AUTO | XFER_DMA_8BIT));
5041 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005042
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005043 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005044
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005045 WR_HARPOON(p_port + hp_portctrl_0,
5046 (SCSI_PORT | DMA_PORT | DMA_RD));
5047 WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005048
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005049 WR_HARPOON(p_port + hp_xfer_cmd,
5050 (XFER_HOST_DMA | XFER_HOST_AUTO | XFER_DMA_8BIT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005051
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005052 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005053}
5054
Linus Torvalds1da177e2005-04-16 15:20:36 -07005055/*---------------------------------------------------------------------
5056 *
5057 * Function: BusMaster Timeout Handler
5058 *
5059 * Description: This function is called after a bus master command busy time
5060 * out is detected. This routines issue halt state machine
5061 * with a software time out for command busy. If command busy
5062 * is still asserted at the end of the time out, it issues
5063 * hard abort with another software time out. It hard abort
5064 * command busy is also time out, it'll just give up.
5065 *
5066 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06005067static unsigned char FPT_busMstrTimeOut(u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005068{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005069 unsigned long timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005070
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005071 timeout = LONG_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005072
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005073 WR_HARPOON(p_port + hp_sys_ctrl, HALT_MACH);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005074
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005075 while ((!(RD_HARPOON(p_port + hp_ext_status) & CMD_ABORTED))
5076 && timeout--) {
5077 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005078
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005079 if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
5080 WR_HARPOON(p_port + hp_sys_ctrl, HARD_ABORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005081
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005082 timeout = LONG_WAIT;
5083 while ((RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY)
5084 && timeout--) {
5085 }
5086 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005087
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005088 RD_HARPOON(p_port + hp_int_status); /*Clear command complete */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005089
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005090 if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005091 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005092 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005093
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005094 else {
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005095 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005096 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005097}
5098
Linus Torvalds1da177e2005-04-16 15:20:36 -07005099/*---------------------------------------------------------------------
5100 *
5101 * Function: Host Data Transfer Abort
5102 *
5103 * Description: Abort any in progress transfer.
5104 *
5105 *---------------------------------------------------------------------*/
Khalid Aziz391e2f22013-05-16 19:44:14 -06005106static void FPT_hostDataXferAbort(u32 port, unsigned char p_card,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005107 struct sccb *pCurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005108{
5109
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005110 unsigned long timeout;
5111 unsigned long remain_cnt;
Khalid Aziz391e2f22013-05-16 19:44:14 -06005112 u32 sg_ptr;
5113 struct blogic_sg_seg *segp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005114
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005115 FPT_BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005116
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005117 if (pCurrSCCB->Sccb_XferState & F_AUTO_SENSE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005118
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005119 if (!(RD_HARPOON(port + hp_int_status) & INT_CMD_COMPL)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005120
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005121 WR_HARPOON(port + hp_bm_ctrl,
5122 (RD_HARPOON(port + hp_bm_ctrl) |
5123 FLUSH_XFER_CNTR));
5124 timeout = LONG_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005125
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005126 while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
5127 && timeout--) {
5128 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005129
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005130 WR_HARPOON(port + hp_bm_ctrl,
5131 (RD_HARPOON(port + hp_bm_ctrl) &
5132 ~FLUSH_XFER_CNTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005133
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005134 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005135
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005136 if (FPT_busMstrTimeOut(port)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005137
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005138 if (pCurrSCCB->HostStatus == 0x00)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005139
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005140 pCurrSCCB->HostStatus =
5141 SCCB_BM_ERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005142
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005143 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005144
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005145 if (RD_HARPOON(port + hp_int_status) &
5146 INT_EXT_STATUS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005147
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005148 if (RD_HARPOON(port + hp_ext_status) &
5149 BAD_EXT_STATUS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005150
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005151 if (pCurrSCCB->HostStatus ==
5152 0x00)
5153 {
5154 pCurrSCCB->HostStatus =
5155 SCCB_BM_ERR;
5156 }
5157 }
5158 }
5159 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005160
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005161 else if (pCurrSCCB->Sccb_XferCnt) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005162
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005163 if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005164
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005165 WR_HARPOON(port + hp_page_ctrl,
5166 (RD_HARPOON(port + hp_page_ctrl) &
5167 ~SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005168
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005169 WR_HARPOON(port + hp_sg_addr, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005170
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005171 sg_ptr = pCurrSCCB->Sccb_sgseg + SG_BUF_CNT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005172
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005173 if (sg_ptr >
5174 (unsigned int)(pCurrSCCB->DataLength /
5175 SG_ELEMENT_SIZE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005176
Khalid Aziz391e2f22013-05-16 19:44:14 -06005177 sg_ptr = (u32)(pCurrSCCB->DataLength /
5178 SG_ELEMENT_SIZE);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005179 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005180
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005181 remain_cnt = pCurrSCCB->Sccb_XferCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005182
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005183 while (remain_cnt < 0x01000000L) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005184
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005185 sg_ptr--;
Khalid Aziz391e2f22013-05-16 19:44:14 -06005186 segp = (struct blogic_sg_seg *)(pCurrSCCB->
5187 DataPointer) + (sg_ptr * 2);
5188 if (remain_cnt > (unsigned long)segp->segbytes)
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005189 remain_cnt -=
Khalid Aziz391e2f22013-05-16 19:44:14 -06005190 (unsigned long)segp->segbytes;
5191 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005192 break;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005193 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005194
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005195 if (remain_cnt < 0x01000000L) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005196
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005197 pCurrSCCB->Sccb_SGoffset = remain_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005198
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005199 pCurrSCCB->Sccb_sgseg = (unsigned short)sg_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005200
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005201 if ((unsigned long)(sg_ptr * SG_ELEMENT_SIZE) ==
5202 pCurrSCCB->DataLength && (remain_cnt == 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005203
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005204 pCurrSCCB->Sccb_XferState |=
5205 F_ALL_XFERRED;
5206 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005207
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005208 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005209
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005210 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005211
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005212 pCurrSCCB->HostStatus =
5213 SCCB_GROSS_FW_ERR;
5214 }
5215 }
5216 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005217
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005218 if (!(pCurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005219
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005220 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005221
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005222 FPT_busMstrTimeOut(port);
5223 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005224
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005225 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005226
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005227 if (RD_HARPOON(port + hp_int_status) &
5228 INT_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005229
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005230 if (RD_HARPOON(port + hp_ext_status) &
5231 BAD_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005232
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005233 if (pCurrSCCB->HostStatus ==
5234 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005235
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005236 pCurrSCCB->HostStatus =
5237 SCCB_BM_ERR;
5238 }
5239 }
5240 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005241
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005242 }
5243 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005244
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005245 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005246
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005247 if ((RD_HARPOON(port + hp_fifo_cnt)) >= BM_THRESHOLD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005248
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005249 timeout = SHORT_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005250
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005251 while ((RD_HARPOON(port + hp_ext_status) &
5252 BM_CMD_BUSY)
5253 && ((RD_HARPOON(port + hp_fifo_cnt)) >=
5254 BM_THRESHOLD) && timeout--) {
5255 }
5256 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005257
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005258 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005259
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005260 WR_HARPOON(port + hp_bm_ctrl,
5261 (RD_HARPOON(port + hp_bm_ctrl) |
5262 FLUSH_XFER_CNTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005263
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005264 timeout = LONG_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005265
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005266 while ((RD_HARPOON(port + hp_ext_status) &
5267 BM_CMD_BUSY) && timeout--) {
5268 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005269
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005270 WR_HARPOON(port + hp_bm_ctrl,
5271 (RD_HARPOON(port + hp_bm_ctrl) &
5272 ~FLUSH_XFER_CNTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005273
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005274 if (RD_HARPOON(port + hp_ext_status) &
5275 BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005276
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005277 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005278
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005279 pCurrSCCB->HostStatus =
5280 SCCB_BM_ERR;
5281 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005282
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005283 FPT_busMstrTimeOut(port);
5284 }
5285 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005286
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005287 if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005288
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005289 if (RD_HARPOON(port + hp_ext_status) &
5290 BAD_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005291
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005292 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005293
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005294 pCurrSCCB->HostStatus =
5295 SCCB_BM_ERR;
5296 }
5297 }
5298 }
5299 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005300
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005301 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005302
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005303 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005304
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005305 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005306
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005307 timeout = LONG_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005308
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005309 while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
5310 && timeout--) {
5311 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005312
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005313 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005314
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005315 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005316
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005317 pCurrSCCB->HostStatus = SCCB_BM_ERR;
5318 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005319
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005320 FPT_busMstrTimeOut(port);
5321 }
5322 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005323
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005324 if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005325
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005326 if (RD_HARPOON(port + hp_ext_status) & BAD_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005327
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005328 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005329
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005330 pCurrSCCB->HostStatus = SCCB_BM_ERR;
5331 }
5332 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005333
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005334 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005335
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005336 if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005337
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005338 WR_HARPOON(port + hp_page_ctrl,
5339 (RD_HARPOON(port + hp_page_ctrl) &
5340 ~SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005341
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005342 WR_HARPOON(port + hp_sg_addr, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005343
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005344 pCurrSCCB->Sccb_sgseg += SG_BUF_CNT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005345
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005346 pCurrSCCB->Sccb_SGoffset = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005347
Khalid Aziz391e2f22013-05-16 19:44:14 -06005348 if ((u32)(pCurrSCCB->Sccb_sgseg * SG_ELEMENT_SIZE) >=
5349 pCurrSCCB->DataLength) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005350
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005351 pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005352 pCurrSCCB->Sccb_sgseg =
5353 (unsigned short)(pCurrSCCB->DataLength /
5354 SG_ELEMENT_SIZE);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005355 }
5356 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005357
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005358 else {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005359 if (!(pCurrSCCB->Sccb_XferState & F_AUTO_SENSE))
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005360 pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
5361 }
5362 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005363
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005364 WR_HARPOON(port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005365}
5366
Linus Torvalds1da177e2005-04-16 15:20:36 -07005367/*---------------------------------------------------------------------
5368 *
5369 * Function: Host Data Transfer Restart
5370 *
5371 * Description: Reset the available count due to a restore data
5372 * pointers message.
5373 *
5374 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005375static void FPT_hostDataXferRestart(struct sccb *currSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005376{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005377 unsigned long data_count;
5378 unsigned int sg_index;
Khalid Aziz391e2f22013-05-16 19:44:14 -06005379 struct blogic_sg_seg *segp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005380
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005381 if (currSCCB->Sccb_XferState & F_SG_XFER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005382
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005383 currSCCB->Sccb_XferCnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005384
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005385 sg_index = 0xffff; /*Index by long words into sg list. */
Khalid Aziz391e2f22013-05-16 19:44:14 -06005386 data_count = 0; /*Running count of SG xfer counts. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005387
Linus Torvalds1da177e2005-04-16 15:20:36 -07005388
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005389 while (data_count < currSCCB->Sccb_ATC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005390
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005391 sg_index++;
Khalid Aziz391e2f22013-05-16 19:44:14 -06005392 segp = (struct blogic_sg_seg *)(currSCCB->DataPointer) +
5393 (sg_index * 2);
5394 data_count += segp->segbytes;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005395 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005396
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005397 if (data_count == currSCCB->Sccb_ATC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005398
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005399 currSCCB->Sccb_SGoffset = 0;
5400 sg_index++;
5401 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005402
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005403 else {
5404 currSCCB->Sccb_SGoffset =
5405 data_count - currSCCB->Sccb_ATC;
5406 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005407
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005408 currSCCB->Sccb_sgseg = (unsigned short)sg_index;
5409 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005410
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005411 else {
5412 currSCCB->Sccb_XferCnt =
5413 currSCCB->DataLength - currSCCB->Sccb_ATC;
5414 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005415}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005416
Linus Torvalds1da177e2005-04-16 15:20:36 -07005417/*---------------------------------------------------------------------
5418 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005419 * Function: FPT_scini
Linus Torvalds1da177e2005-04-16 15:20:36 -07005420 *
5421 * Description: Setup all data structures necessary for SCAM selection.
5422 *
5423 *---------------------------------------------------------------------*/
5424
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005425static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
5426 unsigned char p_power_up)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005427{
5428
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005429 unsigned char loser, assigned_id;
Khalid Aziz391e2f22013-05-16 19:44:14 -06005430 u32 p_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005431
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005432 unsigned char i, k, ScamFlg;
5433 struct sccb_card *currCard;
5434 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005435
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005436 currCard = &FPT_BL_Card[p_card];
5437 p_port = currCard->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005438 pCurrNvRam = currCard->pNvRamInfo;
5439
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005440 if (pCurrNvRam) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005441 ScamFlg = pCurrNvRam->niScamConf;
5442 i = pCurrNvRam->niSysConf;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005443 } else {
5444 ScamFlg =
5445 (unsigned char)FPT_utilEERead(p_port, SCAM_CONFIG / 2);
5446 i = (unsigned
5447 char)(FPT_utilEERead(p_port, (SYSTEM_CONFIG / 2)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005448 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005449 if (!(i & 0x02)) /* check if reset bus in AutoSCSI parameter set */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005450 return;
5451
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005452 FPT_inisci(p_card, p_port, p_our_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005453
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005454 /* Force to wait 1 sec after SCSI bus reset. Some SCAM device FW
5455 too slow to return to SCAM selection */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005456
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005457 /* if (p_power_up)
5458 FPT_Wait1Second(p_port);
5459 else
5460 FPT_Wait(p_port, TO_250ms); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005461
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005462 FPT_Wait1Second(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005463
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005464 if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2)) {
5465 while (!(FPT_scarb(p_port, INIT_SELTD))) {
5466 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005467
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005468 FPT_scsel(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005469
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005470 do {
5471 FPT_scxferc(p_port, SYNC_PTRN);
5472 FPT_scxferc(p_port, DOM_MSTR);
5473 loser =
5474 FPT_scsendi(p_port,
5475 &FPT_scamInfo[p_our_id].id_string[0]);
5476 } while (loser == 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005477
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005478 FPT_scbusf(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005479
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005480 if ((p_power_up) && (!loser)) {
5481 FPT_sresb(p_port, p_card);
5482 FPT_Wait(p_port, TO_250ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005483
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005484 while (!(FPT_scarb(p_port, INIT_SELTD))) {
5485 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005486
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005487 FPT_scsel(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005488
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005489 do {
5490 FPT_scxferc(p_port, SYNC_PTRN);
5491 FPT_scxferc(p_port, DOM_MSTR);
5492 loser =
5493 FPT_scsendi(p_port,
5494 &FPT_scamInfo[p_our_id].
5495 id_string[0]);
5496 } while (loser == 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005497
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005498 FPT_scbusf(p_port);
5499 }
5500 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005501
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005502 else {
5503 loser = 0;
5504 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005505
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005506 if (!loser) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005507
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005508 FPT_scamInfo[p_our_id].state = ID_ASSIGNED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005509
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005510 if (ScamFlg & SCAM_ENABLED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005511
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005512 for (i = 0; i < MAX_SCSI_TAR; i++) {
5513 if ((FPT_scamInfo[i].state == ID_UNASSIGNED) ||
5514 (FPT_scamInfo[i].state == ID_UNUSED)) {
5515 if (FPT_scsell(p_port, i)) {
5516 FPT_scamInfo[i].state = LEGACY;
5517 if ((FPT_scamInfo[i].
5518 id_string[0] != 0xFF)
5519 || (FPT_scamInfo[i].
5520 id_string[1] != 0xFA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005521
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005522 FPT_scamInfo[i].
5523 id_string[0] = 0xFF;
5524 FPT_scamInfo[i].
5525 id_string[1] = 0xFA;
5526 if (pCurrNvRam == NULL)
5527 currCard->
5528 globalFlags
5529 |=
5530 F_UPDATE_EEPROM;
5531 }
5532 }
5533 }
5534 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005535
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005536 FPT_sresb(p_port, p_card);
5537 FPT_Wait1Second(p_port);
5538 while (!(FPT_scarb(p_port, INIT_SELTD))) {
5539 }
5540 FPT_scsel(p_port);
5541 FPT_scasid(p_card, p_port);
5542 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005543
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005544 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005545
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005546 else if ((loser) && (ScamFlg & SCAM_ENABLED)) {
5547 FPT_scamInfo[p_our_id].id_string[0] = SLV_TYPE_CODE0;
5548 assigned_id = 0;
5549 FPT_scwtsel(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005550
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005551 do {
5552 while (FPT_scxferc(p_port, 0x00) != SYNC_PTRN) {
5553 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005554
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005555 i = FPT_scxferc(p_port, 0x00);
5556 if (i == ASSIGN_ID) {
5557 if (!
5558 (FPT_scsendi
5559 (p_port,
5560 &FPT_scamInfo[p_our_id].id_string[0]))) {
5561 i = FPT_scxferc(p_port, 0x00);
5562 if (FPT_scvalq(i)) {
5563 k = FPT_scxferc(p_port, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005564
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005565 if (FPT_scvalq(k)) {
5566 currCard->ourId =
5567 ((unsigned char)(i
5568 <<
5569 3)
5570 +
5571 (k &
5572 (unsigned char)7))
5573 & (unsigned char)
5574 0x3F;
5575 FPT_inisci(p_card,
5576 p_port,
5577 p_our_id);
5578 FPT_scamInfo[currCard->
5579 ourId].
5580 state = ID_ASSIGNED;
5581 FPT_scamInfo[currCard->
5582 ourId].
5583 id_string[0]
5584 = SLV_TYPE_CODE0;
5585 assigned_id = 1;
5586 }
5587 }
5588 }
5589 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005590
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005591 else if (i == SET_P_FLAG) {
5592 if (!(FPT_scsendi(p_port,
5593 &FPT_scamInfo[p_our_id].
5594 id_string[0])))
5595 FPT_scamInfo[p_our_id].id_string[0] |=
5596 0x80;
5597 }
5598 } while (!assigned_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005599
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005600 while (FPT_scxferc(p_port, 0x00) != CFG_CMPLT) {
5601 }
5602 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005603
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005604 if (ScamFlg & SCAM_ENABLED) {
5605 FPT_scbusf(p_port);
5606 if (currCard->globalFlags & F_UPDATE_EEPROM) {
5607 FPT_scsavdi(p_card, p_port);
5608 currCard->globalFlags &= ~F_UPDATE_EEPROM;
5609 }
5610 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005611
Linus Torvalds1da177e2005-04-16 15:20:36 -07005612/*
5613 for (i=0,k=0; i < MAX_SCSI_TAR; i++)
5614 {
James Bottomley 47b5d692005-04-24 02:38:05 -05005615 if ((FPT_scamInfo[i].state == ID_ASSIGNED) ||
5616 (FPT_scamInfo[i].state == LEGACY))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005617 k++;
5618 }
5619
5620 if (k==2)
5621 currCard->globalFlags |= F_SINGLE_DEVICE;
5622 else
5623 currCard->globalFlags &= ~F_SINGLE_DEVICE;
5624*/
5625}
5626
Linus Torvalds1da177e2005-04-16 15:20:36 -07005627/*---------------------------------------------------------------------
5628 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005629 * Function: FPT_scarb
Linus Torvalds1da177e2005-04-16 15:20:36 -07005630 *
5631 * Description: Gain control of the bus and wait SCAM select time (250ms)
5632 *
5633 *---------------------------------------------------------------------*/
5634
Khalid Aziz391e2f22013-05-16 19:44:14 -06005635static int FPT_scarb(u32 p_port, unsigned char p_sel_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005636{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005637 if (p_sel_type == INIT_SELTD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005638
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005639 while (RD_HARPOON(p_port + hp_scsisig) & (SCSI_SEL | SCSI_BSY)) {
5640 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005641
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005642 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005643 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005644
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005645 if (RD_HARPOON(p_port + hp_scsidata_0) != 00)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005646 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005647
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005648 WR_HARPOON(p_port + hp_scsisig,
5649 (RD_HARPOON(p_port + hp_scsisig) | SCSI_BSY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005650
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005651 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005652
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005653 WR_HARPOON(p_port + hp_scsisig,
5654 (RD_HARPOON(p_port + hp_scsisig) &
5655 ~SCSI_BSY));
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005656 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005657 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005658
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005659 WR_HARPOON(p_port + hp_scsisig,
5660 (RD_HARPOON(p_port + hp_scsisig) | SCSI_SEL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005661
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005662 if (RD_HARPOON(p_port + hp_scsidata_0) != 00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005663
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005664 WR_HARPOON(p_port + hp_scsisig,
5665 (RD_HARPOON(p_port + hp_scsisig) &
5666 ~(SCSI_BSY | SCSI_SEL)));
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005667 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005668 }
5669 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005670
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005671 WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
5672 & ~ACTdeassert));
5673 WR_HARPOON(p_port + hp_scsireset, SCAM_EN);
5674 WR_HARPOON(p_port + hp_scsidata_0, 0x00);
5675 WR_HARPOON(p_port + hp_scsidata_1, 0x00);
5676 WR_HARPOON(p_port + hp_portctrl_0, SCSI_BUS_EN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005677
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005678 WR_HARPOON(p_port + hp_scsisig,
5679 (RD_HARPOON(p_port + hp_scsisig) | SCSI_MSG));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005680
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005681 WR_HARPOON(p_port + hp_scsisig, (RD_HARPOON(p_port + hp_scsisig)
5682 & ~SCSI_BSY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005683
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005684 FPT_Wait(p_port, TO_250ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005685
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005686 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005687}
5688
Linus Torvalds1da177e2005-04-16 15:20:36 -07005689/*---------------------------------------------------------------------
5690 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005691 * Function: FPT_scbusf
Linus Torvalds1da177e2005-04-16 15:20:36 -07005692 *
5693 * Description: Release the SCSI bus and disable SCAM selection.
5694 *
5695 *---------------------------------------------------------------------*/
5696
Khalid Aziz391e2f22013-05-16 19:44:14 -06005697static void FPT_scbusf(u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005698{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005699 WR_HARPOON(p_port + hp_page_ctrl,
5700 (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005701
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005702 WR_HARPOON(p_port + hp_scsidata_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005703
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005704 WR_HARPOON(p_port + hp_portctrl_0, (RD_HARPOON(p_port + hp_portctrl_0)
5705 & ~SCSI_BUS_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005706
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005707 WR_HARPOON(p_port + hp_scsisig, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005708
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005709 WR_HARPOON(p_port + hp_scsireset, (RD_HARPOON(p_port + hp_scsireset)
5710 & ~SCAM_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005711
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005712 WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
5713 | ACTdeassert));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005714
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005715 WRW_HARPOON((p_port + hp_intstat), (BUS_FREE | AUTO_INT | SCAM_SEL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005716
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005717 WR_HARPOON(p_port + hp_page_ctrl,
5718 (RD_HARPOON(p_port + hp_page_ctrl) & ~G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005719}
5720
Linus Torvalds1da177e2005-04-16 15:20:36 -07005721/*---------------------------------------------------------------------
5722 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005723 * Function: FPT_scasid
Linus Torvalds1da177e2005-04-16 15:20:36 -07005724 *
5725 * Description: Assign an ID to all the SCAM devices.
5726 *
5727 *---------------------------------------------------------------------*/
5728
Khalid Aziz391e2f22013-05-16 19:44:14 -06005729static void FPT_scasid(unsigned char p_card, u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005730{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005731 unsigned char temp_id_string[ID_STRING_LENGTH];
Linus Torvalds1da177e2005-04-16 15:20:36 -07005732
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005733 unsigned char i, k, scam_id;
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08005734 unsigned char crcBytes[3];
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005735 struct nvram_info *pCurrNvRam;
5736 unsigned short *pCrcBytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005737
James Bottomley 47b5d692005-04-24 02:38:05 -05005738 pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005739
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005740 i = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005741
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005742 while (!i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005743
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005744 for (k = 0; k < ID_STRING_LENGTH; k++) {
5745 temp_id_string[k] = (unsigned char)0x00;
5746 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005747
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005748 FPT_scxferc(p_port, SYNC_PTRN);
5749 FPT_scxferc(p_port, ASSIGN_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005750
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005751 if (!(FPT_sciso(p_port, &temp_id_string[0]))) {
5752 if (pCurrNvRam) {
Alexey Dobriyanfd1e29e2006-03-08 00:14:27 -08005753 pCrcBytes = (unsigned short *)&crcBytes[0];
James Bottomley 47b5d692005-04-24 02:38:05 -05005754 *pCrcBytes = FPT_CalcCrc16(&temp_id_string[0]);
5755 crcBytes[2] = FPT_CalcLrc(&temp_id_string[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005756 temp_id_string[1] = crcBytes[2];
5757 temp_id_string[2] = crcBytes[0];
5758 temp_id_string[3] = crcBytes[1];
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005759 for (k = 4; k < ID_STRING_LENGTH; k++)
5760 temp_id_string[k] = (unsigned char)0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005761 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005762 i = FPT_scmachid(p_card, temp_id_string);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005763
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005764 if (i == CLR_PRIORITY) {
5765 FPT_scxferc(p_port, MISC_CODE);
5766 FPT_scxferc(p_port, CLR_P_FLAG);
5767 i = 0; /*Not the last ID yet. */
5768 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005769
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005770 else if (i != NO_ID_AVAIL) {
5771 if (i < 8)
5772 FPT_scxferc(p_port, ID_0_7);
5773 else
5774 FPT_scxferc(p_port, ID_8_F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005775
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005776 scam_id = (i & (unsigned char)0x07);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005777
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005778 for (k = 1; k < 0x08; k <<= 1)
5779 if (!(k & i))
5780 scam_id += 0x08; /*Count number of zeros in DB0-3. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005781
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005782 FPT_scxferc(p_port, scam_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005783
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005784 i = 0; /*Not the last ID yet. */
5785 }
5786 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005787
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005788 else {
5789 i = 1;
5790 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005791
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005792 } /*End while */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005793
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005794 FPT_scxferc(p_port, SYNC_PTRN);
5795 FPT_scxferc(p_port, CFG_CMPLT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005796}
5797
Linus Torvalds1da177e2005-04-16 15:20:36 -07005798/*---------------------------------------------------------------------
5799 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005800 * Function: FPT_scsel
Linus Torvalds1da177e2005-04-16 15:20:36 -07005801 *
5802 * Description: Select all the SCAM devices.
5803 *
5804 *---------------------------------------------------------------------*/
5805
Khalid Aziz391e2f22013-05-16 19:44:14 -06005806static void FPT_scsel(u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005807{
5808
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005809 WR_HARPOON(p_port + hp_scsisig, SCSI_SEL);
5810 FPT_scwiros(p_port, SCSI_MSG);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005811
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005812 WR_HARPOON(p_port + hp_scsisig, (SCSI_SEL | SCSI_BSY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005813
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005814 WR_HARPOON(p_port + hp_scsisig,
5815 (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5816 WR_HARPOON(p_port + hp_scsidata_0,
5817 (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) |
5818 (unsigned char)(BIT(7) + BIT(6))));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005819
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005820 WR_HARPOON(p_port + hp_scsisig, (SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5821 FPT_scwiros(p_port, SCSI_SEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005822
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005823 WR_HARPOON(p_port + hp_scsidata_0,
5824 (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) &
5825 ~(unsigned char)BIT(6)));
5826 FPT_scwirod(p_port, BIT(6));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005827
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005828 WR_HARPOON(p_port + hp_scsisig,
5829 (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005830}
5831
Linus Torvalds1da177e2005-04-16 15:20:36 -07005832/*---------------------------------------------------------------------
5833 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005834 * Function: FPT_scxferc
Linus Torvalds1da177e2005-04-16 15:20:36 -07005835 *
5836 * Description: Handshake the p_data (DB4-0) across the bus.
5837 *
5838 *---------------------------------------------------------------------*/
5839
Khalid Aziz391e2f22013-05-16 19:44:14 -06005840static unsigned char FPT_scxferc(u32 p_port, unsigned char p_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005841{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005842 unsigned char curr_data, ret_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005843
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005844 curr_data = p_data | BIT(7) | BIT(5); /*Start with DB7 & DB5 asserted. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005845
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005846 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005847
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005848 curr_data &= ~BIT(7);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005849
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005850 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005851
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005852 FPT_scwirod(p_port, BIT(7)); /*Wait for DB7 to be released. */
5853 while (!(RD_HARPOON(p_port + hp_scsidata_0) & BIT(5))) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005854
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005855 ret_data = (RD_HARPOON(p_port + hp_scsidata_0) & (unsigned char)0x1F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005856
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005857 curr_data |= BIT(6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005858
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005859 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005860
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005861 curr_data &= ~BIT(5);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005862
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005863 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005864
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005865 FPT_scwirod(p_port, BIT(5)); /*Wait for DB5 to be released. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005866
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005867 curr_data &= ~(BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0)); /*Release data bits */
5868 curr_data |= BIT(7);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005869
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005870 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005871
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005872 curr_data &= ~BIT(6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005873
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005874 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005875
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005876 FPT_scwirod(p_port, BIT(6)); /*Wait for DB6 to be released. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005877
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005878 return ret_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005879}
5880
Linus Torvalds1da177e2005-04-16 15:20:36 -07005881/*---------------------------------------------------------------------
5882 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005883 * Function: FPT_scsendi
Linus Torvalds1da177e2005-04-16 15:20:36 -07005884 *
5885 * Description: Transfer our Identification string to determine if we
5886 * will be the dominant master.
5887 *
5888 *---------------------------------------------------------------------*/
5889
Khalid Aziz391e2f22013-05-16 19:44:14 -06005890static unsigned char FPT_scsendi(u32 p_port, unsigned char p_id_string[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07005891{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005892 unsigned char ret_data, byte_cnt, bit_cnt, defer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005893
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005894 defer = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005895
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005896 for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005897
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005898 for (bit_cnt = 0x80; bit_cnt != 0; bit_cnt >>= 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005899
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005900 if (defer)
5901 ret_data = FPT_scxferc(p_port, 00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005902
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005903 else if (p_id_string[byte_cnt] & bit_cnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005904
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005905 ret_data = FPT_scxferc(p_port, 02);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005906
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005907 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005908
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005909 ret_data = FPT_scxferc(p_port, 01);
5910 if (ret_data & 02)
5911 defer = 1;
5912 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005913
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005914 if ((ret_data & 0x1C) == 0x10)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005915 return 0x00; /*End of isolation stage, we won! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005916
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005917 if (ret_data & 0x1C)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005918 return 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005919
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005920 if ((defer) && (!(ret_data & 0x1F)))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005921 return 0x01; /*End of isolation stage, we lost. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005922
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005923 } /*bit loop */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005924
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005925 } /*byte loop */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005926
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005927 if (defer)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005928 return 0x01; /*We lost */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005929 else
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005930 return 0; /*We WON! Yeeessss! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005931}
5932
Linus Torvalds1da177e2005-04-16 15:20:36 -07005933/*---------------------------------------------------------------------
5934 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005935 * Function: FPT_sciso
Linus Torvalds1da177e2005-04-16 15:20:36 -07005936 *
5937 * Description: Transfer the Identification string.
5938 *
5939 *---------------------------------------------------------------------*/
5940
Khalid Aziz391e2f22013-05-16 19:44:14 -06005941static unsigned char FPT_sciso(u32 p_port, unsigned char p_id_string[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07005942{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005943 unsigned char ret_data, the_data, byte_cnt, bit_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005944
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005945 the_data = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005946
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005947 for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005948
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005949 for (bit_cnt = 0; bit_cnt < 8; bit_cnt++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005950
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005951 ret_data = FPT_scxferc(p_port, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005952
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005953 if (ret_data & 0xFC)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005954 return 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005955
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005956 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005957
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005958 the_data <<= 1;
5959 if (ret_data & BIT(1)) {
5960 the_data |= 1;
5961 }
5962 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005963
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005964 if ((ret_data & 0x1F) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005965/*
5966 if(bit_cnt != 0 || bit_cnt != 8)
5967 {
5968 byte_cnt = 0;
5969 bit_cnt = 0;
James Bottomley 47b5d692005-04-24 02:38:05 -05005970 FPT_scxferc(p_port, SYNC_PTRN);
5971 FPT_scxferc(p_port, ASSIGN_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005972 continue;
5973 }
5974*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005975 if (byte_cnt)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005976 return 0x00;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005977 else
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005978 return 0xFF;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005979 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005980
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005981 } /*bit loop */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005982
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005983 p_id_string[byte_cnt] = the_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005984
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005985 } /*byte loop */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005986
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005987 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005988}
5989
Linus Torvalds1da177e2005-04-16 15:20:36 -07005990/*---------------------------------------------------------------------
5991 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005992 * Function: FPT_scwirod
Linus Torvalds1da177e2005-04-16 15:20:36 -07005993 *
5994 * Description: Sample the SCSI data bus making sure the signal has been
5995 * deasserted for the correct number of consecutive samples.
5996 *
5997 *---------------------------------------------------------------------*/
5998
Khalid Aziz391e2f22013-05-16 19:44:14 -06005999static void FPT_scwirod(u32 p_port, unsigned char p_data_bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006000{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006001 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006002
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006003 i = 0;
6004 while (i < MAX_SCSI_TAR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006005
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006006 if (RD_HARPOON(p_port + hp_scsidata_0) & p_data_bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006007
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006008 i = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006009
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006010 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07006011
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006012 i++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006013
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006014 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006015}
6016
Linus Torvalds1da177e2005-04-16 15:20:36 -07006017/*---------------------------------------------------------------------
6018 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006019 * Function: FPT_scwiros
Linus Torvalds1da177e2005-04-16 15:20:36 -07006020 *
6021 * Description: Sample the SCSI Signal lines making sure the signal has been
6022 * deasserted for the correct number of consecutive samples.
6023 *
6024 *---------------------------------------------------------------------*/
6025
Khalid Aziz391e2f22013-05-16 19:44:14 -06006026static void FPT_scwiros(u32 p_port, unsigned char p_data_bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006027{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006028 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006029
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006030 i = 0;
6031 while (i < MAX_SCSI_TAR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006032
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006033 if (RD_HARPOON(p_port + hp_scsisig) & p_data_bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006034
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006035 i = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006036
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006037 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07006038
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006039 i++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006040
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006041 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006042}
6043
Linus Torvalds1da177e2005-04-16 15:20:36 -07006044/*---------------------------------------------------------------------
6045 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006046 * Function: FPT_scvalq
Linus Torvalds1da177e2005-04-16 15:20:36 -07006047 *
6048 * Description: Make sure we received a valid data byte.
6049 *
6050 *---------------------------------------------------------------------*/
6051
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08006052static unsigned char FPT_scvalq(unsigned char p_quintet)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006053{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006054 unsigned char count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006055
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006056 for (count = 1; count < 0x08; count <<= 1) {
6057 if (!(p_quintet & count))
6058 p_quintet -= 0x80;
6059 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006060
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006061 if (p_quintet & 0x18)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006062 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006063
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006064 else
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006065 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006066}
6067
Linus Torvalds1da177e2005-04-16 15:20:36 -07006068/*---------------------------------------------------------------------
6069 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006070 * Function: FPT_scsell
Linus Torvalds1da177e2005-04-16 15:20:36 -07006071 *
6072 * Description: Select the specified device ID using a selection timeout
6073 * less than 4ms. If somebody responds then it is a legacy
6074 * drive and this ID must be marked as such.
6075 *
6076 *---------------------------------------------------------------------*/
6077
Khalid Aziz391e2f22013-05-16 19:44:14 -06006078static unsigned char FPT_scsell(u32 p_port, unsigned char targ_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006079{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006080 unsigned long i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006081
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006082 WR_HARPOON(p_port + hp_page_ctrl,
6083 (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006084
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006085 ARAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006086
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006087 WR_HARPOON(p_port + hp_addstat,
6088 (RD_HARPOON(p_port + hp_addstat) | SCAM_TIMER));
6089 WR_HARPOON(p_port + hp_seltimeout, TO_4ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006090
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006091 for (i = p_port + CMD_STRT; i < p_port + CMD_STRT + 12; i += 2) {
6092 WRW_HARPOON(i, (MPM_OP + ACOMMAND));
6093 }
6094 WRW_HARPOON(i, (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006095
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006096 WRW_HARPOON((p_port + hp_intstat),
6097 (RESET | TIMEOUT | SEL | BUS_FREE | AUTO_INT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006098
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006099 WR_HARPOON(p_port + hp_select_id, targ_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006100
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006101 WR_HARPOON(p_port + hp_portctrl_0, SCSI_PORT);
6102 WR_HARPOON(p_port + hp_autostart_3, (SELECT | CMD_ONLY_STRT));
6103 WR_HARPOON(p_port + hp_scsictrl_0, (SEL_TAR | ENA_RESEL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006104
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006105 while (!(RDW_HARPOON((p_port + hp_intstat)) &
6106 (RESET | PROG_HLT | TIMEOUT | AUTO_INT))) {
6107 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006108
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006109 if (RDW_HARPOON((p_port + hp_intstat)) & RESET)
6110 FPT_Wait(p_port, TO_250ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006111
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006112 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006113
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006114 WR_HARPOON(p_port + hp_addstat,
6115 (RD_HARPOON(p_port + hp_addstat) & ~SCAM_TIMER));
6116 WR_HARPOON(p_port + hp_seltimeout, TO_290ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006117
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006118 SGRAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006119
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006120 if (RDW_HARPOON((p_port + hp_intstat)) & (RESET | TIMEOUT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006121
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006122 WRW_HARPOON((p_port + hp_intstat),
6123 (RESET | TIMEOUT | SEL | BUS_FREE | PHASE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006124
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006125 WR_HARPOON(p_port + hp_page_ctrl,
6126 (RD_HARPOON(p_port + hp_page_ctrl) &
6127 ~G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006128
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006129 return 0; /*No legacy device */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006130 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006131
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006132 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006133
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006134 while (!(RDW_HARPOON((p_port + hp_intstat)) & BUS_FREE)) {
6135 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ) {
6136 WR_HARPOON(p_port + hp_scsisig,
6137 (SCSI_ACK + S_ILL_PH));
6138 ACCEPT_MSG(p_port);
6139 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006140 }
6141
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006142 WRW_HARPOON((p_port + hp_intstat), CLR_ALL_INT_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006143
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006144 WR_HARPOON(p_port + hp_page_ctrl,
6145 (RD_HARPOON(p_port + hp_page_ctrl) &
6146 ~G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006147
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006148 return 1; /*Found one of them oldies! */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006149 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006150}
6151
Linus Torvalds1da177e2005-04-16 15:20:36 -07006152/*---------------------------------------------------------------------
6153 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006154 * Function: FPT_scwtsel
Linus Torvalds1da177e2005-04-16 15:20:36 -07006155 *
6156 * Description: Wait to be selected by another SCAM initiator.
6157 *
6158 *---------------------------------------------------------------------*/
6159
Khalid Aziz391e2f22013-05-16 19:44:14 -06006160static void FPT_scwtsel(u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006161{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006162 while (!(RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL)) {
6163 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006164}
6165
Linus Torvalds1da177e2005-04-16 15:20:36 -07006166/*---------------------------------------------------------------------
6167 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006168 * Function: FPT_inisci
Linus Torvalds1da177e2005-04-16 15:20:36 -07006169 *
6170 * Description: Setup the data Structure with the info from the EEPROM.
6171 *
6172 *---------------------------------------------------------------------*/
6173
Khalid Aziz391e2f22013-05-16 19:44:14 -06006174static void FPT_inisci(unsigned char p_card, u32 p_port, unsigned char p_our_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006175{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006176 unsigned char i, k, max_id;
6177 unsigned short ee_data;
6178 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006179
James Bottomley 47b5d692005-04-24 02:38:05 -05006180 pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006181
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006182 if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6183 max_id = 0x08;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006184
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006185 else
6186 max_id = 0x10;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006187
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006188 if (pCurrNvRam) {
6189 for (i = 0; i < max_id; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006190
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006191 for (k = 0; k < 4; k++)
6192 FPT_scamInfo[i].id_string[k] =
6193 pCurrNvRam->niScamTbl[i][k];
6194 for (k = 4; k < ID_STRING_LENGTH; k++)
6195 FPT_scamInfo[i].id_string[k] =
6196 (unsigned char)0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006197
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006198 if (FPT_scamInfo[i].id_string[0] == 0x00)
6199 FPT_scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */
6200 else
6201 FPT_scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006202
6203 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006204 } else {
6205 for (i = 0; i < max_id; i++) {
6206 for (k = 0; k < ID_STRING_LENGTH; k += 2) {
6207 ee_data =
6208 FPT_utilEERead(p_port,
6209 (unsigned
6210 short)((EE_SCAMBASE / 2) +
6211 (unsigned short)(i *
6212 ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
6213 FPT_scamInfo[i].id_string[k] =
6214 (unsigned char)ee_data;
6215 ee_data >>= 8;
6216 FPT_scamInfo[i].id_string[k + 1] =
6217 (unsigned char)ee_data;
6218 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006219
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006220 if ((FPT_scamInfo[i].id_string[0] == 0x00) ||
6221 (FPT_scamInfo[i].id_string[0] == 0xFF))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006222
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006223 FPT_scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006224
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006225 else
6226 FPT_scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006227
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006228 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006229 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006230 for (k = 0; k < ID_STRING_LENGTH; k++)
James Bottomley 47b5d692005-04-24 02:38:05 -05006231 FPT_scamInfo[p_our_id].id_string[k] = FPT_scamHAString[k];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006232
6233}
6234
6235/*---------------------------------------------------------------------
6236 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006237 * Function: FPT_scmachid
Linus Torvalds1da177e2005-04-16 15:20:36 -07006238 *
6239 * Description: Match the Device ID string with our values stored in
6240 * the EEPROM.
6241 *
6242 *---------------------------------------------------------------------*/
6243
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006244static unsigned char FPT_scmachid(unsigned char p_card,
6245 unsigned char p_id_string[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07006246{
6247
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006248 unsigned char i, k, match;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006249
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006250 for (i = 0; i < MAX_SCSI_TAR; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006251
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006252 match = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006253
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006254 for (k = 0; k < ID_STRING_LENGTH; k++) {
6255 if (p_id_string[k] != FPT_scamInfo[i].id_string[k])
6256 match = 0;
6257 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006258
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006259 if (match) {
6260 FPT_scamInfo[i].state = ID_ASSIGNED;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006261 return i;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006262 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006263
Linus Torvalds1da177e2005-04-16 15:20:36 -07006264 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006265
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006266 if (p_id_string[0] & BIT(5))
6267 i = 8;
6268 else
6269 i = MAX_SCSI_TAR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006270
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006271 if (((p_id_string[0] & 0x06) == 0x02)
6272 || ((p_id_string[0] & 0x06) == 0x04))
6273 match = p_id_string[1] & (unsigned char)0x1F;
6274 else
6275 match = 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006276
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006277 while (i > 0) {
6278 i--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006279
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006280 if (FPT_scamInfo[match].state == ID_UNUSED) {
6281 for (k = 0; k < ID_STRING_LENGTH; k++) {
6282 FPT_scamInfo[match].id_string[k] =
6283 p_id_string[k];
6284 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006285
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006286 FPT_scamInfo[match].state = ID_ASSIGNED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006287
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006288 if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
6289 FPT_BL_Card[p_card].globalFlags |=
6290 F_UPDATE_EEPROM;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006291 return match;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006292
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006293 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006294
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006295 match--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006296
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006297 if (match == 0xFF) {
6298 if (p_id_string[0] & BIT(5))
6299 match = 7;
6300 else
6301 match = MAX_SCSI_TAR - 1;
6302 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006303 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006304
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006305 if (p_id_string[0] & BIT(7)) {
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006306 return CLR_PRIORITY;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006307 }
6308
6309 if (p_id_string[0] & BIT(5))
6310 i = 8;
6311 else
6312 i = MAX_SCSI_TAR;
6313
6314 if (((p_id_string[0] & 0x06) == 0x02)
6315 || ((p_id_string[0] & 0x06) == 0x04))
6316 match = p_id_string[1] & (unsigned char)0x1F;
6317 else
6318 match = 7;
6319
6320 while (i > 0) {
6321
6322 i--;
6323
6324 if (FPT_scamInfo[match].state == ID_UNASSIGNED) {
6325 for (k = 0; k < ID_STRING_LENGTH; k++) {
6326 FPT_scamInfo[match].id_string[k] =
6327 p_id_string[k];
6328 }
6329
6330 FPT_scamInfo[match].id_string[0] |= BIT(7);
6331 FPT_scamInfo[match].state = ID_ASSIGNED;
6332 if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
6333 FPT_BL_Card[p_card].globalFlags |=
6334 F_UPDATE_EEPROM;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006335 return match;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006336
6337 }
6338
6339 match--;
6340
6341 if (match == 0xFF) {
6342 if (p_id_string[0] & BIT(5))
6343 match = 7;
6344 else
6345 match = MAX_SCSI_TAR - 1;
6346 }
6347 }
6348
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006349 return NO_ID_AVAIL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006350}
6351
Linus Torvalds1da177e2005-04-16 15:20:36 -07006352/*---------------------------------------------------------------------
6353 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006354 * Function: FPT_scsavdi
Linus Torvalds1da177e2005-04-16 15:20:36 -07006355 *
6356 * Description: Save off the device SCAM ID strings.
6357 *
6358 *---------------------------------------------------------------------*/
6359
Khalid Aziz391e2f22013-05-16 19:44:14 -06006360static void FPT_scsavdi(unsigned char p_card, u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006361{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006362 unsigned char i, k, max_id;
6363 unsigned short ee_data, sum_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006364
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006365 sum_data = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006366
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006367 for (i = 1; i < EE_SCAMBASE / 2; i++) {
6368 sum_data += FPT_utilEERead(p_port, i);
6369 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006370
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006371 FPT_utilEEWriteOnOff(p_port, 1); /* Enable write access to the EEPROM */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006372
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006373 if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6374 max_id = 0x08;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006375
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006376 else
6377 max_id = 0x10;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006378
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006379 for (i = 0; i < max_id; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006380
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006381 for (k = 0; k < ID_STRING_LENGTH; k += 2) {
6382 ee_data = FPT_scamInfo[i].id_string[k + 1];
6383 ee_data <<= 8;
6384 ee_data |= FPT_scamInfo[i].id_string[k];
6385 sum_data += ee_data;
6386 FPT_utilEEWrite(p_port, ee_data,
6387 (unsigned short)((EE_SCAMBASE / 2) +
6388 (unsigned short)(i *
6389 ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
6390 }
6391 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006392
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006393 FPT_utilEEWrite(p_port, sum_data, EEPROM_CHECK_SUM / 2);
6394 FPT_utilEEWriteOnOff(p_port, 0); /* Turn off write access */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006395}
Linus Torvalds1da177e2005-04-16 15:20:36 -07006396
6397/*---------------------------------------------------------------------
6398 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006399 * Function: FPT_XbowInit
Linus Torvalds1da177e2005-04-16 15:20:36 -07006400 *
6401 * Description: Setup the Xbow for normal operation.
6402 *
6403 *---------------------------------------------------------------------*/
6404
Khalid Aziz391e2f22013-05-16 19:44:14 -06006405static void FPT_XbowInit(u32 port, unsigned char ScamFlg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006406{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006407 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006408
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006409 i = RD_HARPOON(port + hp_page_ctrl);
6410 WR_HARPOON(port + hp_page_ctrl, (unsigned char)(i | G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006411
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006412 WR_HARPOON(port + hp_scsireset, 0x00);
6413 WR_HARPOON(port + hp_portctrl_1, HOST_MODE8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006414
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006415 WR_HARPOON(port + hp_scsireset, (DMA_RESET | HPSCSI_RESET | PROG_RESET |
6416 FIFO_CLR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006417
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006418 WR_HARPOON(port + hp_scsireset, SCSI_INI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006419
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006420 WR_HARPOON(port + hp_clkctrl_0, CLKCTRL_DEFAULT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006421
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006422 WR_HARPOON(port + hp_scsisig, 0x00); /* Clear any signals we might */
6423 WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006424
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006425 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006426
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006427 FPT_default_intena = RESET | RSEL | PROG_HLT | TIMEOUT |
6428 BUS_FREE | XFER_CNT_0 | AUTO_INT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006429
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006430 if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2))
James Bottomley 47b5d692005-04-24 02:38:05 -05006431 FPT_default_intena |= SCAM_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006432
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006433 WRW_HARPOON((port + hp_intena), FPT_default_intena);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006434
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006435 WR_HARPOON(port + hp_seltimeout, TO_290ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006436
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006437 /* Turn on SCSI_MODE8 for narrow cards to fix the
6438 strapping issue with the DUAL CHANNEL card */
6439 if (RD_HARPOON(port + hp_page_ctrl) & NARROW_SCSI_CARD)
6440 WR_HARPOON(port + hp_addstat, SCSI_MODE8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006441
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006442 WR_HARPOON(port + hp_page_ctrl, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006443
6444}
6445
Linus Torvalds1da177e2005-04-16 15:20:36 -07006446/*---------------------------------------------------------------------
6447 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006448 * Function: FPT_BusMasterInit
Linus Torvalds1da177e2005-04-16 15:20:36 -07006449 *
6450 * Description: Initialize the BusMaster for normal operations.
6451 *
6452 *---------------------------------------------------------------------*/
6453
Khalid Aziz391e2f22013-05-16 19:44:14 -06006454static void FPT_BusMasterInit(u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006455{
6456
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006457 WR_HARPOON(p_port + hp_sys_ctrl, DRVR_RST);
6458 WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006459
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006460 WR_HARPOON(p_port + hp_host_blk_cnt, XFER_BLK64);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006461
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006462 WR_HARPOON(p_port + hp_bm_ctrl, (BMCTRL_DEFAULT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006463
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006464 WR_HARPOON(p_port + hp_ee_ctrl, (SCSI_TERM_ENA_H));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006465
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006466 RD_HARPOON(p_port + hp_int_status); /*Clear interrupts. */
6467 WR_HARPOON(p_port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
6468 WR_HARPOON(p_port + hp_page_ctrl, (RD_HARPOON(p_port + hp_page_ctrl) &
6469 ~SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006470}
6471
Linus Torvalds1da177e2005-04-16 15:20:36 -07006472/*---------------------------------------------------------------------
6473 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006474 * Function: FPT_DiagEEPROM
Linus Torvalds1da177e2005-04-16 15:20:36 -07006475 *
6476 * Description: Verfiy checksum and 'Key' and initialize the EEPROM if
6477 * necessary.
6478 *
6479 *---------------------------------------------------------------------*/
6480
Khalid Aziz391e2f22013-05-16 19:44:14 -06006481static void FPT_DiagEEPROM(u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006482{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006483 unsigned short index, temp, max_wd_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006484
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006485 if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6486 max_wd_cnt = EEPROM_WD_CNT;
6487 else
6488 max_wd_cnt = EEPROM_WD_CNT * 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006489
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006490 temp = FPT_utilEERead(p_port, FW_SIGNATURE / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006491
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006492 if (temp == 0x4641) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006493
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006494 for (index = 2; index < max_wd_cnt; index++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006495
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006496 temp += FPT_utilEERead(p_port, index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006497
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006498 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006499
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006500 if (temp == FPT_utilEERead(p_port, EEPROM_CHECK_SUM / 2)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006501
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006502 return; /*EEPROM is Okay so return now! */
6503 }
6504 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006505
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006506 FPT_utilEEWriteOnOff(p_port, (unsigned char)1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006507
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006508 for (index = 0; index < max_wd_cnt; index++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006509
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006510 FPT_utilEEWrite(p_port, 0x0000, index);
6511 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006512
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006513 temp = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006514
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006515 FPT_utilEEWrite(p_port, 0x4641, FW_SIGNATURE / 2);
6516 temp += 0x4641;
6517 FPT_utilEEWrite(p_port, 0x3920, MODEL_NUMB_0 / 2);
6518 temp += 0x3920;
6519 FPT_utilEEWrite(p_port, 0x3033, MODEL_NUMB_2 / 2);
6520 temp += 0x3033;
6521 FPT_utilEEWrite(p_port, 0x2020, MODEL_NUMB_4 / 2);
6522 temp += 0x2020;
6523 FPT_utilEEWrite(p_port, 0x70D3, SYSTEM_CONFIG / 2);
6524 temp += 0x70D3;
6525 FPT_utilEEWrite(p_port, 0x0010, BIOS_CONFIG / 2);
6526 temp += 0x0010;
6527 FPT_utilEEWrite(p_port, 0x0003, SCAM_CONFIG / 2);
6528 temp += 0x0003;
6529 FPT_utilEEWrite(p_port, 0x0007, ADAPTER_SCSI_ID / 2);
6530 temp += 0x0007;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006531
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006532 FPT_utilEEWrite(p_port, 0x0000, IGNORE_B_SCAN / 2);
6533 temp += 0x0000;
6534 FPT_utilEEWrite(p_port, 0x0000, SEND_START_ENA / 2);
6535 temp += 0x0000;
6536 FPT_utilEEWrite(p_port, 0x0000, DEVICE_ENABLE / 2);
6537 temp += 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006538
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006539 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL01 / 2);
6540 temp += 0x4242;
6541 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL23 / 2);
6542 temp += 0x4242;
6543 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL45 / 2);
6544 temp += 0x4242;
6545 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL67 / 2);
6546 temp += 0x4242;
6547 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL89 / 2);
6548 temp += 0x4242;
6549 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLab / 2);
6550 temp += 0x4242;
6551 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLcd / 2);
6552 temp += 0x4242;
6553 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLef / 2);
6554 temp += 0x4242;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006555
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006556 FPT_utilEEWrite(p_port, 0x6C46, 64 / 2); /*PRODUCT ID */
6557 temp += 0x6C46;
6558 FPT_utilEEWrite(p_port, 0x7361, 66 / 2); /* FlashPoint LT */
6559 temp += 0x7361;
6560 FPT_utilEEWrite(p_port, 0x5068, 68 / 2);
6561 temp += 0x5068;
6562 FPT_utilEEWrite(p_port, 0x696F, 70 / 2);
6563 temp += 0x696F;
6564 FPT_utilEEWrite(p_port, 0x746E, 72 / 2);
6565 temp += 0x746E;
6566 FPT_utilEEWrite(p_port, 0x4C20, 74 / 2);
6567 temp += 0x4C20;
6568 FPT_utilEEWrite(p_port, 0x2054, 76 / 2);
6569 temp += 0x2054;
6570 FPT_utilEEWrite(p_port, 0x2020, 78 / 2);
6571 temp += 0x2020;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006572
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006573 index = ((EE_SCAMBASE / 2) + (7 * 16));
6574 FPT_utilEEWrite(p_port, (0x0700 + TYPE_CODE0), index);
6575 temp += (0x0700 + TYPE_CODE0);
6576 index++;
6577 FPT_utilEEWrite(p_port, 0x5542, index); /*Vendor ID code */
6578 temp += 0x5542; /* BUSLOGIC */
6579 index++;
6580 FPT_utilEEWrite(p_port, 0x4C53, index);
6581 temp += 0x4C53;
6582 index++;
6583 FPT_utilEEWrite(p_port, 0x474F, index);
6584 temp += 0x474F;
6585 index++;
6586 FPT_utilEEWrite(p_port, 0x4349, index);
6587 temp += 0x4349;
6588 index++;
6589 FPT_utilEEWrite(p_port, 0x5442, index); /*Vendor unique code */
6590 temp += 0x5442; /* BT- 930 */
6591 index++;
6592 FPT_utilEEWrite(p_port, 0x202D, index);
6593 temp += 0x202D;
6594 index++;
6595 FPT_utilEEWrite(p_port, 0x3339, index);
6596 temp += 0x3339;
6597 index++; /*Serial # */
6598 FPT_utilEEWrite(p_port, 0x2030, index); /* 01234567 */
6599 temp += 0x2030;
6600 index++;
6601 FPT_utilEEWrite(p_port, 0x5453, index);
6602 temp += 0x5453;
6603 index++;
6604 FPT_utilEEWrite(p_port, 0x5645, index);
6605 temp += 0x5645;
6606 index++;
6607 FPT_utilEEWrite(p_port, 0x2045, index);
6608 temp += 0x2045;
6609 index++;
6610 FPT_utilEEWrite(p_port, 0x202F, index);
6611 temp += 0x202F;
6612 index++;
6613 FPT_utilEEWrite(p_port, 0x4F4A, index);
6614 temp += 0x4F4A;
6615 index++;
6616 FPT_utilEEWrite(p_port, 0x204E, index);
6617 temp += 0x204E;
6618 index++;
6619 FPT_utilEEWrite(p_port, 0x3539, index);
6620 temp += 0x3539;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006621
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006622 FPT_utilEEWrite(p_port, temp, EEPROM_CHECK_SUM / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006623
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006624 FPT_utilEEWriteOnOff(p_port, (unsigned char)0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006625
6626}
6627
Linus Torvalds1da177e2005-04-16 15:20:36 -07006628/*---------------------------------------------------------------------
6629 *
6630 * Function: Queue Search Select
6631 *
6632 * Description: Try to find a new command to execute.
6633 *
6634 *---------------------------------------------------------------------*/
6635
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006636static void FPT_queueSearchSelect(struct sccb_card *pCurrCard,
6637 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006638{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006639 unsigned char scan_ptr, lun;
6640 struct sccb_mgr_tar_info *currTar_Info;
6641 struct sccb *pOldSccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006642
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006643 scan_ptr = pCurrCard->scanIndex;
6644 do {
James Bottomley 47b5d692005-04-24 02:38:05 -05006645 currTar_Info = &FPT_sccbMgrTbl[p_card][scan_ptr];
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006646 if ((pCurrCard->globalFlags & F_CONLUN_IO) &&
6647 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
6648 TAG_Q_TRYING)) {
6649 if (currTar_Info->TarSelQ_Cnt != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006650
6651 scan_ptr++;
6652 if (scan_ptr == MAX_SCSI_TAR)
6653 scan_ptr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006654
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006655 for (lun = 0; lun < MAX_LUN; lun++) {
6656 if (currTar_Info->TarLUNBusy[lun] == 0) {
6657
6658 pCurrCard->currentSCCB =
6659 currTar_Info->TarSelQ_Head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006660 pOldSccb = NULL;
6661
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006662 while ((pCurrCard->
6663 currentSCCB != NULL)
6664 && (lun !=
6665 pCurrCard->
6666 currentSCCB->Lun)) {
6667 pOldSccb =
6668 pCurrCard->
6669 currentSCCB;
6670 pCurrCard->currentSCCB =
6671 (struct sccb
6672 *)(pCurrCard->
6673 currentSCCB)->
6674 Sccb_forwardlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006675 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006676 if (pCurrCard->currentSCCB ==
6677 NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006678 continue;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006679 if (pOldSccb != NULL) {
6680 pOldSccb->
6681 Sccb_forwardlink =
6682 (struct sccb
6683 *)(pCurrCard->
6684 currentSCCB)->
6685 Sccb_forwardlink;
6686 pOldSccb->
6687 Sccb_backlink =
6688 (struct sccb
6689 *)(pCurrCard->
6690 currentSCCB)->
6691 Sccb_backlink;
6692 currTar_Info->
6693 TarSelQ_Cnt--;
6694 } else {
6695 currTar_Info->
6696 TarSelQ_Head =
6697 (struct sccb
6698 *)(pCurrCard->
6699 currentSCCB)->
6700 Sccb_forwardlink;
6701
6702 if (currTar_Info->
6703 TarSelQ_Head ==
6704 NULL) {
6705 currTar_Info->
6706 TarSelQ_Tail
6707 = NULL;
6708 currTar_Info->
6709 TarSelQ_Cnt
6710 = 0;
6711 } else {
6712 currTar_Info->
6713 TarSelQ_Cnt--;
6714 currTar_Info->
6715 TarSelQ_Head->
6716 Sccb_backlink
6717 =
6718 (struct sccb
6719 *)NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006720 }
6721 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006722 pCurrCard->scanIndex = scan_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006723
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006724 pCurrCard->globalFlags |=
6725 F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006726
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006727 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006728 }
6729 }
6730 }
6731
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006732 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006733 scan_ptr++;
6734 if (scan_ptr == MAX_SCSI_TAR) {
6735 scan_ptr = 0;
6736 }
6737 }
6738
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006739 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006740 if ((currTar_Info->TarSelQ_Cnt != 0) &&
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006741 (currTar_Info->TarLUNBusy[0] == 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006742
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006743 pCurrCard->currentSCCB =
6744 currTar_Info->TarSelQ_Head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006745
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006746 currTar_Info->TarSelQ_Head =
6747 (struct sccb *)(pCurrCard->currentSCCB)->
6748 Sccb_forwardlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006749
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006750 if (currTar_Info->TarSelQ_Head == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006751 currTar_Info->TarSelQ_Tail = NULL;
6752 currTar_Info->TarSelQ_Cnt = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006753 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006754 currTar_Info->TarSelQ_Cnt--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006755 currTar_Info->TarSelQ_Head->
6756 Sccb_backlink = (struct sccb *)NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006757 }
6758
6759 scan_ptr++;
6760 if (scan_ptr == MAX_SCSI_TAR)
6761 scan_ptr = 0;
6762
6763 pCurrCard->scanIndex = scan_ptr;
6764
6765 pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
6766
6767 break;
6768 }
6769
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006770 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006771 scan_ptr++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006772 if (scan_ptr == MAX_SCSI_TAR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006773 scan_ptr = 0;
6774 }
6775 }
6776 }
6777 } while (scan_ptr != pCurrCard->scanIndex);
6778}
6779
Linus Torvalds1da177e2005-04-16 15:20:36 -07006780/*---------------------------------------------------------------------
6781 *
6782 * Function: Queue Select Fail
6783 *
6784 * Description: Add the current SCCB to the head of the Queue.
6785 *
6786 *---------------------------------------------------------------------*/
6787
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006788static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
6789 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006790{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006791 unsigned char thisTarg;
6792 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006793
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006794 if (pCurrCard->currentSCCB != NULL) {
6795 thisTarg =
6796 (unsigned char)(((struct sccb *)(pCurrCard->currentSCCB))->
6797 TargID);
6798 currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006799
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006800 pCurrCard->currentSCCB->Sccb_backlink = (struct sccb *)NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006801
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006802 pCurrCard->currentSCCB->Sccb_forwardlink =
6803 currTar_Info->TarSelQ_Head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006804
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006805 if (currTar_Info->TarSelQ_Cnt == 0) {
6806 currTar_Info->TarSelQ_Tail = pCurrCard->currentSCCB;
6807 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006808
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006809 else {
6810 currTar_Info->TarSelQ_Head->Sccb_backlink =
6811 pCurrCard->currentSCCB;
6812 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006813
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006814 currTar_Info->TarSelQ_Head = pCurrCard->currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006815
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006816 pCurrCard->currentSCCB = NULL;
6817 currTar_Info->TarSelQ_Cnt++;
6818 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006819}
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006820
Linus Torvalds1da177e2005-04-16 15:20:36 -07006821/*---------------------------------------------------------------------
6822 *
6823 * Function: Queue Command Complete
6824 *
6825 * Description: Call the callback function with the current SCCB.
6826 *
6827 *---------------------------------------------------------------------*/
6828
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006829static void FPT_queueCmdComplete(struct sccb_card *pCurrCard,
6830 struct sccb *p_sccb, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006831{
6832
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006833 unsigned char i, SCSIcmd;
6834 CALL_BK_FN callback;
6835 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006836
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006837 SCSIcmd = p_sccb->Cdb[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006838
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006839 if (!(p_sccb->Sccb_XferState & F_ALL_XFERRED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006840
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006841 if ((p_sccb->
6842 ControlByte & (SCCB_DATA_XFER_OUT | SCCB_DATA_XFER_IN))
6843 && (p_sccb->HostStatus == SCCB_COMPLETE)
Hannes Reineckea87afe22021-04-27 10:30:40 +02006844 && (p_sccb->TargetStatus != SAM_STAT_CHECK_CONDITION))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006845
Hannes Reineckea87afe22021-04-27 10:30:40 +02006846 if ((SCSIcmd == READ_6) ||
6847 (SCSIcmd == WRITE_6) ||
6848 (SCSIcmd == READ_10) ||
6849 (SCSIcmd == WRITE_10) ||
6850 (SCSIcmd == WRITE_VERIFY) ||
6851 (SCSIcmd == START_STOP) ||
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006852 (pCurrCard->globalFlags & F_NO_FILTER)
6853 )
6854 p_sccb->HostStatus = SCCB_DATA_UNDER_RUN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006855 }
6856
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006857 if (p_sccb->SccbStatus == SCCB_IN_PROCESS) {
6858 if (p_sccb->HostStatus || p_sccb->TargetStatus)
6859 p_sccb->SccbStatus = SCCB_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006860 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006861 p_sccb->SccbStatus = SCCB_SUCCESS;
6862 }
6863
6864 if (p_sccb->Sccb_XferState & F_AUTO_SENSE) {
6865
6866 p_sccb->CdbLength = p_sccb->Save_CdbLen;
6867 for (i = 0; i < 6; i++) {
6868 p_sccb->Cdb[i] = p_sccb->Save_Cdb[i];
6869 }
6870 }
6871
6872 if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) ||
6873 (p_sccb->OperationCode == RESIDUAL_COMMAND)) {
6874
6875 FPT_utilUpdateResidual(p_sccb);
6876 }
6877
6878 pCurrCard->cmdCounter--;
6879 if (!pCurrCard->cmdCounter) {
6880
6881 if (pCurrCard->globalFlags & F_GREEN_PC) {
6882 WR_HARPOON(pCurrCard->ioPort + hp_clkctrl_0,
6883 (PWR_DWN | CLKCTRL_DEFAULT));
6884 WR_HARPOON(pCurrCard->ioPort + hp_sys_ctrl, STOP_CLK);
6885 }
6886
6887 WR_HARPOON(pCurrCard->ioPort + hp_semaphore,
6888 (RD_HARPOON(pCurrCard->ioPort + hp_semaphore) &
6889 ~SCCB_MGR_ACTIVE));
6890
6891 }
6892
6893 if (pCurrCard->discQCount != 0) {
6894 currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
6895 if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
6896 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
6897 TAG_Q_TRYING))) {
6898 pCurrCard->discQCount--;
6899 pCurrCard->discQ_Tbl[currTar_Info->
6900 LunDiscQ_Idx[p_sccb->Lun]] = NULL;
6901 } else {
6902 if (p_sccb->Sccb_tag) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006903 pCurrCard->discQCount--;
6904 pCurrCard->discQ_Tbl[p_sccb->Sccb_tag] = NULL;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006905 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006906 pCurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006907 pCurrCard->discQ_Tbl[currTar_Info->
6908 LunDiscQ_Idx[0]] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006909 }
6910 }
6911
6912 }
6913
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006914 callback = (CALL_BK_FN) p_sccb->SccbCallback;
6915 callback(p_sccb);
6916 pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
6917 pCurrCard->currentSCCB = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006918}
Linus Torvalds1da177e2005-04-16 15:20:36 -07006919
Linus Torvalds1da177e2005-04-16 15:20:36 -07006920/*---------------------------------------------------------------------
6921 *
6922 * Function: Queue Disconnect
6923 *
6924 * Description: Add SCCB to our disconnect array.
6925 *
6926 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006927static void FPT_queueDisconnect(struct sccb *p_sccb, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006928{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006929 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006930
James Bottomley 47b5d692005-04-24 02:38:05 -05006931 currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006932
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006933 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
6934 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
6935 FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
6936 LunDiscQ_Idx[p_sccb->Lun]] =
6937 p_sccb;
6938 } else {
6939 if (p_sccb->Sccb_tag) {
6940 FPT_BL_Card[p_card].discQ_Tbl[p_sccb->Sccb_tag] =
6941 p_sccb;
6942 FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarLUNBusy[0] =
6943 0;
James Bottomley 47b5d692005-04-24 02:38:05 -05006944 FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarTagQ_Cnt++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006945 } else {
6946 FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
6947 LunDiscQ_Idx[0]] = p_sccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006948 }
6949 }
James Bottomley 47b5d692005-04-24 02:38:05 -05006950 FPT_BL_Card[p_card].currentSCCB = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006951}
6952
Linus Torvalds1da177e2005-04-16 15:20:36 -07006953/*---------------------------------------------------------------------
6954 *
6955 * Function: Queue Flush SCCB
6956 *
6957 * Description: Flush all SCCB's back to the host driver for this target.
6958 *
6959 *---------------------------------------------------------------------*/
6960
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006961static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006962{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006963 unsigned char qtag, thisTarg;
6964 struct sccb *currSCCB;
6965 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006966
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006967 currSCCB = FPT_BL_Card[p_card].currentSCCB;
6968 if (currSCCB != NULL) {
6969 thisTarg = (unsigned char)currSCCB->TargID;
6970 currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006971
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006972 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006973
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006974 if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
6975 (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
6976 thisTarg)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006977
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006978 FPT_BL_Card[p_card].discQ_Tbl[qtag]->
6979 HostStatus = (unsigned char)error_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006980
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006981 FPT_queueCmdComplete(&FPT_BL_Card[p_card],
6982 FPT_BL_Card[p_card].
6983 discQ_Tbl[qtag], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006984
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006985 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
6986 currTar_Info->TarTagQ_Cnt--;
6987
6988 }
6989 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006990 }
6991
6992}
6993
6994/*---------------------------------------------------------------------
6995 *
6996 * Function: Queue Flush Target SCCB
6997 *
6998 * Description: Flush all SCCB's back to the host driver for this target.
6999 *
7000 *---------------------------------------------------------------------*/
7001
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007002static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
7003 unsigned char error_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007004{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007005 unsigned char qtag;
7006 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007007
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007008 currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007009
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007010 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007011
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007012 if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
7013 (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007014
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007015 FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus =
7016 (unsigned char)error_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007017
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007018 FPT_queueCmdComplete(&FPT_BL_Card[p_card],
7019 FPT_BL_Card[p_card].
7020 discQ_Tbl[qtag], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007021
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007022 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
7023 currTar_Info->TarTagQ_Cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007024
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007025 }
7026 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007027
7028}
7029
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007030static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007031{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007032 struct sccb_mgr_tar_info *currTar_Info;
7033 currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007034
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007035 p_SCCB->Sccb_forwardlink = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007036
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007037 p_SCCB->Sccb_backlink = currTar_Info->TarSelQ_Tail;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007038
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007039 if (currTar_Info->TarSelQ_Cnt == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007040
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007041 currTar_Info->TarSelQ_Head = p_SCCB;
7042 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007043
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007044 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007045
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007046 currTar_Info->TarSelQ_Tail->Sccb_forwardlink = p_SCCB;
7047 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007048
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007049 currTar_Info->TarSelQ_Tail = p_SCCB;
7050 currTar_Info->TarSelQ_Cnt++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007051}
7052
Linus Torvalds1da177e2005-04-16 15:20:36 -07007053/*---------------------------------------------------------------------
7054 *
7055 * Function: Queue Find SCCB
7056 *
7057 * Description: Search the target select Queue for this SCCB, and
7058 * remove it if found.
7059 *
7060 *---------------------------------------------------------------------*/
7061
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007062static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB,
7063 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007064{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007065 struct sccb *q_ptr;
7066 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007067
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007068 currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007069
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007070 q_ptr = currTar_Info->TarSelQ_Head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007071
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007072 while (q_ptr != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007073
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007074 if (q_ptr == p_SCCB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007075
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007076 if (currTar_Info->TarSelQ_Head == q_ptr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007077
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007078 currTar_Info->TarSelQ_Head =
7079 q_ptr->Sccb_forwardlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007080 }
7081
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007082 if (currTar_Info->TarSelQ_Tail == q_ptr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007083
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007084 currTar_Info->TarSelQ_Tail =
7085 q_ptr->Sccb_backlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007086 }
7087
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007088 if (q_ptr->Sccb_forwardlink != NULL) {
7089 q_ptr->Sccb_forwardlink->Sccb_backlink =
7090 q_ptr->Sccb_backlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007091 }
7092
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007093 if (q_ptr->Sccb_backlink != NULL) {
7094 q_ptr->Sccb_backlink->Sccb_forwardlink =
7095 q_ptr->Sccb_forwardlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007096 }
7097
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007098 currTar_Info->TarSelQ_Cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007099
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007100 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007101 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007102
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007103 else {
7104 q_ptr = q_ptr->Sccb_forwardlink;
7105 }
7106 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007107
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007108 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007109
7110}
7111
Linus Torvalds1da177e2005-04-16 15:20:36 -07007112/*---------------------------------------------------------------------
7113 *
7114 * Function: Utility Update Residual Count
7115 *
7116 * Description: Update the XferCnt to the remaining byte count.
7117 * If we transferred all the data then just write zero.
7118 * If Non-SG transfer then report Total Cnt - Actual Transfer
7119 * Cnt. For SG transfers add the count fields of all
7120 * remaining SG elements, as well as any partial remaining
7121 * element.
7122 *
7123 *---------------------------------------------------------------------*/
7124
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007125static void FPT_utilUpdateResidual(struct sccb *p_SCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007126{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007127 unsigned long partial_cnt;
7128 unsigned int sg_index;
Khalid Aziz391e2f22013-05-16 19:44:14 -06007129 struct blogic_sg_seg *segp;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007130
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007131 if (p_SCCB->Sccb_XferState & F_ALL_XFERRED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007132
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007133 p_SCCB->DataLength = 0x0000;
7134 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007135
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007136 else if (p_SCCB->Sccb_XferState & F_SG_XFER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007137
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007138 partial_cnt = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007139
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007140 sg_index = p_SCCB->Sccb_sgseg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007141
Linus Torvalds1da177e2005-04-16 15:20:36 -07007142
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007143 if (p_SCCB->Sccb_SGoffset) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007144
7145 partial_cnt = p_SCCB->Sccb_SGoffset;
7146 sg_index++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007147 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007148
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007149 while (((unsigned long)sg_index *
7150 (unsigned long)SG_ELEMENT_SIZE) < p_SCCB->DataLength) {
Khalid Aziz391e2f22013-05-16 19:44:14 -06007151 segp = (struct blogic_sg_seg *)(p_SCCB->DataPointer) +
7152 (sg_index * 2);
7153 partial_cnt += segp->segbytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007154 sg_index++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007155 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007156
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007157 p_SCCB->DataLength = partial_cnt;
7158 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007159
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007160 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007161
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007162 p_SCCB->DataLength -= p_SCCB->Sccb_ATC;
7163 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007164}
7165
Linus Torvalds1da177e2005-04-16 15:20:36 -07007166/*---------------------------------------------------------------------
7167 *
7168 * Function: Wait 1 Second
7169 *
7170 * Description: Wait for 1 second.
7171 *
7172 *---------------------------------------------------------------------*/
7173
Khalid Aziz391e2f22013-05-16 19:44:14 -06007174static void FPT_Wait1Second(u32 p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007175{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007176 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007177
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007178 for (i = 0; i < 4; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007179
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007180 FPT_Wait(p_port, TO_250ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007181
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007182 if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
7183 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007184
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007185 if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
7186 break;
7187 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007188}
7189
Linus Torvalds1da177e2005-04-16 15:20:36 -07007190/*---------------------------------------------------------------------
7191 *
James Bottomley 47b5d692005-04-24 02:38:05 -05007192 * Function: FPT_Wait
Linus Torvalds1da177e2005-04-16 15:20:36 -07007193 *
7194 * Description: Wait the desired delay.
7195 *
7196 *---------------------------------------------------------------------*/
7197
Khalid Aziz391e2f22013-05-16 19:44:14 -06007198static void FPT_Wait(u32 p_port, unsigned char p_delay)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007199{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007200 unsigned char old_timer;
7201 unsigned char green_flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007202
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007203 old_timer = RD_HARPOON(p_port + hp_seltimeout);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007204
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007205 green_flag = RD_HARPOON(p_port + hp_clkctrl_0);
7206 WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007207
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007208 WR_HARPOON(p_port + hp_seltimeout, p_delay);
7209 WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
7210 WRW_HARPOON((p_port + hp_intena), (FPT_default_intena & ~TIMEOUT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007211
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007212 WR_HARPOON(p_port + hp_portctrl_0,
7213 (RD_HARPOON(p_port + hp_portctrl_0) | START_TO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007214
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007215 while (!(RDW_HARPOON((p_port + hp_intstat)) & TIMEOUT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007216
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007217 if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
7218 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007219
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007220 if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
7221 break;
7222 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007223
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007224 WR_HARPOON(p_port + hp_portctrl_0,
7225 (RD_HARPOON(p_port + hp_portctrl_0) & ~START_TO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007226
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007227 WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
7228 WRW_HARPOON((p_port + hp_intena), FPT_default_intena);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007229
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007230 WR_HARPOON(p_port + hp_clkctrl_0, green_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007231
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007232 WR_HARPOON(p_port + hp_seltimeout, old_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007233}
7234
Linus Torvalds1da177e2005-04-16 15:20:36 -07007235/*---------------------------------------------------------------------
7236 *
7237 * Function: Enable/Disable Write to EEPROM
7238 *
7239 * Description: The EEPROM must first be enabled for writes
7240 * A total of 9 clocks are needed.
7241 *
7242 *---------------------------------------------------------------------*/
7243
Khalid Aziz391e2f22013-05-16 19:44:14 -06007244static void FPT_utilEEWriteOnOff(u32 p_port, unsigned char p_mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007245{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007246 unsigned char ee_value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007247
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007248 ee_value =
7249 (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
7250 (EXT_ARB_ACK | SCSI_TERM_ENA_H));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007251
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007252 if (p_mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007253
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007254 FPT_utilEESendCmdAddr(p_port, EWEN, EWEN_ADDR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007255
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007256 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07007257
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007258 FPT_utilEESendCmdAddr(p_port, EWDS, EWDS_ADDR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007259
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007260 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */
7261 WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /*Turn off Master Select */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007262}
7263
Linus Torvalds1da177e2005-04-16 15:20:36 -07007264/*---------------------------------------------------------------------
7265 *
7266 * Function: Write EEPROM
7267 *
7268 * Description: Write a word to the EEPROM at the specified
7269 * address.
7270 *
7271 *---------------------------------------------------------------------*/
7272
Khalid Aziz391e2f22013-05-16 19:44:14 -06007273static void FPT_utilEEWrite(u32 p_port, unsigned short ee_data,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007274 unsigned short ee_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007275{
7276
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007277 unsigned char ee_value;
7278 unsigned short i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007279
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007280 ee_value =
7281 (unsigned
7282 char)((RD_HARPOON(p_port + hp_ee_ctrl) &
7283 (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007284
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007285 FPT_utilEESendCmdAddr(p_port, EE_WRITE, ee_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007286
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007287 ee_value |= (SEE_MS + SEE_CS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007288
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007289 for (i = 0x8000; i != 0; i >>= 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007290
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007291 if (i & ee_data)
7292 ee_value |= SEE_DO;
7293 else
7294 ee_value &= ~SEE_DO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007295
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007296 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7297 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7298 ee_value |= SEE_CLK; /* Clock data! */
7299 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7300 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7301 ee_value &= ~SEE_CLK;
7302 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7303 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7304 }
7305 ee_value &= (EXT_ARB_ACK | SCSI_TERM_ENA_H);
7306 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007307
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007308 FPT_Wait(p_port, TO_10ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007309
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007310 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS | SEE_CS)); /* Set CS to EEPROM */
7311 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /* Turn off CS */
7312 WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /* Turn off Master Select */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007313}
7314
7315/*---------------------------------------------------------------------
7316 *
7317 * Function: Read EEPROM
7318 *
7319 * Description: Read a word from the EEPROM at the desired
7320 * address.
7321 *
7322 *---------------------------------------------------------------------*/
7323
Khalid Aziz391e2f22013-05-16 19:44:14 -06007324static unsigned short FPT_utilEERead(u32 p_port,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007325 unsigned short ee_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007326{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007327 unsigned short i, ee_data1, ee_data2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007328
7329 i = 0;
James Bottomley 47b5d692005-04-24 02:38:05 -05007330 ee_data1 = FPT_utilEEReadOrg(p_port, ee_addr);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007331 do {
James Bottomley 47b5d692005-04-24 02:38:05 -05007332 ee_data2 = FPT_utilEEReadOrg(p_port, ee_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007333
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007334 if (ee_data1 == ee_data2)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007335 return ee_data1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007336
7337 ee_data1 = ee_data2;
7338 i++;
7339
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007340 } while (i < 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007341
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007342 return ee_data1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007343}
7344
7345/*---------------------------------------------------------------------
7346 *
7347 * Function: Read EEPROM Original
7348 *
7349 * Description: Read a word from the EEPROM at the desired
7350 * address.
7351 *
7352 *---------------------------------------------------------------------*/
7353
Khalid Aziz391e2f22013-05-16 19:44:14 -06007354static unsigned short FPT_utilEEReadOrg(u32 p_port, unsigned short ee_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007355{
7356
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007357 unsigned char ee_value;
7358 unsigned short i, ee_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007359
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007360 ee_value =
7361 (unsigned
7362 char)((RD_HARPOON(p_port + hp_ee_ctrl) &
7363 (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007364
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007365 FPT_utilEESendCmdAddr(p_port, EE_READ, ee_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007366
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007367 ee_value |= (SEE_MS + SEE_CS);
7368 ee_data = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007369
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007370 for (i = 1; i <= 16; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007371
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007372 ee_value |= SEE_CLK; /* Clock data! */
7373 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7374 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7375 ee_value &= ~SEE_CLK;
7376 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7377 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007378
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007379 ee_data <<= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007380
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007381 if (RD_HARPOON(p_port + hp_ee_ctrl) & SEE_DI)
7382 ee_data |= 1;
7383 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007384
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007385 ee_value &= ~(SEE_MS + SEE_CS);
7386 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */
7387 WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /*Turn off Master Select */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007388
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007389 return ee_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007390}
7391
Linus Torvalds1da177e2005-04-16 15:20:36 -07007392/*---------------------------------------------------------------------
7393 *
7394 * Function: Send EE command and Address to the EEPROM
7395 *
7396 * Description: Transfers the correct command and sends the address
7397 * to the eeprom.
7398 *
7399 *---------------------------------------------------------------------*/
7400
Khalid Aziz391e2f22013-05-16 19:44:14 -06007401static void FPT_utilEESendCmdAddr(u32 p_port, unsigned char ee_cmd,
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007402 unsigned short ee_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007403{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007404 unsigned char ee_value;
7405 unsigned char narrow_flg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007406
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007407 unsigned short i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007408
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007409 narrow_flg =
7410 (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
7411 NARROW_SCSI_CARD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007412
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007413 ee_value = SEE_MS;
7414 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007415
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007416 ee_value |= SEE_CS; /* Set CS to EEPROM */
7417 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007418
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007419 for (i = 0x04; i != 0; i >>= 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007420
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007421 if (i & ee_cmd)
7422 ee_value |= SEE_DO;
7423 else
7424 ee_value &= ~SEE_DO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007425
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007426 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7427 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7428 ee_value |= SEE_CLK; /* Clock data! */
7429 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7430 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7431 ee_value &= ~SEE_CLK;
7432 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7433 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7434 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007435
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007436 if (narrow_flg)
7437 i = 0x0080;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007438
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007439 else
7440 i = 0x0200;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007441
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007442 while (i != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007443
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007444 if (i & ee_addr)
7445 ee_value |= SEE_DO;
7446 else
7447 ee_value &= ~SEE_DO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007448
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007449 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7450 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7451 ee_value |= SEE_CLK; /* Clock data! */
7452 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7453 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7454 ee_value &= ~SEE_CLK;
7455 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7456 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007457
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007458 i >>= 1;
7459 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007460}
7461
Alexey Dobriyanc823fee2006-03-08 00:14:25 -08007462static unsigned short FPT_CalcCrc16(unsigned char buffer[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07007463{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007464 unsigned short crc = 0;
7465 int i, j;
7466 unsigned short ch;
7467 for (i = 0; i < ID_STRING_LENGTH; i++) {
7468 ch = (unsigned short)buffer[i];
7469 for (j = 0; j < 8; j++) {
7470 if ((crc ^ ch) & 1)
7471 crc = (crc >> 1) ^ CRCMASK;
7472 else
7473 crc >>= 1;
7474 ch >>= 1;
7475 }
7476 }
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007477 return crc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007478}
7479
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08007480static unsigned char FPT_CalcLrc(unsigned char buffer[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07007481{
7482 int i;
Alexey Dobriyandb038cf82006-03-08 00:14:24 -08007483 unsigned char lrc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007484 lrc = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007485 for (i = 0; i < ID_STRING_LENGTH; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007486 lrc ^= buffer[i];
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007487 return lrc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007488}
7489
Linus Torvalds1da177e2005-04-16 15:20:36 -07007490/*
7491 The following inline definitions avoid type conflicts.
7492*/
7493
7494static inline unsigned char
Khalid Aziz839cb992013-05-16 19:44:13 -06007495FlashPoint__ProbeHostAdapter(struct fpoint_info *FlashPointInfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007496{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007497 return FlashPoint_ProbeHostAdapter((struct sccb_mgr_info *)
7498 FlashPointInfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007499}
7500
Khalid Aziz391e2f22013-05-16 19:44:14 -06007501static inline void *
Khalid Aziz839cb992013-05-16 19:44:13 -06007502FlashPoint__HardwareResetHostAdapter(struct fpoint_info *FlashPointInfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007503{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007504 return FlashPoint_HardwareResetHostAdapter((struct sccb_mgr_info *)
7505 FlashPointInfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007506}
7507
7508static inline void
Khalid Aziz391e2f22013-05-16 19:44:14 -06007509FlashPoint__ReleaseHostAdapter(void *CardHandle)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007510{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007511 FlashPoint_ReleaseHostAdapter(CardHandle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007512}
7513
Linus Torvalds1da177e2005-04-16 15:20:36 -07007514static inline void
Khalid Aziz391e2f22013-05-16 19:44:14 -06007515FlashPoint__StartCCB(void *CardHandle, struct blogic_ccb *CCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007516{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007517 FlashPoint_StartCCB(CardHandle, (struct sccb *)CCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007518}
7519
Linus Torvalds1da177e2005-04-16 15:20:36 -07007520static inline void
Khalid Aziz391e2f22013-05-16 19:44:14 -06007521FlashPoint__AbortCCB(void *CardHandle, struct blogic_ccb *CCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007522{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007523 FlashPoint_AbortCCB(CardHandle, (struct sccb *)CCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007524}
7525
Richard Knutsson2065e312007-02-05 16:39:01 -08007526static inline bool
Khalid Aziz391e2f22013-05-16 19:44:14 -06007527FlashPoint__InterruptPending(void *CardHandle)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007528{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007529 return FlashPoint_InterruptPending(CardHandle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007530}
7531
Linus Torvalds1da177e2005-04-16 15:20:36 -07007532static inline int
Khalid Aziz391e2f22013-05-16 19:44:14 -06007533FlashPoint__HandleInterrupt(void *CardHandle)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007534{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007535 return FlashPoint_HandleInterrupt(CardHandle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007536}
7537
Linus Torvalds1da177e2005-04-16 15:20:36 -07007538#define FlashPoint_ProbeHostAdapter FlashPoint__ProbeHostAdapter
7539#define FlashPoint_HardwareResetHostAdapter FlashPoint__HardwareResetHostAdapter
7540#define FlashPoint_ReleaseHostAdapter FlashPoint__ReleaseHostAdapter
7541#define FlashPoint_StartCCB FlashPoint__StartCCB
7542#define FlashPoint_AbortCCB FlashPoint__AbortCCB
7543#define FlashPoint_InterruptPending FlashPoint__InterruptPending
7544#define FlashPoint_HandleInterrupt FlashPoint__HandleInterrupt
7545
Matthew Wilcox78b4b052008-03-13 06:55:08 -06007546#else /* !CONFIG_SCSI_FLASHPOINT */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007547
7548/*
7549 Define prototypes for the FlashPoint SCCB Manager Functions.
7550*/
7551
Khalid Aziz839cb992013-05-16 19:44:13 -06007552extern unsigned char FlashPoint_ProbeHostAdapter(struct fpoint_info *);
Khalid Aziz391e2f22013-05-16 19:44:14 -06007553extern void *FlashPoint_HardwareResetHostAdapter(struct fpoint_info *);
7554extern void FlashPoint_StartCCB(void *, struct blogic_ccb *);
7555extern int FlashPoint_AbortCCB(void *, struct blogic_ccb *);
7556extern bool FlashPoint_InterruptPending(void *);
7557extern int FlashPoint_HandleInterrupt(void *);
7558extern void FlashPoint_ReleaseHostAdapter(void *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007559
Matthew Wilcox78b4b052008-03-13 06:55:08 -06007560#endif /* CONFIG_SCSI_FLASHPOINT */