blob: 8e3d949b7118ac54b9d6864cdd3915deaa8197d3 [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#include <linux/config.h>
19
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#ifndef CONFIG_SCSI_OMIT_FLASHPOINT
21
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#define MAX_CARDS 8
23#undef BUSTYPE_PCI
24
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#define CRCMASK 0xA001
26
Linus Torvalds1da177e2005-04-16 15:20:36 -070027#define FAILURE 0xFFFFFFFFL
28
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -080029#define BIT(x) ((unsigned char)(1<<(x))) /* single-bit mask in bit position x */
30#define BITW(x) ((unsigned short)(1<<(x))) /* single-bit mask in bit position x */
Linus Torvalds1da177e2005-04-16 15:20:36 -070031
Alexey Dobriyan69eb2ea2006-03-08 00:14:29 -080032struct sccb;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -080033typedef void (*CALL_BK_FN) (struct sccb *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070034
Alexey Dobriyan7f101662006-03-08 00:14:30 -080035struct sccb_mgr_info {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -080036 unsigned long si_baseaddr;
37 unsigned char si_present;
38 unsigned char si_intvect;
39 unsigned char si_id;
40 unsigned char si_lun;
41 unsigned short si_fw_revision;
42 unsigned short si_per_targ_init_sync;
43 unsigned short si_per_targ_fast_nego;
44 unsigned short si_per_targ_ultra_nego;
45 unsigned short si_per_targ_no_disc;
46 unsigned short si_per_targ_wide_nego;
47 unsigned short si_flags;
48 unsigned char si_card_family;
49 unsigned char si_bustype;
50 unsigned char si_card_model[3];
51 unsigned char si_relative_cardnum;
52 unsigned char si_reserved[4];
53 unsigned long si_OS_reserved;
54 unsigned char si_XlatInfo[4];
55 unsigned long si_reserved2[5];
56 unsigned long si_secondary_range;
Alexey Dobriyan7f101662006-03-08 00:14:30 -080057};
Linus Torvalds1da177e2005-04-16 15:20:36 -070058
James Bottomley 47b5d692005-04-24 02:38:05 -050059#define SCSI_PARITY_ENA 0x0001
60#define LOW_BYTE_TERM 0x0010
61#define HIGH_BYTE_TERM 0x0020
62#define BUSTYPE_PCI 0x3
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
64#define SUPPORT_16TAR_32LUN 0x0002
65#define SOFT_RESET 0x0004
66#define EXTENDED_TRANSLATION 0x0008
67#define POST_ALL_UNDERRRUNS 0x0040
68#define FLAG_SCAM_ENABLED 0x0080
69#define FLAG_SCAM_LEVEL2 0x0100
70
Linus Torvalds1da177e2005-04-16 15:20:36 -070071#define HARPOON_FAMILY 0x02
72
Alexey Dobriyan323579882006-01-15 02:12:54 +010073/* SCCB struct used for both SCCB and UCB manager compiles!
Linus Torvalds1da177e2005-04-16 15:20:36 -070074 * The UCB Manager treats the SCCB as it's 'native hardware structure'
75 */
76
Linus Torvalds1da177e2005-04-16 15:20:36 -070077#pragma pack(1)
Alexey Dobriyan69eb2ea2006-03-08 00:14:29 -080078struct sccb {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -080079 unsigned char OperationCode;
80 unsigned char ControlByte;
81 unsigned char CdbLength;
82 unsigned char RequestSenseLength;
83 unsigned long DataLength;
84 unsigned long DataPointer;
85 unsigned char CcbRes[2];
86 unsigned char HostStatus;
87 unsigned char TargetStatus;
88 unsigned char TargID;
89 unsigned char Lun;
90 unsigned char Cdb[12];
91 unsigned char CcbRes1;
92 unsigned char Reserved1;
93 unsigned long Reserved2;
94 unsigned long SensePointer;
Linus Torvalds1da177e2005-04-16 15:20:36 -070095
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -080096 CALL_BK_FN SccbCallback; /* VOID (*SccbCallback)(); */
97 unsigned long SccbIOPort; /* Identifies board base port */
98 unsigned char SccbStatus;
99 unsigned char SCCBRes2;
100 unsigned short SccbOSFlags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800102 unsigned long Sccb_XferCnt; /* actual transfer count */
103 unsigned long Sccb_ATC;
104 unsigned long SccbVirtDataPtr; /* virtual addr for OS/2 */
105 unsigned long Sccb_res1;
106 unsigned short Sccb_MGRFlags;
107 unsigned short Sccb_sgseg;
108 unsigned char Sccb_scsimsg; /* identify msg for selection */
109 unsigned char Sccb_tag;
110 unsigned char Sccb_scsistat;
111 unsigned char Sccb_idmsg; /* image of last msg in */
112 struct sccb *Sccb_forwardlink;
113 struct sccb *Sccb_backlink;
114 unsigned long Sccb_savedATC;
115 unsigned char Save_Cdb[6];
116 unsigned char Save_CdbLen;
117 unsigned char Sccb_XferState;
118 unsigned long Sccb_SGoffset;
119};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120
121#pragma pack()
122
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123#define SCATTER_GATHER_COMMAND 0x02
124#define RESIDUAL_COMMAND 0x03
125#define RESIDUAL_SG_COMMAND 0x04
126#define RESET_COMMAND 0x81
127
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800128#define F_USE_CMD_Q 0x20 /*Inidcates TAGGED command. */
129#define TAG_TYPE_MASK 0xC0 /*Type of tag msg to send. */
130#define SCCB_DATA_XFER_OUT 0x10 /* Write */
131#define SCCB_DATA_XFER_IN 0x08 /* Read */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800133#define NO_AUTO_REQUEST_SENSE 0x01 /* No Request Sense Buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800135#define BUS_FREE_ST 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136#define SELECT_ST 1
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800137#define SELECT_BDR_ST 2 /* Select w\ Bus Device Reset */
138#define SELECT_SN_ST 3 /* Select w\ Sync Nego */
139#define SELECT_WN_ST 4 /* Select w\ Wide Data Nego */
140#define SELECT_Q_ST 5 /* Select w\ Tagged Q'ing */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141#define COMMAND_ST 6
142#define DATA_OUT_ST 7
143#define DATA_IN_ST 8
144#define DISCONNECT_ST 9
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145#define ABORT_ST 11
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147#define F_HOST_XFER_DIR 0x01
148#define F_ALL_XFERRED 0x02
149#define F_SG_XFER 0x04
150#define F_AUTO_SENSE 0x08
151#define F_ODD_BALL_CNT 0x10
152#define F_NO_DATA_YET 0x80
153
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154#define F_STATUSLOADED 0x01
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155#define F_DEV_SELECTED 0x04
156
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800157#define SCCB_COMPLETE 0x00 /* SCCB completed without error */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158#define SCCB_DATA_UNDER_RUN 0x0C
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800159#define SCCB_SELECTION_TIMEOUT 0x11 /* Set SCSI selection timed out */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160#define SCCB_DATA_OVER_RUN 0x12
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800161#define SCCB_PHASE_SEQUENCE_FAIL 0x14 /* Target bus phase sequence failure */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800163#define SCCB_GROSS_FW_ERR 0x27 /* Major problem! */
164#define SCCB_BM_ERR 0x30 /* BusMaster error. */
165#define SCCB_PARITY_ERR 0x34 /* SCSI parity error */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166
167#define SCCB_IN_PROCESS 0x00
168#define SCCB_SUCCESS 0x01
169#define SCCB_ABORT 0x02
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170#define SCCB_ERROR 0x04
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172#define ORION_FW_REV 3110
173
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800174#define QUEUE_DEPTH 254+1 /*1 for Normal disconnect 32 for Q'ing. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800176#define MAX_MB_CARDS 4 /* Max. no of cards suppoerted on Mother Board */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177
James Bottomley 47b5d692005-04-24 02:38:05 -0500178#define MAX_SCSI_TAR 16
179#define MAX_LUN 32
180#define LUN_MASK 0x1f
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800182#define SG_BUF_CNT 16 /*Number of prefetched elements. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800184#define SG_ELEMENT_SIZE 8 /*Eight byte per element. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185
Alexey Dobriyanad0e1d92006-03-08 00:14:28 -0800186#define RD_HARPOON(ioport) inb((u32)ioport)
187#define RDW_HARPOON(ioport) inw((u32)ioport)
188#define RD_HARP32(ioport,offset,data) (data = inl((u32)(ioport + offset)))
189#define WR_HARPOON(ioport,val) outb((u8) val, (u32)ioport)
190#define WRW_HARPOON(ioport,val) outw((u16)val, (u32)ioport)
191#define WR_HARP32(ioport,offset,data) outl(data, (u32)(ioport + offset))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193#define TAR_SYNC_MASK (BIT(7)+BIT(6))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194#define SYNC_TRYING BIT(6)
195#define SYNC_SUPPORTED (BIT(7)+BIT(6))
196
197#define TAR_WIDE_MASK (BIT(5)+BIT(4))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198#define WIDE_ENABLED BIT(4)
199#define WIDE_NEGOCIATED BIT(5)
200
201#define TAR_TAG_Q_MASK (BIT(3)+BIT(2))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202#define TAG_Q_TRYING BIT(2)
203#define TAG_Q_REJECT BIT(3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204
205#define TAR_ALLOW_DISC BIT(0)
206
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207#define EE_SYNC_MASK (BIT(0)+BIT(1))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208#define EE_SYNC_5MB BIT(0)
209#define EE_SYNC_10MB BIT(1)
210#define EE_SYNC_20MB (BIT(0)+BIT(1))
211
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212#define EE_WIDE_SCSI BIT(7)
213
Alexey Dobriyanf31dc0c2006-03-08 00:14:31 -0800214struct sccb_mgr_tar_info {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800216 struct sccb *TarSelQ_Head;
217 struct sccb *TarSelQ_Tail;
218 unsigned char TarLUN_CA; /*Contingent Allgiance */
219 unsigned char TarTagQ_Cnt;
220 unsigned char TarSelQ_Cnt;
221 unsigned char TarStatus;
222 unsigned char TarEEValue;
223 unsigned char TarSyncCtrl;
224 unsigned char TarReserved[2]; /* for alignment */
225 unsigned char LunDiscQ_Idx[MAX_LUN];
226 unsigned char TarLUNBusy[MAX_LUN];
Alexey Dobriyanf31dc0c2006-03-08 00:14:31 -0800227};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228
Alexey Dobriyan68d0c1a2006-03-08 00:14:33 -0800229struct nvram_info {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800230 unsigned char niModel; /* Model No. of card */
231 unsigned char niCardNo; /* Card no. */
232 unsigned long niBaseAddr; /* Port Address of card */
233 unsigned char niSysConf; /* Adapter Configuration byte - Byte 16 of eeprom map */
234 unsigned char niScsiConf; /* SCSI Configuration byte - Byte 17 of eeprom map */
235 unsigned char niScamConf; /* SCAM Configuration byte - Byte 20 of eeprom map */
236 unsigned char niAdapId; /* Host Adapter ID - Byte 24 of eerpom map */
237 unsigned char niSyncTbl[MAX_SCSI_TAR / 2]; /* Sync/Wide byte of targets */
238 unsigned char niScamTbl[MAX_SCSI_TAR][4]; /* Compressed Scam name string of Targets */
Alexey Dobriyan68d0c1a2006-03-08 00:14:33 -0800239};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241#define MODEL_LT 1
242#define MODEL_DL 2
243#define MODEL_LW 3
244#define MODEL_DW 4
245
Alexey Dobriyan13e68512006-03-08 00:14:34 -0800246struct sccb_card {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800247 struct sccb *currentSCCB;
248 struct sccb_mgr_info *cardInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800250 unsigned long ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700251
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800252 unsigned short cmdCounter;
253 unsigned char discQCount;
254 unsigned char tagQ_Lst;
255 unsigned char cardIndex;
256 unsigned char scanIndex;
257 unsigned char globalFlags;
258 unsigned char ourId;
259 struct nvram_info *pNvRamInfo;
260 struct sccb *discQ_Tbl[QUEUE_DEPTH];
261
Alexey Dobriyan13e68512006-03-08 00:14:34 -0800262};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263
Linus Torvalds1da177e2005-04-16 15:20:36 -0700264#define F_TAG_STARTED 0x01
265#define F_CONLUN_IO 0x02
266#define F_DO_RENEGO 0x04
267#define F_NO_FILTER 0x08
268#define F_GREEN_PC 0x10
269#define F_HOST_XFER_ACT 0x20
270#define F_NEW_SCCB_CMD 0x40
271#define F_UPDATE_EEPROM 0x80
272
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273#define ID_STRING_LENGTH 32
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800274#define TYPE_CODE0 0x63 /*Level2 Mstr (bits 7-6), */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800276#define SLV_TYPE_CODE0 0xA3 /*Priority Bit set (bits 7-6), */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277
278#define ASSIGN_ID 0x00
279#define SET_P_FLAG 0x01
280#define CFG_CMPLT 0x03
281#define DOM_MSTR 0x0F
282#define SYNC_PTRN 0x1F
283
284#define ID_0_7 0x18
285#define ID_8_F 0x11
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286#define MISC_CODE 0x14
287#define CLR_P_FLAG 0x18
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289#define INIT_SELTD 0x01
290#define LEVEL2_TAR 0x02
291
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800292enum scam_id_st { ID0, ID1, ID2, ID3, ID4, ID5, ID6, ID7, ID8, ID9, ID10, ID11,
293 ID12,
294 ID13, ID14, ID15, ID_UNUSED, ID_UNASSIGNED, ID_ASSIGNED, LEGACY,
295 CLR_PRIORITY, NO_ID_AVAIL
296};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297
298typedef struct SCCBscam_info {
299
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800300 unsigned char id_string[ID_STRING_LENGTH];
301 enum scam_id_st state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800303} SCCBSCAM_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305#define SCSI_REQUEST_SENSE 0x03
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306#define SCSI_READ 0x08
307#define SCSI_WRITE 0x0A
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308#define SCSI_START_STOP_UNIT 0x1B
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309#define SCSI_READ_EXTENDED 0x28
310#define SCSI_WRITE_EXTENDED 0x2A
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311#define SCSI_WRITE_AND_VERIFY 0x2E
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313#define SSGOOD 0x00
314#define SSCHECK 0x02
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315#define SSQ_FULL 0x28
316
Linus Torvalds1da177e2005-04-16 15:20:36 -0700317#define SMCMD_COMP 0x00
318#define SMEXT 0x01
319#define SMSAVE_DATA_PTR 0x02
320#define SMREST_DATA_PTR 0x03
321#define SMDISC 0x04
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322#define SMABORT 0x06
323#define SMREJECT 0x07
324#define SMNO_OP 0x08
325#define SMPARITY 0x09
326#define SMDEV_RESET 0x0C
327#define SMABORT_TAG 0x0D
328#define SMINIT_RECOVERY 0x0F
329#define SMREL_RECOVERY 0x10
330
331#define SMIDENT 0x80
332#define DISC_PRIV 0x40
333
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334#define SMSYNC 0x01
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335#define SMWDTR 0x03
336#define SM8BIT 0x00
337#define SM16BIT 0x01
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800338#define SMIGNORWR 0x23 /* Ignore Wide Residue */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339
340#define SIX_BYTE_CMD 0x06
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341#define TWELVE_BYTE_CMD 0x0C
342
343#define ASYNC 0x00
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800344#define MAX_OFFSET 0x0F /* Maxbyteoffset for Sync Xfers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345
346#define EEPROM_WD_CNT 256
347
348#define EEPROM_CHECK_SUM 0
349#define FW_SIGNATURE 2
350#define MODEL_NUMB_0 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351#define MODEL_NUMB_2 6
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352#define MODEL_NUMB_4 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353#define SYSTEM_CONFIG 16
354#define SCSI_CONFIG 17
355#define BIOS_CONFIG 18
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356#define SCAM_CONFIG 20
357#define ADAPTER_SCSI_ID 24
358
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359#define IGNORE_B_SCAN 32
360#define SEND_START_ENA 34
361#define DEVICE_ENABLE 36
362
363#define SYNC_RATE_TBL 38
364#define SYNC_RATE_TBL01 38
365#define SYNC_RATE_TBL23 40
366#define SYNC_RATE_TBL45 42
367#define SYNC_RATE_TBL67 44
368#define SYNC_RATE_TBL89 46
369#define SYNC_RATE_TBLab 48
370#define SYNC_RATE_TBLcd 50
371#define SYNC_RATE_TBLef 52
372
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800373#define EE_SCAMBASE 256
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800375#define SCAM_ENABLED BIT(2)
376#define SCAM_LEVEL2 BIT(3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800378#define RENEGO_ENA BITW(10)
379#define CONNIO_ENA BITW(11)
380#define GREEN_PC_ENA BITW(12)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800382#define AUTO_RATE_00 00
383#define AUTO_RATE_05 01
384#define AUTO_RATE_10 02
385#define AUTO_RATE_20 03
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800387#define WIDE_NEGO_BIT BIT(7)
388#define DISC_ENABLE_BIT BIT(6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800390#define hp_vendor_id_0 0x00 /* LSB */
391#define ORION_VEND_0 0x4B
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800393#define hp_vendor_id_1 0x01 /* MSB */
394#define ORION_VEND_1 0x10
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800396#define hp_device_id_0 0x02 /* LSB */
397#define ORION_DEV_0 0x30
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800399#define hp_device_id_1 0x03 /* MSB */
400#define ORION_DEV_1 0x81
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401
402 /* Sub Vendor ID and Sub Device ID only available in
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800403 Harpoon Version 2 and higher */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800405#define hp_sub_device_id_0 0x06 /* LSB */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800407#define hp_semaphore 0x0C
408#define SCCB_MGR_ACTIVE BIT(0)
409#define TICKLE_ME BIT(1)
410#define SCCB_MGR_PRESENT BIT(3)
411#define BIOS_IN_USE BIT(4)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800413#define hp_sys_ctrl 0x0F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800415#define STOP_CLK BIT(0) /*Turn off BusMaster Clock */
416#define DRVR_RST BIT(1) /*Firmware Reset to 80C15 chip */
417#define HALT_MACH BIT(3) /*Halt State Machine */
418#define HARD_ABORT BIT(4) /*Hard Abort */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800420#define hp_host_blk_cnt 0x13
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800422#define XFER_BLK64 0x06 /* 1 1 0 64 byte per block */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800424#define BM_THRESHOLD 0x40 /* PCI mode can only xfer 16 bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700425
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800426#define hp_int_mask 0x17
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800428#define INT_CMD_COMPL BIT(0) /* DMA command complete */
429#define INT_EXT_STATUS BIT(1) /* Extended Status Set */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800431#define hp_xfer_cnt_lo 0x18
432#define hp_xfer_cnt_hi 0x1A
433#define hp_xfer_cmd 0x1B
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800435#define XFER_HOST_DMA 0x00 /* 0 0 0 Transfer Host -> DMA */
436#define XFER_DMA_HOST 0x01 /* 0 0 1 Transfer DMA -> Host */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800438#define XFER_HOST_AUTO 0x00 /* 0 0 Auto Transfer Size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800440#define XFER_DMA_8BIT 0x20 /* 0 1 8 BIT Transfer Size */
Alexey Dobriyan85ae97d2006-03-08 00:14:22 -0800441
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800442#define DISABLE_INT BIT(7) /*Do not interrupt at end of cmd. */
Alexey Dobriyan85ae97d2006-03-08 00:14:22 -0800443
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800444#define HOST_WRT_CMD ((DISABLE_INT + XFER_HOST_DMA + XFER_HOST_AUTO + XFER_DMA_8BIT))
445#define HOST_RD_CMD ((DISABLE_INT + XFER_DMA_HOST + XFER_HOST_AUTO + XFER_DMA_8BIT))
Alexey Dobriyan85ae97d2006-03-08 00:14:22 -0800446
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800447#define hp_host_addr_lo 0x1C
448#define hp_host_addr_hmi 0x1E
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800450#define hp_ee_ctrl 0x22
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800452#define EXT_ARB_ACK BIT(7)
453#define SCSI_TERM_ENA_H BIT(6) /* SCSI high byte terminator */
454#define SEE_MS BIT(5)
455#define SEE_CS BIT(3)
456#define SEE_CLK BIT(2)
457#define SEE_DO BIT(1)
458#define SEE_DI BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800460#define EE_READ 0x06
461#define EE_WRITE 0x05
462#define EWEN 0x04
463#define EWEN_ADDR 0x03C0
464#define EWDS 0x04
465#define EWDS_ADDR 0x0000
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800467#define hp_bm_ctrl 0x26
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800469#define SCSI_TERM_ENA_L BIT(0) /*Enable/Disable external terminators */
470#define FLUSH_XFER_CNTR BIT(1) /*Flush transfer counter */
471#define FORCE1_XFER BIT(5) /*Always xfer one byte in byte mode */
472#define FAST_SINGLE BIT(6) /*?? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800474#define BMCTRL_DEFAULT (FORCE1_XFER|FAST_SINGLE|SCSI_TERM_ENA_L)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800476#define hp_sg_addr 0x28
477#define hp_page_ctrl 0x29
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800479#define SCATTER_EN BIT(0)
480#define SGRAM_ARAM BIT(1)
481#define G_INT_DISABLE BIT(3) /* Enable/Disable all Interrupts */
482#define NARROW_SCSI_CARD BIT(4) /* NARROW/WIDE SCSI config pin */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800484#define hp_pci_stat_cfg 0x2D
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800486#define REC_MASTER_ABORT BIT(5) /*received Master abort */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800488#define hp_rev_num 0x33
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800490#define hp_stack_data 0x34
491#define hp_stack_addr 0x35
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800493#define hp_ext_status 0x36
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800495#define BM_FORCE_OFF BIT(0) /*Bus Master is forced to get off */
496#define PCI_TGT_ABORT BIT(0) /*PCI bus master transaction aborted */
497#define PCI_DEV_TMOUT BIT(1) /*PCI Device Time out */
498#define CMD_ABORTED BIT(4) /*Command aborted */
499#define BM_PARITY_ERR BIT(5) /*parity error on data received */
500#define PIO_OVERRUN BIT(6) /*Slave data overrun */
501#define BM_CMD_BUSY BIT(7) /*Bus master transfer command busy */
502#define BAD_EXT_STATUS (BM_FORCE_OFF | PCI_DEV_TMOUT | CMD_ABORTED | \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 BM_PARITY_ERR | PIO_OVERRUN)
504
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800505#define hp_int_status 0x37
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800507#define EXT_STATUS_ON BIT(1) /*Extended status is valid */
508#define SCSI_INTERRUPT BIT(2) /*Global indication of a SCSI int. */
509#define INT_ASSERTED BIT(5) /* */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800511#define hp_fifo_cnt 0x38
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800513#define hp_intena 0x40
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800515#define RESET BITW(7)
516#define PROG_HLT BITW(6)
517#define PARITY BITW(5)
518#define FIFO BITW(4)
519#define SEL BITW(3)
520#define SCAM_SEL BITW(2)
521#define RSEL BITW(1)
522#define TIMEOUT BITW(0)
523#define BUS_FREE BITW(15)
524#define XFER_CNT_0 BITW(14)
525#define PHASE BITW(13)
526#define IUNKWN BITW(12)
527#define ICMD_COMP BITW(11)
528#define ITICKLE BITW(10)
529#define IDO_STRT BITW(9)
530#define ITAR_DISC BITW(8)
531#define AUTO_INT (BITW(12)+BITW(11)+BITW(10)+BITW(9)+BITW(8))
532#define CLR_ALL_INT 0xFFFF
533#define CLR_ALL_INT_1 0xFF00
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800535#define hp_intstat 0x42
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800537#define hp_scsisig 0x44
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800539#define SCSI_SEL BIT(7)
540#define SCSI_BSY BIT(6)
541#define SCSI_REQ BIT(5)
542#define SCSI_ACK BIT(4)
543#define SCSI_ATN BIT(3)
544#define SCSI_CD BIT(2)
545#define SCSI_MSG BIT(1)
546#define SCSI_IOBIT BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800548#define S_SCSI_PHZ (BIT(2)+BIT(1)+BIT(0))
549#define S_MSGO_PH (BIT(2)+BIT(1) )
550#define S_MSGI_PH (BIT(2)+BIT(1)+BIT(0))
551#define S_DATAI_PH ( BIT(0))
552#define S_DATAO_PH 0x00
553#define S_ILL_PH ( BIT(1) )
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800555#define hp_scsictrl_0 0x45
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800557#define SEL_TAR BIT(6)
558#define ENA_ATN BIT(4)
559#define ENA_RESEL BIT(2)
560#define SCSI_RST BIT(1)
561#define ENA_SCAM_SEL BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800563#define hp_portctrl_0 0x46
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800565#define SCSI_PORT BIT(7)
566#define SCSI_INBIT BIT(6)
567#define DMA_PORT BIT(5)
568#define DMA_RD BIT(4)
569#define HOST_PORT BIT(3)
570#define HOST_WRT BIT(2)
571#define SCSI_BUS_EN BIT(1)
572#define START_TO BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800574#define hp_scsireset 0x47
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800576#define SCSI_INI BIT(6)
577#define SCAM_EN BIT(5)
578#define DMA_RESET BIT(3)
579#define HPSCSI_RESET BIT(2)
580#define PROG_RESET BIT(1)
581#define FIFO_CLR BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800583#define hp_xfercnt_0 0x48
584#define hp_xfercnt_2 0x4A
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800586#define hp_fifodata_0 0x4C
587#define hp_addstat 0x4E
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800589#define SCAM_TIMER BIT(7)
590#define SCSI_MODE8 BIT(3)
591#define SCSI_PAR_ERR BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800593#define hp_prgmcnt_0 0x4F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800595#define hp_selfid_0 0x50
596#define hp_selfid_1 0x51
597#define hp_arb_id 0x52
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800599#define hp_select_id 0x53
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800601#define hp_synctarg_base 0x54
602#define hp_synctarg_12 0x54
603#define hp_synctarg_13 0x55
604#define hp_synctarg_14 0x56
605#define hp_synctarg_15 0x57
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800607#define hp_synctarg_8 0x58
608#define hp_synctarg_9 0x59
609#define hp_synctarg_10 0x5A
610#define hp_synctarg_11 0x5B
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800612#define hp_synctarg_4 0x5C
613#define hp_synctarg_5 0x5D
614#define hp_synctarg_6 0x5E
615#define hp_synctarg_7 0x5F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800617#define hp_synctarg_0 0x60
618#define hp_synctarg_1 0x61
619#define hp_synctarg_2 0x62
620#define hp_synctarg_3 0x63
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800622#define NARROW_SCSI BIT(4)
623#define DEFAULT_OFFSET 0x0F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800625#define hp_autostart_0 0x64
626#define hp_autostart_1 0x65
627#define hp_autostart_3 0x67
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800629#define AUTO_IMMED BIT(5)
630#define SELECT BIT(6)
631#define END_DATA (BIT(7)+BIT(6))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800633#define hp_gp_reg_0 0x68
634#define hp_gp_reg_1 0x69
635#define hp_gp_reg_3 0x6B
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800637#define hp_seltimeout 0x6C
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800639#define TO_4ms 0x67 /* 3.9959ms */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800641#define TO_5ms 0x03 /* 4.9152ms */
642#define TO_10ms 0x07 /* 11.xxxms */
643#define TO_250ms 0x99 /* 250.68ms */
644#define TO_290ms 0xB1 /* 289.99ms */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800646#define hp_clkctrl_0 0x6D
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800648#define PWR_DWN BIT(6)
649#define ACTdeassert BIT(4)
650#define CLK_40MHZ (BIT(1) + BIT(0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800652#define CLKCTRL_DEFAULT (ACTdeassert | CLK_40MHZ)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800654#define hp_fiforead 0x6E
655#define hp_fifowrite 0x6F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800657#define hp_offsetctr 0x70
658#define hp_xferstat 0x71
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800660#define FIFO_EMPTY BIT(6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800662#define hp_portctrl_1 0x72
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800664#define CHK_SCSI_P BIT(3)
665#define HOST_MODE8 BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800667#define hp_xfer_pad 0x73
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800669#define ID_UNLOCK BIT(3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800671#define hp_scsidata_0 0x74
672#define hp_scsidata_1 0x75
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800674#define hp_aramBase 0x80
675#define BIOS_DATA_OFFSET 0x60
676#define BIOS_RELATIVE_CARD 0x64
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800678#define AR3 (BITW(9) + BITW(8))
679#define SDATA BITW(10)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800681#define CRD_OP BITW(11) /* Cmp Reg. w/ Data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800683#define CRR_OP BITW(12) /* Cmp Reg. w. Reg. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800685#define CPE_OP (BITW(14)+BITW(11)) /* Cmp SCSI phs & Branch EQ */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800687#define CPN_OP (BITW(14)+BITW(12)) /* Cmp SCSI phs & Branch NOT EQ */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800689#define ADATA_OUT 0x00
690#define ADATA_IN BITW(8)
691#define ACOMMAND BITW(10)
692#define ASTATUS (BITW(10)+BITW(8))
693#define AMSG_OUT (BITW(10)+BITW(9))
694#define AMSG_IN (BITW(10)+BITW(9)+BITW(8))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800696#define BRH_OP BITW(13) /* Branch */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800698#define ALWAYS 0x00
699#define EQUAL BITW(8)
700#define NOT_EQ BITW(9)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800702#define TCB_OP (BITW(13)+BITW(11)) /* Test condition & branch */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800704#define FIFO_0 BITW(10)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800706#define MPM_OP BITW(15) /* Match phase and move data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800708#define MRR_OP BITW(14) /* Move DReg. to Reg. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800710#define S_IDREG (BIT(2)+BIT(1)+BIT(0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800712#define D_AR0 0x00
713#define D_AR1 BIT(0)
714#define D_BUCKET (BIT(2) + BIT(1) + BIT(0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800716#define RAT_OP (BITW(14)+BITW(13)+BITW(11))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800718#define SSI_OP (BITW(15)+BITW(11))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800720#define SSI_ITAR_DISC (ITAR_DISC >> 8)
721#define SSI_IDO_STRT (IDO_STRT >> 8)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800723#define SSI_ICMD_COMP (ICMD_COMP >> 8)
724#define SSI_ITICKLE (ITICKLE >> 8)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800726#define SSI_IUNKWN (IUNKWN >> 8)
727#define SSI_INO_CC (IUNKWN >> 8)
728#define SSI_IRFAIL (IUNKWN >> 8)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800730#define NP 0x10 /*Next Phase */
731#define NTCMD 0x02 /*Non- Tagged Command start */
732#define CMDPZ 0x04 /*Command phase */
733#define DINT 0x12 /*Data Out/In interrupt */
734#define DI 0x13 /*Data Out */
735#define DC 0x19 /*Disconnect Message */
736#define ST 0x1D /*Status Phase */
737#define UNKNWN 0x24 /*Unknown bus action */
738#define CC 0x25 /*Command Completion failure */
739#define TICK 0x26 /*New target reselected us. */
740#define SELCHK 0x28 /*Select & Check SCSI ID latch reg */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800742#define ID_MSG_STRT hp_aramBase + 0x00
743#define NON_TAG_ID_MSG hp_aramBase + 0x06
744#define CMD_STRT hp_aramBase + 0x08
745#define SYNC_MSGS hp_aramBase + 0x08
Alexey Dobriyan85ae97d2006-03-08 00:14:22 -0800746
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800747#define TAG_STRT 0x00
748#define DISCONNECT_START 0x10/2
749#define END_DATA_START 0x14/2
750#define CMD_ONLY_STRT CMDPZ/2
751#define SELCHK_STRT SELCHK/2
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752
753#define GET_XFER_CNT(port, xfercnt) {RD_HARP32(port,hp_xfercnt_0,xfercnt); xfercnt &= 0xFFFFFF;}
754/* #define GET_XFER_CNT(port, xfercnt) (xfercnt = RD_HARPOON(port+hp_xfercnt_2), \
755 xfercnt <<= 16,\
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800756 xfercnt |= RDW_HARPOON((unsigned short)(port+hp_xfercnt_0)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 */
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800758#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 -0700759 addr >>= 16,\
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800760 WRW_HARPOON((port+hp_host_addr_hmi), (unsigned short)(addr & 0x0000FFFFL)),\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 WR_HARP32(port,hp_xfercnt_0,count),\
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800762 WRW_HARPOON((port+hp_xfer_cnt_lo), (unsigned short)(count & 0x0000FFFFL)),\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 count >>= 16,\
764 WR_HARPOON(port+hp_xfer_cnt_hi, (count & 0xFF)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765
766#define ACCEPT_MSG(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
767 WR_HARPOON(port+hp_scsisig, S_ILL_PH);}
768
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769#define ACCEPT_MSG_ATN(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
770 WR_HARPOON(port+hp_scsisig, (S_ILL_PH|SCSI_ATN));}
771
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772#define DISABLE_AUTO(port) (WR_HARPOON(port+hp_scsireset, PROG_RESET),\
773 WR_HARPOON(port+hp_scsireset, 0x00))
774
775#define ARAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
776 (RD_HARPOON(p_port+hp_page_ctrl) | SGRAM_ARAM)))
777
778#define SGRAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
779 (RD_HARPOON(p_port+hp_page_ctrl) & ~SGRAM_ARAM)))
780
781#define MDISABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
782 (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE)))
783
784#define MENABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
785 (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE)))
786
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800787static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card,
788 unsigned char syncFlag);
789static void FPT_ssel(unsigned long port, unsigned char p_card);
790static void FPT_sres(unsigned long port, unsigned char p_card,
791 struct sccb_card *pCurrCard);
792static void FPT_shandem(unsigned long port, unsigned char p_card,
793 struct sccb *pCurrSCCB);
794static void FPT_stsyncn(unsigned long port, unsigned char p_card);
795static void FPT_sisyncr(unsigned long port, unsigned char sync_pulse,
796 unsigned char offset);
797static void FPT_sssyncv(unsigned long p_port, unsigned char p_id,
798 unsigned char p_sync_value,
799 struct sccb_mgr_tar_info *currTar_Info);
800static void FPT_sresb(unsigned long port, unsigned char p_card);
801static void FPT_sxfrp(unsigned long p_port, unsigned char p_card);
802static void FPT_schkdd(unsigned long port, unsigned char p_card);
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -0800803static unsigned char FPT_RdStack(unsigned long port, unsigned char index);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800804static void FPT_WrStack(unsigned long portBase, unsigned char index,
805 unsigned char data);
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -0800806static unsigned char FPT_ChkIfChipInitialized(unsigned long ioPort);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -0800808static void FPT_SendMsg(unsigned long port, unsigned char message);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800809static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
810 unsigned char error_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800812static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card);
813static void FPT_RNVRamData(struct nvram_info *pNvRamInfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -0800815static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800816static void FPT_stwidn(unsigned long port, unsigned char p_card);
817static void FPT_siwidr(unsigned long port, unsigned char width);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800819static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
820 unsigned char p_card);
821static void FPT_queueDisconnect(struct sccb *p_SCCB, unsigned char p_card);
822static void FPT_queueCmdComplete(struct sccb_card *pCurrCard,
823 struct sccb *p_SCCB, unsigned char p_card);
824static void FPT_queueSearchSelect(struct sccb_card *pCurrCard,
Alexey Dobriyandb038cf2006-03-08 00:14:24 -0800825 unsigned char p_card);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800826static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code);
827static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char card);
828static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB,
829 unsigned char p_card);
830static void FPT_utilUpdateResidual(struct sccb *p_SCCB);
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800831static unsigned short FPT_CalcCrc16(unsigned char buffer[]);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800832static unsigned char FPT_CalcLrc(unsigned char buffer[]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800834static void FPT_Wait1Second(unsigned long p_port);
835static void FPT_Wait(unsigned long p_port, unsigned char p_delay);
836static void FPT_utilEEWriteOnOff(unsigned long p_port, unsigned char p_mode);
837static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data,
838 unsigned short ee_addr);
839static unsigned short FPT_utilEERead(unsigned long p_port,
840 unsigned short ee_addr);
841static unsigned short FPT_utilEEReadOrg(unsigned long p_port,
842 unsigned short ee_addr);
843static void FPT_utilEESendCmdAddr(unsigned long p_port, unsigned char ee_cmd,
844 unsigned short ee_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800846static void FPT_phaseDataOut(unsigned long port, unsigned char p_card);
847static void FPT_phaseDataIn(unsigned long port, unsigned char p_card);
848static void FPT_phaseCommand(unsigned long port, unsigned char p_card);
849static void FPT_phaseStatus(unsigned long port, unsigned char p_card);
850static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card);
851static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card);
852static void FPT_phaseIllegal(unsigned long port, unsigned char p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800854static void FPT_phaseDecode(unsigned long port, unsigned char p_card);
855static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card);
856static void FPT_phaseBusFree(unsigned long p_port, unsigned char p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800858static void FPT_XbowInit(unsigned long port, unsigned char scamFlg);
859static void FPT_BusMasterInit(unsigned long p_port);
860static void FPT_DiagEEPROM(unsigned long p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800862static void FPT_dataXferProcessor(unsigned long port,
863 struct sccb_card *pCurrCard);
864static void FPT_busMstrSGDataXferStart(unsigned long port,
865 struct sccb *pCurrSCCB);
866static void FPT_busMstrDataXferStart(unsigned long port,
867 struct sccb *pCurrSCCB);
868static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card,
869 struct sccb *pCurrSCCB);
870static void FPT_hostDataXferRestart(struct sccb *currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800872static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port,
873 unsigned char p_card,
874 struct sccb_card *pCurrCard,
875 unsigned short p_int);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800877static void FPT_SccbMgrTableInitAll(void);
878static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard,
879 unsigned char p_card);
880static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
881 unsigned char target);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800883static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
884 unsigned char p_power_up);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800886static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type);
887static void FPT_scbusf(unsigned long p_port);
888static void FPT_scsel(unsigned long p_port);
889static void FPT_scasid(unsigned char p_card, unsigned long p_port);
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -0800890static unsigned char FPT_scxferc(unsigned long p_port, unsigned char p_data);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800891static unsigned char FPT_scsendi(unsigned long p_port,
892 unsigned char p_id_string[]);
893static unsigned char FPT_sciso(unsigned long p_port,
894 unsigned char p_id_string[]);
895static void FPT_scwirod(unsigned long p_port, unsigned char p_data_bit);
896static void FPT_scwiros(unsigned long p_port, unsigned char p_data_bit);
Alexey Dobriyandb038cf2006-03-08 00:14:24 -0800897static unsigned char FPT_scvalq(unsigned char p_quintet);
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -0800898static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800899static void FPT_scwtsel(unsigned long p_port);
900static void FPT_inisci(unsigned char p_card, unsigned long p_port,
901 unsigned char p_our_id);
902static void FPT_scsavdi(unsigned char p_card, unsigned long p_port);
903static unsigned char FPT_scmachid(unsigned char p_card,
904 unsigned char p_id_string[]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800906static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card);
907static void FPT_autoLoadDefaultMap(unsigned long p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800909static struct sccb_mgr_tar_info FPT_sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] =
910 { {{0}} };
911static struct sccb_card FPT_BL_Card[MAX_CARDS] = { {0} };
912static SCCBSCAM_INFO FPT_scamInfo[MAX_SCSI_TAR] = { {{0}} };
913static struct nvram_info FPT_nvRamInfo[MAX_MB_CARDS] = { {0} };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914
Alexey Dobriyandb038cf2006-03-08 00:14:24 -0800915static unsigned char FPT_mbCards = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800916static unsigned char FPT_scamHAString[] =
917 { 0x63, 0x07, 'B', 'U', 'S', 'L', 'O', 'G', 'I', 'C',
918 ' ', 'B', 'T', '-', '9', '3', '0',
919 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
920 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
921};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800923static unsigned short FPT_default_intena = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800925static void (*FPT_s_PhaseTbl[8]) (unsigned long, unsigned char) = {
9260};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927
928/*---------------------------------------------------------------------
929 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -0800930 * Function: FlashPoint_ProbeHostAdapter
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 *
932 * Description: Setup and/or Search for cards and return info to caller.
933 *
934 *---------------------------------------------------------------------*/
935
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800936static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800938 static unsigned char first_time = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800940 unsigned char i, j, id, ScamFlg;
941 unsigned short temp, temp2, temp3, temp4, temp5, temp6;
942 unsigned long ioport;
943 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800945 ioport = pCardInfo->si_baseaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800947 if (RD_HARPOON(ioport + hp_vendor_id_0) != ORION_VEND_0)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800948 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800950 if ((RD_HARPOON(ioport + hp_vendor_id_1) != ORION_VEND_1))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800951 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800953 if ((RD_HARPOON(ioport + hp_device_id_0) != ORION_DEV_0))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800954 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800956 if ((RD_HARPOON(ioport + hp_device_id_1) != ORION_DEV_1))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800957 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800959 if (RD_HARPOON(ioport + hp_rev_num) != 0x0f) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960
961/* For new Harpoon then check for sub_device ID LSB
962 the bits(0-3) must be all ZERO for compatible with
963 current version of SCCBMgr, else skip this Harpoon
964 device. */
965
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800966 if (RD_HARPOON(ioport + hp_sub_device_id_0) & 0x0f)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800967 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 }
969
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800970 if (first_time) {
971 FPT_SccbMgrTableInitAll();
972 first_time = 0;
James Bottomley 47b5d692005-04-24 02:38:05 -0500973 FPT_mbCards = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800974 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800976 if (FPT_RdStack(ioport, 0) != 0x00) {
977 if (FPT_ChkIfChipInitialized(ioport) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 pCurrNvRam = NULL;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800979 WR_HARPOON(ioport + hp_semaphore, 0x00);
980 FPT_XbowInit(ioport, 0); /*Must Init the SCSI before attempting */
James Bottomley 47b5d692005-04-24 02:38:05 -0500981 FPT_DiagEEPROM(ioport);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800982 } else {
983 if (FPT_mbCards < MAX_MB_CARDS) {
James Bottomley 47b5d692005-04-24 02:38:05 -0500984 pCurrNvRam = &FPT_nvRamInfo[FPT_mbCards];
985 FPT_mbCards++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 pCurrNvRam->niBaseAddr = ioport;
James Bottomley 47b5d692005-04-24 02:38:05 -0500987 FPT_RNVRamData(pCurrNvRam);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800988 } else
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800989 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800991 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 pCurrNvRam = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800994 WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT);
995 WR_HARPOON(ioport + hp_sys_ctrl, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800997 if (pCurrNvRam)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 pCardInfo->si_id = pCurrNvRam->niAdapId;
999 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001000 pCardInfo->si_id =
1001 (unsigned
1002 char)(FPT_utilEERead(ioport,
1003 (ADAPTER_SCSI_ID /
1004 2)) & (unsigned char)0x0FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001006 pCardInfo->si_lun = 0x00;
1007 pCardInfo->si_fw_revision = ORION_FW_REV;
1008 temp2 = 0x0000;
1009 temp3 = 0x0000;
1010 temp4 = 0x0000;
1011 temp5 = 0x0000;
1012 temp6 = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001014 for (id = 0; id < (16 / 2); id++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001016 if (pCurrNvRam) {
1017 temp = (unsigned short)pCurrNvRam->niSyncTbl[id];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001019 (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
1020 } else
1021 temp =
1022 FPT_utilEERead(ioport,
1023 (unsigned short)((SYNC_RATE_TBL / 2)
1024 + id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001026 for (i = 0; i < 2; temp >>= 8, i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001028 temp2 >>= 1;
1029 temp3 >>= 1;
1030 temp4 >>= 1;
1031 temp5 >>= 1;
1032 temp6 >>= 1;
1033 switch (temp & 0x3) {
1034 case AUTO_RATE_20: /* Synchronous, 20 mega-transfers/second */
1035 temp6 |= 0x8000; /* Fall through */
1036 case AUTO_RATE_10: /* Synchronous, 10 mega-transfers/second */
1037 temp5 |= 0x8000; /* Fall through */
1038 case AUTO_RATE_05: /* Synchronous, 5 mega-transfers/second */
1039 temp2 |= 0x8000; /* Fall through */
1040 case AUTO_RATE_00: /* Asynchronous */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 break;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001042 }
1043
1044 if (temp & DISC_ENABLE_BIT)
1045 temp3 |= 0x8000;
1046
1047 if (temp & WIDE_NEGO_BIT)
1048 temp4 |= 0x8000;
1049
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 }
1052
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001053 pCardInfo->si_per_targ_init_sync = temp2;
1054 pCardInfo->si_per_targ_no_disc = temp3;
1055 pCardInfo->si_per_targ_wide_nego = temp4;
1056 pCardInfo->si_per_targ_fast_nego = temp5;
1057 pCardInfo->si_per_targ_ultra_nego = temp6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001059 if (pCurrNvRam)
1060 i = pCurrNvRam->niSysConf;
1061 else
1062 i = (unsigned
1063 char)(FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001065 if (pCurrNvRam)
1066 ScamFlg = pCurrNvRam->niScamConf;
1067 else
1068 ScamFlg =
1069 (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001071 pCardInfo->si_flags = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001073 if (i & 0x01)
1074 pCardInfo->si_flags |= SCSI_PARITY_ENA;
1075
1076 if (!(i & 0x02))
1077 pCardInfo->si_flags |= SOFT_RESET;
1078
1079 if (i & 0x10)
1080 pCardInfo->si_flags |= EXTENDED_TRANSLATION;
1081
1082 if (ScamFlg & SCAM_ENABLED)
1083 pCardInfo->si_flags |= FLAG_SCAM_ENABLED;
1084
1085 if (ScamFlg & SCAM_LEVEL2)
1086 pCardInfo->si_flags |= FLAG_SCAM_LEVEL2;
1087
1088 j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
1089 if (i & 0x04) {
1090 j |= SCSI_TERM_ENA_L;
1091 }
1092 WR_HARPOON(ioport + hp_bm_ctrl, j);
1093
1094 j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
1095 if (i & 0x08) {
1096 j |= SCSI_TERM_ENA_H;
1097 }
1098 WR_HARPOON(ioport + hp_ee_ctrl, j);
1099
1100 if (!(RD_HARPOON(ioport + hp_page_ctrl) & NARROW_SCSI_CARD))
1101
1102 pCardInfo->si_flags |= SUPPORT_16TAR_32LUN;
1103
1104 pCardInfo->si_card_family = HARPOON_FAMILY;
1105 pCardInfo->si_bustype = BUSTYPE_PCI;
1106
1107 if (pCurrNvRam) {
1108 pCardInfo->si_card_model[0] = '9';
1109 switch (pCurrNvRam->niModel & 0x0f) {
1110 case MODEL_LT:
1111 pCardInfo->si_card_model[1] = '3';
1112 pCardInfo->si_card_model[2] = '0';
1113 break;
1114 case MODEL_LW:
1115 pCardInfo->si_card_model[1] = '5';
1116 pCardInfo->si_card_model[2] = '0';
1117 break;
1118 case MODEL_DL:
1119 pCardInfo->si_card_model[1] = '3';
1120 pCardInfo->si_card_model[2] = '2';
1121 break;
1122 case MODEL_DW:
1123 pCardInfo->si_card_model[1] = '5';
1124 pCardInfo->si_card_model[2] = '2';
1125 break;
1126 }
1127 } else {
1128 temp = FPT_utilEERead(ioport, (MODEL_NUMB_0 / 2));
1129 pCardInfo->si_card_model[0] = (unsigned char)(temp >> 8);
1130 temp = FPT_utilEERead(ioport, (MODEL_NUMB_2 / 2));
1131
1132 pCardInfo->si_card_model[1] = (unsigned char)(temp & 0x00FF);
1133 pCardInfo->si_card_model[2] = (unsigned char)(temp >> 8);
1134 }
1135
1136 if (pCardInfo->si_card_model[1] == '3') {
1137 if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
1138 pCardInfo->si_flags |= LOW_BYTE_TERM;
1139 } else if (pCardInfo->si_card_model[2] == '0') {
1140 temp = RD_HARPOON(ioport + hp_xfer_pad);
1141 WR_HARPOON(ioport + hp_xfer_pad, (temp & ~BIT(4)));
1142 if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
1143 pCardInfo->si_flags |= LOW_BYTE_TERM;
1144 WR_HARPOON(ioport + hp_xfer_pad, (temp | BIT(4)));
1145 if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
1146 pCardInfo->si_flags |= HIGH_BYTE_TERM;
1147 WR_HARPOON(ioport + hp_xfer_pad, temp);
1148 } else {
1149 temp = RD_HARPOON(ioport + hp_ee_ctrl);
1150 temp2 = RD_HARPOON(ioport + hp_xfer_pad);
1151 WR_HARPOON(ioport + hp_ee_ctrl, (temp | SEE_CS));
1152 WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4)));
1153 temp3 = 0;
1154 for (i = 0; i < 8; i++) {
1155 temp3 <<= 1;
1156 if (!(RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7)))
1157 temp3 |= 1;
1158 WR_HARPOON(ioport + hp_xfer_pad, (temp2 & ~BIT(4)));
1159 WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4)));
1160 }
1161 WR_HARPOON(ioport + hp_ee_ctrl, temp);
1162 WR_HARPOON(ioport + hp_xfer_pad, temp2);
1163 if (!(temp3 & BIT(7)))
1164 pCardInfo->si_flags |= LOW_BYTE_TERM;
1165 if (!(temp3 & BIT(6)))
1166 pCardInfo->si_flags |= HIGH_BYTE_TERM;
1167 }
1168
1169 ARAM_ACCESS(ioport);
1170
1171 for (i = 0; i < 4; i++) {
1172
1173 pCardInfo->si_XlatInfo[i] =
1174 RD_HARPOON(ioport + hp_aramBase + BIOS_DATA_OFFSET + i);
1175 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176
1177 /* return with -1 if no sort, else return with
1178 logical card number sorted by BIOS (zero-based) */
1179
1180 pCardInfo->si_relative_cardnum =
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001181 (unsigned
1182 char)(RD_HARPOON(ioport + hp_aramBase + BIOS_RELATIVE_CARD) - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001184 SGRAM_ACCESS(ioport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001186 FPT_s_PhaseTbl[0] = FPT_phaseDataOut;
1187 FPT_s_PhaseTbl[1] = FPT_phaseDataIn;
1188 FPT_s_PhaseTbl[2] = FPT_phaseIllegal;
1189 FPT_s_PhaseTbl[3] = FPT_phaseIllegal;
1190 FPT_s_PhaseTbl[4] = FPT_phaseCommand;
1191 FPT_s_PhaseTbl[5] = FPT_phaseStatus;
1192 FPT_s_PhaseTbl[6] = FPT_phaseMsgOut;
1193 FPT_s_PhaseTbl[7] = FPT_phaseMsgIn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001195 pCardInfo->si_present = 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001197 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198}
1199
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200/*---------------------------------------------------------------------
1201 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001202 * Function: FlashPoint_HardwareResetHostAdapter
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 *
1204 * Description: Setup adapter for normal operation (hard reset).
1205 *
1206 *---------------------------------------------------------------------*/
1207
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001208static unsigned long FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info
1209 *pCardInfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001211 struct sccb_card *CurrCard = NULL;
1212 struct nvram_info *pCurrNvRam;
1213 unsigned char i, j, thisCard, ScamFlg;
1214 unsigned short temp, sync_bit_map, id;
1215 unsigned long ioport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001217 ioport = pCardInfo->si_baseaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001219 for (thisCard = 0; thisCard <= MAX_CARDS; thisCard++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001221 if (thisCard == MAX_CARDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001223 return FAILURE;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001224 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001226 if (FPT_BL_Card[thisCard].ioPort == ioport) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001228 CurrCard = &FPT_BL_Card[thisCard];
1229 FPT_SccbMgrTableInitCard(CurrCard, thisCard);
1230 break;
1231 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001233 else if (FPT_BL_Card[thisCard].ioPort == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001235 FPT_BL_Card[thisCard].ioPort = ioport;
1236 CurrCard = &FPT_BL_Card[thisCard];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001238 if (FPT_mbCards)
1239 for (i = 0; i < FPT_mbCards; i++) {
1240 if (CurrCard->ioPort ==
1241 FPT_nvRamInfo[i].niBaseAddr)
1242 CurrCard->pNvRamInfo =
1243 &FPT_nvRamInfo[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001245 FPT_SccbMgrTableInitCard(CurrCard, thisCard);
1246 CurrCard->cardIndex = thisCard;
1247 CurrCard->cardInfo = pCardInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001249 break;
1250 }
1251 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252
1253 pCurrNvRam = CurrCard->pNvRamInfo;
1254
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001255 if (pCurrNvRam) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 ScamFlg = pCurrNvRam->niScamConf;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001257 } else {
1258 ScamFlg =
1259 (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 }
1261
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001262 FPT_BusMasterInit(ioport);
1263 FPT_XbowInit(ioport, ScamFlg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001265 FPT_autoLoadDefaultMap(ioport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001267 for (i = 0, id = 0x01; i != pCardInfo->si_id; i++, id <<= 1) {
1268 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001270 WR_HARPOON(ioport + hp_selfid_0, id);
1271 WR_HARPOON(ioport + hp_selfid_1, 0x00);
1272 WR_HARPOON(ioport + hp_arb_id, pCardInfo->si_id);
1273 CurrCard->ourId = pCardInfo->si_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001275 i = (unsigned char)pCardInfo->si_flags;
1276 if (i & SCSI_PARITY_ENA)
1277 WR_HARPOON(ioport + hp_portctrl_1, (HOST_MODE8 | CHK_SCSI_P));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001279 j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
1280 if (i & LOW_BYTE_TERM)
1281 j |= SCSI_TERM_ENA_L;
1282 WR_HARPOON(ioport + hp_bm_ctrl, j);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001284 j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
1285 if (i & HIGH_BYTE_TERM)
1286 j |= SCSI_TERM_ENA_H;
1287 WR_HARPOON(ioport + hp_ee_ctrl, j);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001289 if (!(pCardInfo->si_flags & SOFT_RESET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001291 FPT_sresb(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001293 FPT_scini(thisCard, pCardInfo->si_id, 0);
1294 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001296 if (pCardInfo->si_flags & POST_ALL_UNDERRRUNS)
1297 CurrCard->globalFlags |= F_NO_FILTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001299 if (pCurrNvRam) {
1300 if (pCurrNvRam->niSysConf & 0x10)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 CurrCard->globalFlags |= F_GREEN_PC;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001302 } else {
1303 if (FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)) & GREEN_PC_ENA)
1304 CurrCard->globalFlags |= F_GREEN_PC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305 }
1306
1307 /* Set global flag to indicate Re-Negotiation to be done on all
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001308 ckeck condition */
1309 if (pCurrNvRam) {
1310 if (pCurrNvRam->niScsiConf & 0x04)
1311 CurrCard->globalFlags |= F_DO_RENEGO;
1312 } else {
1313 if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & RENEGO_ENA)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 CurrCard->globalFlags |= F_DO_RENEGO;
1315 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001317 if (pCurrNvRam) {
1318 if (pCurrNvRam->niScsiConf & 0x08)
1319 CurrCard->globalFlags |= F_CONLUN_IO;
1320 } else {
1321 if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & CONNIO_ENA)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 CurrCard->globalFlags |= F_CONLUN_IO;
1323 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001324
1325 temp = pCardInfo->si_per_targ_no_disc;
1326
1327 for (i = 0, id = 1; i < MAX_SCSI_TAR; i++, id <<= 1) {
1328
1329 if (temp & id)
1330 FPT_sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331 }
1332
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001333 sync_bit_map = 0x0001;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001335 for (id = 0; id < (MAX_SCSI_TAR / 2); id++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001337 if (pCurrNvRam) {
1338 temp = (unsigned short)pCurrNvRam->niSyncTbl[id];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339 temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001340 (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
1341 } else
1342 temp =
1343 FPT_utilEERead(ioport,
1344 (unsigned short)((SYNC_RATE_TBL / 2)
1345 + id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001347 for (i = 0; i < 2; temp >>= 8, i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001349 if (pCardInfo->si_per_targ_init_sync & sync_bit_map) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001351 FPT_sccbMgrTbl[thisCard][id * 2 +
1352 i].TarEEValue =
1353 (unsigned char)temp;
1354 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001356 else {
1357 FPT_sccbMgrTbl[thisCard][id * 2 +
1358 i].TarStatus |=
1359 SYNC_SUPPORTED;
1360 FPT_sccbMgrTbl[thisCard][id * 2 +
1361 i].TarEEValue =
1362 (unsigned char)(temp & ~EE_SYNC_MASK);
1363 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365/* if ((pCardInfo->si_per_targ_wide_nego & sync_bit_map) ||
1366 (id*2+i >= 8)){
1367*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001368 if (pCardInfo->si_per_targ_wide_nego & sync_bit_map) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001370 FPT_sccbMgrTbl[thisCard][id * 2 +
1371 i].TarEEValue |=
1372 EE_WIDE_SCSI;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001374 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001376 else { /* NARROW SCSI */
1377 FPT_sccbMgrTbl[thisCard][id * 2 +
1378 i].TarStatus |=
1379 WIDE_NEGOCIATED;
1380 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001382 sync_bit_map <<= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001384 }
1385 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001387 WR_HARPOON((ioport + hp_semaphore),
1388 (unsigned char)(RD_HARPOON((ioport + hp_semaphore)) |
1389 SCCB_MGR_PRESENT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001391 return (unsigned long)CurrCard;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392}
1393
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08001394static void FlashPoint_ReleaseHostAdapter(unsigned long pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395{
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08001396 unsigned char i;
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08001397 unsigned long portBase;
1398 unsigned long regOffset;
1399 unsigned long scamData;
1400 unsigned long *pScamTbl;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001401 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001403 pCurrNvRam = ((struct sccb_card *)pCurrCard)->pNvRamInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001405 if (pCurrNvRam) {
James Bottomley 47b5d692005-04-24 02:38:05 -05001406 FPT_WrStack(pCurrNvRam->niBaseAddr, 0, pCurrNvRam->niModel);
1407 FPT_WrStack(pCurrNvRam->niBaseAddr, 1, pCurrNvRam->niSysConf);
1408 FPT_WrStack(pCurrNvRam->niBaseAddr, 2, pCurrNvRam->niScsiConf);
1409 FPT_WrStack(pCurrNvRam->niBaseAddr, 3, pCurrNvRam->niScamConf);
1410 FPT_WrStack(pCurrNvRam->niBaseAddr, 4, pCurrNvRam->niAdapId);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001412 for (i = 0; i < MAX_SCSI_TAR / 2; i++)
1413 FPT_WrStack(pCurrNvRam->niBaseAddr,
1414 (unsigned char)(i + 5),
1415 pCurrNvRam->niSyncTbl[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416
1417 portBase = pCurrNvRam->niBaseAddr;
1418
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001419 for (i = 0; i < MAX_SCSI_TAR; i++) {
1420 regOffset = hp_aramBase + 64 + i * 4;
1421 pScamTbl = (unsigned long *)&pCurrNvRam->niScamTbl[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 scamData = *pScamTbl;
1423 WR_HARP32(portBase, regOffset, scamData);
1424 }
1425
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001426 } else {
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001427 FPT_WrStack(((struct sccb_card *)pCurrCard)->ioPort, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428 }
1429}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001431static void FPT_RNVRamData(struct nvram_info *pNvRamInfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432{
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08001433 unsigned char i;
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08001434 unsigned long portBase;
1435 unsigned long regOffset;
1436 unsigned long scamData;
1437 unsigned long *pScamTbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001439 pNvRamInfo->niModel = FPT_RdStack(pNvRamInfo->niBaseAddr, 0);
1440 pNvRamInfo->niSysConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 1);
James Bottomley 47b5d692005-04-24 02:38:05 -05001441 pNvRamInfo->niScsiConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 2);
1442 pNvRamInfo->niScamConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 3);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001443 pNvRamInfo->niAdapId = FPT_RdStack(pNvRamInfo->niBaseAddr, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001445 for (i = 0; i < MAX_SCSI_TAR / 2; i++)
1446 pNvRamInfo->niSyncTbl[i] =
1447 FPT_RdStack(pNvRamInfo->niBaseAddr, (unsigned char)(i + 5));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448
1449 portBase = pNvRamInfo->niBaseAddr;
1450
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001451 for (i = 0; i < MAX_SCSI_TAR; i++) {
1452 regOffset = hp_aramBase + 64 + i * 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453 RD_HARP32(portBase, regOffset, scamData);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001454 pScamTbl = (unsigned long *)&pNvRamInfo->niScamTbl[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 *pScamTbl = scamData;
1456 }
1457
1458}
1459
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08001460static unsigned char FPT_RdStack(unsigned long portBase, unsigned char index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461{
1462 WR_HARPOON(portBase + hp_stack_addr, index);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001463 return RD_HARPOON(portBase + hp_stack_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464}
1465
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001466static void FPT_WrStack(unsigned long portBase, unsigned char index,
1467 unsigned char data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468{
1469 WR_HARPOON(portBase + hp_stack_addr, index);
1470 WR_HARPOON(portBase + hp_stack_data, data);
1471}
1472
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08001473static unsigned char FPT_ChkIfChipInitialized(unsigned long ioPort)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001475 if ((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != FPT_RdStack(ioPort, 4))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001476 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001477 if ((RD_HARPOON(ioPort + hp_clkctrl_0) & CLKCTRL_DEFAULT)
1478 != CLKCTRL_DEFAULT)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001479 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001480 if ((RD_HARPOON(ioPort + hp_seltimeout) == TO_250ms) ||
1481 (RD_HARPOON(ioPort + hp_seltimeout) == TO_290ms))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001482 return 1;
1483 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484
1485}
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001486
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487/*---------------------------------------------------------------------
1488 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001489 * Function: FlashPoint_StartCCB
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 *
1491 * Description: Start a command pointed to by p_Sccb. When the
1492 * command is completed it will be returned via the
1493 * callback function.
1494 *
1495 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001496static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb *p_Sccb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001498 unsigned long ioport;
1499 unsigned char thisCard, lun;
1500 struct sccb *pSaveSccb;
1501 CALL_BK_FN callback;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001503 thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
1504 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001506 if ((p_Sccb->TargID > MAX_SCSI_TAR) || (p_Sccb->Lun > MAX_LUN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508 p_Sccb->HostStatus = SCCB_COMPLETE;
1509 p_Sccb->SccbStatus = SCCB_ERROR;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001510 callback = (CALL_BK_FN) p_Sccb->SccbCallback;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 if (callback)
1512 callback(p_Sccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 return;
1515 }
1516
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001517 FPT_sinits(p_Sccb, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001519 if (!((struct sccb_card *)pCurrCard)->cmdCounter) {
1520 WR_HARPOON(ioport + hp_semaphore,
1521 (RD_HARPOON(ioport + hp_semaphore)
1522 | SCCB_MGR_ACTIVE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001524 if (((struct sccb_card *)pCurrCard)->globalFlags & F_GREEN_PC) {
1525 WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT);
1526 WR_HARPOON(ioport + hp_sys_ctrl, 0x00);
1527 }
1528 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001530 ((struct sccb_card *)pCurrCard)->cmdCounter++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001532 if (RD_HARPOON(ioport + hp_semaphore) & BIOS_IN_USE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001534 WR_HARPOON(ioport + hp_semaphore,
1535 (RD_HARPOON(ioport + hp_semaphore)
1536 | TICKLE_ME));
1537 if (p_Sccb->OperationCode == RESET_COMMAND) {
1538 pSaveSccb =
1539 ((struct sccb_card *)pCurrCard)->currentSCCB;
1540 ((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb;
1541 FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
1542 ((struct sccb_card *)pCurrCard)->currentSCCB =
1543 pSaveSccb;
1544 } else {
1545 FPT_queueAddSccb(p_Sccb, thisCard);
1546 }
1547 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001549 else if ((RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001551 if (p_Sccb->OperationCode == RESET_COMMAND) {
1552 pSaveSccb =
1553 ((struct sccb_card *)pCurrCard)->currentSCCB;
1554 ((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb;
1555 FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
1556 ((struct sccb_card *)pCurrCard)->currentSCCB =
1557 pSaveSccb;
1558 } else {
1559 FPT_queueAddSccb(p_Sccb, thisCard);
1560 }
1561 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001563 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001565 MDISABLE_INT(ioport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001567 if ((((struct sccb_card *)pCurrCard)->globalFlags & F_CONLUN_IO)
1568 &&
1569 ((FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].
1570 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571 lun = p_Sccb->Lun;
1572 else
1573 lun = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001574 if ((((struct sccb_card *)pCurrCard)->currentSCCB == NULL) &&
1575 (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarSelQ_Cnt == 0)
1576 && (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarLUNBusy[lun]
1577 == 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001579 ((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb;
1580 FPT_ssel(p_Sccb->SccbIOPort, thisCard);
1581 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001583 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001585 if (p_Sccb->OperationCode == RESET_COMMAND) {
1586 pSaveSccb =
1587 ((struct sccb_card *)pCurrCard)->
1588 currentSCCB;
1589 ((struct sccb_card *)pCurrCard)->currentSCCB =
1590 p_Sccb;
1591 FPT_queueSelectFail(&FPT_BL_Card[thisCard],
1592 thisCard);
1593 ((struct sccb_card *)pCurrCard)->currentSCCB =
1594 pSaveSccb;
1595 } else {
1596 FPT_queueAddSccb(p_Sccb, thisCard);
1597 }
1598 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001600 MENABLE_INT(ioport);
1601 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603}
1604
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605/*---------------------------------------------------------------------
1606 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001607 * Function: FlashPoint_AbortCCB
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 *
1609 * Description: Abort the command pointed to by p_Sccb. When the
1610 * command is completed it will be returned via the
1611 * callback function.
1612 *
1613 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001614static int FlashPoint_AbortCCB(unsigned long pCurrCard, struct sccb *p_Sccb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615{
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08001616 unsigned long ioport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08001618 unsigned char thisCard;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619 CALL_BK_FN callback;
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08001620 unsigned char TID;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001621 struct sccb *pSaveSCCB;
1622 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001624 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001626 thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001628 if (!(RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001630 if (FPT_queueFindSccb(p_Sccb, thisCard)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001632 ((struct sccb_card *)pCurrCard)->cmdCounter--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001634 if (!((struct sccb_card *)pCurrCard)->cmdCounter)
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001635 WR_HARPOON(ioport + hp_semaphore,
1636 (RD_HARPOON(ioport + hp_semaphore)
1637 & (unsigned
1638 char)(~(SCCB_MGR_ACTIVE |
1639 TICKLE_ME))));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641 p_Sccb->SccbStatus = SCCB_ABORT;
1642 callback = p_Sccb->SccbCallback;
1643 callback(p_Sccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001645 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 }
1647
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001648 else {
1649 if (((struct sccb_card *)pCurrCard)->currentSCCB ==
1650 p_Sccb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651 p_Sccb->SccbStatus = SCCB_ABORT;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001652 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653
1654 }
1655
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001656 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657
1658 TID = p_Sccb->TargID;
1659
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001660 if (p_Sccb->Sccb_tag) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 MDISABLE_INT(ioport);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001662 if (((struct sccb_card *)pCurrCard)->
1663 discQ_Tbl[p_Sccb->Sccb_tag] ==
1664 p_Sccb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 p_Sccb->SccbStatus = SCCB_ABORT;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001666 p_Sccb->Sccb_scsistat =
1667 ABORT_ST;
1668 p_Sccb->Sccb_scsimsg =
1669 SMABORT_TAG;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001671 if (((struct sccb_card *)
1672 pCurrCard)->currentSCCB ==
1673 NULL) {
1674 ((struct sccb_card *)
1675 pCurrCard)->
1676 currentSCCB = p_Sccb;
1677 FPT_ssel(ioport,
1678 thisCard);
1679 } else {
1680 pSaveSCCB =
1681 ((struct sccb_card
1682 *)pCurrCard)->
1683 currentSCCB;
1684 ((struct sccb_card *)
1685 pCurrCard)->
1686 currentSCCB = p_Sccb;
1687 FPT_queueSelectFail((struct sccb_card *)pCurrCard, thisCard);
1688 ((struct sccb_card *)
1689 pCurrCard)->
1690 currentSCCB = pSaveSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 }
1692 }
1693 MENABLE_INT(ioport);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001694 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001695 } else {
1696 currTar_Info =
1697 &FPT_sccbMgrTbl[thisCard][p_Sccb->
1698 TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001700 if (FPT_BL_Card[thisCard].
1701 discQ_Tbl[currTar_Info->
1702 LunDiscQ_Idx[p_Sccb->Lun]]
1703 == p_Sccb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 p_Sccb->SccbStatus = SCCB_ABORT;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001705 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 }
1707 }
1708 }
1709 }
1710 }
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001711 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712}
1713
Linus Torvalds1da177e2005-04-16 15:20:36 -07001714/*---------------------------------------------------------------------
1715 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001716 * Function: FlashPoint_InterruptPending
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 *
1718 * Description: Do a quick check to determine if there is a pending
1719 * interrupt for this card and disable the IRQ Pin if so.
1720 *
1721 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08001722static unsigned char FlashPoint_InterruptPending(unsigned long pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001724 unsigned long ioport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001726 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001728 if (RD_HARPOON(ioport + hp_int_status) & INT_ASSERTED) {
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001729 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001730 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001732 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001734 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735}
1736
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737/*---------------------------------------------------------------------
1738 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001739 * Function: FlashPoint_HandleInterrupt
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 *
1741 * Description: This is our entry point when an interrupt is generated
1742 * by the card and the upper level driver passes it on to
1743 * us.
1744 *
1745 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08001746static int FlashPoint_HandleInterrupt(unsigned long pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001748 struct sccb *currSCCB;
1749 unsigned char thisCard, result, bm_status, bm_int_st;
1750 unsigned short hp_int;
1751 unsigned char i, target;
1752 unsigned long ioport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001754 thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
1755 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001757 MDISABLE_INT(ioport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001759 if ((bm_int_st = RD_HARPOON(ioport + hp_int_status)) & EXT_STATUS_ON)
1760 bm_status =
1761 RD_HARPOON(ioport +
1762 hp_ext_status) & (unsigned char)BAD_EXT_STATUS;
1763 else
1764 bm_status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001766 WR_HARPOON(ioport + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001768 while ((hp_int =
1769 RDW_HARPOON((ioport +
1770 hp_intstat)) & FPT_default_intena) | bm_status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001772 currSCCB = ((struct sccb_card *)pCurrCard)->currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001774 if (hp_int & (FIFO | TIMEOUT | RESET | SCAM_SEL) || bm_status) {
1775 result =
1776 FPT_SccbMgr_bad_isr(ioport, thisCard,
1777 ((struct sccb_card *)pCurrCard),
1778 hp_int);
1779 WRW_HARPOON((ioport + hp_intstat),
1780 (FIFO | TIMEOUT | RESET | SCAM_SEL));
1781 bm_status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001783 if (result) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001785 MENABLE_INT(ioport);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001786 return result;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001787 }
1788 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001790 else if (hp_int & ICMD_COMP) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001792 if (!(hp_int & BUS_FREE)) {
1793 /* Wait for the BusFree before starting a new command. We
1794 must also check for being reselected since the BusFree
1795 may not show up if another device reselects us in 1.5us or
1796 less. SRR Wednesday, 3/8/1995.
1797 */
1798 while (!
1799 (RDW_HARPOON((ioport + hp_intstat)) &
1800 (BUS_FREE | RSEL))) ;
1801 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001802
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001803 if (((struct sccb_card *)pCurrCard)->
1804 globalFlags & F_HOST_XFER_ACT)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001806 FPT_phaseChkFifo(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001807
1808/* WRW_HARPOON((ioport+hp_intstat),
1809 (BUS_FREE | ICMD_COMP | ITAR_DISC | XFER_CNT_0));
1810 */
1811
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001812 WRW_HARPOON((ioport + hp_intstat), CLR_ALL_INT_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001814 FPT_autoCmdCmplt(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001816 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001818 else if (hp_int & ITAR_DISC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001820 if (((struct sccb_card *)pCurrCard)->
1821 globalFlags & F_HOST_XFER_ACT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001823 FPT_phaseChkFifo(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825 }
1826
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001827 if (RD_HARPOON(ioport + hp_gp_reg_1) == SMSAVE_DATA_PTR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001828
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001829 WR_HARPOON(ioport + hp_gp_reg_1, 0x00);
1830 currSCCB->Sccb_XferState |= F_NO_DATA_YET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001832 currSCCB->Sccb_savedATC = currSCCB->Sccb_ATC;
1833 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001834
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001835 currSCCB->Sccb_scsistat = DISCONNECT_ST;
1836 FPT_queueDisconnect(currSCCB, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001838 /* Wait for the BusFree before starting a new command. We
1839 must also check for being reselected since the BusFree
1840 may not show up if another device reselects us in 1.5us or
1841 less. SRR Wednesday, 3/8/1995.
1842 */
1843 while (!
1844 (RDW_HARPOON((ioport + hp_intstat)) &
1845 (BUS_FREE | RSEL))
1846 && !((RDW_HARPOON((ioport + hp_intstat)) & PHASE)
1847 && RD_HARPOON((ioport + hp_scsisig)) ==
1848 (SCSI_BSY | SCSI_REQ | SCSI_CD | SCSI_MSG |
1849 SCSI_IOBIT))) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001850
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001851 /*
1852 The additional loop exit condition above detects a timing problem
1853 with the revision D/E harpoon chips. The caller should reset the
1854 host adapter to recover when 0xFE is returned.
1855 */
1856 if (!
1857 (RDW_HARPOON((ioport + hp_intstat)) &
1858 (BUS_FREE | RSEL))) {
1859 MENABLE_INT(ioport);
1860 return 0xFE;
1861 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001862
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001863 WRW_HARPOON((ioport + hp_intstat),
1864 (BUS_FREE | ITAR_DISC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001865
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001866 ((struct sccb_card *)pCurrCard)->globalFlags |=
1867 F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001869 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001870
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001871 else if (hp_int & RSEL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001873 WRW_HARPOON((ioport + hp_intstat),
1874 (PROG_HLT | RSEL | PHASE | BUS_FREE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001875
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001876 if (RDW_HARPOON((ioport + hp_intstat)) & ITAR_DISC) {
1877 if (((struct sccb_card *)pCurrCard)->
1878 globalFlags & F_HOST_XFER_ACT) {
1879 FPT_phaseChkFifo(ioport, thisCard);
1880 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001881
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001882 if (RD_HARPOON(ioport + hp_gp_reg_1) ==
1883 SMSAVE_DATA_PTR) {
1884 WR_HARPOON(ioport + hp_gp_reg_1, 0x00);
1885 currSCCB->Sccb_XferState |=
1886 F_NO_DATA_YET;
1887 currSCCB->Sccb_savedATC =
1888 currSCCB->Sccb_ATC;
1889 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001891 WRW_HARPOON((ioport + hp_intstat),
1892 (BUS_FREE | ITAR_DISC));
1893 currSCCB->Sccb_scsistat = DISCONNECT_ST;
1894 FPT_queueDisconnect(currSCCB, thisCard);
1895 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001897 FPT_sres(ioport, thisCard,
1898 ((struct sccb_card *)pCurrCard));
1899 FPT_phaseDecode(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001901 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001903 else if ((hp_int & IDO_STRT) && (!(hp_int & BUS_FREE))) {
1904
1905 WRW_HARPOON((ioport + hp_intstat),
1906 (IDO_STRT | XFER_CNT_0));
1907 FPT_phaseDecode(ioport, thisCard);
1908
1909 }
1910
1911 else if ((hp_int & IUNKWN) || (hp_int & PROG_HLT)) {
1912 WRW_HARPOON((ioport + hp_intstat),
1913 (PHASE | IUNKWN | PROG_HLT));
1914 if ((RD_HARPOON(ioport + hp_prgmcnt_0) & (unsigned char)
1915 0x3f) < (unsigned char)SELCHK) {
1916 FPT_phaseDecode(ioport, thisCard);
1917 } else {
1918 /* Harpoon problem some SCSI target device respond to selection
1919 with short BUSY pulse (<400ns) this will make the Harpoon is not able
1920 to latch the correct Target ID into reg. x53.
1921 The work around require to correct this reg. But when write to this
1922 reg. (0x53) also increment the FIFO write addr reg (0x6f), thus we
1923 need to read this reg first then restore it later. After update to 0x53 */
1924
1925 i = (unsigned
1926 char)(RD_HARPOON(ioport + hp_fifowrite));
1927 target =
1928 (unsigned
1929 char)(RD_HARPOON(ioport + hp_gp_reg_3));
1930 WR_HARPOON(ioport + hp_xfer_pad,
1931 (unsigned char)ID_UNLOCK);
1932 WR_HARPOON(ioport + hp_select_id,
1933 (unsigned char)(target | target <<
1934 4));
1935 WR_HARPOON(ioport + hp_xfer_pad,
1936 (unsigned char)0x00);
1937 WR_HARPOON(ioport + hp_fifowrite, i);
1938 WR_HARPOON(ioport + hp_autostart_3,
1939 (AUTO_IMMED + TAG_STRT));
1940 }
1941 }
1942
1943 else if (hp_int & XFER_CNT_0) {
1944
1945 WRW_HARPOON((ioport + hp_intstat), XFER_CNT_0);
1946
1947 FPT_schkdd(ioport, thisCard);
1948
1949 }
1950
1951 else if (hp_int & BUS_FREE) {
1952
1953 WRW_HARPOON((ioport + hp_intstat), BUS_FREE);
1954
1955 if (((struct sccb_card *)pCurrCard)->
1956 globalFlags & F_HOST_XFER_ACT) {
1957
1958 FPT_hostDataXferAbort(ioport, thisCard,
1959 currSCCB);
1960 }
1961
1962 FPT_phaseBusFree(ioport, thisCard);
1963 }
1964
1965 else if (hp_int & ITICKLE) {
1966
1967 WRW_HARPOON((ioport + hp_intstat), ITICKLE);
1968 ((struct sccb_card *)pCurrCard)->globalFlags |=
1969 F_NEW_SCCB_CMD;
1970 }
1971
1972 if (((struct sccb_card *)pCurrCard)->
1973 globalFlags & F_NEW_SCCB_CMD) {
1974
1975 ((struct sccb_card *)pCurrCard)->globalFlags &=
1976 ~F_NEW_SCCB_CMD;
1977
1978 if (((struct sccb_card *)pCurrCard)->currentSCCB ==
1979 NULL) {
1980
1981 FPT_queueSearchSelect(((struct sccb_card *)
1982 pCurrCard), thisCard);
1983 }
1984
1985 if (((struct sccb_card *)pCurrCard)->currentSCCB !=
1986 NULL) {
1987 ((struct sccb_card *)pCurrCard)->globalFlags &=
1988 ~F_NEW_SCCB_CMD;
1989 FPT_ssel(ioport, thisCard);
1990 }
1991
1992 break;
1993
1994 }
1995
1996 } /*end while */
1997
1998 MENABLE_INT(ioport);
1999
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002000 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002001}
2002
2003/*---------------------------------------------------------------------
2004 *
2005 * Function: Sccb_bad_isr
2006 *
2007 * Description: Some type of interrupt has occurred which is slightly
2008 * out of the ordinary. We will now decode it fully, in
2009 * this routine. This is broken up in an attempt to save
2010 * processing time.
2011 *
2012 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002013static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port,
2014 unsigned char p_card,
2015 struct sccb_card *pCurrCard,
2016 unsigned short p_int)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002018 unsigned char temp, ScamFlg;
2019 struct sccb_mgr_tar_info *currTar_Info;
2020 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002021
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002022 if (RD_HARPOON(p_port + hp_ext_status) &
2023 (BM_FORCE_OFF | PCI_DEV_TMOUT | BM_PARITY_ERR | PIO_OVERRUN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002024
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002025 if (pCurrCard->globalFlags & F_HOST_XFER_ACT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002027 FPT_hostDataXferAbort(p_port, p_card,
2028 pCurrCard->currentSCCB);
2029 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002030
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002031 if (RD_HARPOON(p_port + hp_pci_stat_cfg) & REC_MASTER_ABORT)
2032 {
2033 WR_HARPOON(p_port + hp_pci_stat_cfg,
2034 (RD_HARPOON(p_port + hp_pci_stat_cfg) &
2035 ~REC_MASTER_ABORT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002037 WR_HARPOON(p_port + hp_host_blk_cnt, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002039 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002040
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002041 if (pCurrCard->currentSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002043 if (!pCurrCard->currentSCCB->HostStatus)
2044 pCurrCard->currentSCCB->HostStatus =
2045 SCCB_BM_ERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002046
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002047 FPT_sxfrp(p_port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002049 temp = (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
2050 (EXT_ARB_ACK | SCSI_TERM_ENA_H));
2051 WR_HARPOON(p_port + hp_ee_ctrl,
2052 ((unsigned char)temp | SEE_MS | SEE_CS));
2053 WR_HARPOON(p_port + hp_ee_ctrl, temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002054
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002055 if (!
2056 (RDW_HARPOON((p_port + hp_intstat)) &
2057 (BUS_FREE | RESET))) {
2058 FPT_phaseDecode(p_port, p_card);
2059 }
2060 }
2061 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002063 else if (p_int & RESET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002065 WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
2066 WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
2067 if (pCurrCard->currentSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002068
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002069 if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002071 FPT_hostDataXferAbort(p_port, p_card,
2072 pCurrCard->currentSCCB);
2073 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002075 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002076
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002077 FPT_sresb(p_port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002078
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002079 while (RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST) {
2080 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002082 pCurrNvRam = pCurrCard->pNvRamInfo;
2083 if (pCurrNvRam) {
2084 ScamFlg = pCurrNvRam->niScamConf;
2085 } else {
2086 ScamFlg =
2087 (unsigned char)FPT_utilEERead(p_port,
2088 SCAM_CONFIG / 2);
2089 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002091 FPT_XbowInit(p_port, ScamFlg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002092
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002093 FPT_scini(p_card, pCurrCard->ourId, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002094
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002095 return 0xFF;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002096 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002098 else if (p_int & FIFO) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002100 WRW_HARPOON((p_port + hp_intstat), FIFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002102 if (pCurrCard->currentSCCB != NULL)
2103 FPT_sxfrp(p_port, p_card);
2104 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002106 else if (p_int & TIMEOUT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002108 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002110 WRW_HARPOON((p_port + hp_intstat),
2111 (PROG_HLT | TIMEOUT | SEL | BUS_FREE | PHASE |
2112 IUNKWN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002114 pCurrCard->currentSCCB->HostStatus = SCCB_SELECTION_TIMEOUT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002116 currTar_Info =
2117 &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
2118 if ((pCurrCard->globalFlags & F_CONLUN_IO)
2119 && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
2120 TAG_Q_TRYING))
2121 currTar_Info->TarLUNBusy[pCurrCard->currentSCCB->Lun] =
2122 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002124 currTar_Info->TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002126 if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
2127 currTar_Info->TarSyncCtrl = 0;
2128 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2129 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002131 if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
2132 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2133 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002135 FPT_sssyncv(p_port, pCurrCard->currentSCCB->TargID, NARROW_SCSI,
2136 currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002138 FPT_queueCmdComplete(pCurrCard, pCurrCard->currentSCCB, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002140 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002142 else if (p_int & SCAM_SEL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002144 FPT_scarb(p_port, LEVEL2_TAR);
2145 FPT_scsel(p_port);
2146 FPT_scasid(p_card, p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002148 FPT_scbusf(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002149
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002150 WRW_HARPOON((p_port + hp_intstat), SCAM_SEL);
2151 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002153 return 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154}
2155
Linus Torvalds1da177e2005-04-16 15:20:36 -07002156/*---------------------------------------------------------------------
2157 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 * Function: SccbMgrTableInit
2159 *
2160 * Description: Initialize all Sccb manager data structures.
2161 *
2162 *---------------------------------------------------------------------*/
2163
James Bottomley 47b5d692005-04-24 02:38:05 -05002164static void FPT_SccbMgrTableInitAll()
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002166 unsigned char thisCard;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002168 for (thisCard = 0; thisCard < MAX_CARDS; thisCard++) {
2169 FPT_SccbMgrTableInitCard(&FPT_BL_Card[thisCard], thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002170
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002171 FPT_BL_Card[thisCard].ioPort = 0x00;
2172 FPT_BL_Card[thisCard].cardInfo = NULL;
2173 FPT_BL_Card[thisCard].cardIndex = 0xFF;
2174 FPT_BL_Card[thisCard].ourId = 0x00;
2175 FPT_BL_Card[thisCard].pNvRamInfo = NULL;
2176 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177}
2178
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179/*---------------------------------------------------------------------
2180 *
2181 * Function: SccbMgrTableInit
2182 *
2183 * Description: Initialize all Sccb manager data structures.
2184 *
2185 *---------------------------------------------------------------------*/
2186
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002187static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard,
2188 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002190 unsigned char scsiID, qtag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002192 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002193 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194 }
2195
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002196 for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
2197 FPT_sccbMgrTbl[p_card][scsiID].TarStatus = 0;
2198 FPT_sccbMgrTbl[p_card][scsiID].TarEEValue = 0;
2199 FPT_SccbMgrTableInitTarget(p_card, scsiID);
2200 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002202 pCurrCard->scanIndex = 0x00;
2203 pCurrCard->currentSCCB = NULL;
2204 pCurrCard->globalFlags = 0x00;
2205 pCurrCard->cmdCounter = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206 pCurrCard->tagQ_Lst = 0x01;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002207 pCurrCard->discQCount = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208
2209}
2210
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211/*---------------------------------------------------------------------
2212 *
2213 * Function: SccbMgrTableInit
2214 *
2215 * Description: Initialize all Sccb manager data structures.
2216 *
2217 *---------------------------------------------------------------------*/
2218
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002219static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
2220 unsigned char target)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221{
2222
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08002223 unsigned char lun, qtag;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002224 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225
James Bottomley 47b5d692005-04-24 02:38:05 -05002226 currTar_Info = &FPT_sccbMgrTbl[p_card][target];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002227
2228 currTar_Info->TarSelQ_Cnt = 0;
2229 currTar_Info->TarSyncCtrl = 0;
2230
2231 currTar_Info->TarSelQ_Head = NULL;
2232 currTar_Info->TarSelQ_Tail = NULL;
2233 currTar_Info->TarTagQ_Cnt = 0;
James Bottomley 47b5d692005-04-24 02:38:05 -05002234 currTar_Info->TarLUN_CA = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002236 for (lun = 0; lun < MAX_LUN; lun++) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002237 currTar_Info->TarLUNBusy[lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002238 currTar_Info->LunDiscQ_Idx[lun] = 0;
2239 }
2240
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002241 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
2242 if (FPT_BL_Card[p_card].discQ_Tbl[qtag] != NULL) {
2243 if (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
2244 target) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002245 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
2246 FPT_BL_Card[p_card].discQCount--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 }
2248 }
2249 }
2250}
2251
Linus Torvalds1da177e2005-04-16 15:20:36 -07002252/*---------------------------------------------------------------------
2253 *
2254 * Function: sfetm
2255 *
2256 * Description: Read in a message byte from the SCSI bus, and check
2257 * for a parity error.
2258 *
2259 *---------------------------------------------------------------------*/
2260
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002261static unsigned char FPT_sfm(unsigned long port, struct sccb *pCurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262{
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08002263 unsigned char message;
Alexey Dobriyanc823fee2006-03-08 00:14:25 -08002264 unsigned short TimeOutLoop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002265
2266 TimeOutLoop = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002267 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2268 (TimeOutLoop++ < 20000)) {
2269 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002271 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002273 message = RD_HARPOON(port + hp_scsidata_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002275 WR_HARPOON(port + hp_scsisig, SCSI_ACK + S_MSGI_PH);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276
2277 if (TimeOutLoop > 20000)
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002278 message = 0x00; /* force message byte = 0 if Time Out on Req */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002280 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
2281 (RD_HARPOON(port + hp_addstat) & SCSI_PAR_ERR)) {
2282 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2283 WR_HARPOON(port + hp_xferstat, 0);
2284 WR_HARPOON(port + hp_fiforead, 0);
2285 WR_HARPOON(port + hp_fifowrite, 0);
2286 if (pCurrSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 pCurrSCCB->Sccb_scsimsg = SMPARITY;
2288 }
2289 message = 0x00;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002290 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291 ACCEPT_MSG_ATN(port);
2292 TimeOutLoop = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002293 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2294 (TimeOutLoop++ < 20000)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002296 if (TimeOutLoop > 20000) {
2297 WRW_HARPOON((port + hp_intstat), PARITY);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002298 return message;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002300 if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) !=
2301 S_MSGI_PH) {
2302 WRW_HARPOON((port + hp_intstat), PARITY);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002303 return message;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002304 }
2305 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002307 RD_HARPOON(port + hp_scsidata_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002309 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002311 } while (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312
2313 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002314 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2315 WR_HARPOON(port + hp_xferstat, 0);
2316 WR_HARPOON(port + hp_fiforead, 0);
2317 WR_HARPOON(port + hp_fifowrite, 0);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002318 return message;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002319}
2320
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321/*---------------------------------------------------------------------
2322 *
James Bottomley 47b5d692005-04-24 02:38:05 -05002323 * Function: FPT_ssel
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324 *
2325 * Description: Load up automation and select target device.
2326 *
2327 *---------------------------------------------------------------------*/
2328
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08002329static void FPT_ssel(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330{
2331
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002332 unsigned char auto_loaded, i, target, *theCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002334 unsigned long cdb_reg;
2335 struct sccb_card *CurrCard;
2336 struct sccb *currSCCB;
2337 struct sccb_mgr_tar_info *currTar_Info;
2338 unsigned char lastTag, lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002339
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002340 CurrCard = &FPT_BL_Card[p_card];
2341 currSCCB = CurrCard->currentSCCB;
2342 target = currSCCB->TargID;
2343 currTar_Info = &FPT_sccbMgrTbl[p_card][target];
2344 lastTag = CurrCard->tagQ_Lst;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002346 ARAM_ACCESS(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347
2348 if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
2349 currSCCB->ControlByte &= ~F_USE_CMD_Q;
2350
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002351 if (((CurrCard->globalFlags & F_CONLUN_IO) &&
2352 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002354 lun = currSCCB->Lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355 else
2356 lun = 0;
2357
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002358 if (CurrCard->globalFlags & F_TAG_STARTED) {
2359 if (!(currSCCB->ControlByte & F_USE_CMD_Q)) {
2360 if ((currTar_Info->TarLUN_CA == 0)
2361 && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
2362 == TAG_Q_TRYING)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002364 if (currTar_Info->TarTagQ_Cnt != 0) {
2365 currTar_Info->TarLUNBusy[lun] = 1;
2366 FPT_queueSelectFail(CurrCard, p_card);
2367 SGRAM_ACCESS(port);
2368 return;
2369 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002371 else {
2372 currTar_Info->TarLUNBusy[lun] = 1;
2373 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002375 }
2376 /*End non-tagged */
2377 else {
2378 currTar_Info->TarLUNBusy[lun] = 1;
2379 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002381 }
2382 /*!Use cmd Q Tagged */
2383 else {
2384 if (currTar_Info->TarLUN_CA == 1) {
2385 FPT_queueSelectFail(CurrCard, p_card);
2386 SGRAM_ACCESS(port);
2387 return;
2388 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002389
James Bottomley 47b5d692005-04-24 02:38:05 -05002390 currTar_Info->TarLUNBusy[lun] = 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002391
2392 } /*else use cmd Q tagged */
2393
2394 }
2395 /*if glob tagged started */
2396 else {
2397 currTar_Info->TarLUNBusy[lun] = 1;
2398 }
2399
2400 if ((((CurrCard->globalFlags & F_CONLUN_IO) &&
2401 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
2402 || (!(currSCCB->ControlByte & F_USE_CMD_Q)))) {
2403 if (CurrCard->discQCount >= QUEUE_DEPTH) {
2404 currTar_Info->TarLUNBusy[lun] = 1;
2405 FPT_queueSelectFail(CurrCard, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406 SGRAM_ACCESS(port);
2407 return;
2408 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002409 for (i = 1; i < QUEUE_DEPTH; i++) {
2410 if (++lastTag >= QUEUE_DEPTH)
2411 lastTag = 1;
2412 if (CurrCard->discQ_Tbl[lastTag] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413 CurrCard->tagQ_Lst = lastTag;
2414 currTar_Info->LunDiscQ_Idx[lun] = lastTag;
2415 CurrCard->discQ_Tbl[lastTag] = currSCCB;
2416 CurrCard->discQCount++;
2417 break;
2418 }
2419 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002420 if (i == QUEUE_DEPTH) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002421 currTar_Info->TarLUNBusy[lun] = 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002422 FPT_queueSelectFail(CurrCard, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423 SGRAM_ACCESS(port);
2424 return;
2425 }
2426 }
2427
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002428 auto_loaded = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002430 WR_HARPOON(port + hp_select_id, target);
2431 WR_HARPOON(port + hp_gp_reg_3, target); /* Use by new automation logic */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002433 if (currSCCB->OperationCode == RESET_COMMAND) {
2434 WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
2435 (currSCCB->
2436 Sccb_idmsg & ~DISC_PRIV)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002438 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + NP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002440 currSCCB->Sccb_scsimsg = SMDEV_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002442 WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
2443 auto_loaded = 1;
2444 currSCCB->Sccb_scsistat = SELECT_BDR_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002446 if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
2447 currTar_Info->TarSyncCtrl = 0;
2448 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002449 }
2450
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002451 if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
2452 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2453 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002455 FPT_sssyncv(port, target, NARROW_SCSI, currTar_Info);
2456 FPT_SccbMgrTableInitTarget(p_card, target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002458 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002460 else if (currSCCB->Sccb_scsistat == ABORT_ST) {
2461 WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
2462 (currSCCB->
2463 Sccb_idmsg & ~DISC_PRIV)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002465 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002467 WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT +
2468 (((unsigned
2469 char)(currSCCB->
2470 ControlByte &
2471 TAG_TYPE_MASK)
2472 >> 6) | (unsigned char)
2473 0x20)));
2474 WRW_HARPOON((port + SYNC_MSGS + 2),
2475 (MPM_OP + AMSG_OUT + currSCCB->Sccb_tag));
2476 WRW_HARPOON((port + SYNC_MSGS + 4), (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002478 WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
2479 auto_loaded = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002481 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002483 else if (!(currTar_Info->TarStatus & WIDE_NEGOCIATED)) {
2484 auto_loaded = FPT_siwidn(port, p_card);
2485 currSCCB->Sccb_scsistat = SELECT_WN_ST;
2486 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002488 else if (!((currTar_Info->TarStatus & TAR_SYNC_MASK)
2489 == SYNC_SUPPORTED)) {
2490 auto_loaded = FPT_sisyncn(port, p_card, 0);
2491 currSCCB->Sccb_scsistat = SELECT_SN_ST;
2492 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002494 if (!auto_loaded) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002496 if (currSCCB->ControlByte & F_USE_CMD_Q) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002498 CurrCard->globalFlags |= F_TAG_STARTED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002500 if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
2501 == TAG_Q_REJECT) {
2502 currSCCB->ControlByte &= ~F_USE_CMD_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002504 /* Fix up the start instruction with a jump to
2505 Non-Tag-CMD handling */
2506 WRW_HARPOON((port + ID_MSG_STRT),
2507 BRH_OP + ALWAYS + NTCMD);
2508
2509 WRW_HARPOON((port + NON_TAG_ID_MSG),
2510 (MPM_OP + AMSG_OUT +
2511 currSCCB->Sccb_idmsg));
2512
2513 WR_HARPOON(port + hp_autostart_3,
2514 (SELECT + SELCHK_STRT));
2515
2516 /* Setup our STATE so we know what happend when
2517 the wheels fall off. */
2518 currSCCB->Sccb_scsistat = SELECT_ST;
2519
2520 currTar_Info->TarLUNBusy[lun] = 1;
2521 }
2522
2523 else {
2524 WRW_HARPOON((port + ID_MSG_STRT),
2525 (MPM_OP + AMSG_OUT +
2526 currSCCB->Sccb_idmsg));
2527
2528 WRW_HARPOON((port + ID_MSG_STRT + 2),
2529 (MPM_OP + AMSG_OUT +
2530 (((unsigned char)(currSCCB->
2531 ControlByte &
2532 TAG_TYPE_MASK)
2533 >> 6) | (unsigned char)0x20)));
2534
2535 for (i = 1; i < QUEUE_DEPTH; i++) {
2536 if (++lastTag >= QUEUE_DEPTH)
2537 lastTag = 1;
2538 if (CurrCard->discQ_Tbl[lastTag] ==
2539 NULL) {
2540 WRW_HARPOON((port +
2541 ID_MSG_STRT + 6),
2542 (MPM_OP + AMSG_OUT +
2543 lastTag));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544 CurrCard->tagQ_Lst = lastTag;
2545 currSCCB->Sccb_tag = lastTag;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002546 CurrCard->discQ_Tbl[lastTag] =
2547 currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548 CurrCard->discQCount++;
2549 break;
2550 }
2551 }
2552
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002553 if (i == QUEUE_DEPTH) {
2554 currTar_Info->TarLUNBusy[lun] = 1;
2555 FPT_queueSelectFail(CurrCard, p_card);
2556 SGRAM_ACCESS(port);
2557 return;
2558 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002560 currSCCB->Sccb_scsistat = SELECT_Q_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002562 WR_HARPOON(port + hp_autostart_3,
2563 (SELECT + SELCHK_STRT));
2564 }
2565 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002567 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002569 WRW_HARPOON((port + ID_MSG_STRT),
2570 BRH_OP + ALWAYS + NTCMD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002572 WRW_HARPOON((port + NON_TAG_ID_MSG),
2573 (MPM_OP + AMSG_OUT + currSCCB->Sccb_idmsg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002575 currSCCB->Sccb_scsistat = SELECT_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002577 WR_HARPOON(port + hp_autostart_3,
2578 (SELECT + SELCHK_STRT));
2579 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002581 theCCB = (unsigned char *)&currSCCB->Cdb[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002583 cdb_reg = port + CMD_STRT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002585 for (i = 0; i < currSCCB->CdbLength; i++) {
2586 WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + *theCCB));
2587 cdb_reg += 2;
2588 theCCB++;
2589 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002591 if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
2592 WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002593
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002594 }
2595 /* auto_loaded */
2596 WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
2597 WR_HARPOON(port + hp_xferstat, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002599 WRW_HARPOON((port + hp_intstat), (PROG_HLT | TIMEOUT | SEL | BUS_FREE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002601 WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002603 if (!(currSCCB->Sccb_MGRFlags & F_DEV_SELECTED)) {
2604 WR_HARPOON(port + hp_scsictrl_0,
2605 (SEL_TAR | ENA_ATN | ENA_RESEL | ENA_SCAM_SEL));
2606 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002607
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08002608/* auto_loaded = (RD_HARPOON(port+hp_autostart_3) & (unsigned char)0x1F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002609 auto_loaded |= AUTO_IMMED; */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002610 auto_loaded = AUTO_IMMED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002612 DISABLE_AUTO(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002614 WR_HARPOON(port + hp_autostart_3, auto_loaded);
2615 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002617 SGRAM_ACCESS(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618}
2619
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620/*---------------------------------------------------------------------
2621 *
James Bottomley 47b5d692005-04-24 02:38:05 -05002622 * Function: FPT_sres
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623 *
2624 * Description: Hookup the correct CCB and handle the incoming messages.
2625 *
2626 *---------------------------------------------------------------------*/
2627
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002628static void FPT_sres(unsigned long port, unsigned char p_card,
2629 struct sccb_card *pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630{
2631
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002632 unsigned char our_target, message, lun = 0, tag, msgRetryCount;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002634 struct sccb_mgr_tar_info *currTar_Info;
2635 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002637 if (pCurrCard->currentSCCB != NULL) {
2638 currTar_Info =
2639 &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640 DISABLE_AUTO(port);
2641
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002642 WR_HARPOON((port + hp_scsictrl_0), (ENA_RESEL | ENA_SCAM_SEL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643
2644 currSCCB = pCurrCard->currentSCCB;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002645 if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2647 currSCCB->Sccb_scsistat = BUS_FREE_ST;
2648 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002649 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2651 currSCCB->Sccb_scsistat = BUS_FREE_ST;
2652 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002653 if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
2654 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
2655 TAG_Q_TRYING))) {
2656 currTar_Info->TarLUNBusy[currSCCB->Lun] = 0;
2657 if (currSCCB->Sccb_scsistat != ABORT_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658 pCurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002659 pCurrCard->discQ_Tbl[currTar_Info->
2660 LunDiscQ_Idx[currSCCB->
2661 Lun]]
2662 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002664 } else {
2665 currTar_Info->TarLUNBusy[0] = 0;
2666 if (currSCCB->Sccb_tag) {
2667 if (currSCCB->Sccb_scsistat != ABORT_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668 pCurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002669 pCurrCard->discQ_Tbl[currSCCB->
2670 Sccb_tag] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002671 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002672 } else {
2673 if (currSCCB->Sccb_scsistat != ABORT_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674 pCurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002675 pCurrCard->discQ_Tbl[currTar_Info->
2676 LunDiscQ_Idx[0]] =
2677 NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002678 }
2679 }
2680 }
2681
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002682 FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683 }
2684
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002685 WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002687 our_target = (unsigned char)(RD_HARPOON(port + hp_select_id) >> 4);
James Bottomley 47b5d692005-04-24 02:38:05 -05002688 currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690 msgRetryCount = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002691 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002692
James Bottomley 47b5d692005-04-24 02:38:05 -05002693 currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694 tag = 0;
2695
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002696 while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
2697 if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002699 WRW_HARPOON((port + hp_intstat), PHASE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700 return;
2701 }
2702 }
2703
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002704 WRW_HARPOON((port + hp_intstat), PHASE);
2705 if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002707 message = FPT_sfm(port, pCurrCard->currentSCCB);
2708 if (message) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002710 if (message <= (0x80 | LUN_MASK)) {
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08002711 lun = message & (unsigned char)LUN_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002712
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002713 if ((currTar_Info->
2714 TarStatus & TAR_TAG_Q_MASK) ==
2715 TAG_Q_TRYING) {
2716 if (currTar_Info->TarTagQ_Cnt !=
2717 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002719 if (!
2720 (currTar_Info->
2721 TarLUN_CA)) {
2722 ACCEPT_MSG(port); /*Release the ACK for ID msg. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002724 message =
2725 FPT_sfm
2726 (port,
2727 pCurrCard->
2728 currentSCCB);
2729 if (message) {
2730 ACCEPT_MSG
2731 (port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732 }
2733
2734 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002735 message
2736 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002738 if (message !=
2739 0) {
2740 tag =
2741 FPT_sfm
2742 (port,
2743 pCurrCard->
2744 currentSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002746 if (!
2747 (tag))
2748 message
2749 =
2750 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751 }
2752
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002753 }
2754 /*C.A. exists! */
2755 }
2756 /*End Q cnt != 0 */
2757 }
2758 /*End Tag cmds supported! */
2759 }
2760 /*End valid ID message. */
2761 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762
2763 ACCEPT_MSG_ATN(port);
2764 }
2765
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002766 }
2767 /* End good id message. */
2768 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769
James Bottomley 47b5d692005-04-24 02:38:05 -05002770 message = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002772 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773 ACCEPT_MSG_ATN(port);
2774
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002775 while (!
2776 (RDW_HARPOON((port + hp_intstat)) &
2777 (PHASE | RESET))
2778 && !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
2779 && (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002780
2781 return;
2782 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002784 if (message == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785 msgRetryCount++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002786 if (msgRetryCount == 1) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002787 FPT_SendMsg(port, SMPARITY);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002788 } else {
James Bottomley 47b5d692005-04-24 02:38:05 -05002789 FPT_SendMsg(port, SMDEV_RESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002791 FPT_sssyncv(port, our_target, NARROW_SCSI,
2792 currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002794 if (FPT_sccbMgrTbl[p_card][our_target].
2795 TarEEValue & EE_SYNC_MASK) {
2796
2797 FPT_sccbMgrTbl[p_card][our_target].
2798 TarStatus &= ~TAR_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799
2800 }
2801
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002802 if (FPT_sccbMgrTbl[p_card][our_target].
2803 TarEEValue & EE_WIDE_SCSI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002805 FPT_sccbMgrTbl[p_card][our_target].
2806 TarStatus &= ~TAR_WIDE_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002807 }
2808
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002809 FPT_queueFlushTargSccb(p_card, our_target,
2810 SCCB_COMPLETE);
2811 FPT_SccbMgrTableInitTarget(p_card, our_target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812 return;
2813 }
2814 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002815 } while (message == 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002817 if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
2818 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002819 currTar_Info->TarLUNBusy[lun] = 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002820 pCurrCard->currentSCCB =
2821 pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[lun]];
2822 if (pCurrCard->currentSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002824 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825 ACCEPT_MSG_ATN(port);
2826 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002827 } else {
James Bottomley 47b5d692005-04-24 02:38:05 -05002828 currTar_Info->TarLUNBusy[0] = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002829
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002830 if (tag) {
2831 if (pCurrCard->discQ_Tbl[tag] != NULL) {
2832 pCurrCard->currentSCCB =
2833 pCurrCard->discQ_Tbl[tag];
2834 currTar_Info->TarTagQ_Cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002836 } else {
2837 ACCEPT_MSG_ATN(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002839 } else {
2840 pCurrCard->currentSCCB =
2841 pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]];
2842 if (pCurrCard->currentSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002843 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002844 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002845 ACCEPT_MSG_ATN(port);
2846 }
2847 }
2848 }
2849
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002850 if (pCurrCard->currentSCCB != NULL) {
2851 if (pCurrCard->currentSCCB->Sccb_scsistat == ABORT_ST) {
2852 /* During Abort Tag command, the target could have got re-selected
2853 and completed the command. Check the select Q and remove the CCB
2854 if it is in the Select Q */
James Bottomley 47b5d692005-04-24 02:38:05 -05002855 FPT_queueFindSccb(pCurrCard->currentSCCB, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002856 }
2857 }
2858
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002859 while (!(RDW_HARPOON((port + hp_intstat)) & (PHASE | RESET)) &&
2860 !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ) &&
2861 (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862}
2863
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08002864static void FPT_SendMsg(unsigned long port, unsigned char message)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002866 while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
2867 if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002869 WRW_HARPOON((port + hp_intstat), PHASE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870 return;
2871 }
2872 }
2873
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002874 WRW_HARPOON((port + hp_intstat), PHASE);
2875 if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGO_PH) {
2876 WRW_HARPOON((port + hp_intstat),
2877 (BUS_FREE | PHASE | XFER_CNT_0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002878
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002879 WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002880
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002881 WR_HARPOON(port + hp_scsidata_0, message);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002882
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002883 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002884
2885 ACCEPT_MSG(port);
2886
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002887 WR_HARPOON(port + hp_portctrl_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002888
2889 if ((message == SMABORT) || (message == SMDEV_RESET) ||
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002890 (message == SMABORT_TAG)) {
2891 while (!
2892 (RDW_HARPOON((port + hp_intstat)) &
2893 (BUS_FREE | PHASE))) {
2894 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002895
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002896 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
2897 WRW_HARPOON((port + hp_intstat), BUS_FREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002898 }
2899 }
2900 }
2901}
2902
2903/*---------------------------------------------------------------------
2904 *
James Bottomley 47b5d692005-04-24 02:38:05 -05002905 * Function: FPT_sdecm
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906 *
2907 * Description: Determine the proper responce to the message from the
2908 * target device.
2909 *
2910 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002911static void FPT_sdecm(unsigned char message, unsigned long port,
2912 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002913{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002914 struct sccb *currSCCB;
2915 struct sccb_card *CurrCard;
2916 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002917
James Bottomley 47b5d692005-04-24 02:38:05 -05002918 CurrCard = &FPT_BL_Card[p_card];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002919 currSCCB = CurrCard->currentSCCB;
2920
James Bottomley 47b5d692005-04-24 02:38:05 -05002921 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002922
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002923 if (message == SMREST_DATA_PTR) {
2924 if (!(currSCCB->Sccb_XferState & F_NO_DATA_YET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925 currSCCB->Sccb_ATC = currSCCB->Sccb_savedATC;
2926
James Bottomley 47b5d692005-04-24 02:38:05 -05002927 FPT_hostDataXferRestart(currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002928 }
2929
2930 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002931 WR_HARPOON(port + hp_autostart_1,
2932 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002933 }
2934
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002935 else if (message == SMCMD_COMP) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002936
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002937 if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
2938 currTar_Info->TarStatus &=
2939 ~(unsigned char)TAR_TAG_Q_MASK;
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08002940 currTar_Info->TarStatus |= (unsigned char)TAG_Q_REJECT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002941 }
2942
2943 ACCEPT_MSG(port);
2944
2945 }
2946
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002947 else if ((message == SMNO_OP) || (message >= SMIDENT)
2948 || (message == SMINIT_RECOVERY) || (message == SMREL_RECOVERY)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002949
2950 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002951 WR_HARPOON(port + hp_autostart_1,
2952 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953 }
2954
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002955 else if (message == SMREJECT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956
2957 if ((currSCCB->Sccb_scsistat == SELECT_SN_ST) ||
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002958 (currSCCB->Sccb_scsistat == SELECT_WN_ST) ||
2959 ((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)
2960 || ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) ==
2961 TAG_Q_TRYING))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002962 {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002963 WRW_HARPOON((port + hp_intstat), BUS_FREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964
2965 ACCEPT_MSG(port);
2966
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002967 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2968 (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002969 {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002970 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002971
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002972 if (currSCCB->Lun == 0x00) {
2973 if ((currSCCB->Sccb_scsistat == SELECT_SN_ST)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002974
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002975 currTar_Info->TarStatus |=
2976 (unsigned char)SYNC_SUPPORTED;
2977
2978 currTar_Info->TarEEValue &=
2979 ~EE_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002980 }
2981
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002982 else if ((currSCCB->Sccb_scsistat ==
2983 SELECT_WN_ST)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002984
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002985 currTar_Info->TarStatus =
2986 (currTar_Info->
2987 TarStatus & ~WIDE_ENABLED) |
2988 WIDE_NEGOCIATED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002989
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002990 currTar_Info->TarEEValue &=
2991 ~EE_WIDE_SCSI;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002992
2993 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002994
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002995 else if ((currTar_Info->
2996 TarStatus & TAR_TAG_Q_MASK) ==
2997 TAG_Q_TRYING) {
2998 currTar_Info->TarStatus =
2999 (currTar_Info->
3000 TarStatus & ~(unsigned char)
3001 TAR_TAG_Q_MASK) | TAG_Q_REJECT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002
3003 currSCCB->ControlByte &= ~F_USE_CMD_Q;
3004 CurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003005 CurrCard->discQ_Tbl[currSCCB->
3006 Sccb_tag] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007 currSCCB->Sccb_tag = 0x00;
3008
3009 }
3010 }
3011
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003012 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003014 if (currSCCB->Lun == 0x00) {
3015 WRW_HARPOON((port + hp_intstat),
3016 BUS_FREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017 CurrCard->globalFlags |= F_NEW_SCCB_CMD;
3018 }
3019 }
3020
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003021 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003023 if ((CurrCard->globalFlags & F_CONLUN_IO) &&
3024 ((currTar_Info->
3025 TarStatus & TAR_TAG_Q_MASK) !=
3026 TAG_Q_TRYING))
3027 currTar_Info->TarLUNBusy[currSCCB->
3028 Lun] = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029 else
James Bottomley 47b5d692005-04-24 02:38:05 -05003030 currTar_Info->TarLUNBusy[0] = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003032 currSCCB->ControlByte &=
3033 ~(unsigned char)F_USE_CMD_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003035 WR_HARPOON(port + hp_autostart_1,
3036 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037
3038 }
3039 }
3040
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003041 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003042 ACCEPT_MSG(port);
3043
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003044 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
3045 (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003046 {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003047 }
3048
3049 if (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)) {
3050 WR_HARPOON(port + hp_autostart_1,
3051 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003052 }
3053 }
3054 }
3055
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003056 else if (message == SMEXT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057
3058 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003059 FPT_shandem(port, p_card, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003060 }
3061
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003062 else if (message == SMIGNORWR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003064 ACCEPT_MSG(port); /* ACK the RESIDUE MSG */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003066 message = FPT_sfm(port, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003067
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003068 if (currSCCB->Sccb_scsimsg != SMPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003070 WR_HARPOON(port + hp_autostart_1,
3071 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072 }
3073
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003074 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075
3076 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
3077 currSCCB->Sccb_scsimsg = SMREJECT;
3078
3079 ACCEPT_MSG_ATN(port);
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 }
3083}
3084
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085/*---------------------------------------------------------------------
3086 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003087 * Function: FPT_shandem
Linus Torvalds1da177e2005-04-16 15:20:36 -07003088 *
3089 * Description: Decide what to do with the extended message.
3090 *
3091 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003092static void FPT_shandem(unsigned long port, unsigned char p_card,
3093 struct sccb *pCurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003094{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003095 unsigned char length, message;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003096
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003097 length = FPT_sfm(port, pCurrSCCB);
3098 if (length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003099
3100 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003101 message = FPT_sfm(port, pCurrSCCB);
3102 if (message) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003104 if (message == SMSYNC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003106 if (length == 0x03) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107
3108 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003109 FPT_stsyncn(port, p_card);
3110 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003111
3112 pCurrSCCB->Sccb_scsimsg = SMREJECT;
3113 ACCEPT_MSG_ATN(port);
3114 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003115 } else if (message == SMWDTR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003116
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003117 if (length == 0x02) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003118
3119 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003120 FPT_stwidn(port, p_card);
3121 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003122
3123 pCurrSCCB->Sccb_scsimsg = SMREJECT;
3124 ACCEPT_MSG_ATN(port);
3125
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003126 WR_HARPOON(port + hp_autostart_1,
3127 (AUTO_IMMED +
3128 DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003129 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003130 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131
3132 pCurrSCCB->Sccb_scsimsg = SMREJECT;
3133 ACCEPT_MSG_ATN(port);
3134
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003135 WR_HARPOON(port + hp_autostart_1,
3136 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003137 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003138 } else {
3139 if (pCurrSCCB->Sccb_scsimsg != SMPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003140 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003141 WR_HARPOON(port + hp_autostart_1,
3142 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003143 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003144 } else {
3145 if (pCurrSCCB->Sccb_scsimsg == SMPARITY)
3146 WR_HARPOON(port + hp_autostart_1,
3147 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003148 }
3149}
3150
Linus Torvalds1da177e2005-04-16 15:20:36 -07003151/*---------------------------------------------------------------------
3152 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003153 * Function: FPT_sisyncn
Linus Torvalds1da177e2005-04-16 15:20:36 -07003154 *
3155 * Description: Read in a message byte from the SCSI bus, and check
3156 * for a parity error.
3157 *
3158 *---------------------------------------------------------------------*/
3159
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003160static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card,
3161 unsigned char syncFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003162{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003163 struct sccb *currSCCB;
3164 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003165
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003166 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3167 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003168
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003169 if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003171 WRW_HARPOON((port + ID_MSG_STRT),
3172 (MPM_OP + AMSG_OUT +
3173 (currSCCB->
3174 Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003175
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003176 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003178 WRW_HARPOON((port + SYNC_MSGS + 0),
3179 (MPM_OP + AMSG_OUT + SMEXT));
3180 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
3181 WRW_HARPOON((port + SYNC_MSGS + 4),
3182 (MPM_OP + AMSG_OUT + SMSYNC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003183
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003184 if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003186 WRW_HARPOON((port + SYNC_MSGS + 6),
3187 (MPM_OP + AMSG_OUT + 12));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003188
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003189 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
3190 EE_SYNC_10MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003192 WRW_HARPOON((port + SYNC_MSGS + 6),
3193 (MPM_OP + AMSG_OUT + 25));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003195 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
3196 EE_SYNC_5MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003198 WRW_HARPOON((port + SYNC_MSGS + 6),
3199 (MPM_OP + AMSG_OUT + 50));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003200
Linus Torvalds1da177e2005-04-16 15:20:36 -07003201 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003202 WRW_HARPOON((port + SYNC_MSGS + 6),
3203 (MPM_OP + AMSG_OUT + 00));
3204
3205 WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
3206 WRW_HARPOON((port + SYNC_MSGS + 10),
3207 (MPM_OP + AMSG_OUT + DEFAULT_OFFSET));
3208 WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
3209
3210 if (syncFlag == 0) {
3211 WR_HARPOON(port + hp_autostart_3,
3212 (SELECT + SELCHK_STRT));
3213 currTar_Info->TarStatus =
3214 ((currTar_Info->
3215 TarStatus & ~(unsigned char)TAR_SYNC_MASK) |
3216 (unsigned char)SYNC_TRYING);
3217 } else {
3218 WR_HARPOON(port + hp_autostart_3,
3219 (AUTO_IMMED + CMD_ONLY_STRT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003220 }
3221
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08003222 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003223 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003224
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003225 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003226
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003227 currTar_Info->TarStatus |= (unsigned char)SYNC_SUPPORTED;
3228 currTar_Info->TarEEValue &= ~EE_SYNC_MASK;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08003229 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003230 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231}
3232
Linus Torvalds1da177e2005-04-16 15:20:36 -07003233/*---------------------------------------------------------------------
3234 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003235 * Function: FPT_stsyncn
Linus Torvalds1da177e2005-04-16 15:20:36 -07003236 *
3237 * Description: The has sent us a Sync Nego message so handle it as
3238 * necessary.
3239 *
3240 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08003241static void FPT_stsyncn(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003242{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003243 unsigned char sync_msg, offset, sync_reg, our_sync_msg;
3244 struct sccb *currSCCB;
3245 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003246
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003247 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3248 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003249
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003250 sync_msg = FPT_sfm(port, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003251
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003252 if ((sync_msg == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3253 WR_HARPOON(port + hp_autostart_1,
3254 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003255 return;
3256 }
3257
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003258 ACCEPT_MSG(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003260 offset = FPT_sfm(port, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003261
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003262 if ((offset == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3263 WR_HARPOON(port + hp_autostart_1,
3264 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003265 return;
3266 }
3267
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003268 if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003270 our_sync_msg = 12; /* Setup our Message to 20mb/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003271
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003272 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_10MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003274 our_sync_msg = 25; /* Setup our Message to 10mb/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003275
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003276 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_5MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003277
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003278 our_sync_msg = 50; /* Setup our Message to 5mb/s */
3279 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003280
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003281 our_sync_msg = 0; /* Message = Async */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003282
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003283 if (sync_msg < our_sync_msg) {
3284 sync_msg = our_sync_msg; /*if faster, then set to max. */
3285 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003286
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003287 if (offset == ASYNC)
3288 sync_msg = ASYNC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003289
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003290 if (offset > MAX_OFFSET)
3291 offset = MAX_OFFSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003292
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003293 sync_reg = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003294
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003295 if (sync_msg > 12)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003296
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003297 sync_reg = 0x20; /* Use 10MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003298
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003299 if (sync_msg > 25)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003300
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003301 sync_reg = 0x40; /* Use 6.6MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003302
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003303 if (sync_msg > 38)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003304
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003305 sync_reg = 0x60; /* Use 5MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003306
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003307 if (sync_msg > 50)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003308
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003309 sync_reg = 0x80; /* Use 4MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003310
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003311 if (sync_msg > 62)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003312
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003313 sync_reg = 0xA0; /* Use 3.33MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003314
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003315 if (sync_msg > 75)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003316
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003317 sync_reg = 0xC0; /* Use 2.85MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003318
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003319 if (sync_msg > 87)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003320
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003321 sync_reg = 0xE0; /* Use 2.5MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003322
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003323 if (sync_msg > 100) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003324
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003325 sync_reg = 0x00; /* Use ASYNC */
3326 offset = 0x00;
3327 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003328
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003329 if (currTar_Info->TarStatus & WIDE_ENABLED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003330
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003331 sync_reg |= offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003332
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003333 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003334
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003335 sync_reg |= (offset | NARROW_SCSI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003336
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003337 FPT_sssyncv(port, currSCCB->TargID, sync_reg, currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003338
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003339 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003340
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003341 ACCEPT_MSG(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003342
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003343 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3344 ~(unsigned char)TAR_SYNC_MASK) |
3345 (unsigned char)SYNC_SUPPORTED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003346
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003347 WR_HARPOON(port + hp_autostart_1,
3348 (AUTO_IMMED + DISCONNECT_START));
3349 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003350
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003351 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003352
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003353 ACCEPT_MSG_ATN(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003354
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003355 FPT_sisyncr(port, sync_msg, offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003356
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003357 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3358 ~(unsigned char)TAR_SYNC_MASK) |
3359 (unsigned char)SYNC_SUPPORTED);
3360 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003361}
3362
Linus Torvalds1da177e2005-04-16 15:20:36 -07003363/*---------------------------------------------------------------------
3364 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003365 * Function: FPT_sisyncr
Linus Torvalds1da177e2005-04-16 15:20:36 -07003366 *
3367 * Description: Answer the targets sync message.
3368 *
3369 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003370static void FPT_sisyncr(unsigned long port, unsigned char sync_pulse,
3371 unsigned char offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003372{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003373 ARAM_ACCESS(port);
3374 WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT));
3375 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
3376 WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMSYNC));
3377 WRW_HARPOON((port + SYNC_MSGS + 6), (MPM_OP + AMSG_OUT + sync_pulse));
3378 WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
3379 WRW_HARPOON((port + SYNC_MSGS + 10), (MPM_OP + AMSG_OUT + offset));
3380 WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
3381 SGRAM_ACCESS(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003382
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003383 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3384 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003385
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003386 WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003387
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003388 while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
3389 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390}
3391
Linus Torvalds1da177e2005-04-16 15:20:36 -07003392/*---------------------------------------------------------------------
3393 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003394 * Function: FPT_siwidn
Linus Torvalds1da177e2005-04-16 15:20:36 -07003395 *
3396 * Description: Read in a message byte from the SCSI bus, and check
3397 * for a parity error.
3398 *
3399 *---------------------------------------------------------------------*/
3400
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08003401static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003402{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003403 struct sccb *currSCCB;
3404 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003405
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003406 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3407 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003408
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003409 if (!((currTar_Info->TarStatus & TAR_WIDE_MASK) == WIDE_NEGOCIATED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003410
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003411 WRW_HARPOON((port + ID_MSG_STRT),
3412 (MPM_OP + AMSG_OUT +
3413 (currSCCB->
3414 Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003415
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003416 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003417
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003418 WRW_HARPOON((port + SYNC_MSGS + 0),
3419 (MPM_OP + AMSG_OUT + SMEXT));
3420 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
3421 WRW_HARPOON((port + SYNC_MSGS + 4),
3422 (MPM_OP + AMSG_OUT + SMWDTR));
3423 WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
3424 WRW_HARPOON((port + SYNC_MSGS + 8),
3425 (MPM_OP + AMSG_OUT + SM16BIT));
3426 WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003427
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003428 WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003429
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003430 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3431 ~(unsigned char)TAR_WIDE_MASK) |
3432 (unsigned char)WIDE_ENABLED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003433
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08003434 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003435 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003436
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003437 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003438
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003439 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3440 ~(unsigned char)TAR_WIDE_MASK) |
3441 WIDE_NEGOCIATED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003442
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003443 currTar_Info->TarEEValue &= ~EE_WIDE_SCSI;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08003444 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003445 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003446}
3447
Linus Torvalds1da177e2005-04-16 15:20:36 -07003448/*---------------------------------------------------------------------
3449 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003450 * Function: FPT_stwidn
Linus Torvalds1da177e2005-04-16 15:20:36 -07003451 *
3452 * Description: The has sent us a Wide Nego message so handle it as
3453 * necessary.
3454 *
3455 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08003456static void FPT_stwidn(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003458 unsigned char width;
3459 struct sccb *currSCCB;
3460 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003461
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003462 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3463 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003464
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003465 width = FPT_sfm(port, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003466
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003467 if ((width == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3468 WR_HARPOON(port + hp_autostart_1,
3469 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003470 return;
3471 }
3472
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003473 if (!(currTar_Info->TarEEValue & EE_WIDE_SCSI))
3474 width = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003475
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003476 if (width) {
3477 currTar_Info->TarStatus |= WIDE_ENABLED;
3478 width = 0;
3479 } else {
3480 width = NARROW_SCSI;
3481 currTar_Info->TarStatus &= ~WIDE_ENABLED;
3482 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003483
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003484 FPT_sssyncv(port, currSCCB->TargID, width, currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003485
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003486 if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003487
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003488 currTar_Info->TarStatus |= WIDE_NEGOCIATED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003490 if (!
3491 ((currTar_Info->TarStatus & TAR_SYNC_MASK) ==
3492 SYNC_SUPPORTED)) {
3493 ACCEPT_MSG_ATN(port);
3494 ARAM_ACCESS(port);
3495 FPT_sisyncn(port, p_card, 1);
3496 currSCCB->Sccb_scsistat = SELECT_SN_ST;
3497 SGRAM_ACCESS(port);
3498 } else {
3499 ACCEPT_MSG(port);
3500 WR_HARPOON(port + hp_autostart_1,
3501 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003502 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003503 }
3504
3505 else {
3506
3507 ACCEPT_MSG_ATN(port);
3508
3509 if (currTar_Info->TarEEValue & EE_WIDE_SCSI)
3510 width = SM16BIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003511 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003512 width = SM8BIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003513
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003514 FPT_siwidr(port, width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003515
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003516 currTar_Info->TarStatus |= (WIDE_NEGOCIATED | WIDE_ENABLED);
3517 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003518}
3519
Linus Torvalds1da177e2005-04-16 15:20:36 -07003520/*---------------------------------------------------------------------
3521 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003522 * Function: FPT_siwidr
Linus Torvalds1da177e2005-04-16 15:20:36 -07003523 *
3524 * Description: Answer the targets Wide nego message.
3525 *
3526 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08003527static void FPT_siwidr(unsigned long port, unsigned char width)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003528{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003529 ARAM_ACCESS(port);
3530 WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT));
3531 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
3532 WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMWDTR));
3533 WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
3534 WRW_HARPOON((port + SYNC_MSGS + 8), (MPM_OP + AMSG_OUT + width));
3535 WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
3536 SGRAM_ACCESS(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003537
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003538 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3539 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003540
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003541 WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003542
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003543 while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
3544 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003545}
3546
Linus Torvalds1da177e2005-04-16 15:20:36 -07003547/*---------------------------------------------------------------------
3548 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003549 * Function: FPT_sssyncv
Linus Torvalds1da177e2005-04-16 15:20:36 -07003550 *
3551 * Description: Write the desired value to the Sync Register for the
3552 * ID specified.
3553 *
3554 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003555static void FPT_sssyncv(unsigned long p_port, unsigned char p_id,
3556 unsigned char p_sync_value,
3557 struct sccb_mgr_tar_info *currTar_Info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003558{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003559 unsigned char index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003560
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003561 index = p_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003562
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003563 switch (index) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003564
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003565 case 0:
3566 index = 12; /* hp_synctarg_0 */
3567 break;
3568 case 1:
3569 index = 13; /* hp_synctarg_1 */
3570 break;
3571 case 2:
3572 index = 14; /* hp_synctarg_2 */
3573 break;
3574 case 3:
3575 index = 15; /* hp_synctarg_3 */
3576 break;
3577 case 4:
3578 index = 8; /* hp_synctarg_4 */
3579 break;
3580 case 5:
3581 index = 9; /* hp_synctarg_5 */
3582 break;
3583 case 6:
3584 index = 10; /* hp_synctarg_6 */
3585 break;
3586 case 7:
3587 index = 11; /* hp_synctarg_7 */
3588 break;
3589 case 8:
3590 index = 4; /* hp_synctarg_8 */
3591 break;
3592 case 9:
3593 index = 5; /* hp_synctarg_9 */
3594 break;
3595 case 10:
3596 index = 6; /* hp_synctarg_10 */
3597 break;
3598 case 11:
3599 index = 7; /* hp_synctarg_11 */
3600 break;
3601 case 12:
3602 index = 0; /* hp_synctarg_12 */
3603 break;
3604 case 13:
3605 index = 1; /* hp_synctarg_13 */
3606 break;
3607 case 14:
3608 index = 2; /* hp_synctarg_14 */
3609 break;
3610 case 15:
3611 index = 3; /* hp_synctarg_15 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003612
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003613 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003615 WR_HARPOON(p_port + hp_synctarg_base + index, p_sync_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003616
3617 currTar_Info->TarSyncCtrl = p_sync_value;
3618}
3619
Linus Torvalds1da177e2005-04-16 15:20:36 -07003620/*---------------------------------------------------------------------
3621 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003622 * Function: FPT_sresb
Linus Torvalds1da177e2005-04-16 15:20:36 -07003623 *
3624 * Description: Reset the desired card's SCSI bus.
3625 *
3626 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08003627static void FPT_sresb(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003628{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003629 unsigned char scsiID, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003630
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003631 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003632
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003633 WR_HARPOON(port + hp_page_ctrl,
3634 (RD_HARPOON(port + hp_page_ctrl) | G_INT_DISABLE));
3635 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003636
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003637 WR_HARPOON(port + hp_scsictrl_0, SCSI_RST);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003638
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003639 scsiID = RD_HARPOON(port + hp_seltimeout);
3640 WR_HARPOON(port + hp_seltimeout, TO_5ms);
3641 WRW_HARPOON((port + hp_intstat), TIMEOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003642
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003643 WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT | START_TO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003644
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003645 while (!(RDW_HARPOON((port + hp_intstat)) & TIMEOUT)) {
3646 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003648 WR_HARPOON(port + hp_seltimeout, scsiID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003649
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003650 WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003652 FPT_Wait(port, TO_5ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003654 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003655
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003656 WR_HARPOON(port + hp_int_mask, (RD_HARPOON(port + hp_int_mask) | 0x00));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003657
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003658 for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
3659 currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003660
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003661 if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
3662 currTar_Info->TarSyncCtrl = 0;
3663 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
3664 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003665
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003666 if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
3667 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
3668 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003669
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003670 FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003671
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003672 FPT_SccbMgrTableInitTarget(p_card, scsiID);
3673 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003674
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003675 FPT_BL_Card[p_card].scanIndex = 0x00;
3676 FPT_BL_Card[p_card].currentSCCB = NULL;
3677 FPT_BL_Card[p_card].globalFlags &= ~(F_TAG_STARTED | F_HOST_XFER_ACT
3678 | F_NEW_SCCB_CMD);
3679 FPT_BL_Card[p_card].cmdCounter = 0x00;
James Bottomley 47b5d692005-04-24 02:38:05 -05003680 FPT_BL_Card[p_card].discQCount = 0x00;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003681 FPT_BL_Card[p_card].tagQ_Lst = 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003683 for (i = 0; i < QUEUE_DEPTH; i++)
James Bottomley 47b5d692005-04-24 02:38:05 -05003684 FPT_BL_Card[p_card].discQ_Tbl[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003685
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003686 WR_HARPOON(port + hp_page_ctrl,
3687 (RD_HARPOON(port + hp_page_ctrl) & ~G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003688
3689}
3690
3691/*---------------------------------------------------------------------
3692 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003693 * Function: FPT_ssenss
Linus Torvalds1da177e2005-04-16 15:20:36 -07003694 *
3695 * Description: Setup for the Auto Sense command.
3696 *
3697 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003698static void FPT_ssenss(struct sccb_card *pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003699{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003700 unsigned char i;
3701 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003703 currSCCB = pCurrCard->currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003704
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003705 currSCCB->Save_CdbLen = currSCCB->CdbLength;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003707 for (i = 0; i < 6; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003709 currSCCB->Save_Cdb[i] = currSCCB->Cdb[i];
3710 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003711
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003712 currSCCB->CdbLength = SIX_BYTE_CMD;
3713 currSCCB->Cdb[0] = SCSI_REQUEST_SENSE;
3714 currSCCB->Cdb[1] = currSCCB->Cdb[1] & (unsigned char)0xE0; /*Keep LUN. */
3715 currSCCB->Cdb[2] = 0x00;
3716 currSCCB->Cdb[3] = 0x00;
3717 currSCCB->Cdb[4] = currSCCB->RequestSenseLength;
3718 currSCCB->Cdb[5] = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003719
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003720 currSCCB->Sccb_XferCnt = (unsigned long)currSCCB->RequestSenseLength;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003721
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003722 currSCCB->Sccb_ATC = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003724 currSCCB->Sccb_XferState |= F_AUTO_SENSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003726 currSCCB->Sccb_XferState &= ~F_SG_XFER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003727
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003728 currSCCB->Sccb_idmsg = currSCCB->Sccb_idmsg & ~(unsigned char)DISC_PRIV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003729
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003730 currSCCB->ControlByte = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003731
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003732 currSCCB->Sccb_MGRFlags &= F_STATUSLOADED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003733}
3734
Linus Torvalds1da177e2005-04-16 15:20:36 -07003735/*---------------------------------------------------------------------
3736 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003737 * Function: FPT_sxfrp
Linus Torvalds1da177e2005-04-16 15:20:36 -07003738 *
3739 * Description: Transfer data into the bit bucket until the device
3740 * decides to switch phase.
3741 *
3742 *---------------------------------------------------------------------*/
3743
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08003744static void FPT_sxfrp(unsigned long p_port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003745{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003746 unsigned char curr_phz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003747
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003748 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003749
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003750 if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003751
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003752 FPT_hostDataXferAbort(p_port, p_card,
3753 FPT_BL_Card[p_card].currentSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003754
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003755 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003756
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003757 /* If the Automation handled the end of the transfer then do not
3758 match the phase or we will get out of sync with the ISR. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003759
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003760 if (RDW_HARPOON((p_port + hp_intstat)) &
3761 (BUS_FREE | XFER_CNT_0 | AUTO_INT))
3762 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003763
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003764 WR_HARPOON(p_port + hp_xfercnt_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003766 curr_phz = RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003767
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003768 WRW_HARPOON((p_port + hp_intstat), XFER_CNT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003770 WR_HARPOON(p_port + hp_scsisig, curr_phz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003771
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003772 while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET)) &&
3773 (curr_phz ==
3774 (RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ)))
3775 {
3776 if (curr_phz & (unsigned char)SCSI_IOBIT) {
3777 WR_HARPOON(p_port + hp_portctrl_0,
3778 (SCSI_PORT | HOST_PORT | SCSI_INBIT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003780 if (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
3781 RD_HARPOON(p_port + hp_fifodata_0);
3782 }
3783 } else {
3784 WR_HARPOON(p_port + hp_portctrl_0,
3785 (SCSI_PORT | HOST_PORT | HOST_WRT));
3786 if (RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY) {
3787 WR_HARPOON(p_port + hp_fifodata_0, 0xFA);
3788 }
3789 }
3790 } /* End of While loop for padding data I/O phase */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003792 while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
3793 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ)
3794 break;
3795 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003796
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003797 WR_HARPOON(p_port + hp_portctrl_0,
3798 (SCSI_PORT | HOST_PORT | SCSI_INBIT));
3799 while (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
3800 RD_HARPOON(p_port + hp_fifodata_0);
3801 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003802
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003803 if (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
3804 WR_HARPOON(p_port + hp_autostart_0,
3805 (AUTO_IMMED + DISCONNECT_START));
3806 while (!(RDW_HARPOON((p_port + hp_intstat)) & AUTO_INT)) {
3807 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003808
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003809 if (RDW_HARPOON((p_port + hp_intstat)) &
3810 (ICMD_COMP | ITAR_DISC))
3811 while (!
3812 (RDW_HARPOON((p_port + hp_intstat)) &
3813 (BUS_FREE | RSEL))) ;
3814 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003815}
3816
Linus Torvalds1da177e2005-04-16 15:20:36 -07003817/*---------------------------------------------------------------------
3818 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003819 * Function: FPT_schkdd
Linus Torvalds1da177e2005-04-16 15:20:36 -07003820 *
3821 * Description: Make sure data has been flushed from both FIFOs and abort
3822 * the operations if necessary.
3823 *
3824 *---------------------------------------------------------------------*/
3825
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08003826static void FPT_schkdd(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003827{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003828 unsigned short TimeOutLoop;
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08003829 unsigned char sPhase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003831 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003832
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003833 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003834
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003835 if ((currSCCB->Sccb_scsistat != DATA_OUT_ST) &&
3836 (currSCCB->Sccb_scsistat != DATA_IN_ST)) {
3837 return;
3838 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003840 if (currSCCB->Sccb_XferState & F_ODD_BALL_CNT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003842 currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003843
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003844 currSCCB->Sccb_XferCnt = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003846 currSCCB->Sccb_XferState &= ~F_ODD_BALL_CNT;
3847 WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
3848 WR_HARPOON(port + hp_xferstat, 0x00);
3849 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003850
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003851 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003852
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003853 currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003854
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003855 currSCCB->Sccb_XferCnt = 0;
3856 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003857
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003858 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
3859 (currSCCB->HostStatus == SCCB_COMPLETE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003860
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003861 currSCCB->HostStatus = SCCB_PARITY_ERR;
3862 WRW_HARPOON((port + hp_intstat), PARITY);
3863 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003864
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003865 FPT_hostDataXferAbort(port, p_card, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003866
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003867 while (RD_HARPOON(port + hp_scsisig) & SCSI_ACK) {
3868 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003870 TimeOutLoop = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003871
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003872 while (RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY) {
3873 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
3874 return;
3875 }
3876 if (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) {
3877 break;
3878 }
3879 if (RDW_HARPOON((port + hp_intstat)) & RESET) {
3880 return;
3881 }
3882 if ((RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
3883 || (TimeOutLoop++ > 0x3000))
3884 break;
3885 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003886
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003887 sPhase = RD_HARPOON(port + hp_scsisig) & (SCSI_BSY | S_SCSI_PHZ);
3888 if ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) ||
3889 (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) ||
3890 (sPhase == (SCSI_BSY | S_DATAO_PH)) ||
3891 (sPhase == (SCSI_BSY | S_DATAI_PH))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003892
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003893 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003894
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003895 if (!(currSCCB->Sccb_XferState & F_ALL_XFERRED)) {
3896 if (currSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
3897 FPT_phaseDataIn(port, p_card);
3898 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003899
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003900 else {
3901 FPT_phaseDataOut(port, p_card);
3902 }
3903 } else {
3904 FPT_sxfrp(port, p_card);
3905 if (!(RDW_HARPOON((port + hp_intstat)) &
3906 (BUS_FREE | ICMD_COMP | ITAR_DISC | RESET))) {
3907 WRW_HARPOON((port + hp_intstat), AUTO_INT);
3908 FPT_phaseDecode(port, p_card);
3909 }
3910 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003912 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003913
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003914 else {
3915 WR_HARPOON(port + hp_portctrl_0, 0x00);
3916 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003917}
3918
Linus Torvalds1da177e2005-04-16 15:20:36 -07003919/*---------------------------------------------------------------------
3920 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003921 * Function: FPT_sinits
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922 *
3923 * Description: Setup SCCB manager fields in this SCCB.
3924 *
3925 *---------------------------------------------------------------------*/
3926
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003927static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003929 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003930
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003931 if ((p_sccb->TargID > MAX_SCSI_TAR) || (p_sccb->Lun > MAX_LUN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003932 return;
3933 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003934 currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003935
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003936 p_sccb->Sccb_XferState = 0x00;
3937 p_sccb->Sccb_XferCnt = p_sccb->DataLength;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003938
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003939 if ((p_sccb->OperationCode == SCATTER_GATHER_COMMAND) ||
3940 (p_sccb->OperationCode == RESIDUAL_SG_COMMAND)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003941
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003942 p_sccb->Sccb_SGoffset = 0;
3943 p_sccb->Sccb_XferState = F_SG_XFER;
3944 p_sccb->Sccb_XferCnt = 0x00;
3945 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003947 if (p_sccb->DataLength == 0x00)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003948
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003949 p_sccb->Sccb_XferState |= F_ALL_XFERRED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003950
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003951 if (p_sccb->ControlByte & F_USE_CMD_Q) {
3952 if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
3953 p_sccb->ControlByte &= ~F_USE_CMD_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003955 else
3956 currTar_Info->TarStatus |= TAG_Q_TRYING;
3957 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958
3959/* For !single SCSI device in system & device allow Disconnect
3960 or command is tag_q type then send Cmd with Disconnect Enable
3961 else send Cmd with Disconnect Disable */
3962
3963/*
James Bottomley 47b5d692005-04-24 02:38:05 -05003964 if (((!(FPT_BL_Card[p_card].globalFlags & F_SINGLE_DEVICE)) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965 (currTar_Info->TarStatus & TAR_ALLOW_DISC)) ||
3966 (currTar_Info->TarStatus & TAG_Q_TRYING)) {
3967*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003968 if ((currTar_Info->TarStatus & TAR_ALLOW_DISC) ||
3969 (currTar_Info->TarStatus & TAG_Q_TRYING)) {
3970 p_sccb->Sccb_idmsg =
3971 (unsigned char)(SMIDENT | DISC_PRIV) | p_sccb->Lun;
3972 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003973
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003974 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003975
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003976 p_sccb->Sccb_idmsg = (unsigned char)SMIDENT | p_sccb->Lun;
3977 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003978
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003979 p_sccb->HostStatus = 0x00;
3980 p_sccb->TargetStatus = 0x00;
3981 p_sccb->Sccb_tag = 0x00;
3982 p_sccb->Sccb_MGRFlags = 0x00;
3983 p_sccb->Sccb_sgseg = 0x00;
3984 p_sccb->Sccb_ATC = 0x00;
3985 p_sccb->Sccb_savedATC = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003986/*
3987 p_sccb->SccbVirtDataPtr = 0x00;
3988 p_sccb->Sccb_forwardlink = NULL;
3989 p_sccb->Sccb_backlink = NULL;
3990 */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003991 p_sccb->Sccb_scsistat = BUS_FREE_ST;
3992 p_sccb->SccbStatus = SCCB_IN_PROCESS;
3993 p_sccb->Sccb_scsimsg = SMNO_OP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003994
3995}
3996
Linus Torvalds1da177e2005-04-16 15:20:36 -07003997/*---------------------------------------------------------------------
3998 *
3999 * Function: Phase Decode
4000 *
4001 * Description: Determine the phase and call the appropriate function.
4002 *
4003 *---------------------------------------------------------------------*/
4004
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004005static void FPT_phaseDecode(unsigned long p_port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004006{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004007 unsigned char phase_ref;
4008 void (*phase) (unsigned long, unsigned char);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004010 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004011
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004012 phase_ref =
4013 (unsigned char)(RD_HARPOON(p_port + hp_scsisig) & S_SCSI_PHZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004014
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004015 phase = FPT_s_PhaseTbl[phase_ref];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004017 (*phase) (p_port, p_card); /* Call the correct phase func */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004018}
4019
Linus Torvalds1da177e2005-04-16 15:20:36 -07004020/*---------------------------------------------------------------------
4021 *
4022 * Function: Data Out Phase
4023 *
4024 * Description: Start up both the BusMaster and Xbow.
4025 *
4026 *---------------------------------------------------------------------*/
4027
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004028static void FPT_phaseDataOut(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004029{
4030
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004031 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004032
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004033 currSCCB = FPT_BL_Card[p_card].currentSCCB;
4034 if (currSCCB == NULL) {
4035 return; /* Exit if No SCCB record */
4036 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004037
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004038 currSCCB->Sccb_scsistat = DATA_OUT_ST;
4039 currSCCB->Sccb_XferState &= ~(F_HOST_XFER_DIR | F_NO_DATA_YET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004040
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004041 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004043 WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004045 WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004047 FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004048
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004049 if (currSCCB->Sccb_XferCnt == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004050
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004051 if ((currSCCB->ControlByte & SCCB_DATA_XFER_OUT) &&
4052 (currSCCB->HostStatus == SCCB_COMPLETE))
4053 currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004055 FPT_sxfrp(port, p_card);
4056 if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
4057 FPT_phaseDecode(port, p_card);
4058 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004059}
4060
Linus Torvalds1da177e2005-04-16 15:20:36 -07004061/*---------------------------------------------------------------------
4062 *
4063 * Function: Data In Phase
4064 *
4065 * Description: Startup the BusMaster and the XBOW.
4066 *
4067 *---------------------------------------------------------------------*/
4068
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004069static void FPT_phaseDataIn(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004070{
4071
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004072 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004073
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004074 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004076 if (currSCCB == NULL) {
4077 return; /* Exit if No SCCB record */
4078 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004080 currSCCB->Sccb_scsistat = DATA_IN_ST;
4081 currSCCB->Sccb_XferState |= F_HOST_XFER_DIR;
4082 currSCCB->Sccb_XferState &= ~F_NO_DATA_YET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004084 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004085
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004086 WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004088 WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004090 FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004091
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004092 if (currSCCB->Sccb_XferCnt == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004093
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004094 if ((currSCCB->ControlByte & SCCB_DATA_XFER_IN) &&
4095 (currSCCB->HostStatus == SCCB_COMPLETE))
4096 currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004097
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004098 FPT_sxfrp(port, p_card);
4099 if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
4100 FPT_phaseDecode(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004101
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004102 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004103}
4104
4105/*---------------------------------------------------------------------
4106 *
4107 * Function: Command Phase
4108 *
4109 * Description: Load the CDB into the automation and start it up.
4110 *
4111 *---------------------------------------------------------------------*/
4112
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004113static void FPT_phaseCommand(unsigned long p_port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004115 struct sccb *currSCCB;
4116 unsigned long cdb_reg;
4117 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004118
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004119 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004120
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004121 if (currSCCB->OperationCode == RESET_COMMAND) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004123 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4124 currSCCB->CdbLength = SIX_BYTE_CMD;
4125 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004126
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004127 WR_HARPOON(p_port + hp_scsisig, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004129 ARAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004130
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004131 cdb_reg = p_port + CMD_STRT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004132
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004133 for (i = 0; i < currSCCB->CdbLength; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004134
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004135 if (currSCCB->OperationCode == RESET_COMMAND)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004136
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004137 WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + 0x00));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004138
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004139 else
4140 WRW_HARPOON(cdb_reg,
4141 (MPM_OP + ACOMMAND + currSCCB->Cdb[i]));
4142 cdb_reg += 2;
4143 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004144
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004145 if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
4146 WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004147
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004148 WR_HARPOON(p_port + hp_portctrl_0, (SCSI_PORT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004149
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004150 currSCCB->Sccb_scsistat = COMMAND_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004151
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004152 WR_HARPOON(p_port + hp_autostart_3, (AUTO_IMMED | CMD_ONLY_STRT));
4153 SGRAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004154}
4155
Linus Torvalds1da177e2005-04-16 15:20:36 -07004156/*---------------------------------------------------------------------
4157 *
4158 * Function: Status phase
4159 *
4160 * Description: Bring in the status and command complete message bytes
4161 *
4162 *---------------------------------------------------------------------*/
4163
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004164static void FPT_phaseStatus(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004165{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004166 /* Start-up the automation to finish off this command and let the
4167 isr handle the interrupt for command complete when it comes in.
4168 We could wait here for the interrupt to be generated?
4169 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004170
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004171 WR_HARPOON(port + hp_scsisig, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004172
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004173 WR_HARPOON(port + hp_autostart_0, (AUTO_IMMED + END_DATA_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004174}
4175
Linus Torvalds1da177e2005-04-16 15:20:36 -07004176/*---------------------------------------------------------------------
4177 *
4178 * Function: Phase Message Out
4179 *
4180 * Description: Send out our message (if we have one) and handle whatever
4181 * else is involed.
4182 *
4183 *---------------------------------------------------------------------*/
4184
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004185static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004186{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004187 unsigned char message, scsiID;
4188 struct sccb *currSCCB;
4189 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004190
James Bottomley 47b5d692005-04-24 02:38:05 -05004191 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004192
4193 if (currSCCB != NULL) {
4194
4195 message = currSCCB->Sccb_scsimsg;
4196 scsiID = currSCCB->TargID;
4197
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004198 if (message == SMDEV_RESET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004199
James Bottomley 47b5d692005-04-24 02:38:05 -05004200 currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004201 currTar_Info->TarSyncCtrl = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004202 FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004203
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004204 if (FPT_sccbMgrTbl[p_card][scsiID].
4205 TarEEValue & EE_SYNC_MASK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004206
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004207 FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
4208 ~TAR_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004209
4210 }
4211
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004212 if (FPT_sccbMgrTbl[p_card][scsiID].
4213 TarEEValue & EE_WIDE_SCSI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004214
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004215 FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
4216 ~TAR_WIDE_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004217 }
4218
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004219 FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
4220 FPT_SccbMgrTableInitTarget(p_card, scsiID);
4221 } else if (currSCCB->Sccb_scsistat == ABORT_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004222 currSCCB->HostStatus = SCCB_COMPLETE;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004223 if (FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] !=
4224 NULL) {
4225 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4226 Sccb_tag] = NULL;
James Bottomley 47b5d692005-04-24 02:38:05 -05004227 FPT_sccbMgrTbl[p_card][scsiID].TarTagQ_Cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004228 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004229
Linus Torvalds1da177e2005-04-16 15:20:36 -07004230 }
4231
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004232 else if (currSCCB->Sccb_scsistat < COMMAND_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004233
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004234 if (message == SMNO_OP) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004235 currSCCB->Sccb_MGRFlags |= F_DEV_SELECTED;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004236
4237 FPT_ssel(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004238 return;
4239 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004240 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004241
4242 if (message == SMABORT)
4243
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004244 FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004245 }
4246
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004247 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248 message = SMABORT;
4249 }
4250
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004251 WRW_HARPOON((port + hp_intstat), (BUS_FREE | PHASE | XFER_CNT_0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004252
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004253 WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004254
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004255 WR_HARPOON(port + hp_scsidata_0, message);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004256
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004257 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004258
4259 ACCEPT_MSG(port);
4260
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004261 WR_HARPOON(port + hp_portctrl_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004262
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004263 if ((message == SMABORT) || (message == SMDEV_RESET) ||
4264 (message == SMABORT_TAG)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004265
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004266 while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | PHASE))) {
4267 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004268
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004269 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
4270 WRW_HARPOON((port + hp_intstat), BUS_FREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004272 if (currSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004273
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004274 if ((FPT_BL_Card[p_card].
4275 globalFlags & F_CONLUN_IO)
4276 &&
4277 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4278 TarStatus & TAR_TAG_Q_MASK) !=
4279 TAG_Q_TRYING))
4280 FPT_sccbMgrTbl[p_card][currSCCB->
4281 TargID].
4282 TarLUNBusy[currSCCB->Lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004284 FPT_sccbMgrTbl[p_card][currSCCB->
4285 TargID].
4286 TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004287
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004288 FPT_queueCmdComplete(&FPT_BL_Card[p_card],
4289 currSCCB, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004290 }
4291
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004292 else {
4293 FPT_BL_Card[p_card].globalFlags |=
4294 F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004295 }
4296 }
4297
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004298 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004299
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004300 FPT_sxfrp(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004301 }
4302 }
4303
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004304 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004305
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004306 if (message == SMPARITY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004307 currSCCB->Sccb_scsimsg = SMNO_OP;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004308 WR_HARPOON(port + hp_autostart_1,
4309 (AUTO_IMMED + DISCONNECT_START));
4310 } else {
4311 FPT_sxfrp(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312 }
4313 }
4314}
4315
Linus Torvalds1da177e2005-04-16 15:20:36 -07004316/*---------------------------------------------------------------------
4317 *
4318 * Function: Message In phase
4319 *
4320 * Description: Bring in the message and determine what to do with it.
4321 *
4322 *---------------------------------------------------------------------*/
4323
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004324static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004325{
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08004326 unsigned char message;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004327 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004328
James Bottomley 47b5d692005-04-24 02:38:05 -05004329 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004330
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004331 if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004332
James Bottomley 47b5d692005-04-24 02:38:05 -05004333 FPT_phaseChkFifo(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004334 }
4335
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004336 message = RD_HARPOON(port + hp_scsidata_0);
4337 if ((message == SMDISC) || (message == SMSAVE_DATA_PTR)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004338
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004339 WR_HARPOON(port + hp_autostart_1,
4340 (AUTO_IMMED + END_DATA_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004341
4342 }
4343
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004344 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004346 message = FPT_sfm(port, currSCCB);
4347 if (message) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004348
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004349 FPT_sdecm(message, port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004351 } else {
4352 if (currSCCB->Sccb_scsimsg != SMPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004353 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004354 WR_HARPOON(port + hp_autostart_1,
4355 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004356 }
4357 }
4358
4359}
4360
Linus Torvalds1da177e2005-04-16 15:20:36 -07004361/*---------------------------------------------------------------------
4362 *
4363 * Function: Illegal phase
4364 *
4365 * Description: Target switched to some illegal phase, so all we can do
4366 * is report an error back to the host (if that is possible)
4367 * and send an ABORT message to the misbehaving target.
4368 *
4369 *---------------------------------------------------------------------*/
4370
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004371static void FPT_phaseIllegal(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004372{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004373 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004374
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004375 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004376
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004377 WR_HARPOON(port + hp_scsisig, RD_HARPOON(port + hp_scsisig));
4378 if (currSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004379
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004380 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4381 currSCCB->Sccb_scsistat = ABORT_ST;
4382 currSCCB->Sccb_scsimsg = SMABORT;
4383 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004384
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004385 ACCEPT_MSG_ATN(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004386}
4387
Linus Torvalds1da177e2005-04-16 15:20:36 -07004388/*---------------------------------------------------------------------
4389 *
4390 * Function: Phase Check FIFO
4391 *
4392 * Description: Make sure data has been flushed from both FIFOs and abort
4393 * the operations if necessary.
4394 *
4395 *---------------------------------------------------------------------*/
4396
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004397static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004399 unsigned long xfercnt;
4400 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004401
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004402 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004403
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004404 if (currSCCB->Sccb_scsistat == DATA_IN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004405
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004406 while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) &&
4407 (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)) {
4408 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004409
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004410 if (!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) {
4411 currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004413 currSCCB->Sccb_XferCnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004414
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004415 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
4416 (currSCCB->HostStatus == SCCB_COMPLETE)) {
4417 currSCCB->HostStatus = SCCB_PARITY_ERR;
4418 WRW_HARPOON((port + hp_intstat), PARITY);
4419 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004420
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004421 FPT_hostDataXferAbort(port, p_card, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004422
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004423 FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004424
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004425 while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY))
4426 && (RD_HARPOON(port + hp_ext_status) &
4427 BM_CMD_BUSY)) {
4428 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004429
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004430 }
4431 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004432
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004433 /*End Data In specific code. */
4434 GET_XFER_CNT(port, xfercnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004436 WR_HARPOON(port + hp_xfercnt_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004437
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004438 WR_HARPOON(port + hp_portctrl_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004439
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004440 currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - xfercnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004441
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004442 currSCCB->Sccb_XferCnt = xfercnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004443
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004444 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
4445 (currSCCB->HostStatus == SCCB_COMPLETE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004446
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004447 currSCCB->HostStatus = SCCB_PARITY_ERR;
4448 WRW_HARPOON((port + hp_intstat), PARITY);
4449 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004450
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004451 FPT_hostDataXferAbort(port, p_card, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004452
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004453 WR_HARPOON(port + hp_fifowrite, 0x00);
4454 WR_HARPOON(port + hp_fiforead, 0x00);
4455 WR_HARPOON(port + hp_xferstat, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004457 WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004458}
4459
Linus Torvalds1da177e2005-04-16 15:20:36 -07004460/*---------------------------------------------------------------------
4461 *
4462 * Function: Phase Bus Free
4463 *
4464 * Description: We just went bus free so figure out if it was
4465 * because of command complete or from a disconnect.
4466 *
4467 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004468static void FPT_phaseBusFree(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004469{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004470 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004471
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004472 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004473
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004474 if (currSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004475
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004476 DISABLE_AUTO(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004477
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004478 if (currSCCB->OperationCode == RESET_COMMAND) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004479
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004480 if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4481 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4482 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4483 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4484 TarLUNBusy[currSCCB->Lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004485 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004486 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4487 TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004488
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004489 FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
4490 p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004491
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004492 FPT_queueSearchSelect(&FPT_BL_Card[p_card], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004493
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004494 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004495
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004496 else if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
4497 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4498 (unsigned char)SYNC_SUPPORTED;
4499 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4500 ~EE_SYNC_MASK;
4501 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004502
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004503 else if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
4504 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
4505 (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4506 TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004507
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004508 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4509 ~EE_WIDE_SCSI;
4510 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004511
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004512 else if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
4513 /* Make sure this is not a phony BUS_FREE. If we were
4514 reselected or if BUSY is NOT on then this is a
4515 valid BUS FREE. SRR Wednesday, 5/10/1995. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004516
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004517 if ((!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ||
4518 (RDW_HARPOON((port + hp_intstat)) & RSEL)) {
4519 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4520 TarStatus &= ~TAR_TAG_Q_MASK;
4521 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4522 TarStatus |= TAG_Q_REJECT;
4523 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004524
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004525 else {
4526 return;
4527 }
4528 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004529
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004530 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004531
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004532 currSCCB->Sccb_scsistat = BUS_FREE_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004533
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004534 if (!currSCCB->HostStatus) {
4535 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4536 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004537
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004538 if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4539 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4540 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4541 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4542 TarLUNBusy[currSCCB->Lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004543 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004544 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4545 TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004546
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004547 FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
4548 p_card);
4549 return;
4550 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004551
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004552 FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004553
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004554 } /*end if !=null */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004555}
4556
Linus Torvalds1da177e2005-04-16 15:20:36 -07004557/*---------------------------------------------------------------------
4558 *
4559 * Function: Auto Load Default Map
4560 *
4561 * Description: Load the Automation RAM with the defualt map values.
4562 *
4563 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004564static void FPT_autoLoadDefaultMap(unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004565{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004566 unsigned long map_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004567
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004568 ARAM_ACCESS(p_port);
4569 map_addr = p_port + hp_aramBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004570
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004571 WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0xC0)); /*ID MESSAGE */
4572 map_addr += 2;
4573 WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x20)); /*SIMPLE TAG QUEUEING MSG */
4574 map_addr += 2;
4575 WRW_HARPOON(map_addr, RAT_OP); /*RESET ATTENTION */
4576 map_addr += 2;
4577 WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x00)); /*TAG ID MSG */
4578 map_addr += 2;
4579 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 0 */
4580 map_addr += 2;
4581 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 1 */
4582 map_addr += 2;
4583 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 2 */
4584 map_addr += 2;
4585 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 3 */
4586 map_addr += 2;
4587 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 4 */
4588 map_addr += 2;
4589 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 5 */
4590 map_addr += 2;
4591 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 6 */
4592 map_addr += 2;
4593 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 7 */
4594 map_addr += 2;
4595 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 8 */
4596 map_addr += 2;
4597 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 9 */
4598 map_addr += 2;
4599 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 10 */
4600 map_addr += 2;
4601 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 11 */
4602 map_addr += 2;
4603 WRW_HARPOON(map_addr, (CPE_OP + ADATA_OUT + DINT)); /*JUMP IF DATA OUT */
4604 map_addr += 2;
4605 WRW_HARPOON(map_addr, (TCB_OP + FIFO_0 + DI)); /*JUMP IF NO DATA IN FIFO */
4606 map_addr += 2; /*This means AYNC DATA IN */
4607 WRW_HARPOON(map_addr, (SSI_OP + SSI_IDO_STRT)); /*STOP AND INTERRUPT */
4608 map_addr += 2;
4609 WRW_HARPOON(map_addr, (CPE_OP + ADATA_IN + DINT)); /*JUMP IF NOT DATA IN PHZ */
4610 map_addr += 2;
4611 WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST)); /*IF NOT MSG IN CHECK 4 DATA IN */
4612 map_addr += 2;
4613 WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x02)); /*SAVE DATA PTR MSG? */
4614 map_addr += 2;
4615 WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + DC)); /*GO CHECK FOR DISCONNECT MSG */
4616 map_addr += 2;
4617 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR1)); /*SAVE DATA PTRS MSG */
4618 map_addr += 2;
4619 WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST)); /*IF NOT MSG IN CHECK DATA IN */
4620 map_addr += 2;
4621 WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x04)); /*DISCONNECT MSG? */
4622 map_addr += 2;
4623 WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + UNKNWN)); /*UKNKNOWN MSG */
4624 map_addr += 2;
4625 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET)); /*XFER DISCONNECT MSG */
4626 map_addr += 2;
4627 WRW_HARPOON(map_addr, (SSI_OP + SSI_ITAR_DISC)); /*STOP AND INTERRUPT */
4628 map_addr += 2;
4629 WRW_HARPOON(map_addr, (CPN_OP + ASTATUS + UNKNWN)); /*JUMP IF NOT STATUS PHZ. */
4630 map_addr += 2;
4631 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR0)); /*GET STATUS BYTE */
4632 map_addr += 2;
4633 WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + CC)); /*ERROR IF NOT MSG IN PHZ */
4634 map_addr += 2;
4635 WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x00)); /*CHECK FOR CMD COMPLETE MSG. */
4636 map_addr += 2;
4637 WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + CC)); /*ERROR IF NOT CMD COMPLETE MSG. */
4638 map_addr += 2;
4639 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET)); /*GET CMD COMPLETE MSG */
4640 map_addr += 2;
4641 WRW_HARPOON(map_addr, (SSI_OP + SSI_ICMD_COMP)); /*END OF COMMAND */
4642 map_addr += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004643
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004644 WRW_HARPOON(map_addr, (SSI_OP + SSI_IUNKWN)); /*RECEIVED UNKNOWN MSG BYTE */
4645 map_addr += 2;
4646 WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */
4647 map_addr += 2;
4648 WRW_HARPOON(map_addr, (SSI_OP + SSI_ITICKLE)); /*BIOS Tickled the Mgr */
4649 map_addr += 2;
4650 WRW_HARPOON(map_addr, (SSI_OP + SSI_IRFAIL)); /*EXPECTED ID/TAG MESSAGES AND */
4651 map_addr += 2; /* DIDN'T GET ONE */
4652 WRW_HARPOON(map_addr, (CRR_OP + AR3 + S_IDREG)); /* comp SCSI SEL ID & AR3 */
4653 map_addr += 2;
4654 WRW_HARPOON(map_addr, (BRH_OP + EQUAL + 0x00)); /*SEL ID OK then Conti. */
4655 map_addr += 2;
4656 WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004657
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004658 SGRAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004659}
4660
4661/*---------------------------------------------------------------------
4662 *
4663 * Function: Auto Command Complete
4664 *
4665 * Description: Post command back to host and find another command
4666 * to execute.
4667 *
4668 *---------------------------------------------------------------------*/
4669
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004670static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004671{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004672 struct sccb *currSCCB;
4673 unsigned char status_byte;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004674
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004675 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004676
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004677 status_byte = RD_HARPOON(p_port + hp_gp_reg_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004678
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004679 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004680
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004681 if (status_byte != SSGOOD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004682
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004683 if (status_byte == SSQ_FULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004684
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004685 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4686 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4687 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4688 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4689 TarLUNBusy[currSCCB->Lun] = 1;
4690 if (FPT_BL_Card[p_card].discQCount != 0)
James Bottomley 47b5d692005-04-24 02:38:05 -05004691 FPT_BL_Card[p_card].discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004692 FPT_BL_Card[p_card].
4693 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4694 [currSCCB->TargID].
4695 LunDiscQ_Idx[currSCCB->Lun]] =
4696 NULL;
4697 } else {
4698 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4699 TarLUNBusy[0] = 1;
4700 if (currSCCB->Sccb_tag) {
4701 if (FPT_BL_Card[p_card].discQCount != 0)
4702 FPT_BL_Card[p_card].
4703 discQCount--;
4704 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4705 Sccb_tag]
4706 = NULL;
4707 } else {
4708 if (FPT_BL_Card[p_card].discQCount != 0)
4709 FPT_BL_Card[p_card].
4710 discQCount--;
4711 FPT_BL_Card[p_card].
4712 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4713 [currSCCB->TargID].
4714 LunDiscQ_Idx[0]] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004715 }
4716 }
4717
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004718 currSCCB->Sccb_MGRFlags |= F_STATUSLOADED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004719
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004720 FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004721
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004722 return;
4723 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004724
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004725 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
4726 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4727 (unsigned char)SYNC_SUPPORTED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004728
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004729 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4730 ~EE_SYNC_MASK;
4731 FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004732
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004733 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4734 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4735 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4736 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4737 TarLUNBusy[currSCCB->Lun] = 1;
4738 if (FPT_BL_Card[p_card].discQCount != 0)
James Bottomley 47b5d692005-04-24 02:38:05 -05004739 FPT_BL_Card[p_card].discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004740 FPT_BL_Card[p_card].
4741 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4742 [currSCCB->TargID].
4743 LunDiscQ_Idx[currSCCB->Lun]] =
4744 NULL;
4745 } else {
4746 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4747 TarLUNBusy[0] = 1;
4748 if (currSCCB->Sccb_tag) {
4749 if (FPT_BL_Card[p_card].discQCount != 0)
4750 FPT_BL_Card[p_card].
4751 discQCount--;
4752 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4753 Sccb_tag]
4754 = NULL;
4755 } else {
4756 if (FPT_BL_Card[p_card].discQCount != 0)
4757 FPT_BL_Card[p_card].
4758 discQCount--;
4759 FPT_BL_Card[p_card].
4760 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4761 [currSCCB->TargID].
4762 LunDiscQ_Idx[0]] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004763 }
4764 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004765 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004766
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004767 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004768
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004769 if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004770
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004771 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
4772 (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4773 TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004774
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004775 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4776 ~EE_WIDE_SCSI;
4777 FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004778
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004779 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4780 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4781 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4782 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4783 TarLUNBusy[currSCCB->Lun] = 1;
4784 if (FPT_BL_Card[p_card].discQCount != 0)
James Bottomley 47b5d692005-04-24 02:38:05 -05004785 FPT_BL_Card[p_card].discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004786 FPT_BL_Card[p_card].
4787 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4788 [currSCCB->TargID].
4789 LunDiscQ_Idx[currSCCB->Lun]] =
4790 NULL;
4791 } else {
4792 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4793 TarLUNBusy[0] = 1;
4794 if (currSCCB->Sccb_tag) {
4795 if (FPT_BL_Card[p_card].discQCount != 0)
4796 FPT_BL_Card[p_card].
4797 discQCount--;
4798 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4799 Sccb_tag]
4800 = NULL;
4801 } else {
4802 if (FPT_BL_Card[p_card].discQCount != 0)
4803 FPT_BL_Card[p_card].
4804 discQCount--;
4805 FPT_BL_Card[p_card].
4806 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4807 [currSCCB->TargID].
4808 LunDiscQ_Idx[0]] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004809 }
4810 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004811 return;
4812
4813 }
4814
4815 if (status_byte == SSCHECK) {
4816 if (FPT_BL_Card[p_card].globalFlags & F_DO_RENEGO) {
4817 if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4818 TarEEValue & EE_SYNC_MASK) {
4819 FPT_sccbMgrTbl[p_card][currSCCB->
4820 TargID].
4821 TarStatus &= ~TAR_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004822 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004823 if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4824 TarEEValue & EE_WIDE_SCSI) {
4825 FPT_sccbMgrTbl[p_card][currSCCB->
4826 TargID].
4827 TarStatus &= ~TAR_WIDE_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004828 }
4829 }
4830 }
4831
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004832 if (!(currSCCB->Sccb_XferState & F_AUTO_SENSE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004833
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004834 currSCCB->SccbStatus = SCCB_ERROR;
4835 currSCCB->TargetStatus = status_byte;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004836
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004837 if (status_byte == SSCHECK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004838
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004839 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4840 TarLUN_CA = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004841
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004842 if (currSCCB->RequestSenseLength !=
4843 NO_AUTO_REQUEST_SENSE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004844
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004845 if (currSCCB->RequestSenseLength == 0)
4846 currSCCB->RequestSenseLength =
4847 14;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004848
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004849 FPT_ssenss(&FPT_BL_Card[p_card]);
4850 FPT_BL_Card[p_card].globalFlags |=
4851 F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004852
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004853 if (((FPT_BL_Card[p_card].
4854 globalFlags & F_CONLUN_IO)
4855 &&
4856 ((FPT_sccbMgrTbl[p_card]
4857 [currSCCB->TargID].
4858 TarStatus & TAR_TAG_Q_MASK) !=
4859 TAG_Q_TRYING))) {
4860 FPT_sccbMgrTbl[p_card]
4861 [currSCCB->TargID].
4862 TarLUNBusy[currSCCB->Lun] =
4863 1;
4864 if (FPT_BL_Card[p_card].
4865 discQCount != 0)
4866 FPT_BL_Card[p_card].
4867 discQCount--;
4868 FPT_BL_Card[p_card].
4869 discQ_Tbl[FPT_sccbMgrTbl
4870 [p_card]
4871 [currSCCB->
4872 TargID].
4873 LunDiscQ_Idx
4874 [currSCCB->Lun]] =
4875 NULL;
4876 } else {
4877 FPT_sccbMgrTbl[p_card]
4878 [currSCCB->TargID].
4879 TarLUNBusy[0] = 1;
4880 if (currSCCB->Sccb_tag) {
4881 if (FPT_BL_Card[p_card].
4882 discQCount != 0)
4883 FPT_BL_Card
4884 [p_card].
4885 discQCount--;
4886 FPT_BL_Card[p_card].
4887 discQ_Tbl[currSCCB->
4888 Sccb_tag]
4889 = NULL;
4890 } else {
4891 if (FPT_BL_Card[p_card].
4892 discQCount != 0)
4893 FPT_BL_Card
4894 [p_card].
4895 discQCount--;
4896 FPT_BL_Card[p_card].
4897 discQ_Tbl
4898 [FPT_sccbMgrTbl
4899 [p_card][currSCCB->
4900 TargID].
4901 LunDiscQ_Idx[0]] =
4902 NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004903 }
4904 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004905 return;
4906 }
4907 }
4908 }
4909 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004910
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004911 if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4912 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4913 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4914 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->
4915 Lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004916 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004917 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004918
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004919 FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004920}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004921
4922#define SHORT_WAIT 0x0000000F
4923#define LONG_WAIT 0x0000FFFFL
4924
Linus Torvalds1da177e2005-04-16 15:20:36 -07004925/*---------------------------------------------------------------------
4926 *
4927 * Function: Data Transfer Processor
4928 *
4929 * Description: This routine performs two tasks.
4930 * (1) Start data transfer by calling HOST_DATA_XFER_START
4931 * function. Once data transfer is started, (2) Depends
4932 * on the type of data transfer mode Scatter/Gather mode
4933 * or NON Scatter/Gather mode. In NON Scatter/Gather mode,
4934 * this routine checks Sccb_MGRFlag (F_HOST_XFER_ACT bit) for
4935 * data transfer done. In Scatter/Gather mode, this routine
4936 * checks bus master command complete and dual rank busy
4937 * bit to keep chaining SC transfer command. Similarly,
4938 * in Scatter/Gather mode, it checks Sccb_MGRFlag
4939 * (F_HOST_XFER_ACT bit) for data transfer done.
4940 *
4941 *---------------------------------------------------------------------*/
4942
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004943static void FPT_dataXferProcessor(unsigned long port,
4944 struct sccb_card *pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004945{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004946 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004947
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004948 currSCCB = pCurrCard->currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004949
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004950 if (currSCCB->Sccb_XferState & F_SG_XFER) {
4951 if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
4952 {
4953 currSCCB->Sccb_sgseg += (unsigned char)SG_BUF_CNT;
4954 currSCCB->Sccb_SGoffset = 0x00;
4955 }
4956 pCurrCard->globalFlags |= F_HOST_XFER_ACT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004957
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004958 FPT_busMstrSGDataXferStart(port, currSCCB);
4959 }
4960
4961 else {
4962 if (!(pCurrCard->globalFlags & F_HOST_XFER_ACT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004963 pCurrCard->globalFlags |= F_HOST_XFER_ACT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004964
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004965 FPT_busMstrDataXferStart(port, currSCCB);
4966 }
4967 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004968}
4969
Linus Torvalds1da177e2005-04-16 15:20:36 -07004970/*---------------------------------------------------------------------
4971 *
4972 * Function: BusMaster Scatter Gather Data Transfer Start
4973 *
4974 * Description:
4975 *
4976 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004977static void FPT_busMstrSGDataXferStart(unsigned long p_port,
4978 struct sccb *pcurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004979{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004980 unsigned long count, addr, tmpSGCnt;
4981 unsigned int sg_index;
4982 unsigned char sg_count, i;
4983 unsigned long reg_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004984
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004985 if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004986
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004987 count = ((unsigned long)HOST_RD_CMD) << 24;
4988 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004989
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004990 else {
4991 count = ((unsigned long)HOST_WRT_CMD) << 24;
4992 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004993
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004994 sg_count = 0;
4995 tmpSGCnt = 0;
4996 sg_index = pcurrSCCB->Sccb_sgseg;
4997 reg_offset = hp_aramBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004998
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004999 i = (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
5000 ~(SGRAM_ARAM | SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005001
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005002 WR_HARPOON(p_port + hp_page_ctrl, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005003
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005004 while ((sg_count < (unsigned char)SG_BUF_CNT) &&
5005 ((unsigned long)(sg_index * (unsigned int)SG_ELEMENT_SIZE) <
5006 pcurrSCCB->DataLength)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005007
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005008 tmpSGCnt += *(((unsigned long *)pcurrSCCB->DataPointer) +
5009 (sg_index * 2));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005010
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005011 count |= *(((unsigned long *)pcurrSCCB->DataPointer) +
5012 (sg_index * 2));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005013
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005014 addr = *(((unsigned long *)pcurrSCCB->DataPointer) +
5015 ((sg_index * 2) + 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005016
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005017 if ((!sg_count) && (pcurrSCCB->Sccb_SGoffset)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005018
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005019 addr +=
5020 ((count & 0x00FFFFFFL) - pcurrSCCB->Sccb_SGoffset);
5021 count =
5022 (count & 0xFF000000L) | pcurrSCCB->Sccb_SGoffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005023
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005024 tmpSGCnt = count & 0x00FFFFFFL;
5025 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005026
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005027 WR_HARP32(p_port, reg_offset, addr);
5028 reg_offset += 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005029
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005030 WR_HARP32(p_port, reg_offset, count);
5031 reg_offset += 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005032
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005033 count &= 0xFF000000L;
5034 sg_index++;
5035 sg_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005036
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005037 } /*End While */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005038
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005039 pcurrSCCB->Sccb_XferCnt = tmpSGCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005040
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005041 WR_HARPOON(p_port + hp_sg_addr, (sg_count << 4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005042
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005043 if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005044
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005045 WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005046
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005047 WR_HARPOON(p_port + hp_portctrl_0,
5048 (DMA_PORT | SCSI_PORT | SCSI_INBIT));
5049 WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
5050 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005051
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005052 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005053
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005054 if ((!(RD_HARPOON(p_port + hp_synctarg_0) & NARROW_SCSI)) &&
5055 (tmpSGCnt & 0x000000001)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005056
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005057 pcurrSCCB->Sccb_XferState |= F_ODD_BALL_CNT;
5058 tmpSGCnt--;
5059 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005060
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005061 WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005062
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005063 WR_HARPOON(p_port + hp_portctrl_0,
5064 (SCSI_PORT | DMA_PORT | DMA_RD));
5065 WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
5066 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005067
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005068 WR_HARPOON(p_port + hp_page_ctrl, (unsigned char)(i | SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005069
5070}
5071
Linus Torvalds1da177e2005-04-16 15:20:36 -07005072/*---------------------------------------------------------------------
5073 *
5074 * Function: BusMaster Data Transfer Start
5075 *
5076 * Description:
5077 *
5078 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005079static void FPT_busMstrDataXferStart(unsigned long p_port,
5080 struct sccb *pcurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005081{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005082 unsigned long addr, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005083
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005084 if (!(pcurrSCCB->Sccb_XferState & F_AUTO_SENSE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005085
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005086 count = pcurrSCCB->Sccb_XferCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005087
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005088 addr =
5089 (unsigned long)pcurrSCCB->DataPointer + pcurrSCCB->Sccb_ATC;
5090 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005091
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005092 else {
5093 addr = pcurrSCCB->SensePointer;
5094 count = pcurrSCCB->RequestSenseLength;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005095
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005096 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005097
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005098 HP_SETUP_ADDR_CNT(p_port, addr, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005099
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005100 if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005101
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005102 WR_HARPOON(p_port + hp_portctrl_0,
5103 (DMA_PORT | SCSI_PORT | SCSI_INBIT));
5104 WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005105
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005106 WR_HARPOON(p_port + hp_xfer_cmd,
5107 (XFER_DMA_HOST | XFER_HOST_AUTO | XFER_DMA_8BIT));
5108 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005109
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005110 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005111
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005112 WR_HARPOON(p_port + hp_portctrl_0,
5113 (SCSI_PORT | DMA_PORT | DMA_RD));
5114 WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005115
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005116 WR_HARPOON(p_port + hp_xfer_cmd,
5117 (XFER_HOST_DMA | XFER_HOST_AUTO | XFER_DMA_8BIT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005118
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005119 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005120}
5121
Linus Torvalds1da177e2005-04-16 15:20:36 -07005122/*---------------------------------------------------------------------
5123 *
5124 * Function: BusMaster Timeout Handler
5125 *
5126 * Description: This function is called after a bus master command busy time
5127 * out is detected. This routines issue halt state machine
5128 * with a software time out for command busy. If command busy
5129 * is still asserted at the end of the time out, it issues
5130 * hard abort with another software time out. It hard abort
5131 * command busy is also time out, it'll just give up.
5132 *
5133 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08005134static unsigned char FPT_busMstrTimeOut(unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005135{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005136 unsigned long timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005137
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005138 timeout = LONG_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005139
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005140 WR_HARPOON(p_port + hp_sys_ctrl, HALT_MACH);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005141
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005142 while ((!(RD_HARPOON(p_port + hp_ext_status) & CMD_ABORTED))
5143 && timeout--) {
5144 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005145
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005146 if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
5147 WR_HARPOON(p_port + hp_sys_ctrl, HARD_ABORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005148
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005149 timeout = LONG_WAIT;
5150 while ((RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY)
5151 && timeout--) {
5152 }
5153 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005154
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005155 RD_HARPOON(p_port + hp_int_status); /*Clear command complete */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005156
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005157 if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005158 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005159 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005160
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005161 else {
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005162 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005163 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005164}
5165
Linus Torvalds1da177e2005-04-16 15:20:36 -07005166/*---------------------------------------------------------------------
5167 *
5168 * Function: Host Data Transfer Abort
5169 *
5170 * Description: Abort any in progress transfer.
5171 *
5172 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005173static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card,
5174 struct sccb *pCurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005175{
5176
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005177 unsigned long timeout;
5178 unsigned long remain_cnt;
5179 unsigned int sg_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005180
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005181 FPT_BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005182
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005183 if (pCurrSCCB->Sccb_XferState & F_AUTO_SENSE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005184
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005185 if (!(RD_HARPOON(port + hp_int_status) & INT_CMD_COMPL)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005186
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005187 WR_HARPOON(port + hp_bm_ctrl,
5188 (RD_HARPOON(port + hp_bm_ctrl) |
5189 FLUSH_XFER_CNTR));
5190 timeout = LONG_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005191
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005192 while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
5193 && timeout--) {
5194 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005195
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005196 WR_HARPOON(port + hp_bm_ctrl,
5197 (RD_HARPOON(port + hp_bm_ctrl) &
5198 ~FLUSH_XFER_CNTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005199
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005200 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005201
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005202 if (FPT_busMstrTimeOut(port)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005203
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005204 if (pCurrSCCB->HostStatus == 0x00)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005205
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005206 pCurrSCCB->HostStatus =
5207 SCCB_BM_ERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005208
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005209 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005210
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005211 if (RD_HARPOON(port + hp_int_status) &
5212 INT_EXT_STATUS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005213
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005214 if (RD_HARPOON(port + hp_ext_status) &
5215 BAD_EXT_STATUS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005216
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005217 if (pCurrSCCB->HostStatus ==
5218 0x00)
5219 {
5220 pCurrSCCB->HostStatus =
5221 SCCB_BM_ERR;
5222 }
5223 }
5224 }
5225 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005226
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005227 else if (pCurrSCCB->Sccb_XferCnt) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005228
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005229 if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005230
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005231 WR_HARPOON(port + hp_page_ctrl,
5232 (RD_HARPOON(port + hp_page_ctrl) &
5233 ~SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005234
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005235 WR_HARPOON(port + hp_sg_addr, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005236
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005237 sg_ptr = pCurrSCCB->Sccb_sgseg + SG_BUF_CNT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005238
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005239 if (sg_ptr >
5240 (unsigned int)(pCurrSCCB->DataLength /
5241 SG_ELEMENT_SIZE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005242
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005243 sg_ptr =
5244 (unsigned int)(pCurrSCCB->DataLength /
5245 SG_ELEMENT_SIZE);
5246 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005247
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005248 remain_cnt = pCurrSCCB->Sccb_XferCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005249
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005250 while (remain_cnt < 0x01000000L) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005251
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005252 sg_ptr--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005253
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005254 if (remain_cnt >
5255 (unsigned
5256 long)(*(((unsigned long *)pCurrSCCB->
5257 DataPointer) + (sg_ptr * 2)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005258
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005259 remain_cnt -=
5260 (unsigned
5261 long)(*(((unsigned long *)
5262 pCurrSCCB->DataPointer) +
5263 (sg_ptr * 2)));
5264 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005265
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005266 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005267
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005268 break;
5269 }
5270 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005271
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005272 if (remain_cnt < 0x01000000L) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005273
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005274 pCurrSCCB->Sccb_SGoffset = remain_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005275
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005276 pCurrSCCB->Sccb_sgseg = (unsigned short)sg_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005277
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005278 if ((unsigned long)(sg_ptr * SG_ELEMENT_SIZE) ==
5279 pCurrSCCB->DataLength && (remain_cnt == 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005280
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005281 pCurrSCCB->Sccb_XferState |=
5282 F_ALL_XFERRED;
5283 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005284
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005285 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005286
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005287 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005288
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005289 pCurrSCCB->HostStatus =
5290 SCCB_GROSS_FW_ERR;
5291 }
5292 }
5293 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005294
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005295 if (!(pCurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005296
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005297 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005298
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005299 FPT_busMstrTimeOut(port);
5300 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005301
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005302 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005303
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005304 if (RD_HARPOON(port + hp_int_status) &
5305 INT_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005306
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005307 if (RD_HARPOON(port + hp_ext_status) &
5308 BAD_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005309
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005310 if (pCurrSCCB->HostStatus ==
5311 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005312
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005313 pCurrSCCB->HostStatus =
5314 SCCB_BM_ERR;
5315 }
5316 }
5317 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005318
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005319 }
5320 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005321
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005322 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005323
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005324 if ((RD_HARPOON(port + hp_fifo_cnt)) >= BM_THRESHOLD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005325
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005326 timeout = SHORT_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005327
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005328 while ((RD_HARPOON(port + hp_ext_status) &
5329 BM_CMD_BUSY)
5330 && ((RD_HARPOON(port + hp_fifo_cnt)) >=
5331 BM_THRESHOLD) && timeout--) {
5332 }
5333 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005334
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005335 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005336
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005337 WR_HARPOON(port + hp_bm_ctrl,
5338 (RD_HARPOON(port + hp_bm_ctrl) |
5339 FLUSH_XFER_CNTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005340
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005341 timeout = LONG_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005342
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005343 while ((RD_HARPOON(port + hp_ext_status) &
5344 BM_CMD_BUSY) && timeout--) {
5345 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005346
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005347 WR_HARPOON(port + hp_bm_ctrl,
5348 (RD_HARPOON(port + hp_bm_ctrl) &
5349 ~FLUSH_XFER_CNTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005350
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005351 if (RD_HARPOON(port + hp_ext_status) &
5352 BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005353
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005354 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005355
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005356 pCurrSCCB->HostStatus =
5357 SCCB_BM_ERR;
5358 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005359
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005360 FPT_busMstrTimeOut(port);
5361 }
5362 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005363
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005364 if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005365
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005366 if (RD_HARPOON(port + hp_ext_status) &
5367 BAD_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005368
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005369 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005370
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005371 pCurrSCCB->HostStatus =
5372 SCCB_BM_ERR;
5373 }
5374 }
5375 }
5376 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005377
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005378 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005379
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005380 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005381
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005382 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005383
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005384 timeout = LONG_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005385
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005386 while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
5387 && timeout--) {
5388 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005389
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005390 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005391
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005392 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005393
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005394 pCurrSCCB->HostStatus = SCCB_BM_ERR;
5395 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005396
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005397 FPT_busMstrTimeOut(port);
5398 }
5399 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005400
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005401 if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005402
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005403 if (RD_HARPOON(port + hp_ext_status) & BAD_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005404
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005405 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005406
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005407 pCurrSCCB->HostStatus = SCCB_BM_ERR;
5408 }
5409 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005410
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005411 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005412
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005413 if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005414
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005415 WR_HARPOON(port + hp_page_ctrl,
5416 (RD_HARPOON(port + hp_page_ctrl) &
5417 ~SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005418
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005419 WR_HARPOON(port + hp_sg_addr, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005420
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005421 pCurrSCCB->Sccb_sgseg += SG_BUF_CNT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005422
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005423 pCurrSCCB->Sccb_SGoffset = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005424
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005425 if ((unsigned long)(pCurrSCCB->Sccb_sgseg *
5426 SG_ELEMENT_SIZE) >=
5427 pCurrSCCB->DataLength) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005428
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005429 pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005430
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005431 pCurrSCCB->Sccb_sgseg =
5432 (unsigned short)(pCurrSCCB->DataLength /
5433 SG_ELEMENT_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005434
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005435 }
5436 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005437
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005438 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005439
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005440 if (!(pCurrSCCB->Sccb_XferState & F_AUTO_SENSE))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005441
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005442 pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
5443 }
5444 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005445
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005446 WR_HARPOON(port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005447}
5448
Linus Torvalds1da177e2005-04-16 15:20:36 -07005449/*---------------------------------------------------------------------
5450 *
5451 * Function: Host Data Transfer Restart
5452 *
5453 * Description: Reset the available count due to a restore data
5454 * pointers message.
5455 *
5456 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005457static void FPT_hostDataXferRestart(struct sccb *currSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005458{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005459 unsigned long data_count;
5460 unsigned int sg_index;
5461 unsigned long *sg_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005462
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005463 if (currSCCB->Sccb_XferState & F_SG_XFER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005464
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005465 currSCCB->Sccb_XferCnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005466
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005467 sg_index = 0xffff; /*Index by long words into sg list. */
5468 data_count = 0; /*Running count of SG xfer counts. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005469
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005470 sg_ptr = (unsigned long *)currSCCB->DataPointer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005471
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005472 while (data_count < currSCCB->Sccb_ATC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005473
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005474 sg_index++;
5475 data_count += *(sg_ptr + (sg_index * 2));
5476 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005477
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005478 if (data_count == currSCCB->Sccb_ATC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005479
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005480 currSCCB->Sccb_SGoffset = 0;
5481 sg_index++;
5482 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005483
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005484 else {
5485 currSCCB->Sccb_SGoffset =
5486 data_count - currSCCB->Sccb_ATC;
5487 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005488
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005489 currSCCB->Sccb_sgseg = (unsigned short)sg_index;
5490 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005491
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005492 else {
5493 currSCCB->Sccb_XferCnt =
5494 currSCCB->DataLength - currSCCB->Sccb_ATC;
5495 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005496}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005497
Linus Torvalds1da177e2005-04-16 15:20:36 -07005498/*---------------------------------------------------------------------
5499 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005500 * Function: FPT_scini
Linus Torvalds1da177e2005-04-16 15:20:36 -07005501 *
5502 * Description: Setup all data structures necessary for SCAM selection.
5503 *
5504 *---------------------------------------------------------------------*/
5505
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005506static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
5507 unsigned char p_power_up)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005508{
5509
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005510 unsigned char loser, assigned_id;
5511 unsigned long p_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005512
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005513 unsigned char i, k, ScamFlg;
5514 struct sccb_card *currCard;
5515 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005516
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005517 currCard = &FPT_BL_Card[p_card];
5518 p_port = currCard->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005519 pCurrNvRam = currCard->pNvRamInfo;
5520
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005521 if (pCurrNvRam) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005522 ScamFlg = pCurrNvRam->niScamConf;
5523 i = pCurrNvRam->niSysConf;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005524 } else {
5525 ScamFlg =
5526 (unsigned char)FPT_utilEERead(p_port, SCAM_CONFIG / 2);
5527 i = (unsigned
5528 char)(FPT_utilEERead(p_port, (SYSTEM_CONFIG / 2)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005529 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005530 if (!(i & 0x02)) /* check if reset bus in AutoSCSI parameter set */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005531 return;
5532
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005533 FPT_inisci(p_card, p_port, p_our_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005534
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005535 /* Force to wait 1 sec after SCSI bus reset. Some SCAM device FW
5536 too slow to return to SCAM selection */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005537
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005538 /* if (p_power_up)
5539 FPT_Wait1Second(p_port);
5540 else
5541 FPT_Wait(p_port, TO_250ms); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005542
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005543 FPT_Wait1Second(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005544
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005545 if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2)) {
5546 while (!(FPT_scarb(p_port, INIT_SELTD))) {
5547 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005548
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005549 FPT_scsel(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005550
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005551 do {
5552 FPT_scxferc(p_port, SYNC_PTRN);
5553 FPT_scxferc(p_port, DOM_MSTR);
5554 loser =
5555 FPT_scsendi(p_port,
5556 &FPT_scamInfo[p_our_id].id_string[0]);
5557 } while (loser == 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005558
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005559 FPT_scbusf(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005560
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005561 if ((p_power_up) && (!loser)) {
5562 FPT_sresb(p_port, p_card);
5563 FPT_Wait(p_port, TO_250ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005564
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005565 while (!(FPT_scarb(p_port, INIT_SELTD))) {
5566 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005567
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005568 FPT_scsel(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005569
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005570 do {
5571 FPT_scxferc(p_port, SYNC_PTRN);
5572 FPT_scxferc(p_port, DOM_MSTR);
5573 loser =
5574 FPT_scsendi(p_port,
5575 &FPT_scamInfo[p_our_id].
5576 id_string[0]);
5577 } while (loser == 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005578
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005579 FPT_scbusf(p_port);
5580 }
5581 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005582
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005583 else {
5584 loser = 0;
5585 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005586
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005587 if (!loser) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005588
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005589 FPT_scamInfo[p_our_id].state = ID_ASSIGNED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005590
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005591 if (ScamFlg & SCAM_ENABLED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005592
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005593 for (i = 0; i < MAX_SCSI_TAR; i++) {
5594 if ((FPT_scamInfo[i].state == ID_UNASSIGNED) ||
5595 (FPT_scamInfo[i].state == ID_UNUSED)) {
5596 if (FPT_scsell(p_port, i)) {
5597 FPT_scamInfo[i].state = LEGACY;
5598 if ((FPT_scamInfo[i].
5599 id_string[0] != 0xFF)
5600 || (FPT_scamInfo[i].
5601 id_string[1] != 0xFA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005602
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005603 FPT_scamInfo[i].
5604 id_string[0] = 0xFF;
5605 FPT_scamInfo[i].
5606 id_string[1] = 0xFA;
5607 if (pCurrNvRam == NULL)
5608 currCard->
5609 globalFlags
5610 |=
5611 F_UPDATE_EEPROM;
5612 }
5613 }
5614 }
5615 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005616
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005617 FPT_sresb(p_port, p_card);
5618 FPT_Wait1Second(p_port);
5619 while (!(FPT_scarb(p_port, INIT_SELTD))) {
5620 }
5621 FPT_scsel(p_port);
5622 FPT_scasid(p_card, p_port);
5623 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005624
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005625 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005626
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005627 else if ((loser) && (ScamFlg & SCAM_ENABLED)) {
5628 FPT_scamInfo[p_our_id].id_string[0] = SLV_TYPE_CODE0;
5629 assigned_id = 0;
5630 FPT_scwtsel(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005631
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005632 do {
5633 while (FPT_scxferc(p_port, 0x00) != SYNC_PTRN) {
5634 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005635
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005636 i = FPT_scxferc(p_port, 0x00);
5637 if (i == ASSIGN_ID) {
5638 if (!
5639 (FPT_scsendi
5640 (p_port,
5641 &FPT_scamInfo[p_our_id].id_string[0]))) {
5642 i = FPT_scxferc(p_port, 0x00);
5643 if (FPT_scvalq(i)) {
5644 k = FPT_scxferc(p_port, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005645
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005646 if (FPT_scvalq(k)) {
5647 currCard->ourId =
5648 ((unsigned char)(i
5649 <<
5650 3)
5651 +
5652 (k &
5653 (unsigned char)7))
5654 & (unsigned char)
5655 0x3F;
5656 FPT_inisci(p_card,
5657 p_port,
5658 p_our_id);
5659 FPT_scamInfo[currCard->
5660 ourId].
5661 state = ID_ASSIGNED;
5662 FPT_scamInfo[currCard->
5663 ourId].
5664 id_string[0]
5665 = SLV_TYPE_CODE0;
5666 assigned_id = 1;
5667 }
5668 }
5669 }
5670 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005671
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005672 else if (i == SET_P_FLAG) {
5673 if (!(FPT_scsendi(p_port,
5674 &FPT_scamInfo[p_our_id].
5675 id_string[0])))
5676 FPT_scamInfo[p_our_id].id_string[0] |=
5677 0x80;
5678 }
5679 } while (!assigned_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005680
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005681 while (FPT_scxferc(p_port, 0x00) != CFG_CMPLT) {
5682 }
5683 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005684
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005685 if (ScamFlg & SCAM_ENABLED) {
5686 FPT_scbusf(p_port);
5687 if (currCard->globalFlags & F_UPDATE_EEPROM) {
5688 FPT_scsavdi(p_card, p_port);
5689 currCard->globalFlags &= ~F_UPDATE_EEPROM;
5690 }
5691 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005692
Linus Torvalds1da177e2005-04-16 15:20:36 -07005693/*
5694 for (i=0,k=0; i < MAX_SCSI_TAR; i++)
5695 {
James Bottomley 47b5d692005-04-24 02:38:05 -05005696 if ((FPT_scamInfo[i].state == ID_ASSIGNED) ||
5697 (FPT_scamInfo[i].state == LEGACY))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005698 k++;
5699 }
5700
5701 if (k==2)
5702 currCard->globalFlags |= F_SINGLE_DEVICE;
5703 else
5704 currCard->globalFlags &= ~F_SINGLE_DEVICE;
5705*/
5706}
5707
Linus Torvalds1da177e2005-04-16 15:20:36 -07005708/*---------------------------------------------------------------------
5709 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005710 * Function: FPT_scarb
Linus Torvalds1da177e2005-04-16 15:20:36 -07005711 *
5712 * Description: Gain control of the bus and wait SCAM select time (250ms)
5713 *
5714 *---------------------------------------------------------------------*/
5715
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08005716static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005717{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005718 if (p_sel_type == INIT_SELTD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005719
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005720 while (RD_HARPOON(p_port + hp_scsisig) & (SCSI_SEL | SCSI_BSY)) {
5721 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005722
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005723 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005724 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005725
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005726 if (RD_HARPOON(p_port + hp_scsidata_0) != 00)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005727 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005728
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005729 WR_HARPOON(p_port + hp_scsisig,
5730 (RD_HARPOON(p_port + hp_scsisig) | SCSI_BSY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005731
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005732 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005733
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005734 WR_HARPOON(p_port + hp_scsisig,
5735 (RD_HARPOON(p_port + hp_scsisig) &
5736 ~SCSI_BSY));
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005737 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005738 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005739
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005740 WR_HARPOON(p_port + hp_scsisig,
5741 (RD_HARPOON(p_port + hp_scsisig) | SCSI_SEL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005742
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005743 if (RD_HARPOON(p_port + hp_scsidata_0) != 00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005744
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005745 WR_HARPOON(p_port + hp_scsisig,
5746 (RD_HARPOON(p_port + hp_scsisig) &
5747 ~(SCSI_BSY | SCSI_SEL)));
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005748 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005749 }
5750 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005751
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005752 WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
5753 & ~ACTdeassert));
5754 WR_HARPOON(p_port + hp_scsireset, SCAM_EN);
5755 WR_HARPOON(p_port + hp_scsidata_0, 0x00);
5756 WR_HARPOON(p_port + hp_scsidata_1, 0x00);
5757 WR_HARPOON(p_port + hp_portctrl_0, SCSI_BUS_EN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005758
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005759 WR_HARPOON(p_port + hp_scsisig,
5760 (RD_HARPOON(p_port + hp_scsisig) | SCSI_MSG));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005761
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005762 WR_HARPOON(p_port + hp_scsisig, (RD_HARPOON(p_port + hp_scsisig)
5763 & ~SCSI_BSY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005764
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005765 FPT_Wait(p_port, TO_250ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005766
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005767 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005768}
5769
Linus Torvalds1da177e2005-04-16 15:20:36 -07005770/*---------------------------------------------------------------------
5771 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005772 * Function: FPT_scbusf
Linus Torvalds1da177e2005-04-16 15:20:36 -07005773 *
5774 * Description: Release the SCSI bus and disable SCAM selection.
5775 *
5776 *---------------------------------------------------------------------*/
5777
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08005778static void FPT_scbusf(unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005779{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005780 WR_HARPOON(p_port + hp_page_ctrl,
5781 (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005782
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005783 WR_HARPOON(p_port + hp_scsidata_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005784
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005785 WR_HARPOON(p_port + hp_portctrl_0, (RD_HARPOON(p_port + hp_portctrl_0)
5786 & ~SCSI_BUS_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005787
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005788 WR_HARPOON(p_port + hp_scsisig, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005789
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005790 WR_HARPOON(p_port + hp_scsireset, (RD_HARPOON(p_port + hp_scsireset)
5791 & ~SCAM_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005792
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005793 WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
5794 | ACTdeassert));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005795
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005796 WRW_HARPOON((p_port + hp_intstat), (BUS_FREE | AUTO_INT | SCAM_SEL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005797
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005798 WR_HARPOON(p_port + hp_page_ctrl,
5799 (RD_HARPOON(p_port + hp_page_ctrl) & ~G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005800}
5801
Linus Torvalds1da177e2005-04-16 15:20:36 -07005802/*---------------------------------------------------------------------
5803 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005804 * Function: FPT_scasid
Linus Torvalds1da177e2005-04-16 15:20:36 -07005805 *
5806 * Description: Assign an ID to all the SCAM devices.
5807 *
5808 *---------------------------------------------------------------------*/
5809
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08005810static void FPT_scasid(unsigned char p_card, unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005811{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005812 unsigned char temp_id_string[ID_STRING_LENGTH];
Linus Torvalds1da177e2005-04-16 15:20:36 -07005813
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005814 unsigned char i, k, scam_id;
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08005815 unsigned char crcBytes[3];
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005816 struct nvram_info *pCurrNvRam;
5817 unsigned short *pCrcBytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005818
James Bottomley 47b5d692005-04-24 02:38:05 -05005819 pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005820
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005821 i = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005822
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005823 while (!i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005824
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005825 for (k = 0; k < ID_STRING_LENGTH; k++) {
5826 temp_id_string[k] = (unsigned char)0x00;
5827 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005828
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005829 FPT_scxferc(p_port, SYNC_PTRN);
5830 FPT_scxferc(p_port, ASSIGN_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005831
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005832 if (!(FPT_sciso(p_port, &temp_id_string[0]))) {
5833 if (pCurrNvRam) {
Alexey Dobriyanfd1e29e2006-03-08 00:14:27 -08005834 pCrcBytes = (unsigned short *)&crcBytes[0];
James Bottomley 47b5d692005-04-24 02:38:05 -05005835 *pCrcBytes = FPT_CalcCrc16(&temp_id_string[0]);
5836 crcBytes[2] = FPT_CalcLrc(&temp_id_string[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005837 temp_id_string[1] = crcBytes[2];
5838 temp_id_string[2] = crcBytes[0];
5839 temp_id_string[3] = crcBytes[1];
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005840 for (k = 4; k < ID_STRING_LENGTH; k++)
5841 temp_id_string[k] = (unsigned char)0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005842 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005843 i = FPT_scmachid(p_card, temp_id_string);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005844
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005845 if (i == CLR_PRIORITY) {
5846 FPT_scxferc(p_port, MISC_CODE);
5847 FPT_scxferc(p_port, CLR_P_FLAG);
5848 i = 0; /*Not the last ID yet. */
5849 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005850
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005851 else if (i != NO_ID_AVAIL) {
5852 if (i < 8)
5853 FPT_scxferc(p_port, ID_0_7);
5854 else
5855 FPT_scxferc(p_port, ID_8_F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005856
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005857 scam_id = (i & (unsigned char)0x07);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005858
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005859 for (k = 1; k < 0x08; k <<= 1)
5860 if (!(k & i))
5861 scam_id += 0x08; /*Count number of zeros in DB0-3. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005862
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005863 FPT_scxferc(p_port, scam_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005864
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005865 i = 0; /*Not the last ID yet. */
5866 }
5867 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005868
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005869 else {
5870 i = 1;
5871 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005872
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005873 } /*End while */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005874
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005875 FPT_scxferc(p_port, SYNC_PTRN);
5876 FPT_scxferc(p_port, CFG_CMPLT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005877}
5878
Linus Torvalds1da177e2005-04-16 15:20:36 -07005879/*---------------------------------------------------------------------
5880 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005881 * Function: FPT_scsel
Linus Torvalds1da177e2005-04-16 15:20:36 -07005882 *
5883 * Description: Select all the SCAM devices.
5884 *
5885 *---------------------------------------------------------------------*/
5886
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08005887static void FPT_scsel(unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005888{
5889
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005890 WR_HARPOON(p_port + hp_scsisig, SCSI_SEL);
5891 FPT_scwiros(p_port, SCSI_MSG);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005892
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005893 WR_HARPOON(p_port + hp_scsisig, (SCSI_SEL | SCSI_BSY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005894
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005895 WR_HARPOON(p_port + hp_scsisig,
5896 (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5897 WR_HARPOON(p_port + hp_scsidata_0,
5898 (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) |
5899 (unsigned char)(BIT(7) + BIT(6))));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005900
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005901 WR_HARPOON(p_port + hp_scsisig, (SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5902 FPT_scwiros(p_port, SCSI_SEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005903
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005904 WR_HARPOON(p_port + hp_scsidata_0,
5905 (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) &
5906 ~(unsigned char)BIT(6)));
5907 FPT_scwirod(p_port, BIT(6));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005908
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005909 WR_HARPOON(p_port + hp_scsisig,
5910 (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005911}
5912
Linus Torvalds1da177e2005-04-16 15:20:36 -07005913/*---------------------------------------------------------------------
5914 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005915 * Function: FPT_scxferc
Linus Torvalds1da177e2005-04-16 15:20:36 -07005916 *
5917 * Description: Handshake the p_data (DB4-0) across the bus.
5918 *
5919 *---------------------------------------------------------------------*/
5920
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08005921static unsigned char FPT_scxferc(unsigned long p_port, unsigned char p_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005922{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005923 unsigned char curr_data, ret_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005924
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005925 curr_data = p_data | BIT(7) | BIT(5); /*Start with DB7 & DB5 asserted. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005926
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005927 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005928
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005929 curr_data &= ~BIT(7);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005930
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005931 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005932
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005933 FPT_scwirod(p_port, BIT(7)); /*Wait for DB7 to be released. */
5934 while (!(RD_HARPOON(p_port + hp_scsidata_0) & BIT(5))) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005935
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005936 ret_data = (RD_HARPOON(p_port + hp_scsidata_0) & (unsigned char)0x1F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005937
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005938 curr_data |= BIT(6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005939
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005940 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005941
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005942 curr_data &= ~BIT(5);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005943
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005944 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005945
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005946 FPT_scwirod(p_port, BIT(5)); /*Wait for DB5 to be released. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005947
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005948 curr_data &= ~(BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0)); /*Release data bits */
5949 curr_data |= BIT(7);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005950
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005951 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005952
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005953 curr_data &= ~BIT(6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005954
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005955 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005956
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005957 FPT_scwirod(p_port, BIT(6)); /*Wait for DB6 to be released. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005958
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005959 return ret_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005960}
5961
Linus Torvalds1da177e2005-04-16 15:20:36 -07005962/*---------------------------------------------------------------------
5963 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005964 * Function: FPT_scsendi
Linus Torvalds1da177e2005-04-16 15:20:36 -07005965 *
5966 * Description: Transfer our Identification string to determine if we
5967 * will be the dominant master.
5968 *
5969 *---------------------------------------------------------------------*/
5970
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005971static unsigned char FPT_scsendi(unsigned long p_port,
5972 unsigned char p_id_string[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07005973{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005974 unsigned char ret_data, byte_cnt, bit_cnt, defer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005975
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005976 defer = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005977
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005978 for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005979
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005980 for (bit_cnt = 0x80; bit_cnt != 0; bit_cnt >>= 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005981
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005982 if (defer)
5983 ret_data = FPT_scxferc(p_port, 00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005984
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005985 else if (p_id_string[byte_cnt] & bit_cnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005986
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005987 ret_data = FPT_scxferc(p_port, 02);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005988
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005989 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005990
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005991 ret_data = FPT_scxferc(p_port, 01);
5992 if (ret_data & 02)
5993 defer = 1;
5994 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005995
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005996 if ((ret_data & 0x1C) == 0x10)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005997 return 0x00; /*End of isolation stage, we won! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005998
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005999 if (ret_data & 0x1C)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006000 return 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006001
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006002 if ((defer) && (!(ret_data & 0x1F)))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006003 return 0x01; /*End of isolation stage, we lost. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006004
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006005 } /*bit loop */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006006
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006007 } /*byte loop */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006008
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006009 if (defer)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006010 return 0x01; /*We lost */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006011 else
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006012 return 0; /*We WON! Yeeessss! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006013}
6014
Linus Torvalds1da177e2005-04-16 15:20:36 -07006015/*---------------------------------------------------------------------
6016 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006017 * Function: FPT_sciso
Linus Torvalds1da177e2005-04-16 15:20:36 -07006018 *
6019 * Description: Transfer the Identification string.
6020 *
6021 *---------------------------------------------------------------------*/
6022
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006023static unsigned char FPT_sciso(unsigned long p_port,
6024 unsigned char p_id_string[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07006025{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006026 unsigned char ret_data, the_data, byte_cnt, bit_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006027
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006028 the_data = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006029
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006030 for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006031
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006032 for (bit_cnt = 0; bit_cnt < 8; bit_cnt++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006033
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006034 ret_data = FPT_scxferc(p_port, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006035
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006036 if (ret_data & 0xFC)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006037 return 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006038
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006039 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006040
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006041 the_data <<= 1;
6042 if (ret_data & BIT(1)) {
6043 the_data |= 1;
6044 }
6045 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006046
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006047 if ((ret_data & 0x1F) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006048/*
6049 if(bit_cnt != 0 || bit_cnt != 8)
6050 {
6051 byte_cnt = 0;
6052 bit_cnt = 0;
James Bottomley 47b5d692005-04-24 02:38:05 -05006053 FPT_scxferc(p_port, SYNC_PTRN);
6054 FPT_scxferc(p_port, ASSIGN_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006055 continue;
6056 }
6057*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006058 if (byte_cnt)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006059 return 0x00;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006060 else
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006061 return 0xFF;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006062 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006063
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006064 } /*bit loop */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006065
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006066 p_id_string[byte_cnt] = the_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006067
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006068 } /*byte loop */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006069
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006070 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006071}
6072
Linus Torvalds1da177e2005-04-16 15:20:36 -07006073/*---------------------------------------------------------------------
6074 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006075 * Function: FPT_scwirod
Linus Torvalds1da177e2005-04-16 15:20:36 -07006076 *
6077 * Description: Sample the SCSI data bus making sure the signal has been
6078 * deasserted for the correct number of consecutive samples.
6079 *
6080 *---------------------------------------------------------------------*/
6081
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08006082static void FPT_scwirod(unsigned long p_port, unsigned char p_data_bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006083{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006084 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006085
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006086 i = 0;
6087 while (i < MAX_SCSI_TAR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006088
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006089 if (RD_HARPOON(p_port + hp_scsidata_0) & p_data_bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006090
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006091 i = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006092
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006093 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07006094
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006095 i++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006096
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006097 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006098}
6099
Linus Torvalds1da177e2005-04-16 15:20:36 -07006100/*---------------------------------------------------------------------
6101 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006102 * Function: FPT_scwiros
Linus Torvalds1da177e2005-04-16 15:20:36 -07006103 *
6104 * Description: Sample the SCSI Signal lines making sure the signal has been
6105 * deasserted for the correct number of consecutive samples.
6106 *
6107 *---------------------------------------------------------------------*/
6108
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08006109static void FPT_scwiros(unsigned long p_port, unsigned char p_data_bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006110{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006111 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006112
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006113 i = 0;
6114 while (i < MAX_SCSI_TAR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006115
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006116 if (RD_HARPOON(p_port + hp_scsisig) & p_data_bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006117
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006118 i = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006119
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006120 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07006121
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006122 i++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006123
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006124 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006125}
6126
Linus Torvalds1da177e2005-04-16 15:20:36 -07006127/*---------------------------------------------------------------------
6128 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006129 * Function: FPT_scvalq
Linus Torvalds1da177e2005-04-16 15:20:36 -07006130 *
6131 * Description: Make sure we received a valid data byte.
6132 *
6133 *---------------------------------------------------------------------*/
6134
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08006135static unsigned char FPT_scvalq(unsigned char p_quintet)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006136{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006137 unsigned char count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006138
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006139 for (count = 1; count < 0x08; count <<= 1) {
6140 if (!(p_quintet & count))
6141 p_quintet -= 0x80;
6142 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006143
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006144 if (p_quintet & 0x18)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006145 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006146
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006147 else
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006148 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006149}
6150
Linus Torvalds1da177e2005-04-16 15:20:36 -07006151/*---------------------------------------------------------------------
6152 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006153 * Function: FPT_scsell
Linus Torvalds1da177e2005-04-16 15:20:36 -07006154 *
6155 * Description: Select the specified device ID using a selection timeout
6156 * less than 4ms. If somebody responds then it is a legacy
6157 * drive and this ID must be marked as such.
6158 *
6159 *---------------------------------------------------------------------*/
6160
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08006161static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006162{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006163 unsigned long i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006164
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006165 WR_HARPOON(p_port + hp_page_ctrl,
6166 (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006167
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006168 ARAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006169
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006170 WR_HARPOON(p_port + hp_addstat,
6171 (RD_HARPOON(p_port + hp_addstat) | SCAM_TIMER));
6172 WR_HARPOON(p_port + hp_seltimeout, TO_4ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006173
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006174 for (i = p_port + CMD_STRT; i < p_port + CMD_STRT + 12; i += 2) {
6175 WRW_HARPOON(i, (MPM_OP + ACOMMAND));
6176 }
6177 WRW_HARPOON(i, (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006178
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006179 WRW_HARPOON((p_port + hp_intstat),
6180 (RESET | TIMEOUT | SEL | BUS_FREE | AUTO_INT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006181
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006182 WR_HARPOON(p_port + hp_select_id, targ_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006183
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006184 WR_HARPOON(p_port + hp_portctrl_0, SCSI_PORT);
6185 WR_HARPOON(p_port + hp_autostart_3, (SELECT | CMD_ONLY_STRT));
6186 WR_HARPOON(p_port + hp_scsictrl_0, (SEL_TAR | ENA_RESEL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006187
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006188 while (!(RDW_HARPOON((p_port + hp_intstat)) &
6189 (RESET | PROG_HLT | TIMEOUT | AUTO_INT))) {
6190 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006191
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006192 if (RDW_HARPOON((p_port + hp_intstat)) & RESET)
6193 FPT_Wait(p_port, TO_250ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006194
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006195 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006196
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006197 WR_HARPOON(p_port + hp_addstat,
6198 (RD_HARPOON(p_port + hp_addstat) & ~SCAM_TIMER));
6199 WR_HARPOON(p_port + hp_seltimeout, TO_290ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006200
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006201 SGRAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006202
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006203 if (RDW_HARPOON((p_port + hp_intstat)) & (RESET | TIMEOUT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006204
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006205 WRW_HARPOON((p_port + hp_intstat),
6206 (RESET | TIMEOUT | SEL | BUS_FREE | PHASE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006207
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006208 WR_HARPOON(p_port + hp_page_ctrl,
6209 (RD_HARPOON(p_port + hp_page_ctrl) &
6210 ~G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006211
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006212 return 0; /*No legacy device */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006213 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006214
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006215 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006216
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006217 while (!(RDW_HARPOON((p_port + hp_intstat)) & BUS_FREE)) {
6218 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ) {
6219 WR_HARPOON(p_port + hp_scsisig,
6220 (SCSI_ACK + S_ILL_PH));
6221 ACCEPT_MSG(p_port);
6222 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006223 }
6224
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006225 WRW_HARPOON((p_port + hp_intstat), CLR_ALL_INT_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006226
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006227 WR_HARPOON(p_port + hp_page_ctrl,
6228 (RD_HARPOON(p_port + hp_page_ctrl) &
6229 ~G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006230
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006231 return 1; /*Found one of them oldies! */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006232 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006233}
6234
Linus Torvalds1da177e2005-04-16 15:20:36 -07006235/*---------------------------------------------------------------------
6236 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006237 * Function: FPT_scwtsel
Linus Torvalds1da177e2005-04-16 15:20:36 -07006238 *
6239 * Description: Wait to be selected by another SCAM initiator.
6240 *
6241 *---------------------------------------------------------------------*/
6242
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08006243static void FPT_scwtsel(unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006244{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006245 while (!(RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL)) {
6246 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006247}
6248
Linus Torvalds1da177e2005-04-16 15:20:36 -07006249/*---------------------------------------------------------------------
6250 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006251 * Function: FPT_inisci
Linus Torvalds1da177e2005-04-16 15:20:36 -07006252 *
6253 * Description: Setup the data Structure with the info from the EEPROM.
6254 *
6255 *---------------------------------------------------------------------*/
6256
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006257static void FPT_inisci(unsigned char p_card, unsigned long p_port,
6258 unsigned char p_our_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006259{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006260 unsigned char i, k, max_id;
6261 unsigned short ee_data;
6262 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006263
James Bottomley 47b5d692005-04-24 02:38:05 -05006264 pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006265
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006266 if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6267 max_id = 0x08;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006268
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006269 else
6270 max_id = 0x10;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006271
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006272 if (pCurrNvRam) {
6273 for (i = 0; i < max_id; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006274
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006275 for (k = 0; k < 4; k++)
6276 FPT_scamInfo[i].id_string[k] =
6277 pCurrNvRam->niScamTbl[i][k];
6278 for (k = 4; k < ID_STRING_LENGTH; k++)
6279 FPT_scamInfo[i].id_string[k] =
6280 (unsigned char)0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006281
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006282 if (FPT_scamInfo[i].id_string[0] == 0x00)
6283 FPT_scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */
6284 else
6285 FPT_scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006286
6287 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006288 } else {
6289 for (i = 0; i < max_id; i++) {
6290 for (k = 0; k < ID_STRING_LENGTH; k += 2) {
6291 ee_data =
6292 FPT_utilEERead(p_port,
6293 (unsigned
6294 short)((EE_SCAMBASE / 2) +
6295 (unsigned short)(i *
6296 ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
6297 FPT_scamInfo[i].id_string[k] =
6298 (unsigned char)ee_data;
6299 ee_data >>= 8;
6300 FPT_scamInfo[i].id_string[k + 1] =
6301 (unsigned char)ee_data;
6302 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006303
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006304 if ((FPT_scamInfo[i].id_string[0] == 0x00) ||
6305 (FPT_scamInfo[i].id_string[0] == 0xFF))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006306
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006307 FPT_scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006308
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006309 else
6310 FPT_scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006311
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006312 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006313 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006314 for (k = 0; k < ID_STRING_LENGTH; k++)
James Bottomley 47b5d692005-04-24 02:38:05 -05006315 FPT_scamInfo[p_our_id].id_string[k] = FPT_scamHAString[k];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006316
6317}
6318
6319/*---------------------------------------------------------------------
6320 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006321 * Function: FPT_scmachid
Linus Torvalds1da177e2005-04-16 15:20:36 -07006322 *
6323 * Description: Match the Device ID string with our values stored in
6324 * the EEPROM.
6325 *
6326 *---------------------------------------------------------------------*/
6327
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006328static unsigned char FPT_scmachid(unsigned char p_card,
6329 unsigned char p_id_string[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07006330{
6331
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006332 unsigned char i, k, match;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006333
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006334 for (i = 0; i < MAX_SCSI_TAR; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006335
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006336 match = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006337
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006338 for (k = 0; k < ID_STRING_LENGTH; k++) {
6339 if (p_id_string[k] != FPT_scamInfo[i].id_string[k])
6340 match = 0;
6341 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006342
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006343 if (match) {
6344 FPT_scamInfo[i].state = ID_ASSIGNED;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006345 return i;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006346 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006347
Linus Torvalds1da177e2005-04-16 15:20:36 -07006348 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006349
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006350 if (p_id_string[0] & BIT(5))
6351 i = 8;
6352 else
6353 i = MAX_SCSI_TAR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006354
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006355 if (((p_id_string[0] & 0x06) == 0x02)
6356 || ((p_id_string[0] & 0x06) == 0x04))
6357 match = p_id_string[1] & (unsigned char)0x1F;
6358 else
6359 match = 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006360
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006361 while (i > 0) {
6362 i--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006363
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006364 if (FPT_scamInfo[match].state == ID_UNUSED) {
6365 for (k = 0; k < ID_STRING_LENGTH; k++) {
6366 FPT_scamInfo[match].id_string[k] =
6367 p_id_string[k];
6368 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006369
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006370 FPT_scamInfo[match].state = ID_ASSIGNED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006371
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006372 if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
6373 FPT_BL_Card[p_card].globalFlags |=
6374 F_UPDATE_EEPROM;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006375 return match;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006376
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006377 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006378
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006379 match--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006380
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006381 if (match == 0xFF) {
6382 if (p_id_string[0] & BIT(5))
6383 match = 7;
6384 else
6385 match = MAX_SCSI_TAR - 1;
6386 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006387 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006388
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006389 if (p_id_string[0] & BIT(7)) {
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006390 return CLR_PRIORITY;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006391 }
6392
6393 if (p_id_string[0] & BIT(5))
6394 i = 8;
6395 else
6396 i = MAX_SCSI_TAR;
6397
6398 if (((p_id_string[0] & 0x06) == 0x02)
6399 || ((p_id_string[0] & 0x06) == 0x04))
6400 match = p_id_string[1] & (unsigned char)0x1F;
6401 else
6402 match = 7;
6403
6404 while (i > 0) {
6405
6406 i--;
6407
6408 if (FPT_scamInfo[match].state == ID_UNASSIGNED) {
6409 for (k = 0; k < ID_STRING_LENGTH; k++) {
6410 FPT_scamInfo[match].id_string[k] =
6411 p_id_string[k];
6412 }
6413
6414 FPT_scamInfo[match].id_string[0] |= BIT(7);
6415 FPT_scamInfo[match].state = ID_ASSIGNED;
6416 if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
6417 FPT_BL_Card[p_card].globalFlags |=
6418 F_UPDATE_EEPROM;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006419 return match;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006420
6421 }
6422
6423 match--;
6424
6425 if (match == 0xFF) {
6426 if (p_id_string[0] & BIT(5))
6427 match = 7;
6428 else
6429 match = MAX_SCSI_TAR - 1;
6430 }
6431 }
6432
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006433 return NO_ID_AVAIL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006434}
6435
Linus Torvalds1da177e2005-04-16 15:20:36 -07006436/*---------------------------------------------------------------------
6437 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006438 * Function: FPT_scsavdi
Linus Torvalds1da177e2005-04-16 15:20:36 -07006439 *
6440 * Description: Save off the device SCAM ID strings.
6441 *
6442 *---------------------------------------------------------------------*/
6443
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08006444static void FPT_scsavdi(unsigned char p_card, unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006445{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006446 unsigned char i, k, max_id;
6447 unsigned short ee_data, sum_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006448
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006449 sum_data = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006450
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006451 for (i = 1; i < EE_SCAMBASE / 2; i++) {
6452 sum_data += FPT_utilEERead(p_port, i);
6453 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006454
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006455 FPT_utilEEWriteOnOff(p_port, 1); /* Enable write access to the EEPROM */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006456
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006457 if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6458 max_id = 0x08;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006459
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006460 else
6461 max_id = 0x10;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006462
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006463 for (i = 0; i < max_id; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006464
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006465 for (k = 0; k < ID_STRING_LENGTH; k += 2) {
6466 ee_data = FPT_scamInfo[i].id_string[k + 1];
6467 ee_data <<= 8;
6468 ee_data |= FPT_scamInfo[i].id_string[k];
6469 sum_data += ee_data;
6470 FPT_utilEEWrite(p_port, ee_data,
6471 (unsigned short)((EE_SCAMBASE / 2) +
6472 (unsigned short)(i *
6473 ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
6474 }
6475 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006476
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006477 FPT_utilEEWrite(p_port, sum_data, EEPROM_CHECK_SUM / 2);
6478 FPT_utilEEWriteOnOff(p_port, 0); /* Turn off write access */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006479}
Linus Torvalds1da177e2005-04-16 15:20:36 -07006480
6481/*---------------------------------------------------------------------
6482 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006483 * Function: FPT_XbowInit
Linus Torvalds1da177e2005-04-16 15:20:36 -07006484 *
6485 * Description: Setup the Xbow for normal operation.
6486 *
6487 *---------------------------------------------------------------------*/
6488
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08006489static void FPT_XbowInit(unsigned long port, unsigned char ScamFlg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006490{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006491 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006492
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006493 i = RD_HARPOON(port + hp_page_ctrl);
6494 WR_HARPOON(port + hp_page_ctrl, (unsigned char)(i | G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006495
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006496 WR_HARPOON(port + hp_scsireset, 0x00);
6497 WR_HARPOON(port + hp_portctrl_1, HOST_MODE8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006498
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006499 WR_HARPOON(port + hp_scsireset, (DMA_RESET | HPSCSI_RESET | PROG_RESET |
6500 FIFO_CLR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006501
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006502 WR_HARPOON(port + hp_scsireset, SCSI_INI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006503
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006504 WR_HARPOON(port + hp_clkctrl_0, CLKCTRL_DEFAULT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006505
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006506 WR_HARPOON(port + hp_scsisig, 0x00); /* Clear any signals we might */
6507 WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006508
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006509 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006510
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006511 FPT_default_intena = RESET | RSEL | PROG_HLT | TIMEOUT |
6512 BUS_FREE | XFER_CNT_0 | AUTO_INT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006513
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006514 if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2))
James Bottomley 47b5d692005-04-24 02:38:05 -05006515 FPT_default_intena |= SCAM_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006516
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006517 WRW_HARPOON((port + hp_intena), FPT_default_intena);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006518
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006519 WR_HARPOON(port + hp_seltimeout, TO_290ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006520
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006521 /* Turn on SCSI_MODE8 for narrow cards to fix the
6522 strapping issue with the DUAL CHANNEL card */
6523 if (RD_HARPOON(port + hp_page_ctrl) & NARROW_SCSI_CARD)
6524 WR_HARPOON(port + hp_addstat, SCSI_MODE8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006525
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006526 WR_HARPOON(port + hp_page_ctrl, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006527
6528}
6529
Linus Torvalds1da177e2005-04-16 15:20:36 -07006530/*---------------------------------------------------------------------
6531 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006532 * Function: FPT_BusMasterInit
Linus Torvalds1da177e2005-04-16 15:20:36 -07006533 *
6534 * Description: Initialize the BusMaster for normal operations.
6535 *
6536 *---------------------------------------------------------------------*/
6537
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08006538static void FPT_BusMasterInit(unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006539{
6540
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006541 WR_HARPOON(p_port + hp_sys_ctrl, DRVR_RST);
6542 WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006543
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006544 WR_HARPOON(p_port + hp_host_blk_cnt, XFER_BLK64);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006545
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006546 WR_HARPOON(p_port + hp_bm_ctrl, (BMCTRL_DEFAULT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006547
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006548 WR_HARPOON(p_port + hp_ee_ctrl, (SCSI_TERM_ENA_H));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006549
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006550 RD_HARPOON(p_port + hp_int_status); /*Clear interrupts. */
6551 WR_HARPOON(p_port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
6552 WR_HARPOON(p_port + hp_page_ctrl, (RD_HARPOON(p_port + hp_page_ctrl) &
6553 ~SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006554}
6555
Linus Torvalds1da177e2005-04-16 15:20:36 -07006556/*---------------------------------------------------------------------
6557 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006558 * Function: FPT_DiagEEPROM
Linus Torvalds1da177e2005-04-16 15:20:36 -07006559 *
6560 * Description: Verfiy checksum and 'Key' and initialize the EEPROM if
6561 * necessary.
6562 *
6563 *---------------------------------------------------------------------*/
6564
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08006565static void FPT_DiagEEPROM(unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006566{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006567 unsigned short index, temp, max_wd_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006568
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006569 if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6570 max_wd_cnt = EEPROM_WD_CNT;
6571 else
6572 max_wd_cnt = EEPROM_WD_CNT * 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006573
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006574 temp = FPT_utilEERead(p_port, FW_SIGNATURE / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006575
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006576 if (temp == 0x4641) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006577
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006578 for (index = 2; index < max_wd_cnt; index++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006579
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006580 temp += FPT_utilEERead(p_port, index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006581
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006582 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006583
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006584 if (temp == FPT_utilEERead(p_port, EEPROM_CHECK_SUM / 2)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006585
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006586 return; /*EEPROM is Okay so return now! */
6587 }
6588 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006589
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006590 FPT_utilEEWriteOnOff(p_port, (unsigned char)1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006591
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006592 for (index = 0; index < max_wd_cnt; index++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006593
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006594 FPT_utilEEWrite(p_port, 0x0000, index);
6595 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006596
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006597 temp = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006598
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006599 FPT_utilEEWrite(p_port, 0x4641, FW_SIGNATURE / 2);
6600 temp += 0x4641;
6601 FPT_utilEEWrite(p_port, 0x3920, MODEL_NUMB_0 / 2);
6602 temp += 0x3920;
6603 FPT_utilEEWrite(p_port, 0x3033, MODEL_NUMB_2 / 2);
6604 temp += 0x3033;
6605 FPT_utilEEWrite(p_port, 0x2020, MODEL_NUMB_4 / 2);
6606 temp += 0x2020;
6607 FPT_utilEEWrite(p_port, 0x70D3, SYSTEM_CONFIG / 2);
6608 temp += 0x70D3;
6609 FPT_utilEEWrite(p_port, 0x0010, BIOS_CONFIG / 2);
6610 temp += 0x0010;
6611 FPT_utilEEWrite(p_port, 0x0003, SCAM_CONFIG / 2);
6612 temp += 0x0003;
6613 FPT_utilEEWrite(p_port, 0x0007, ADAPTER_SCSI_ID / 2);
6614 temp += 0x0007;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006615
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006616 FPT_utilEEWrite(p_port, 0x0000, IGNORE_B_SCAN / 2);
6617 temp += 0x0000;
6618 FPT_utilEEWrite(p_port, 0x0000, SEND_START_ENA / 2);
6619 temp += 0x0000;
6620 FPT_utilEEWrite(p_port, 0x0000, DEVICE_ENABLE / 2);
6621 temp += 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006622
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006623 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL01 / 2);
6624 temp += 0x4242;
6625 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL23 / 2);
6626 temp += 0x4242;
6627 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL45 / 2);
6628 temp += 0x4242;
6629 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL67 / 2);
6630 temp += 0x4242;
6631 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL89 / 2);
6632 temp += 0x4242;
6633 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLab / 2);
6634 temp += 0x4242;
6635 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLcd / 2);
6636 temp += 0x4242;
6637 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLef / 2);
6638 temp += 0x4242;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006639
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006640 FPT_utilEEWrite(p_port, 0x6C46, 64 / 2); /*PRODUCT ID */
6641 temp += 0x6C46;
6642 FPT_utilEEWrite(p_port, 0x7361, 66 / 2); /* FlashPoint LT */
6643 temp += 0x7361;
6644 FPT_utilEEWrite(p_port, 0x5068, 68 / 2);
6645 temp += 0x5068;
6646 FPT_utilEEWrite(p_port, 0x696F, 70 / 2);
6647 temp += 0x696F;
6648 FPT_utilEEWrite(p_port, 0x746E, 72 / 2);
6649 temp += 0x746E;
6650 FPT_utilEEWrite(p_port, 0x4C20, 74 / 2);
6651 temp += 0x4C20;
6652 FPT_utilEEWrite(p_port, 0x2054, 76 / 2);
6653 temp += 0x2054;
6654 FPT_utilEEWrite(p_port, 0x2020, 78 / 2);
6655 temp += 0x2020;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006656
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006657 index = ((EE_SCAMBASE / 2) + (7 * 16));
6658 FPT_utilEEWrite(p_port, (0x0700 + TYPE_CODE0), index);
6659 temp += (0x0700 + TYPE_CODE0);
6660 index++;
6661 FPT_utilEEWrite(p_port, 0x5542, index); /*Vendor ID code */
6662 temp += 0x5542; /* BUSLOGIC */
6663 index++;
6664 FPT_utilEEWrite(p_port, 0x4C53, index);
6665 temp += 0x4C53;
6666 index++;
6667 FPT_utilEEWrite(p_port, 0x474F, index);
6668 temp += 0x474F;
6669 index++;
6670 FPT_utilEEWrite(p_port, 0x4349, index);
6671 temp += 0x4349;
6672 index++;
6673 FPT_utilEEWrite(p_port, 0x5442, index); /*Vendor unique code */
6674 temp += 0x5442; /* BT- 930 */
6675 index++;
6676 FPT_utilEEWrite(p_port, 0x202D, index);
6677 temp += 0x202D;
6678 index++;
6679 FPT_utilEEWrite(p_port, 0x3339, index);
6680 temp += 0x3339;
6681 index++; /*Serial # */
6682 FPT_utilEEWrite(p_port, 0x2030, index); /* 01234567 */
6683 temp += 0x2030;
6684 index++;
6685 FPT_utilEEWrite(p_port, 0x5453, index);
6686 temp += 0x5453;
6687 index++;
6688 FPT_utilEEWrite(p_port, 0x5645, index);
6689 temp += 0x5645;
6690 index++;
6691 FPT_utilEEWrite(p_port, 0x2045, index);
6692 temp += 0x2045;
6693 index++;
6694 FPT_utilEEWrite(p_port, 0x202F, index);
6695 temp += 0x202F;
6696 index++;
6697 FPT_utilEEWrite(p_port, 0x4F4A, index);
6698 temp += 0x4F4A;
6699 index++;
6700 FPT_utilEEWrite(p_port, 0x204E, index);
6701 temp += 0x204E;
6702 index++;
6703 FPT_utilEEWrite(p_port, 0x3539, index);
6704 temp += 0x3539;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006705
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006706 FPT_utilEEWrite(p_port, temp, EEPROM_CHECK_SUM / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006707
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006708 FPT_utilEEWriteOnOff(p_port, (unsigned char)0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006709
6710}
6711
Linus Torvalds1da177e2005-04-16 15:20:36 -07006712/*---------------------------------------------------------------------
6713 *
6714 * Function: Queue Search Select
6715 *
6716 * Description: Try to find a new command to execute.
6717 *
6718 *---------------------------------------------------------------------*/
6719
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006720static void FPT_queueSearchSelect(struct sccb_card *pCurrCard,
6721 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006722{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006723 unsigned char scan_ptr, lun;
6724 struct sccb_mgr_tar_info *currTar_Info;
6725 struct sccb *pOldSccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006726
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006727 scan_ptr = pCurrCard->scanIndex;
6728 do {
James Bottomley 47b5d692005-04-24 02:38:05 -05006729 currTar_Info = &FPT_sccbMgrTbl[p_card][scan_ptr];
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006730 if ((pCurrCard->globalFlags & F_CONLUN_IO) &&
6731 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
6732 TAG_Q_TRYING)) {
6733 if (currTar_Info->TarSelQ_Cnt != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006734
6735 scan_ptr++;
6736 if (scan_ptr == MAX_SCSI_TAR)
6737 scan_ptr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006738
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006739 for (lun = 0; lun < MAX_LUN; lun++) {
6740 if (currTar_Info->TarLUNBusy[lun] == 0) {
6741
6742 pCurrCard->currentSCCB =
6743 currTar_Info->TarSelQ_Head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006744 pOldSccb = NULL;
6745
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006746 while ((pCurrCard->
6747 currentSCCB != NULL)
6748 && (lun !=
6749 pCurrCard->
6750 currentSCCB->Lun)) {
6751 pOldSccb =
6752 pCurrCard->
6753 currentSCCB;
6754 pCurrCard->currentSCCB =
6755 (struct sccb
6756 *)(pCurrCard->
6757 currentSCCB)->
6758 Sccb_forwardlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006759 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006760 if (pCurrCard->currentSCCB ==
6761 NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006762 continue;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006763 if (pOldSccb != NULL) {
6764 pOldSccb->
6765 Sccb_forwardlink =
6766 (struct sccb
6767 *)(pCurrCard->
6768 currentSCCB)->
6769 Sccb_forwardlink;
6770 pOldSccb->
6771 Sccb_backlink =
6772 (struct sccb
6773 *)(pCurrCard->
6774 currentSCCB)->
6775 Sccb_backlink;
6776 currTar_Info->
6777 TarSelQ_Cnt--;
6778 } else {
6779 currTar_Info->
6780 TarSelQ_Head =
6781 (struct sccb
6782 *)(pCurrCard->
6783 currentSCCB)->
6784 Sccb_forwardlink;
6785
6786 if (currTar_Info->
6787 TarSelQ_Head ==
6788 NULL) {
6789 currTar_Info->
6790 TarSelQ_Tail
6791 = NULL;
6792 currTar_Info->
6793 TarSelQ_Cnt
6794 = 0;
6795 } else {
6796 currTar_Info->
6797 TarSelQ_Cnt--;
6798 currTar_Info->
6799 TarSelQ_Head->
6800 Sccb_backlink
6801 =
6802 (struct sccb
6803 *)NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006804 }
6805 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006806 pCurrCard->scanIndex = scan_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006807
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006808 pCurrCard->globalFlags |=
6809 F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006810
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006811 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006812 }
6813 }
6814 }
6815
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006816 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006817 scan_ptr++;
6818 if (scan_ptr == MAX_SCSI_TAR) {
6819 scan_ptr = 0;
6820 }
6821 }
6822
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006823 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006824 if ((currTar_Info->TarSelQ_Cnt != 0) &&
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006825 (currTar_Info->TarLUNBusy[0] == 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006826
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006827 pCurrCard->currentSCCB =
6828 currTar_Info->TarSelQ_Head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006829
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006830 currTar_Info->TarSelQ_Head =
6831 (struct sccb *)(pCurrCard->currentSCCB)->
6832 Sccb_forwardlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006833
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006834 if (currTar_Info->TarSelQ_Head == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006835 currTar_Info->TarSelQ_Tail = NULL;
6836 currTar_Info->TarSelQ_Cnt = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006837 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006838 currTar_Info->TarSelQ_Cnt--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006839 currTar_Info->TarSelQ_Head->
6840 Sccb_backlink = (struct sccb *)NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006841 }
6842
6843 scan_ptr++;
6844 if (scan_ptr == MAX_SCSI_TAR)
6845 scan_ptr = 0;
6846
6847 pCurrCard->scanIndex = scan_ptr;
6848
6849 pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
6850
6851 break;
6852 }
6853
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006854 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006855 scan_ptr++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006856 if (scan_ptr == MAX_SCSI_TAR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006857 scan_ptr = 0;
6858 }
6859 }
6860 }
6861 } while (scan_ptr != pCurrCard->scanIndex);
6862}
6863
Linus Torvalds1da177e2005-04-16 15:20:36 -07006864/*---------------------------------------------------------------------
6865 *
6866 * Function: Queue Select Fail
6867 *
6868 * Description: Add the current SCCB to the head of the Queue.
6869 *
6870 *---------------------------------------------------------------------*/
6871
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006872static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
6873 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006874{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006875 unsigned char thisTarg;
6876 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006877
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006878 if (pCurrCard->currentSCCB != NULL) {
6879 thisTarg =
6880 (unsigned char)(((struct sccb *)(pCurrCard->currentSCCB))->
6881 TargID);
6882 currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006883
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006884 pCurrCard->currentSCCB->Sccb_backlink = (struct sccb *)NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006885
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006886 pCurrCard->currentSCCB->Sccb_forwardlink =
6887 currTar_Info->TarSelQ_Head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006888
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006889 if (currTar_Info->TarSelQ_Cnt == 0) {
6890 currTar_Info->TarSelQ_Tail = pCurrCard->currentSCCB;
6891 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006892
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006893 else {
6894 currTar_Info->TarSelQ_Head->Sccb_backlink =
6895 pCurrCard->currentSCCB;
6896 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006897
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006898 currTar_Info->TarSelQ_Head = pCurrCard->currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006899
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006900 pCurrCard->currentSCCB = NULL;
6901 currTar_Info->TarSelQ_Cnt++;
6902 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006903}
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006904
Linus Torvalds1da177e2005-04-16 15:20:36 -07006905/*---------------------------------------------------------------------
6906 *
6907 * Function: Queue Command Complete
6908 *
6909 * Description: Call the callback function with the current SCCB.
6910 *
6911 *---------------------------------------------------------------------*/
6912
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006913static void FPT_queueCmdComplete(struct sccb_card *pCurrCard,
6914 struct sccb *p_sccb, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006915{
6916
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006917 unsigned char i, SCSIcmd;
6918 CALL_BK_FN callback;
6919 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006920
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006921 SCSIcmd = p_sccb->Cdb[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006922
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006923 if (!(p_sccb->Sccb_XferState & F_ALL_XFERRED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006924
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006925 if ((p_sccb->
6926 ControlByte & (SCCB_DATA_XFER_OUT | SCCB_DATA_XFER_IN))
6927 && (p_sccb->HostStatus == SCCB_COMPLETE)
6928 && (p_sccb->TargetStatus != SSCHECK))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006929
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006930 if ((SCSIcmd == SCSI_READ) ||
6931 (SCSIcmd == SCSI_WRITE) ||
6932 (SCSIcmd == SCSI_READ_EXTENDED) ||
6933 (SCSIcmd == SCSI_WRITE_EXTENDED) ||
6934 (SCSIcmd == SCSI_WRITE_AND_VERIFY) ||
6935 (SCSIcmd == SCSI_START_STOP_UNIT) ||
6936 (pCurrCard->globalFlags & F_NO_FILTER)
6937 )
6938 p_sccb->HostStatus = SCCB_DATA_UNDER_RUN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006939 }
6940
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006941 if (p_sccb->SccbStatus == SCCB_IN_PROCESS) {
6942 if (p_sccb->HostStatus || p_sccb->TargetStatus)
6943 p_sccb->SccbStatus = SCCB_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006944 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006945 p_sccb->SccbStatus = SCCB_SUCCESS;
6946 }
6947
6948 if (p_sccb->Sccb_XferState & F_AUTO_SENSE) {
6949
6950 p_sccb->CdbLength = p_sccb->Save_CdbLen;
6951 for (i = 0; i < 6; i++) {
6952 p_sccb->Cdb[i] = p_sccb->Save_Cdb[i];
6953 }
6954 }
6955
6956 if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) ||
6957 (p_sccb->OperationCode == RESIDUAL_COMMAND)) {
6958
6959 FPT_utilUpdateResidual(p_sccb);
6960 }
6961
6962 pCurrCard->cmdCounter--;
6963 if (!pCurrCard->cmdCounter) {
6964
6965 if (pCurrCard->globalFlags & F_GREEN_PC) {
6966 WR_HARPOON(pCurrCard->ioPort + hp_clkctrl_0,
6967 (PWR_DWN | CLKCTRL_DEFAULT));
6968 WR_HARPOON(pCurrCard->ioPort + hp_sys_ctrl, STOP_CLK);
6969 }
6970
6971 WR_HARPOON(pCurrCard->ioPort + hp_semaphore,
6972 (RD_HARPOON(pCurrCard->ioPort + hp_semaphore) &
6973 ~SCCB_MGR_ACTIVE));
6974
6975 }
6976
6977 if (pCurrCard->discQCount != 0) {
6978 currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
6979 if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
6980 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
6981 TAG_Q_TRYING))) {
6982 pCurrCard->discQCount--;
6983 pCurrCard->discQ_Tbl[currTar_Info->
6984 LunDiscQ_Idx[p_sccb->Lun]] = NULL;
6985 } else {
6986 if (p_sccb->Sccb_tag) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006987 pCurrCard->discQCount--;
6988 pCurrCard->discQ_Tbl[p_sccb->Sccb_tag] = NULL;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006989 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006990 pCurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006991 pCurrCard->discQ_Tbl[currTar_Info->
6992 LunDiscQ_Idx[0]] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006993 }
6994 }
6995
6996 }
6997
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006998 callback = (CALL_BK_FN) p_sccb->SccbCallback;
6999 callback(p_sccb);
7000 pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
7001 pCurrCard->currentSCCB = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007002}
Linus Torvalds1da177e2005-04-16 15:20:36 -07007003
Linus Torvalds1da177e2005-04-16 15:20:36 -07007004/*---------------------------------------------------------------------
7005 *
7006 * Function: Queue Disconnect
7007 *
7008 * Description: Add SCCB to our disconnect array.
7009 *
7010 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007011static void FPT_queueDisconnect(struct sccb *p_sccb, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007012{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007013 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007014
James Bottomley 47b5d692005-04-24 02:38:05 -05007015 currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007016
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007017 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
7018 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
7019 FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
7020 LunDiscQ_Idx[p_sccb->Lun]] =
7021 p_sccb;
7022 } else {
7023 if (p_sccb->Sccb_tag) {
7024 FPT_BL_Card[p_card].discQ_Tbl[p_sccb->Sccb_tag] =
7025 p_sccb;
7026 FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarLUNBusy[0] =
7027 0;
James Bottomley 47b5d692005-04-24 02:38:05 -05007028 FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarTagQ_Cnt++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007029 } else {
7030 FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
7031 LunDiscQ_Idx[0]] = p_sccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007032 }
7033 }
James Bottomley 47b5d692005-04-24 02:38:05 -05007034 FPT_BL_Card[p_card].currentSCCB = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007035}
7036
Linus Torvalds1da177e2005-04-16 15:20:36 -07007037/*---------------------------------------------------------------------
7038 *
7039 * Function: Queue Flush SCCB
7040 *
7041 * Description: Flush all SCCB's back to the host driver for this target.
7042 *
7043 *---------------------------------------------------------------------*/
7044
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007045static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007046{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007047 unsigned char qtag, thisTarg;
7048 struct sccb *currSCCB;
7049 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007050
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007051 currSCCB = FPT_BL_Card[p_card].currentSCCB;
7052 if (currSCCB != NULL) {
7053 thisTarg = (unsigned char)currSCCB->TargID;
7054 currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007055
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007056 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007057
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007058 if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
7059 (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
7060 thisTarg)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007061
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007062 FPT_BL_Card[p_card].discQ_Tbl[qtag]->
7063 HostStatus = (unsigned char)error_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007064
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007065 FPT_queueCmdComplete(&FPT_BL_Card[p_card],
7066 FPT_BL_Card[p_card].
7067 discQ_Tbl[qtag], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007068
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007069 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
7070 currTar_Info->TarTagQ_Cnt--;
7071
7072 }
7073 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007074 }
7075
7076}
7077
7078/*---------------------------------------------------------------------
7079 *
7080 * Function: Queue Flush Target SCCB
7081 *
7082 * Description: Flush all SCCB's back to the host driver for this target.
7083 *
7084 *---------------------------------------------------------------------*/
7085
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007086static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
7087 unsigned char error_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007088{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007089 unsigned char qtag;
7090 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007091
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007092 currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007093
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007094 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007095
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007096 if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
7097 (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007098
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007099 FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus =
7100 (unsigned char)error_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007101
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007102 FPT_queueCmdComplete(&FPT_BL_Card[p_card],
7103 FPT_BL_Card[p_card].
7104 discQ_Tbl[qtag], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007105
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007106 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
7107 currTar_Info->TarTagQ_Cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007108
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007109 }
7110 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007111
7112}
7113
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007114static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007115{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007116 struct sccb_mgr_tar_info *currTar_Info;
7117 currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007118
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007119 p_SCCB->Sccb_forwardlink = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007120
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007121 p_SCCB->Sccb_backlink = currTar_Info->TarSelQ_Tail;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007122
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007123 if (currTar_Info->TarSelQ_Cnt == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007124
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007125 currTar_Info->TarSelQ_Head = p_SCCB;
7126 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007127
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007128 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007129
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007130 currTar_Info->TarSelQ_Tail->Sccb_forwardlink = p_SCCB;
7131 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007132
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007133 currTar_Info->TarSelQ_Tail = p_SCCB;
7134 currTar_Info->TarSelQ_Cnt++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007135}
7136
Linus Torvalds1da177e2005-04-16 15:20:36 -07007137/*---------------------------------------------------------------------
7138 *
7139 * Function: Queue Find SCCB
7140 *
7141 * Description: Search the target select Queue for this SCCB, and
7142 * remove it if found.
7143 *
7144 *---------------------------------------------------------------------*/
7145
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007146static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB,
7147 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007148{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007149 struct sccb *q_ptr;
7150 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007151
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007152 currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007153
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007154 q_ptr = currTar_Info->TarSelQ_Head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007155
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007156 while (q_ptr != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007157
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007158 if (q_ptr == p_SCCB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007159
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007160 if (currTar_Info->TarSelQ_Head == q_ptr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007161
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007162 currTar_Info->TarSelQ_Head =
7163 q_ptr->Sccb_forwardlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007164 }
7165
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007166 if (currTar_Info->TarSelQ_Tail == q_ptr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007167
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007168 currTar_Info->TarSelQ_Tail =
7169 q_ptr->Sccb_backlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007170 }
7171
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007172 if (q_ptr->Sccb_forwardlink != NULL) {
7173 q_ptr->Sccb_forwardlink->Sccb_backlink =
7174 q_ptr->Sccb_backlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007175 }
7176
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007177 if (q_ptr->Sccb_backlink != NULL) {
7178 q_ptr->Sccb_backlink->Sccb_forwardlink =
7179 q_ptr->Sccb_forwardlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007180 }
7181
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007182 currTar_Info->TarSelQ_Cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007183
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007184 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007185 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007186
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007187 else {
7188 q_ptr = q_ptr->Sccb_forwardlink;
7189 }
7190 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007191
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007192 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007193
7194}
7195
Linus Torvalds1da177e2005-04-16 15:20:36 -07007196/*---------------------------------------------------------------------
7197 *
7198 * Function: Utility Update Residual Count
7199 *
7200 * Description: Update the XferCnt to the remaining byte count.
7201 * If we transferred all the data then just write zero.
7202 * If Non-SG transfer then report Total Cnt - Actual Transfer
7203 * Cnt. For SG transfers add the count fields of all
7204 * remaining SG elements, as well as any partial remaining
7205 * element.
7206 *
7207 *---------------------------------------------------------------------*/
7208
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007209static void FPT_utilUpdateResidual(struct sccb *p_SCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007210{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007211 unsigned long partial_cnt;
7212 unsigned int sg_index;
7213 unsigned long *sg_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007214
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007215 if (p_SCCB->Sccb_XferState & F_ALL_XFERRED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007216
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007217 p_SCCB->DataLength = 0x0000;
7218 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007219
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007220 else if (p_SCCB->Sccb_XferState & F_SG_XFER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007221
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007222 partial_cnt = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007223
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007224 sg_index = p_SCCB->Sccb_sgseg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007225
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007226 sg_ptr = (unsigned long *)p_SCCB->DataPointer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007227
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007228 if (p_SCCB->Sccb_SGoffset) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007229
7230 partial_cnt = p_SCCB->Sccb_SGoffset;
7231 sg_index++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007232 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007233
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007234 while (((unsigned long)sg_index *
7235 (unsigned long)SG_ELEMENT_SIZE) < p_SCCB->DataLength) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007236
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007237 partial_cnt += *(sg_ptr + (sg_index * 2));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007238 sg_index++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007239 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007240
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007241 p_SCCB->DataLength = partial_cnt;
7242 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007243
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007244 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007245
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007246 p_SCCB->DataLength -= p_SCCB->Sccb_ATC;
7247 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007248}
7249
Linus Torvalds1da177e2005-04-16 15:20:36 -07007250/*---------------------------------------------------------------------
7251 *
7252 * Function: Wait 1 Second
7253 *
7254 * Description: Wait for 1 second.
7255 *
7256 *---------------------------------------------------------------------*/
7257
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08007258static void FPT_Wait1Second(unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007259{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007260 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007261
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007262 for (i = 0; i < 4; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007263
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007264 FPT_Wait(p_port, TO_250ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007265
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007266 if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
7267 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007268
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007269 if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
7270 break;
7271 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007272}
7273
Linus Torvalds1da177e2005-04-16 15:20:36 -07007274/*---------------------------------------------------------------------
7275 *
James Bottomley 47b5d692005-04-24 02:38:05 -05007276 * Function: FPT_Wait
Linus Torvalds1da177e2005-04-16 15:20:36 -07007277 *
7278 * Description: Wait the desired delay.
7279 *
7280 *---------------------------------------------------------------------*/
7281
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08007282static void FPT_Wait(unsigned long p_port, unsigned char p_delay)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007283{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007284 unsigned char old_timer;
7285 unsigned char green_flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007286
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007287 old_timer = RD_HARPOON(p_port + hp_seltimeout);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007288
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007289 green_flag = RD_HARPOON(p_port + hp_clkctrl_0);
7290 WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007291
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007292 WR_HARPOON(p_port + hp_seltimeout, p_delay);
7293 WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
7294 WRW_HARPOON((p_port + hp_intena), (FPT_default_intena & ~TIMEOUT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007295
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007296 WR_HARPOON(p_port + hp_portctrl_0,
7297 (RD_HARPOON(p_port + hp_portctrl_0) | START_TO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007298
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007299 while (!(RDW_HARPOON((p_port + hp_intstat)) & TIMEOUT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007300
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007301 if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
7302 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007303
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007304 if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
7305 break;
7306 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007307
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007308 WR_HARPOON(p_port + hp_portctrl_0,
7309 (RD_HARPOON(p_port + hp_portctrl_0) & ~START_TO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007310
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007311 WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
7312 WRW_HARPOON((p_port + hp_intena), FPT_default_intena);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007313
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007314 WR_HARPOON(p_port + hp_clkctrl_0, green_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007315
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007316 WR_HARPOON(p_port + hp_seltimeout, old_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007317}
7318
Linus Torvalds1da177e2005-04-16 15:20:36 -07007319/*---------------------------------------------------------------------
7320 *
7321 * Function: Enable/Disable Write to EEPROM
7322 *
7323 * Description: The EEPROM must first be enabled for writes
7324 * A total of 9 clocks are needed.
7325 *
7326 *---------------------------------------------------------------------*/
7327
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007328static void FPT_utilEEWriteOnOff(unsigned long p_port, unsigned char p_mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007329{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007330 unsigned char ee_value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007331
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007332 ee_value =
7333 (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
7334 (EXT_ARB_ACK | SCSI_TERM_ENA_H));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007335
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007336 if (p_mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007337
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007338 FPT_utilEESendCmdAddr(p_port, EWEN, EWEN_ADDR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007339
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007340 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07007341
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007342 FPT_utilEESendCmdAddr(p_port, EWDS, EWDS_ADDR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007343
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007344 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */
7345 WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /*Turn off Master Select */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007346}
7347
Linus Torvalds1da177e2005-04-16 15:20:36 -07007348/*---------------------------------------------------------------------
7349 *
7350 * Function: Write EEPROM
7351 *
7352 * Description: Write a word to the EEPROM at the specified
7353 * address.
7354 *
7355 *---------------------------------------------------------------------*/
7356
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007357static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data,
7358 unsigned short ee_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007359{
7360
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007361 unsigned char ee_value;
7362 unsigned short i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007363
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007364 ee_value =
7365 (unsigned
7366 char)((RD_HARPOON(p_port + hp_ee_ctrl) &
7367 (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007368
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007369 FPT_utilEESendCmdAddr(p_port, EE_WRITE, ee_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007370
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007371 ee_value |= (SEE_MS + SEE_CS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007372
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007373 for (i = 0x8000; i != 0; i >>= 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007374
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007375 if (i & ee_data)
7376 ee_value |= SEE_DO;
7377 else
7378 ee_value &= ~SEE_DO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007379
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007380 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7381 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7382 ee_value |= SEE_CLK; /* Clock data! */
7383 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7384 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7385 ee_value &= ~SEE_CLK;
7386 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7387 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7388 }
7389 ee_value &= (EXT_ARB_ACK | SCSI_TERM_ENA_H);
7390 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007391
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007392 FPT_Wait(p_port, TO_10ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007393
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007394 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS | SEE_CS)); /* Set CS to EEPROM */
7395 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /* Turn off CS */
7396 WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /* Turn off Master Select */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007397}
7398
7399/*---------------------------------------------------------------------
7400 *
7401 * Function: Read EEPROM
7402 *
7403 * Description: Read a word from the EEPROM at the desired
7404 * address.
7405 *
7406 *---------------------------------------------------------------------*/
7407
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007408static unsigned short FPT_utilEERead(unsigned long p_port,
7409 unsigned short ee_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007410{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007411 unsigned short i, ee_data1, ee_data2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007412
7413 i = 0;
James Bottomley 47b5d692005-04-24 02:38:05 -05007414 ee_data1 = FPT_utilEEReadOrg(p_port, ee_addr);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007415 do {
James Bottomley 47b5d692005-04-24 02:38:05 -05007416 ee_data2 = FPT_utilEEReadOrg(p_port, ee_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007417
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007418 if (ee_data1 == ee_data2)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007419 return ee_data1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007420
7421 ee_data1 = ee_data2;
7422 i++;
7423
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007424 } while (i < 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007425
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007426 return ee_data1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007427}
7428
7429/*---------------------------------------------------------------------
7430 *
7431 * Function: Read EEPROM Original
7432 *
7433 * Description: Read a word from the EEPROM at the desired
7434 * address.
7435 *
7436 *---------------------------------------------------------------------*/
7437
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007438static unsigned short FPT_utilEEReadOrg(unsigned long p_port,
7439 unsigned short ee_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007440{
7441
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007442 unsigned char ee_value;
7443 unsigned short i, ee_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007444
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007445 ee_value =
7446 (unsigned
7447 char)((RD_HARPOON(p_port + hp_ee_ctrl) &
7448 (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007449
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007450 FPT_utilEESendCmdAddr(p_port, EE_READ, ee_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007451
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007452 ee_value |= (SEE_MS + SEE_CS);
7453 ee_data = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007454
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007455 for (i = 1; i <= 16; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007456
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007457 ee_value |= SEE_CLK; /* Clock data! */
7458 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7459 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7460 ee_value &= ~SEE_CLK;
7461 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7462 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007463
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007464 ee_data <<= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007465
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007466 if (RD_HARPOON(p_port + hp_ee_ctrl) & SEE_DI)
7467 ee_data |= 1;
7468 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007469
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007470 ee_value &= ~(SEE_MS + SEE_CS);
7471 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */
7472 WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /*Turn off Master Select */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007473
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007474 return ee_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007475}
7476
Linus Torvalds1da177e2005-04-16 15:20:36 -07007477/*---------------------------------------------------------------------
7478 *
7479 * Function: Send EE command and Address to the EEPROM
7480 *
7481 * Description: Transfers the correct command and sends the address
7482 * to the eeprom.
7483 *
7484 *---------------------------------------------------------------------*/
7485
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007486static void FPT_utilEESendCmdAddr(unsigned long p_port, unsigned char ee_cmd,
7487 unsigned short ee_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007488{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007489 unsigned char ee_value;
7490 unsigned char narrow_flg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007491
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007492 unsigned short i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007493
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007494 narrow_flg =
7495 (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
7496 NARROW_SCSI_CARD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007497
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007498 ee_value = SEE_MS;
7499 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007500
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007501 ee_value |= SEE_CS; /* Set CS to EEPROM */
7502 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007503
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007504 for (i = 0x04; i != 0; i >>= 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007505
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007506 if (i & ee_cmd)
7507 ee_value |= SEE_DO;
7508 else
7509 ee_value &= ~SEE_DO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007510
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007511 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7512 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7513 ee_value |= SEE_CLK; /* Clock data! */
7514 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7515 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7516 ee_value &= ~SEE_CLK;
7517 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7518 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7519 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007520
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007521 if (narrow_flg)
7522 i = 0x0080;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007523
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007524 else
7525 i = 0x0200;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007526
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007527 while (i != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007528
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007529 if (i & ee_addr)
7530 ee_value |= SEE_DO;
7531 else
7532 ee_value &= ~SEE_DO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007533
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007534 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7535 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7536 ee_value |= SEE_CLK; /* Clock data! */
7537 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7538 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7539 ee_value &= ~SEE_CLK;
7540 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7541 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007542
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007543 i >>= 1;
7544 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007545}
7546
Alexey Dobriyanc823fee2006-03-08 00:14:25 -08007547static unsigned short FPT_CalcCrc16(unsigned char buffer[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07007548{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007549 unsigned short crc = 0;
7550 int i, j;
7551 unsigned short ch;
7552 for (i = 0; i < ID_STRING_LENGTH; i++) {
7553 ch = (unsigned short)buffer[i];
7554 for (j = 0; j < 8; j++) {
7555 if ((crc ^ ch) & 1)
7556 crc = (crc >> 1) ^ CRCMASK;
7557 else
7558 crc >>= 1;
7559 ch >>= 1;
7560 }
7561 }
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007562 return crc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007563}
7564
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08007565static unsigned char FPT_CalcLrc(unsigned char buffer[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07007566{
7567 int i;
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08007568 unsigned char lrc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007569 lrc = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007570 for (i = 0; i < ID_STRING_LENGTH; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007571 lrc ^= buffer[i];
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007572 return lrc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007573}
7574
Linus Torvalds1da177e2005-04-16 15:20:36 -07007575/*
7576 The following inline definitions avoid type conflicts.
7577*/
7578
7579static inline unsigned char
7580FlashPoint__ProbeHostAdapter(struct FlashPoint_Info *FlashPointInfo)
7581{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007582 return FlashPoint_ProbeHostAdapter((struct sccb_mgr_info *)
7583 FlashPointInfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007584}
7585
Linus Torvalds1da177e2005-04-16 15:20:36 -07007586static inline FlashPoint_CardHandle_T
7587FlashPoint__HardwareResetHostAdapter(struct FlashPoint_Info *FlashPointInfo)
7588{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007589 return FlashPoint_HardwareResetHostAdapter((struct sccb_mgr_info *)
7590 FlashPointInfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007591}
7592
7593static inline void
7594FlashPoint__ReleaseHostAdapter(FlashPoint_CardHandle_T CardHandle)
7595{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007596 FlashPoint_ReleaseHostAdapter(CardHandle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007597}
7598
Linus Torvalds1da177e2005-04-16 15:20:36 -07007599static inline void
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007600FlashPoint__StartCCB(FlashPoint_CardHandle_T CardHandle,
7601 struct BusLogic_CCB *CCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007602{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007603 FlashPoint_StartCCB(CardHandle, (struct sccb *)CCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007604}
7605
Linus Torvalds1da177e2005-04-16 15:20:36 -07007606static inline void
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007607FlashPoint__AbortCCB(FlashPoint_CardHandle_T CardHandle,
7608 struct BusLogic_CCB *CCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007609{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007610 FlashPoint_AbortCCB(CardHandle, (struct sccb *)CCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007611}
7612
Linus Torvalds1da177e2005-04-16 15:20:36 -07007613static inline boolean
7614FlashPoint__InterruptPending(FlashPoint_CardHandle_T CardHandle)
7615{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007616 return FlashPoint_InterruptPending(CardHandle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007617}
7618
Linus Torvalds1da177e2005-04-16 15:20:36 -07007619static inline int
7620FlashPoint__HandleInterrupt(FlashPoint_CardHandle_T CardHandle)
7621{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007622 return FlashPoint_HandleInterrupt(CardHandle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007623}
7624
Linus Torvalds1da177e2005-04-16 15:20:36 -07007625#define FlashPoint_ProbeHostAdapter FlashPoint__ProbeHostAdapter
7626#define FlashPoint_HardwareResetHostAdapter FlashPoint__HardwareResetHostAdapter
7627#define FlashPoint_ReleaseHostAdapter FlashPoint__ReleaseHostAdapter
7628#define FlashPoint_StartCCB FlashPoint__StartCCB
7629#define FlashPoint_AbortCCB FlashPoint__AbortCCB
7630#define FlashPoint_InterruptPending FlashPoint__InterruptPending
7631#define FlashPoint_HandleInterrupt FlashPoint__HandleInterrupt
7632
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007633#else /* CONFIG_SCSI_OMIT_FLASHPOINT */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007634
7635/*
7636 Define prototypes for the FlashPoint SCCB Manager Functions.
7637*/
7638
7639extern unsigned char FlashPoint_ProbeHostAdapter(struct FlashPoint_Info *);
7640extern FlashPoint_CardHandle_T
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007641FlashPoint_HardwareResetHostAdapter(struct FlashPoint_Info *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007642extern void FlashPoint_StartCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *);
7643extern int FlashPoint_AbortCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *);
7644extern boolean FlashPoint_InterruptPending(FlashPoint_CardHandle_T);
7645extern int FlashPoint_HandleInterrupt(FlashPoint_CardHandle_T);
7646extern void FlashPoint_ReleaseHostAdapter(FlashPoint_CardHandle_T);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007647
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007648#endif /* CONFIG_SCSI_OMIT_FLASHPOINT */