blob: 7c00680495867d0a81a2f81d379a270fb1ff846a [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
Linus Torvalds1da177e2005-04-16 15:20:36 -070019#ifndef CONFIG_SCSI_OMIT_FLASHPOINT
20
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#define MAX_CARDS 8
22#undef BUSTYPE_PCI
23
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#define CRCMASK 0xA001
25
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#define FAILURE 0xFFFFFFFFL
27
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -080028#define BIT(x) ((unsigned char)(1<<(x))) /* single-bit mask in bit position x */
29#define BITW(x) ((unsigned short)(1<<(x))) /* single-bit mask in bit position x */
Linus Torvalds1da177e2005-04-16 15:20:36 -070030
Alexey Dobriyan69eb2ea2006-03-08 00:14:29 -080031struct sccb;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -080032typedef void (*CALL_BK_FN) (struct sccb *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070033
Alexey Dobriyan7f101662006-03-08 00:14:30 -080034struct sccb_mgr_info {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -080035 unsigned long si_baseaddr;
36 unsigned char si_present;
37 unsigned char si_intvect;
38 unsigned char si_id;
39 unsigned char si_lun;
40 unsigned short si_fw_revision;
41 unsigned short si_per_targ_init_sync;
42 unsigned short si_per_targ_fast_nego;
43 unsigned short si_per_targ_ultra_nego;
44 unsigned short si_per_targ_no_disc;
45 unsigned short si_per_targ_wide_nego;
46 unsigned short si_flags;
47 unsigned char si_card_family;
48 unsigned char si_bustype;
49 unsigned char si_card_model[3];
50 unsigned char si_relative_cardnum;
51 unsigned char si_reserved[4];
52 unsigned long si_OS_reserved;
53 unsigned char si_XlatInfo[4];
54 unsigned long si_reserved2[5];
55 unsigned long si_secondary_range;
Alexey Dobriyan7f101662006-03-08 00:14:30 -080056};
Linus Torvalds1da177e2005-04-16 15:20:36 -070057
James Bottomley 47b5d692005-04-24 02:38:05 -050058#define SCSI_PARITY_ENA 0x0001
59#define LOW_BYTE_TERM 0x0010
60#define HIGH_BYTE_TERM 0x0020
61#define BUSTYPE_PCI 0x3
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
63#define SUPPORT_16TAR_32LUN 0x0002
64#define SOFT_RESET 0x0004
65#define EXTENDED_TRANSLATION 0x0008
66#define POST_ALL_UNDERRRUNS 0x0040
67#define FLAG_SCAM_ENABLED 0x0080
68#define FLAG_SCAM_LEVEL2 0x0100
69
Linus Torvalds1da177e2005-04-16 15:20:36 -070070#define HARPOON_FAMILY 0x02
71
Alexey Dobriyan323579882006-01-15 02:12:54 +010072/* SCCB struct used for both SCCB and UCB manager compiles!
Linus Torvalds1da177e2005-04-16 15:20:36 -070073 * The UCB Manager treats the SCCB as it's 'native hardware structure'
74 */
75
Linus Torvalds1da177e2005-04-16 15:20:36 -070076#pragma pack(1)
Alexey Dobriyan69eb2ea2006-03-08 00:14:29 -080077struct sccb {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -080078 unsigned char OperationCode;
79 unsigned char ControlByte;
80 unsigned char CdbLength;
81 unsigned char RequestSenseLength;
82 unsigned long DataLength;
83 unsigned long DataPointer;
84 unsigned char CcbRes[2];
85 unsigned char HostStatus;
86 unsigned char TargetStatus;
87 unsigned char TargID;
88 unsigned char Lun;
89 unsigned char Cdb[12];
90 unsigned char CcbRes1;
91 unsigned char Reserved1;
92 unsigned long Reserved2;
93 unsigned long SensePointer;
Linus Torvalds1da177e2005-04-16 15:20:36 -070094
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -080095 CALL_BK_FN SccbCallback; /* VOID (*SccbCallback)(); */
96 unsigned long SccbIOPort; /* Identifies board base port */
97 unsigned char SccbStatus;
98 unsigned char SCCBRes2;
99 unsigned short SccbOSFlags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800101 unsigned long Sccb_XferCnt; /* actual transfer count */
102 unsigned long Sccb_ATC;
103 unsigned long SccbVirtDataPtr; /* virtual addr for OS/2 */
104 unsigned long Sccb_res1;
105 unsigned short Sccb_MGRFlags;
106 unsigned short Sccb_sgseg;
107 unsigned char Sccb_scsimsg; /* identify msg for selection */
108 unsigned char Sccb_tag;
109 unsigned char Sccb_scsistat;
110 unsigned char Sccb_idmsg; /* image of last msg in */
111 struct sccb *Sccb_forwardlink;
112 struct sccb *Sccb_backlink;
113 unsigned long Sccb_savedATC;
114 unsigned char Save_Cdb[6];
115 unsigned char Save_CdbLen;
116 unsigned char Sccb_XferState;
117 unsigned long Sccb_SGoffset;
118};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119
120#pragma pack()
121
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122#define SCATTER_GATHER_COMMAND 0x02
123#define RESIDUAL_COMMAND 0x03
124#define RESIDUAL_SG_COMMAND 0x04
125#define RESET_COMMAND 0x81
126
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800127#define F_USE_CMD_Q 0x20 /*Inidcates TAGGED command. */
128#define TAG_TYPE_MASK 0xC0 /*Type of tag msg to send. */
129#define SCCB_DATA_XFER_OUT 0x10 /* Write */
130#define SCCB_DATA_XFER_IN 0x08 /* Read */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700131
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800132#define NO_AUTO_REQUEST_SENSE 0x01 /* No Request Sense Buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800134#define BUS_FREE_ST 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135#define SELECT_ST 1
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800136#define SELECT_BDR_ST 2 /* Select w\ Bus Device Reset */
137#define SELECT_SN_ST 3 /* Select w\ Sync Nego */
138#define SELECT_WN_ST 4 /* Select w\ Wide Data Nego */
139#define SELECT_Q_ST 5 /* Select w\ Tagged Q'ing */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140#define COMMAND_ST 6
141#define DATA_OUT_ST 7
142#define DATA_IN_ST 8
143#define DISCONNECT_ST 9
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144#define ABORT_ST 11
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146#define F_HOST_XFER_DIR 0x01
147#define F_ALL_XFERRED 0x02
148#define F_SG_XFER 0x04
149#define F_AUTO_SENSE 0x08
150#define F_ODD_BALL_CNT 0x10
151#define F_NO_DATA_YET 0x80
152
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153#define F_STATUSLOADED 0x01
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154#define F_DEV_SELECTED 0x04
155
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800156#define SCCB_COMPLETE 0x00 /* SCCB completed without error */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157#define SCCB_DATA_UNDER_RUN 0x0C
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800158#define SCCB_SELECTION_TIMEOUT 0x11 /* Set SCSI selection timed out */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700159#define SCCB_DATA_OVER_RUN 0x12
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800160#define SCCB_PHASE_SEQUENCE_FAIL 0x14 /* Target bus phase sequence failure */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800162#define SCCB_GROSS_FW_ERR 0x27 /* Major problem! */
163#define SCCB_BM_ERR 0x30 /* BusMaster error. */
164#define SCCB_PARITY_ERR 0x34 /* SCSI parity error */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165
166#define SCCB_IN_PROCESS 0x00
167#define SCCB_SUCCESS 0x01
168#define SCCB_ABORT 0x02
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169#define SCCB_ERROR 0x04
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171#define ORION_FW_REV 3110
172
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800173#define QUEUE_DEPTH 254+1 /*1 for Normal disconnect 32 for Q'ing. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800175#define MAX_MB_CARDS 4 /* Max. no of cards suppoerted on Mother Board */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176
James Bottomley 47b5d692005-04-24 02:38:05 -0500177#define MAX_SCSI_TAR 16
178#define MAX_LUN 32
179#define LUN_MASK 0x1f
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800181#define SG_BUF_CNT 16 /*Number of prefetched elements. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800183#define SG_ELEMENT_SIZE 8 /*Eight byte per element. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184
Alexey Dobriyanad0e1d92006-03-08 00:14:28 -0800185#define RD_HARPOON(ioport) inb((u32)ioport)
186#define RDW_HARPOON(ioport) inw((u32)ioport)
187#define RD_HARP32(ioport,offset,data) (data = inl((u32)(ioport + offset)))
188#define WR_HARPOON(ioport,val) outb((u8) val, (u32)ioport)
189#define WRW_HARPOON(ioport,val) outw((u16)val, (u32)ioport)
190#define WR_HARP32(ioport,offset,data) outl(data, (u32)(ioport + offset))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192#define TAR_SYNC_MASK (BIT(7)+BIT(6))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193#define SYNC_TRYING BIT(6)
194#define SYNC_SUPPORTED (BIT(7)+BIT(6))
195
196#define TAR_WIDE_MASK (BIT(5)+BIT(4))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197#define WIDE_ENABLED BIT(4)
198#define WIDE_NEGOCIATED BIT(5)
199
200#define TAR_TAG_Q_MASK (BIT(3)+BIT(2))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201#define TAG_Q_TRYING BIT(2)
202#define TAG_Q_REJECT BIT(3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203
204#define TAR_ALLOW_DISC BIT(0)
205
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206#define EE_SYNC_MASK (BIT(0)+BIT(1))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207#define EE_SYNC_5MB BIT(0)
208#define EE_SYNC_10MB BIT(1)
209#define EE_SYNC_20MB (BIT(0)+BIT(1))
210
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211#define EE_WIDE_SCSI BIT(7)
212
Alexey Dobriyanf31dc0cd2006-03-08 00:14:31 -0800213struct sccb_mgr_tar_info {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800215 struct sccb *TarSelQ_Head;
216 struct sccb *TarSelQ_Tail;
217 unsigned char TarLUN_CA; /*Contingent Allgiance */
218 unsigned char TarTagQ_Cnt;
219 unsigned char TarSelQ_Cnt;
220 unsigned char TarStatus;
221 unsigned char TarEEValue;
222 unsigned char TarSyncCtrl;
223 unsigned char TarReserved[2]; /* for alignment */
224 unsigned char LunDiscQ_Idx[MAX_LUN];
225 unsigned char TarLUNBusy[MAX_LUN];
Alexey Dobriyanf31dc0cd2006-03-08 00:14:31 -0800226};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227
Alexey Dobriyan68d0c1a2006-03-08 00:14:33 -0800228struct nvram_info {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800229 unsigned char niModel; /* Model No. of card */
230 unsigned char niCardNo; /* Card no. */
231 unsigned long niBaseAddr; /* Port Address of card */
232 unsigned char niSysConf; /* Adapter Configuration byte - Byte 16 of eeprom map */
233 unsigned char niScsiConf; /* SCSI Configuration byte - Byte 17 of eeprom map */
234 unsigned char niScamConf; /* SCAM Configuration byte - Byte 20 of eeprom map */
235 unsigned char niAdapId; /* Host Adapter ID - Byte 24 of eerpom map */
236 unsigned char niSyncTbl[MAX_SCSI_TAR / 2]; /* Sync/Wide byte of targets */
237 unsigned char niScamTbl[MAX_SCSI_TAR][4]; /* Compressed Scam name string of Targets */
Alexey Dobriyan68d0c1a2006-03-08 00:14:33 -0800238};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240#define MODEL_LT 1
241#define MODEL_DL 2
242#define MODEL_LW 3
243#define MODEL_DW 4
244
Alexey Dobriyan13e68512006-03-08 00:14:34 -0800245struct sccb_card {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800246 struct sccb *currentSCCB;
247 struct sccb_mgr_info *cardInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800249 unsigned long ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800251 unsigned short cmdCounter;
252 unsigned char discQCount;
253 unsigned char tagQ_Lst;
254 unsigned char cardIndex;
255 unsigned char scanIndex;
256 unsigned char globalFlags;
257 unsigned char ourId;
258 struct nvram_info *pNvRamInfo;
259 struct sccb *discQ_Tbl[QUEUE_DEPTH];
260
Alexey Dobriyan13e68512006-03-08 00:14:34 -0800261};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263#define F_TAG_STARTED 0x01
264#define F_CONLUN_IO 0x02
265#define F_DO_RENEGO 0x04
266#define F_NO_FILTER 0x08
267#define F_GREEN_PC 0x10
268#define F_HOST_XFER_ACT 0x20
269#define F_NEW_SCCB_CMD 0x40
270#define F_UPDATE_EEPROM 0x80
271
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272#define ID_STRING_LENGTH 32
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800273#define TYPE_CODE0 0x63 /*Level2 Mstr (bits 7-6), */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800275#define SLV_TYPE_CODE0 0xA3 /*Priority Bit set (bits 7-6), */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276
277#define ASSIGN_ID 0x00
278#define SET_P_FLAG 0x01
279#define CFG_CMPLT 0x03
280#define DOM_MSTR 0x0F
281#define SYNC_PTRN 0x1F
282
283#define ID_0_7 0x18
284#define ID_8_F 0x11
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285#define MISC_CODE 0x14
286#define CLR_P_FLAG 0x18
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288#define INIT_SELTD 0x01
289#define LEVEL2_TAR 0x02
290
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800291enum scam_id_st { ID0, ID1, ID2, ID3, ID4, ID5, ID6, ID7, ID8, ID9, ID10, ID11,
292 ID12,
293 ID13, ID14, ID15, ID_UNUSED, ID_UNASSIGNED, ID_ASSIGNED, LEGACY,
294 CLR_PRIORITY, NO_ID_AVAIL
295};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296
297typedef struct SCCBscam_info {
298
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800299 unsigned char id_string[ID_STRING_LENGTH];
300 enum scam_id_st state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800302} SCCBSCAM_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304#define SCSI_REQUEST_SENSE 0x03
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305#define SCSI_READ 0x08
306#define SCSI_WRITE 0x0A
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307#define SCSI_START_STOP_UNIT 0x1B
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308#define SCSI_READ_EXTENDED 0x28
309#define SCSI_WRITE_EXTENDED 0x2A
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310#define SCSI_WRITE_AND_VERIFY 0x2E
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312#define SSGOOD 0x00
313#define SSCHECK 0x02
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314#define SSQ_FULL 0x28
315
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316#define SMCMD_COMP 0x00
317#define SMEXT 0x01
318#define SMSAVE_DATA_PTR 0x02
319#define SMREST_DATA_PTR 0x03
320#define SMDISC 0x04
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321#define SMABORT 0x06
322#define SMREJECT 0x07
323#define SMNO_OP 0x08
324#define SMPARITY 0x09
325#define SMDEV_RESET 0x0C
326#define SMABORT_TAG 0x0D
327#define SMINIT_RECOVERY 0x0F
328#define SMREL_RECOVERY 0x10
329
330#define SMIDENT 0x80
331#define DISC_PRIV 0x40
332
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333#define SMSYNC 0x01
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334#define SMWDTR 0x03
335#define SM8BIT 0x00
336#define SM16BIT 0x01
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800337#define SMIGNORWR 0x23 /* Ignore Wide Residue */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338
339#define SIX_BYTE_CMD 0x06
Linus Torvalds1da177e2005-04-16 15:20:36 -0700340#define TWELVE_BYTE_CMD 0x0C
341
342#define ASYNC 0x00
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800343#define MAX_OFFSET 0x0F /* Maxbyteoffset for Sync Xfers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344
345#define EEPROM_WD_CNT 256
346
347#define EEPROM_CHECK_SUM 0
348#define FW_SIGNATURE 2
349#define MODEL_NUMB_0 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350#define MODEL_NUMB_2 6
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351#define MODEL_NUMB_4 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352#define SYSTEM_CONFIG 16
353#define SCSI_CONFIG 17
354#define BIOS_CONFIG 18
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355#define SCAM_CONFIG 20
356#define ADAPTER_SCSI_ID 24
357
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358#define IGNORE_B_SCAN 32
359#define SEND_START_ENA 34
360#define DEVICE_ENABLE 36
361
362#define SYNC_RATE_TBL 38
363#define SYNC_RATE_TBL01 38
364#define SYNC_RATE_TBL23 40
365#define SYNC_RATE_TBL45 42
366#define SYNC_RATE_TBL67 44
367#define SYNC_RATE_TBL89 46
368#define SYNC_RATE_TBLab 48
369#define SYNC_RATE_TBLcd 50
370#define SYNC_RATE_TBLef 52
371
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800372#define EE_SCAMBASE 256
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800374#define SCAM_ENABLED BIT(2)
375#define SCAM_LEVEL2 BIT(3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800377#define RENEGO_ENA BITW(10)
378#define CONNIO_ENA BITW(11)
379#define GREEN_PC_ENA BITW(12)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800381#define AUTO_RATE_00 00
382#define AUTO_RATE_05 01
383#define AUTO_RATE_10 02
384#define AUTO_RATE_20 03
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800386#define WIDE_NEGO_BIT BIT(7)
387#define DISC_ENABLE_BIT BIT(6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800389#define hp_vendor_id_0 0x00 /* LSB */
390#define ORION_VEND_0 0x4B
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800392#define hp_vendor_id_1 0x01 /* MSB */
393#define ORION_VEND_1 0x10
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800395#define hp_device_id_0 0x02 /* LSB */
396#define ORION_DEV_0 0x30
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800398#define hp_device_id_1 0x03 /* MSB */
399#define ORION_DEV_1 0x81
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400
401 /* Sub Vendor ID and Sub Device ID only available in
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800402 Harpoon Version 2 and higher */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800404#define hp_sub_device_id_0 0x06 /* LSB */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800406#define hp_semaphore 0x0C
407#define SCCB_MGR_ACTIVE BIT(0)
408#define TICKLE_ME BIT(1)
409#define SCCB_MGR_PRESENT BIT(3)
410#define BIOS_IN_USE BIT(4)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800412#define hp_sys_ctrl 0x0F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800414#define STOP_CLK BIT(0) /*Turn off BusMaster Clock */
415#define DRVR_RST BIT(1) /*Firmware Reset to 80C15 chip */
416#define HALT_MACH BIT(3) /*Halt State Machine */
417#define HARD_ABORT BIT(4) /*Hard Abort */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800419#define hp_host_blk_cnt 0x13
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800421#define XFER_BLK64 0x06 /* 1 1 0 64 byte per block */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800423#define BM_THRESHOLD 0x40 /* PCI mode can only xfer 16 bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800425#define hp_int_mask 0x17
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800427#define INT_CMD_COMPL BIT(0) /* DMA command complete */
428#define INT_EXT_STATUS BIT(1) /* Extended Status Set */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800430#define hp_xfer_cnt_lo 0x18
431#define hp_xfer_cnt_hi 0x1A
432#define hp_xfer_cmd 0x1B
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800434#define XFER_HOST_DMA 0x00 /* 0 0 0 Transfer Host -> DMA */
435#define XFER_DMA_HOST 0x01 /* 0 0 1 Transfer DMA -> Host */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800437#define XFER_HOST_AUTO 0x00 /* 0 0 Auto Transfer Size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800439#define XFER_DMA_8BIT 0x20 /* 0 1 8 BIT Transfer Size */
Alexey Dobriyan85ae97d82006-03-08 00:14:22 -0800440
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800441#define DISABLE_INT BIT(7) /*Do not interrupt at end of cmd. */
Alexey Dobriyan85ae97d82006-03-08 00:14:22 -0800442
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800443#define HOST_WRT_CMD ((DISABLE_INT + XFER_HOST_DMA + XFER_HOST_AUTO + XFER_DMA_8BIT))
444#define HOST_RD_CMD ((DISABLE_INT + XFER_DMA_HOST + XFER_HOST_AUTO + XFER_DMA_8BIT))
Alexey Dobriyan85ae97d82006-03-08 00:14:22 -0800445
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800446#define hp_host_addr_lo 0x1C
447#define hp_host_addr_hmi 0x1E
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800449#define hp_ee_ctrl 0x22
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800451#define EXT_ARB_ACK BIT(7)
452#define SCSI_TERM_ENA_H BIT(6) /* SCSI high byte terminator */
453#define SEE_MS BIT(5)
454#define SEE_CS BIT(3)
455#define SEE_CLK BIT(2)
456#define SEE_DO BIT(1)
457#define SEE_DI BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800459#define EE_READ 0x06
460#define EE_WRITE 0x05
461#define EWEN 0x04
462#define EWEN_ADDR 0x03C0
463#define EWDS 0x04
464#define EWDS_ADDR 0x0000
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800466#define hp_bm_ctrl 0x26
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800468#define SCSI_TERM_ENA_L BIT(0) /*Enable/Disable external terminators */
469#define FLUSH_XFER_CNTR BIT(1) /*Flush transfer counter */
470#define FORCE1_XFER BIT(5) /*Always xfer one byte in byte mode */
471#define FAST_SINGLE BIT(6) /*?? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800473#define BMCTRL_DEFAULT (FORCE1_XFER|FAST_SINGLE|SCSI_TERM_ENA_L)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800475#define hp_sg_addr 0x28
476#define hp_page_ctrl 0x29
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800478#define SCATTER_EN BIT(0)
479#define SGRAM_ARAM BIT(1)
480#define G_INT_DISABLE BIT(3) /* Enable/Disable all Interrupts */
481#define NARROW_SCSI_CARD BIT(4) /* NARROW/WIDE SCSI config pin */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800483#define hp_pci_stat_cfg 0x2D
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800485#define REC_MASTER_ABORT BIT(5) /*received Master abort */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800487#define hp_rev_num 0x33
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800489#define hp_stack_data 0x34
490#define hp_stack_addr 0x35
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800492#define hp_ext_status 0x36
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800494#define BM_FORCE_OFF BIT(0) /*Bus Master is forced to get off */
495#define PCI_TGT_ABORT BIT(0) /*PCI bus master transaction aborted */
496#define PCI_DEV_TMOUT BIT(1) /*PCI Device Time out */
497#define CMD_ABORTED BIT(4) /*Command aborted */
498#define BM_PARITY_ERR BIT(5) /*parity error on data received */
499#define PIO_OVERRUN BIT(6) /*Slave data overrun */
500#define BM_CMD_BUSY BIT(7) /*Bus master transfer command busy */
501#define BAD_EXT_STATUS (BM_FORCE_OFF | PCI_DEV_TMOUT | CMD_ABORTED | \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 BM_PARITY_ERR | PIO_OVERRUN)
503
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800504#define hp_int_status 0x37
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800506#define EXT_STATUS_ON BIT(1) /*Extended status is valid */
507#define SCSI_INTERRUPT BIT(2) /*Global indication of a SCSI int. */
508#define INT_ASSERTED BIT(5) /* */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800510#define hp_fifo_cnt 0x38
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800512#define hp_intena 0x40
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800514#define RESET BITW(7)
515#define PROG_HLT BITW(6)
516#define PARITY BITW(5)
517#define FIFO BITW(4)
518#define SEL BITW(3)
519#define SCAM_SEL BITW(2)
520#define RSEL BITW(1)
521#define TIMEOUT BITW(0)
522#define BUS_FREE BITW(15)
523#define XFER_CNT_0 BITW(14)
524#define PHASE BITW(13)
525#define IUNKWN BITW(12)
526#define ICMD_COMP BITW(11)
527#define ITICKLE BITW(10)
528#define IDO_STRT BITW(9)
529#define ITAR_DISC BITW(8)
530#define AUTO_INT (BITW(12)+BITW(11)+BITW(10)+BITW(9)+BITW(8))
531#define CLR_ALL_INT 0xFFFF
532#define CLR_ALL_INT_1 0xFF00
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800534#define hp_intstat 0x42
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800536#define hp_scsisig 0x44
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800538#define SCSI_SEL BIT(7)
539#define SCSI_BSY BIT(6)
540#define SCSI_REQ BIT(5)
541#define SCSI_ACK BIT(4)
542#define SCSI_ATN BIT(3)
543#define SCSI_CD BIT(2)
544#define SCSI_MSG BIT(1)
545#define SCSI_IOBIT BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800547#define S_SCSI_PHZ (BIT(2)+BIT(1)+BIT(0))
548#define S_MSGO_PH (BIT(2)+BIT(1) )
549#define S_MSGI_PH (BIT(2)+BIT(1)+BIT(0))
550#define S_DATAI_PH ( BIT(0))
551#define S_DATAO_PH 0x00
552#define S_ILL_PH ( BIT(1) )
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800554#define hp_scsictrl_0 0x45
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800556#define SEL_TAR BIT(6)
557#define ENA_ATN BIT(4)
558#define ENA_RESEL BIT(2)
559#define SCSI_RST BIT(1)
560#define ENA_SCAM_SEL BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800562#define hp_portctrl_0 0x46
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800564#define SCSI_PORT BIT(7)
565#define SCSI_INBIT BIT(6)
566#define DMA_PORT BIT(5)
567#define DMA_RD BIT(4)
568#define HOST_PORT BIT(3)
569#define HOST_WRT BIT(2)
570#define SCSI_BUS_EN BIT(1)
571#define START_TO BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800573#define hp_scsireset 0x47
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800575#define SCSI_INI BIT(6)
576#define SCAM_EN BIT(5)
577#define DMA_RESET BIT(3)
578#define HPSCSI_RESET BIT(2)
579#define PROG_RESET BIT(1)
580#define FIFO_CLR BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800582#define hp_xfercnt_0 0x48
583#define hp_xfercnt_2 0x4A
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800585#define hp_fifodata_0 0x4C
586#define hp_addstat 0x4E
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800588#define SCAM_TIMER BIT(7)
589#define SCSI_MODE8 BIT(3)
590#define SCSI_PAR_ERR BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800592#define hp_prgmcnt_0 0x4F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800594#define hp_selfid_0 0x50
595#define hp_selfid_1 0x51
596#define hp_arb_id 0x52
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800598#define hp_select_id 0x53
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800600#define hp_synctarg_base 0x54
601#define hp_synctarg_12 0x54
602#define hp_synctarg_13 0x55
603#define hp_synctarg_14 0x56
604#define hp_synctarg_15 0x57
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800606#define hp_synctarg_8 0x58
607#define hp_synctarg_9 0x59
608#define hp_synctarg_10 0x5A
609#define hp_synctarg_11 0x5B
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800611#define hp_synctarg_4 0x5C
612#define hp_synctarg_5 0x5D
613#define hp_synctarg_6 0x5E
614#define hp_synctarg_7 0x5F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800616#define hp_synctarg_0 0x60
617#define hp_synctarg_1 0x61
618#define hp_synctarg_2 0x62
619#define hp_synctarg_3 0x63
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800621#define NARROW_SCSI BIT(4)
622#define DEFAULT_OFFSET 0x0F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800624#define hp_autostart_0 0x64
625#define hp_autostart_1 0x65
626#define hp_autostart_3 0x67
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800628#define AUTO_IMMED BIT(5)
629#define SELECT BIT(6)
630#define END_DATA (BIT(7)+BIT(6))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800632#define hp_gp_reg_0 0x68
633#define hp_gp_reg_1 0x69
634#define hp_gp_reg_3 0x6B
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800636#define hp_seltimeout 0x6C
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800638#define TO_4ms 0x67 /* 3.9959ms */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800640#define TO_5ms 0x03 /* 4.9152ms */
641#define TO_10ms 0x07 /* 11.xxxms */
642#define TO_250ms 0x99 /* 250.68ms */
643#define TO_290ms 0xB1 /* 289.99ms */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800645#define hp_clkctrl_0 0x6D
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800647#define PWR_DWN BIT(6)
648#define ACTdeassert BIT(4)
649#define CLK_40MHZ (BIT(1) + BIT(0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800651#define CLKCTRL_DEFAULT (ACTdeassert | CLK_40MHZ)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800653#define hp_fiforead 0x6E
654#define hp_fifowrite 0x6F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800656#define hp_offsetctr 0x70
657#define hp_xferstat 0x71
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800659#define FIFO_EMPTY BIT(6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800661#define hp_portctrl_1 0x72
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800663#define CHK_SCSI_P BIT(3)
664#define HOST_MODE8 BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800666#define hp_xfer_pad 0x73
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800668#define ID_UNLOCK BIT(3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800670#define hp_scsidata_0 0x74
671#define hp_scsidata_1 0x75
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800673#define hp_aramBase 0x80
674#define BIOS_DATA_OFFSET 0x60
675#define BIOS_RELATIVE_CARD 0x64
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800677#define AR3 (BITW(9) + BITW(8))
678#define SDATA BITW(10)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800680#define CRD_OP BITW(11) /* Cmp Reg. w/ Data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800682#define CRR_OP BITW(12) /* Cmp Reg. w. Reg. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800684#define CPE_OP (BITW(14)+BITW(11)) /* Cmp SCSI phs & Branch EQ */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800686#define CPN_OP (BITW(14)+BITW(12)) /* Cmp SCSI phs & Branch NOT EQ */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800688#define ADATA_OUT 0x00
689#define ADATA_IN BITW(8)
690#define ACOMMAND BITW(10)
691#define ASTATUS (BITW(10)+BITW(8))
692#define AMSG_OUT (BITW(10)+BITW(9))
693#define AMSG_IN (BITW(10)+BITW(9)+BITW(8))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800695#define BRH_OP BITW(13) /* Branch */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800697#define ALWAYS 0x00
698#define EQUAL BITW(8)
699#define NOT_EQ BITW(9)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800701#define TCB_OP (BITW(13)+BITW(11)) /* Test condition & branch */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800703#define FIFO_0 BITW(10)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800705#define MPM_OP BITW(15) /* Match phase and move data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800707#define MRR_OP BITW(14) /* Move DReg. to Reg. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800709#define S_IDREG (BIT(2)+BIT(1)+BIT(0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800711#define D_AR0 0x00
712#define D_AR1 BIT(0)
713#define D_BUCKET (BIT(2) + BIT(1) + BIT(0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800715#define RAT_OP (BITW(14)+BITW(13)+BITW(11))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800717#define SSI_OP (BITW(15)+BITW(11))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800719#define SSI_ITAR_DISC (ITAR_DISC >> 8)
720#define SSI_IDO_STRT (IDO_STRT >> 8)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800722#define SSI_ICMD_COMP (ICMD_COMP >> 8)
723#define SSI_ITICKLE (ITICKLE >> 8)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800725#define SSI_IUNKWN (IUNKWN >> 8)
726#define SSI_INO_CC (IUNKWN >> 8)
727#define SSI_IRFAIL (IUNKWN >> 8)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800729#define NP 0x10 /*Next Phase */
730#define NTCMD 0x02 /*Non- Tagged Command start */
731#define CMDPZ 0x04 /*Command phase */
732#define DINT 0x12 /*Data Out/In interrupt */
733#define DI 0x13 /*Data Out */
734#define DC 0x19 /*Disconnect Message */
735#define ST 0x1D /*Status Phase */
736#define UNKNWN 0x24 /*Unknown bus action */
737#define CC 0x25 /*Command Completion failure */
738#define TICK 0x26 /*New target reselected us. */
739#define SELCHK 0x28 /*Select & Check SCSI ID latch reg */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800741#define ID_MSG_STRT hp_aramBase + 0x00
742#define NON_TAG_ID_MSG hp_aramBase + 0x06
743#define CMD_STRT hp_aramBase + 0x08
744#define SYNC_MSGS hp_aramBase + 0x08
Alexey Dobriyan85ae97d82006-03-08 00:14:22 -0800745
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800746#define TAG_STRT 0x00
747#define DISCONNECT_START 0x10/2
748#define END_DATA_START 0x14/2
749#define CMD_ONLY_STRT CMDPZ/2
750#define SELCHK_STRT SELCHK/2
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751
752#define GET_XFER_CNT(port, xfercnt) {RD_HARP32(port,hp_xfercnt_0,xfercnt); xfercnt &= 0xFFFFFF;}
753/* #define GET_XFER_CNT(port, xfercnt) (xfercnt = RD_HARPOON(port+hp_xfercnt_2), \
754 xfercnt <<= 16,\
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800755 xfercnt |= RDW_HARPOON((unsigned short)(port+hp_xfercnt_0)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 */
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800757#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 -0700758 addr >>= 16,\
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800759 WRW_HARPOON((port+hp_host_addr_hmi), (unsigned short)(addr & 0x0000FFFFL)),\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 WR_HARP32(port,hp_xfercnt_0,count),\
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800761 WRW_HARPOON((port+hp_xfer_cnt_lo), (unsigned short)(count & 0x0000FFFFL)),\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 count >>= 16,\
763 WR_HARPOON(port+hp_xfer_cnt_hi, (count & 0xFF)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764
765#define ACCEPT_MSG(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
766 WR_HARPOON(port+hp_scsisig, S_ILL_PH);}
767
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768#define ACCEPT_MSG_ATN(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
769 WR_HARPOON(port+hp_scsisig, (S_ILL_PH|SCSI_ATN));}
770
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771#define DISABLE_AUTO(port) (WR_HARPOON(port+hp_scsireset, PROG_RESET),\
772 WR_HARPOON(port+hp_scsireset, 0x00))
773
774#define ARAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
775 (RD_HARPOON(p_port+hp_page_ctrl) | SGRAM_ARAM)))
776
777#define SGRAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
778 (RD_HARPOON(p_port+hp_page_ctrl) & ~SGRAM_ARAM)))
779
780#define MDISABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
781 (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE)))
782
783#define MENABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
784 (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE)))
785
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800786static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card,
787 unsigned char syncFlag);
788static void FPT_ssel(unsigned long port, unsigned char p_card);
789static void FPT_sres(unsigned long port, unsigned char p_card,
790 struct sccb_card *pCurrCard);
791static void FPT_shandem(unsigned long port, unsigned char p_card,
792 struct sccb *pCurrSCCB);
793static void FPT_stsyncn(unsigned long port, unsigned char p_card);
794static void FPT_sisyncr(unsigned long port, unsigned char sync_pulse,
795 unsigned char offset);
796static void FPT_sssyncv(unsigned long p_port, unsigned char p_id,
797 unsigned char p_sync_value,
798 struct sccb_mgr_tar_info *currTar_Info);
799static void FPT_sresb(unsigned long port, unsigned char p_card);
800static void FPT_sxfrp(unsigned long p_port, unsigned char p_card);
801static void FPT_schkdd(unsigned long port, unsigned char p_card);
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -0800802static unsigned char FPT_RdStack(unsigned long port, unsigned char index);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800803static void FPT_WrStack(unsigned long portBase, unsigned char index,
804 unsigned char data);
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -0800805static unsigned char FPT_ChkIfChipInitialized(unsigned long ioPort);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -0800807static void FPT_SendMsg(unsigned long port, unsigned char message);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800808static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
809 unsigned char error_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800811static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card);
812static void FPT_RNVRamData(struct nvram_info *pNvRamInfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -0800814static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800815static void FPT_stwidn(unsigned long port, unsigned char p_card);
816static void FPT_siwidr(unsigned long port, unsigned char width);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800818static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
819 unsigned char p_card);
820static void FPT_queueDisconnect(struct sccb *p_SCCB, unsigned char p_card);
821static void FPT_queueCmdComplete(struct sccb_card *pCurrCard,
822 struct sccb *p_SCCB, unsigned char p_card);
823static void FPT_queueSearchSelect(struct sccb_card *pCurrCard,
Alexey Dobriyandb038cf2006-03-08 00:14:24 -0800824 unsigned char p_card);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800825static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code);
826static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char card);
827static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB,
828 unsigned char p_card);
829static void FPT_utilUpdateResidual(struct sccb *p_SCCB);
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800830static unsigned short FPT_CalcCrc16(unsigned char buffer[]);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800831static unsigned char FPT_CalcLrc(unsigned char buffer[]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800833static void FPT_Wait1Second(unsigned long p_port);
834static void FPT_Wait(unsigned long p_port, unsigned char p_delay);
835static void FPT_utilEEWriteOnOff(unsigned long p_port, unsigned char p_mode);
836static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data,
837 unsigned short ee_addr);
838static unsigned short FPT_utilEERead(unsigned long p_port,
839 unsigned short ee_addr);
840static unsigned short FPT_utilEEReadOrg(unsigned long p_port,
841 unsigned short ee_addr);
842static void FPT_utilEESendCmdAddr(unsigned long p_port, unsigned char ee_cmd,
843 unsigned short ee_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800845static void FPT_phaseDataOut(unsigned long port, unsigned char p_card);
846static void FPT_phaseDataIn(unsigned long port, unsigned char p_card);
847static void FPT_phaseCommand(unsigned long port, unsigned char p_card);
848static void FPT_phaseStatus(unsigned long port, unsigned char p_card);
849static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card);
850static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card);
851static void FPT_phaseIllegal(unsigned long port, unsigned char p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800853static void FPT_phaseDecode(unsigned long port, unsigned char p_card);
854static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card);
855static void FPT_phaseBusFree(unsigned long p_port, unsigned char p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800857static void FPT_XbowInit(unsigned long port, unsigned char scamFlg);
858static void FPT_BusMasterInit(unsigned long p_port);
859static void FPT_DiagEEPROM(unsigned long p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800861static void FPT_dataXferProcessor(unsigned long port,
862 struct sccb_card *pCurrCard);
863static void FPT_busMstrSGDataXferStart(unsigned long port,
864 struct sccb *pCurrSCCB);
865static void FPT_busMstrDataXferStart(unsigned long port,
866 struct sccb *pCurrSCCB);
867static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card,
868 struct sccb *pCurrSCCB);
869static void FPT_hostDataXferRestart(struct sccb *currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800871static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port,
872 unsigned char p_card,
873 struct sccb_card *pCurrCard,
874 unsigned short p_int);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800876static void FPT_SccbMgrTableInitAll(void);
877static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard,
878 unsigned char p_card);
879static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
880 unsigned char target);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800882static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
883 unsigned char p_power_up);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800885static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type);
886static void FPT_scbusf(unsigned long p_port);
887static void FPT_scsel(unsigned long p_port);
888static void FPT_scasid(unsigned char p_card, unsigned long p_port);
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -0800889static unsigned char FPT_scxferc(unsigned long p_port, unsigned char p_data);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800890static unsigned char FPT_scsendi(unsigned long p_port,
891 unsigned char p_id_string[]);
892static unsigned char FPT_sciso(unsigned long p_port,
893 unsigned char p_id_string[]);
894static void FPT_scwirod(unsigned long p_port, unsigned char p_data_bit);
895static void FPT_scwiros(unsigned long p_port, unsigned char p_data_bit);
Alexey Dobriyandb038cf2006-03-08 00:14:24 -0800896static unsigned char FPT_scvalq(unsigned char p_quintet);
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -0800897static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800898static void FPT_scwtsel(unsigned long p_port);
899static void FPT_inisci(unsigned char p_card, unsigned long p_port,
900 unsigned char p_our_id);
901static void FPT_scsavdi(unsigned char p_card, unsigned long p_port);
902static unsigned char FPT_scmachid(unsigned char p_card,
903 unsigned char p_id_string[]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800905static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card);
906static void FPT_autoLoadDefaultMap(unsigned long p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800908static struct sccb_mgr_tar_info FPT_sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] =
909 { {{0}} };
910static struct sccb_card FPT_BL_Card[MAX_CARDS] = { {0} };
911static SCCBSCAM_INFO FPT_scamInfo[MAX_SCSI_TAR] = { {{0}} };
912static struct nvram_info FPT_nvRamInfo[MAX_MB_CARDS] = { {0} };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913
Alexey Dobriyandb038cf2006-03-08 00:14:24 -0800914static unsigned char FPT_mbCards = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800915static unsigned char FPT_scamHAString[] =
916 { 0x63, 0x07, 'B', 'U', 'S', 'L', 'O', 'G', 'I', 'C',
917 ' ', 'B', 'T', '-', '9', '3', '0',
918 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
919 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
920};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800922static unsigned short FPT_default_intena = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800924static void (*FPT_s_PhaseTbl[8]) (unsigned long, unsigned char) = {
9250};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926
927/*---------------------------------------------------------------------
928 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -0800929 * Function: FlashPoint_ProbeHostAdapter
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 *
931 * Description: Setup and/or Search for cards and return info to caller.
932 *
933 *---------------------------------------------------------------------*/
934
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800935static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800937 static unsigned char first_time = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800939 unsigned char i, j, id, ScamFlg;
940 unsigned short temp, temp2, temp3, temp4, temp5, temp6;
941 unsigned long ioport;
942 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800944 ioport = pCardInfo->si_baseaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800946 if (RD_HARPOON(ioport + hp_vendor_id_0) != ORION_VEND_0)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800947 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800949 if ((RD_HARPOON(ioport + hp_vendor_id_1) != ORION_VEND_1))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800950 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800952 if ((RD_HARPOON(ioport + hp_device_id_0) != ORION_DEV_0))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800953 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800955 if ((RD_HARPOON(ioport + hp_device_id_1) != ORION_DEV_1))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800956 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800958 if (RD_HARPOON(ioport + hp_rev_num) != 0x0f) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959
960/* For new Harpoon then check for sub_device ID LSB
961 the bits(0-3) must be all ZERO for compatible with
962 current version of SCCBMgr, else skip this Harpoon
963 device. */
964
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800965 if (RD_HARPOON(ioport + hp_sub_device_id_0) & 0x0f)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800966 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 }
968
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800969 if (first_time) {
970 FPT_SccbMgrTableInitAll();
971 first_time = 0;
James Bottomley 47b5d692005-04-24 02:38:05 -0500972 FPT_mbCards = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800973 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800975 if (FPT_RdStack(ioport, 0) != 0x00) {
976 if (FPT_ChkIfChipInitialized(ioport) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 pCurrNvRam = NULL;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800978 WR_HARPOON(ioport + hp_semaphore, 0x00);
979 FPT_XbowInit(ioport, 0); /*Must Init the SCSI before attempting */
James Bottomley 47b5d692005-04-24 02:38:05 -0500980 FPT_DiagEEPROM(ioport);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800981 } else {
982 if (FPT_mbCards < MAX_MB_CARDS) {
James Bottomley 47b5d692005-04-24 02:38:05 -0500983 pCurrNvRam = &FPT_nvRamInfo[FPT_mbCards];
984 FPT_mbCards++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 pCurrNvRam->niBaseAddr = ioport;
James Bottomley 47b5d692005-04-24 02:38:05 -0500986 FPT_RNVRamData(pCurrNvRam);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800987 } else
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800988 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800990 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 pCurrNvRam = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800993 WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT);
994 WR_HARPOON(ioport + hp_sys_ctrl, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800996 if (pCurrNvRam)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 pCardInfo->si_id = pCurrNvRam->niAdapId;
998 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800999 pCardInfo->si_id =
1000 (unsigned
1001 char)(FPT_utilEERead(ioport,
1002 (ADAPTER_SCSI_ID /
1003 2)) & (unsigned char)0x0FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001005 pCardInfo->si_lun = 0x00;
1006 pCardInfo->si_fw_revision = ORION_FW_REV;
1007 temp2 = 0x0000;
1008 temp3 = 0x0000;
1009 temp4 = 0x0000;
1010 temp5 = 0x0000;
1011 temp6 = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001013 for (id = 0; id < (16 / 2); id++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001015 if (pCurrNvRam) {
1016 temp = (unsigned short)pCurrNvRam->niSyncTbl[id];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001018 (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
1019 } else
1020 temp =
1021 FPT_utilEERead(ioport,
1022 (unsigned short)((SYNC_RATE_TBL / 2)
1023 + id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001025 for (i = 0; i < 2; temp >>= 8, i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001027 temp2 >>= 1;
1028 temp3 >>= 1;
1029 temp4 >>= 1;
1030 temp5 >>= 1;
1031 temp6 >>= 1;
1032 switch (temp & 0x3) {
1033 case AUTO_RATE_20: /* Synchronous, 20 mega-transfers/second */
1034 temp6 |= 0x8000; /* Fall through */
1035 case AUTO_RATE_10: /* Synchronous, 10 mega-transfers/second */
1036 temp5 |= 0x8000; /* Fall through */
1037 case AUTO_RATE_05: /* Synchronous, 5 mega-transfers/second */
1038 temp2 |= 0x8000; /* Fall through */
1039 case AUTO_RATE_00: /* Asynchronous */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 break;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001041 }
1042
1043 if (temp & DISC_ENABLE_BIT)
1044 temp3 |= 0x8000;
1045
1046 if (temp & WIDE_NEGO_BIT)
1047 temp4 |= 0x8000;
1048
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 }
1051
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001052 pCardInfo->si_per_targ_init_sync = temp2;
1053 pCardInfo->si_per_targ_no_disc = temp3;
1054 pCardInfo->si_per_targ_wide_nego = temp4;
1055 pCardInfo->si_per_targ_fast_nego = temp5;
1056 pCardInfo->si_per_targ_ultra_nego = temp6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001058 if (pCurrNvRam)
1059 i = pCurrNvRam->niSysConf;
1060 else
1061 i = (unsigned
1062 char)(FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001064 if (pCurrNvRam)
1065 ScamFlg = pCurrNvRam->niScamConf;
1066 else
1067 ScamFlg =
1068 (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001070 pCardInfo->si_flags = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001072 if (i & 0x01)
1073 pCardInfo->si_flags |= SCSI_PARITY_ENA;
1074
1075 if (!(i & 0x02))
1076 pCardInfo->si_flags |= SOFT_RESET;
1077
1078 if (i & 0x10)
1079 pCardInfo->si_flags |= EXTENDED_TRANSLATION;
1080
1081 if (ScamFlg & SCAM_ENABLED)
1082 pCardInfo->si_flags |= FLAG_SCAM_ENABLED;
1083
1084 if (ScamFlg & SCAM_LEVEL2)
1085 pCardInfo->si_flags |= FLAG_SCAM_LEVEL2;
1086
1087 j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
1088 if (i & 0x04) {
1089 j |= SCSI_TERM_ENA_L;
1090 }
1091 WR_HARPOON(ioport + hp_bm_ctrl, j);
1092
1093 j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
1094 if (i & 0x08) {
1095 j |= SCSI_TERM_ENA_H;
1096 }
1097 WR_HARPOON(ioport + hp_ee_ctrl, j);
1098
1099 if (!(RD_HARPOON(ioport + hp_page_ctrl) & NARROW_SCSI_CARD))
1100
1101 pCardInfo->si_flags |= SUPPORT_16TAR_32LUN;
1102
1103 pCardInfo->si_card_family = HARPOON_FAMILY;
1104 pCardInfo->si_bustype = BUSTYPE_PCI;
1105
1106 if (pCurrNvRam) {
1107 pCardInfo->si_card_model[0] = '9';
1108 switch (pCurrNvRam->niModel & 0x0f) {
1109 case MODEL_LT:
1110 pCardInfo->si_card_model[1] = '3';
1111 pCardInfo->si_card_model[2] = '0';
1112 break;
1113 case MODEL_LW:
1114 pCardInfo->si_card_model[1] = '5';
1115 pCardInfo->si_card_model[2] = '0';
1116 break;
1117 case MODEL_DL:
1118 pCardInfo->si_card_model[1] = '3';
1119 pCardInfo->si_card_model[2] = '2';
1120 break;
1121 case MODEL_DW:
1122 pCardInfo->si_card_model[1] = '5';
1123 pCardInfo->si_card_model[2] = '2';
1124 break;
1125 }
1126 } else {
1127 temp = FPT_utilEERead(ioport, (MODEL_NUMB_0 / 2));
1128 pCardInfo->si_card_model[0] = (unsigned char)(temp >> 8);
1129 temp = FPT_utilEERead(ioport, (MODEL_NUMB_2 / 2));
1130
1131 pCardInfo->si_card_model[1] = (unsigned char)(temp & 0x00FF);
1132 pCardInfo->si_card_model[2] = (unsigned char)(temp >> 8);
1133 }
1134
1135 if (pCardInfo->si_card_model[1] == '3') {
1136 if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
1137 pCardInfo->si_flags |= LOW_BYTE_TERM;
1138 } else if (pCardInfo->si_card_model[2] == '0') {
1139 temp = RD_HARPOON(ioport + hp_xfer_pad);
1140 WR_HARPOON(ioport + hp_xfer_pad, (temp & ~BIT(4)));
1141 if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
1142 pCardInfo->si_flags |= LOW_BYTE_TERM;
1143 WR_HARPOON(ioport + hp_xfer_pad, (temp | BIT(4)));
1144 if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
1145 pCardInfo->si_flags |= HIGH_BYTE_TERM;
1146 WR_HARPOON(ioport + hp_xfer_pad, temp);
1147 } else {
1148 temp = RD_HARPOON(ioport + hp_ee_ctrl);
1149 temp2 = RD_HARPOON(ioport + hp_xfer_pad);
1150 WR_HARPOON(ioport + hp_ee_ctrl, (temp | SEE_CS));
1151 WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4)));
1152 temp3 = 0;
1153 for (i = 0; i < 8; i++) {
1154 temp3 <<= 1;
1155 if (!(RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7)))
1156 temp3 |= 1;
1157 WR_HARPOON(ioport + hp_xfer_pad, (temp2 & ~BIT(4)));
1158 WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4)));
1159 }
1160 WR_HARPOON(ioport + hp_ee_ctrl, temp);
1161 WR_HARPOON(ioport + hp_xfer_pad, temp2);
1162 if (!(temp3 & BIT(7)))
1163 pCardInfo->si_flags |= LOW_BYTE_TERM;
1164 if (!(temp3 & BIT(6)))
1165 pCardInfo->si_flags |= HIGH_BYTE_TERM;
1166 }
1167
1168 ARAM_ACCESS(ioport);
1169
1170 for (i = 0; i < 4; i++) {
1171
1172 pCardInfo->si_XlatInfo[i] =
1173 RD_HARPOON(ioport + hp_aramBase + BIOS_DATA_OFFSET + i);
1174 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175
1176 /* return with -1 if no sort, else return with
1177 logical card number sorted by BIOS (zero-based) */
1178
1179 pCardInfo->si_relative_cardnum =
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001180 (unsigned
1181 char)(RD_HARPOON(ioport + hp_aramBase + BIOS_RELATIVE_CARD) - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001183 SGRAM_ACCESS(ioport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001185 FPT_s_PhaseTbl[0] = FPT_phaseDataOut;
1186 FPT_s_PhaseTbl[1] = FPT_phaseDataIn;
1187 FPT_s_PhaseTbl[2] = FPT_phaseIllegal;
1188 FPT_s_PhaseTbl[3] = FPT_phaseIllegal;
1189 FPT_s_PhaseTbl[4] = FPT_phaseCommand;
1190 FPT_s_PhaseTbl[5] = FPT_phaseStatus;
1191 FPT_s_PhaseTbl[6] = FPT_phaseMsgOut;
1192 FPT_s_PhaseTbl[7] = FPT_phaseMsgIn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001194 pCardInfo->si_present = 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001196 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197}
1198
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199/*---------------------------------------------------------------------
1200 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001201 * Function: FlashPoint_HardwareResetHostAdapter
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 *
1203 * Description: Setup adapter for normal operation (hard reset).
1204 *
1205 *---------------------------------------------------------------------*/
1206
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001207static unsigned long FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info
1208 *pCardInfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001210 struct sccb_card *CurrCard = NULL;
1211 struct nvram_info *pCurrNvRam;
1212 unsigned char i, j, thisCard, ScamFlg;
1213 unsigned short temp, sync_bit_map, id;
1214 unsigned long ioport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001216 ioport = pCardInfo->si_baseaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001218 for (thisCard = 0; thisCard <= MAX_CARDS; thisCard++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001220 if (thisCard == MAX_CARDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001222 return FAILURE;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001223 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001225 if (FPT_BL_Card[thisCard].ioPort == ioport) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001227 CurrCard = &FPT_BL_Card[thisCard];
1228 FPT_SccbMgrTableInitCard(CurrCard, thisCard);
1229 break;
1230 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001232 else if (FPT_BL_Card[thisCard].ioPort == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001234 FPT_BL_Card[thisCard].ioPort = ioport;
1235 CurrCard = &FPT_BL_Card[thisCard];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001237 if (FPT_mbCards)
1238 for (i = 0; i < FPT_mbCards; i++) {
1239 if (CurrCard->ioPort ==
1240 FPT_nvRamInfo[i].niBaseAddr)
1241 CurrCard->pNvRamInfo =
1242 &FPT_nvRamInfo[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001244 FPT_SccbMgrTableInitCard(CurrCard, thisCard);
1245 CurrCard->cardIndex = thisCard;
1246 CurrCard->cardInfo = pCardInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001248 break;
1249 }
1250 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251
1252 pCurrNvRam = CurrCard->pNvRamInfo;
1253
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001254 if (pCurrNvRam) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255 ScamFlg = pCurrNvRam->niScamConf;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001256 } else {
1257 ScamFlg =
1258 (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 }
1260
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001261 FPT_BusMasterInit(ioport);
1262 FPT_XbowInit(ioport, ScamFlg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001264 FPT_autoLoadDefaultMap(ioport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001266 for (i = 0, id = 0x01; i != pCardInfo->si_id; i++, id <<= 1) {
1267 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001269 WR_HARPOON(ioport + hp_selfid_0, id);
1270 WR_HARPOON(ioport + hp_selfid_1, 0x00);
1271 WR_HARPOON(ioport + hp_arb_id, pCardInfo->si_id);
1272 CurrCard->ourId = pCardInfo->si_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001274 i = (unsigned char)pCardInfo->si_flags;
1275 if (i & SCSI_PARITY_ENA)
1276 WR_HARPOON(ioport + hp_portctrl_1, (HOST_MODE8 | CHK_SCSI_P));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001278 j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
1279 if (i & LOW_BYTE_TERM)
1280 j |= SCSI_TERM_ENA_L;
1281 WR_HARPOON(ioport + hp_bm_ctrl, j);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001283 j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
1284 if (i & HIGH_BYTE_TERM)
1285 j |= SCSI_TERM_ENA_H;
1286 WR_HARPOON(ioport + hp_ee_ctrl, j);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001288 if (!(pCardInfo->si_flags & SOFT_RESET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001290 FPT_sresb(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001292 FPT_scini(thisCard, pCardInfo->si_id, 0);
1293 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001295 if (pCardInfo->si_flags & POST_ALL_UNDERRRUNS)
1296 CurrCard->globalFlags |= F_NO_FILTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001298 if (pCurrNvRam) {
1299 if (pCurrNvRam->niSysConf & 0x10)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 CurrCard->globalFlags |= F_GREEN_PC;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001301 } else {
1302 if (FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)) & GREEN_PC_ENA)
1303 CurrCard->globalFlags |= F_GREEN_PC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 }
1305
1306 /* Set global flag to indicate Re-Negotiation to be done on all
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001307 ckeck condition */
1308 if (pCurrNvRam) {
1309 if (pCurrNvRam->niScsiConf & 0x04)
1310 CurrCard->globalFlags |= F_DO_RENEGO;
1311 } else {
1312 if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & RENEGO_ENA)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313 CurrCard->globalFlags |= F_DO_RENEGO;
1314 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001316 if (pCurrNvRam) {
1317 if (pCurrNvRam->niScsiConf & 0x08)
1318 CurrCard->globalFlags |= F_CONLUN_IO;
1319 } else {
1320 if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & CONNIO_ENA)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 CurrCard->globalFlags |= F_CONLUN_IO;
1322 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001323
1324 temp = pCardInfo->si_per_targ_no_disc;
1325
1326 for (i = 0, id = 1; i < MAX_SCSI_TAR; i++, id <<= 1) {
1327
1328 if (temp & id)
1329 FPT_sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 }
1331
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001332 sync_bit_map = 0x0001;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001334 for (id = 0; id < (MAX_SCSI_TAR / 2); id++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001336 if (pCurrNvRam) {
1337 temp = (unsigned short)pCurrNvRam->niSyncTbl[id];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001339 (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
1340 } else
1341 temp =
1342 FPT_utilEERead(ioport,
1343 (unsigned short)((SYNC_RATE_TBL / 2)
1344 + id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001346 for (i = 0; i < 2; temp >>= 8, i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001348 if (pCardInfo->si_per_targ_init_sync & sync_bit_map) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001350 FPT_sccbMgrTbl[thisCard][id * 2 +
1351 i].TarEEValue =
1352 (unsigned char)temp;
1353 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001355 else {
1356 FPT_sccbMgrTbl[thisCard][id * 2 +
1357 i].TarStatus |=
1358 SYNC_SUPPORTED;
1359 FPT_sccbMgrTbl[thisCard][id * 2 +
1360 i].TarEEValue =
1361 (unsigned char)(temp & ~EE_SYNC_MASK);
1362 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364/* if ((pCardInfo->si_per_targ_wide_nego & sync_bit_map) ||
1365 (id*2+i >= 8)){
1366*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001367 if (pCardInfo->si_per_targ_wide_nego & sync_bit_map) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001369 FPT_sccbMgrTbl[thisCard][id * 2 +
1370 i].TarEEValue |=
1371 EE_WIDE_SCSI;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001373 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001375 else { /* NARROW SCSI */
1376 FPT_sccbMgrTbl[thisCard][id * 2 +
1377 i].TarStatus |=
1378 WIDE_NEGOCIATED;
1379 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001381 sync_bit_map <<= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001383 }
1384 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001386 WR_HARPOON((ioport + hp_semaphore),
1387 (unsigned char)(RD_HARPOON((ioport + hp_semaphore)) |
1388 SCCB_MGR_PRESENT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001390 return (unsigned long)CurrCard;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391}
1392
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08001393static void FlashPoint_ReleaseHostAdapter(unsigned long pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394{
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08001395 unsigned char i;
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08001396 unsigned long portBase;
1397 unsigned long regOffset;
1398 unsigned long scamData;
1399 unsigned long *pScamTbl;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001400 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001402 pCurrNvRam = ((struct sccb_card *)pCurrCard)->pNvRamInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001404 if (pCurrNvRam) {
James Bottomley 47b5d692005-04-24 02:38:05 -05001405 FPT_WrStack(pCurrNvRam->niBaseAddr, 0, pCurrNvRam->niModel);
1406 FPT_WrStack(pCurrNvRam->niBaseAddr, 1, pCurrNvRam->niSysConf);
1407 FPT_WrStack(pCurrNvRam->niBaseAddr, 2, pCurrNvRam->niScsiConf);
1408 FPT_WrStack(pCurrNvRam->niBaseAddr, 3, pCurrNvRam->niScamConf);
1409 FPT_WrStack(pCurrNvRam->niBaseAddr, 4, pCurrNvRam->niAdapId);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001411 for (i = 0; i < MAX_SCSI_TAR / 2; i++)
1412 FPT_WrStack(pCurrNvRam->niBaseAddr,
1413 (unsigned char)(i + 5),
1414 pCurrNvRam->niSyncTbl[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415
1416 portBase = pCurrNvRam->niBaseAddr;
1417
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001418 for (i = 0; i < MAX_SCSI_TAR; i++) {
1419 regOffset = hp_aramBase + 64 + i * 4;
1420 pScamTbl = (unsigned long *)&pCurrNvRam->niScamTbl[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 scamData = *pScamTbl;
1422 WR_HARP32(portBase, regOffset, scamData);
1423 }
1424
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001425 } else {
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001426 FPT_WrStack(((struct sccb_card *)pCurrCard)->ioPort, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 }
1428}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001430static void FPT_RNVRamData(struct nvram_info *pNvRamInfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431{
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08001432 unsigned char i;
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08001433 unsigned long portBase;
1434 unsigned long regOffset;
1435 unsigned long scamData;
1436 unsigned long *pScamTbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001438 pNvRamInfo->niModel = FPT_RdStack(pNvRamInfo->niBaseAddr, 0);
1439 pNvRamInfo->niSysConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 1);
James Bottomley 47b5d692005-04-24 02:38:05 -05001440 pNvRamInfo->niScsiConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 2);
1441 pNvRamInfo->niScamConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 3);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001442 pNvRamInfo->niAdapId = FPT_RdStack(pNvRamInfo->niBaseAddr, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001444 for (i = 0; i < MAX_SCSI_TAR / 2; i++)
1445 pNvRamInfo->niSyncTbl[i] =
1446 FPT_RdStack(pNvRamInfo->niBaseAddr, (unsigned char)(i + 5));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447
1448 portBase = pNvRamInfo->niBaseAddr;
1449
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001450 for (i = 0; i < MAX_SCSI_TAR; i++) {
1451 regOffset = hp_aramBase + 64 + i * 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 RD_HARP32(portBase, regOffset, scamData);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001453 pScamTbl = (unsigned long *)&pNvRamInfo->niScamTbl[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 *pScamTbl = scamData;
1455 }
1456
1457}
1458
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08001459static unsigned char FPT_RdStack(unsigned long portBase, unsigned char index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460{
1461 WR_HARPOON(portBase + hp_stack_addr, index);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001462 return RD_HARPOON(portBase + hp_stack_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463}
1464
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001465static void FPT_WrStack(unsigned long portBase, unsigned char index,
1466 unsigned char data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467{
1468 WR_HARPOON(portBase + hp_stack_addr, index);
1469 WR_HARPOON(portBase + hp_stack_data, data);
1470}
1471
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08001472static unsigned char FPT_ChkIfChipInitialized(unsigned long ioPort)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001474 if ((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != FPT_RdStack(ioPort, 4))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001475 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001476 if ((RD_HARPOON(ioPort + hp_clkctrl_0) & CLKCTRL_DEFAULT)
1477 != CLKCTRL_DEFAULT)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001478 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001479 if ((RD_HARPOON(ioPort + hp_seltimeout) == TO_250ms) ||
1480 (RD_HARPOON(ioPort + hp_seltimeout) == TO_290ms))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001481 return 1;
1482 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483
1484}
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001485
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486/*---------------------------------------------------------------------
1487 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001488 * Function: FlashPoint_StartCCB
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 *
1490 * Description: Start a command pointed to by p_Sccb. When the
1491 * command is completed it will be returned via the
1492 * callback function.
1493 *
1494 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001495static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb *p_Sccb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001497 unsigned long ioport;
1498 unsigned char thisCard, lun;
1499 struct sccb *pSaveSccb;
1500 CALL_BK_FN callback;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001502 thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
1503 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001505 if ((p_Sccb->TargID > MAX_SCSI_TAR) || (p_Sccb->Lun > MAX_LUN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 p_Sccb->HostStatus = SCCB_COMPLETE;
1508 p_Sccb->SccbStatus = SCCB_ERROR;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001509 callback = (CALL_BK_FN) p_Sccb->SccbCallback;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 if (callback)
1511 callback(p_Sccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513 return;
1514 }
1515
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001516 FPT_sinits(p_Sccb, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001518 if (!((struct sccb_card *)pCurrCard)->cmdCounter) {
1519 WR_HARPOON(ioport + hp_semaphore,
1520 (RD_HARPOON(ioport + hp_semaphore)
1521 | SCCB_MGR_ACTIVE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001523 if (((struct sccb_card *)pCurrCard)->globalFlags & F_GREEN_PC) {
1524 WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT);
1525 WR_HARPOON(ioport + hp_sys_ctrl, 0x00);
1526 }
1527 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001529 ((struct sccb_card *)pCurrCard)->cmdCounter++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001531 if (RD_HARPOON(ioport + hp_semaphore) & BIOS_IN_USE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001533 WR_HARPOON(ioport + hp_semaphore,
1534 (RD_HARPOON(ioport + hp_semaphore)
1535 | TICKLE_ME));
1536 if (p_Sccb->OperationCode == RESET_COMMAND) {
1537 pSaveSccb =
1538 ((struct sccb_card *)pCurrCard)->currentSCCB;
1539 ((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb;
1540 FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
1541 ((struct sccb_card *)pCurrCard)->currentSCCB =
1542 pSaveSccb;
1543 } else {
1544 FPT_queueAddSccb(p_Sccb, thisCard);
1545 }
1546 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001548 else if ((RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001550 if (p_Sccb->OperationCode == RESET_COMMAND) {
1551 pSaveSccb =
1552 ((struct sccb_card *)pCurrCard)->currentSCCB;
1553 ((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb;
1554 FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
1555 ((struct sccb_card *)pCurrCard)->currentSCCB =
1556 pSaveSccb;
1557 } else {
1558 FPT_queueAddSccb(p_Sccb, thisCard);
1559 }
1560 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001562 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001564 MDISABLE_INT(ioport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001566 if ((((struct sccb_card *)pCurrCard)->globalFlags & F_CONLUN_IO)
1567 &&
1568 ((FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].
1569 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570 lun = p_Sccb->Lun;
1571 else
1572 lun = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001573 if ((((struct sccb_card *)pCurrCard)->currentSCCB == NULL) &&
1574 (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarSelQ_Cnt == 0)
1575 && (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarLUNBusy[lun]
1576 == 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001578 ((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb;
1579 FPT_ssel(p_Sccb->SccbIOPort, thisCard);
1580 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001582 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001584 if (p_Sccb->OperationCode == RESET_COMMAND) {
1585 pSaveSccb =
1586 ((struct sccb_card *)pCurrCard)->
1587 currentSCCB;
1588 ((struct sccb_card *)pCurrCard)->currentSCCB =
1589 p_Sccb;
1590 FPT_queueSelectFail(&FPT_BL_Card[thisCard],
1591 thisCard);
1592 ((struct sccb_card *)pCurrCard)->currentSCCB =
1593 pSaveSccb;
1594 } else {
1595 FPT_queueAddSccb(p_Sccb, thisCard);
1596 }
1597 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001599 MENABLE_INT(ioport);
1600 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602}
1603
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604/*---------------------------------------------------------------------
1605 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001606 * Function: FlashPoint_AbortCCB
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607 *
1608 * Description: Abort the command pointed to by p_Sccb. When the
1609 * command is completed it will be returned via the
1610 * callback function.
1611 *
1612 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001613static int FlashPoint_AbortCCB(unsigned long pCurrCard, struct sccb *p_Sccb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614{
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08001615 unsigned long ioport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08001617 unsigned char thisCard;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618 CALL_BK_FN callback;
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08001619 unsigned char TID;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001620 struct sccb *pSaveSCCB;
1621 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001623 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001625 thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001627 if (!(RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001629 if (FPT_queueFindSccb(p_Sccb, thisCard)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001631 ((struct sccb_card *)pCurrCard)->cmdCounter--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001633 if (!((struct sccb_card *)pCurrCard)->cmdCounter)
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001634 WR_HARPOON(ioport + hp_semaphore,
1635 (RD_HARPOON(ioport + hp_semaphore)
1636 & (unsigned
1637 char)(~(SCCB_MGR_ACTIVE |
1638 TICKLE_ME))));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 p_Sccb->SccbStatus = SCCB_ABORT;
1641 callback = p_Sccb->SccbCallback;
1642 callback(p_Sccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001644 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645 }
1646
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001647 else {
1648 if (((struct sccb_card *)pCurrCard)->currentSCCB ==
1649 p_Sccb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650 p_Sccb->SccbStatus = SCCB_ABORT;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001651 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652
1653 }
1654
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001655 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656
1657 TID = p_Sccb->TargID;
1658
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001659 if (p_Sccb->Sccb_tag) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 MDISABLE_INT(ioport);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001661 if (((struct sccb_card *)pCurrCard)->
1662 discQ_Tbl[p_Sccb->Sccb_tag] ==
1663 p_Sccb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664 p_Sccb->SccbStatus = SCCB_ABORT;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001665 p_Sccb->Sccb_scsistat =
1666 ABORT_ST;
1667 p_Sccb->Sccb_scsimsg =
1668 SMABORT_TAG;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001670 if (((struct sccb_card *)
1671 pCurrCard)->currentSCCB ==
1672 NULL) {
1673 ((struct sccb_card *)
1674 pCurrCard)->
1675 currentSCCB = p_Sccb;
1676 FPT_ssel(ioport,
1677 thisCard);
1678 } else {
1679 pSaveSCCB =
1680 ((struct sccb_card
1681 *)pCurrCard)->
1682 currentSCCB;
1683 ((struct sccb_card *)
1684 pCurrCard)->
1685 currentSCCB = p_Sccb;
1686 FPT_queueSelectFail((struct sccb_card *)pCurrCard, thisCard);
1687 ((struct sccb_card *)
1688 pCurrCard)->
1689 currentSCCB = pSaveSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690 }
1691 }
1692 MENABLE_INT(ioport);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001693 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001694 } else {
1695 currTar_Info =
1696 &FPT_sccbMgrTbl[thisCard][p_Sccb->
1697 TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001699 if (FPT_BL_Card[thisCard].
1700 discQ_Tbl[currTar_Info->
1701 LunDiscQ_Idx[p_Sccb->Lun]]
1702 == p_Sccb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 p_Sccb->SccbStatus = SCCB_ABORT;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001704 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705 }
1706 }
1707 }
1708 }
1709 }
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001710 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711}
1712
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713/*---------------------------------------------------------------------
1714 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001715 * Function: FlashPoint_InterruptPending
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 *
1717 * Description: Do a quick check to determine if there is a pending
1718 * interrupt for this card and disable the IRQ Pin if so.
1719 *
1720 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08001721static unsigned char FlashPoint_InterruptPending(unsigned long pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001723 unsigned long ioport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001725 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001727 if (RD_HARPOON(ioport + hp_int_status) & INT_ASSERTED) {
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001728 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001729 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001731 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001733 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734}
1735
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736/*---------------------------------------------------------------------
1737 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001738 * Function: FlashPoint_HandleInterrupt
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 *
1740 * Description: This is our entry point when an interrupt is generated
1741 * by the card and the upper level driver passes it on to
1742 * us.
1743 *
1744 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08001745static int FlashPoint_HandleInterrupt(unsigned long pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001747 struct sccb *currSCCB;
1748 unsigned char thisCard, result, bm_status, bm_int_st;
1749 unsigned short hp_int;
1750 unsigned char i, target;
1751 unsigned long ioport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001753 thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
1754 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001756 MDISABLE_INT(ioport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001758 if ((bm_int_st = RD_HARPOON(ioport + hp_int_status)) & EXT_STATUS_ON)
1759 bm_status =
1760 RD_HARPOON(ioport +
1761 hp_ext_status) & (unsigned char)BAD_EXT_STATUS;
1762 else
1763 bm_status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001764
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001765 WR_HARPOON(ioport + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001767 while ((hp_int =
1768 RDW_HARPOON((ioport +
1769 hp_intstat)) & FPT_default_intena) | bm_status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001771 currSCCB = ((struct sccb_card *)pCurrCard)->currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001773 if (hp_int & (FIFO | TIMEOUT | RESET | SCAM_SEL) || bm_status) {
1774 result =
1775 FPT_SccbMgr_bad_isr(ioport, thisCard,
1776 ((struct sccb_card *)pCurrCard),
1777 hp_int);
1778 WRW_HARPOON((ioport + hp_intstat),
1779 (FIFO | TIMEOUT | RESET | SCAM_SEL));
1780 bm_status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001782 if (result) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001784 MENABLE_INT(ioport);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001785 return result;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001786 }
1787 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001789 else if (hp_int & ICMD_COMP) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001791 if (!(hp_int & BUS_FREE)) {
1792 /* Wait for the BusFree before starting a new command. We
1793 must also check for being reselected since the BusFree
1794 may not show up if another device reselects us in 1.5us or
1795 less. SRR Wednesday, 3/8/1995.
1796 */
1797 while (!
1798 (RDW_HARPOON((ioport + hp_intstat)) &
1799 (BUS_FREE | RSEL))) ;
1800 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001802 if (((struct sccb_card *)pCurrCard)->
1803 globalFlags & F_HOST_XFER_ACT)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001805 FPT_phaseChkFifo(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806
1807/* WRW_HARPOON((ioport+hp_intstat),
1808 (BUS_FREE | ICMD_COMP | ITAR_DISC | XFER_CNT_0));
1809 */
1810
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001811 WRW_HARPOON((ioport + hp_intstat), CLR_ALL_INT_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001812
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001813 FPT_autoCmdCmplt(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001815 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001816
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001817 else if (hp_int & ITAR_DISC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001819 if (((struct sccb_card *)pCurrCard)->
1820 globalFlags & F_HOST_XFER_ACT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001822 FPT_phaseChkFifo(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824 }
1825
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001826 if (RD_HARPOON(ioport + hp_gp_reg_1) == SMSAVE_DATA_PTR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001828 WR_HARPOON(ioport + hp_gp_reg_1, 0x00);
1829 currSCCB->Sccb_XferState |= F_NO_DATA_YET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001831 currSCCB->Sccb_savedATC = currSCCB->Sccb_ATC;
1832 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001834 currSCCB->Sccb_scsistat = DISCONNECT_ST;
1835 FPT_queueDisconnect(currSCCB, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001836
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001837 /* Wait for the BusFree before starting a new command. We
1838 must also check for being reselected since the BusFree
1839 may not show up if another device reselects us in 1.5us or
1840 less. SRR Wednesday, 3/8/1995.
1841 */
1842 while (!
1843 (RDW_HARPOON((ioport + hp_intstat)) &
1844 (BUS_FREE | RSEL))
1845 && !((RDW_HARPOON((ioport + hp_intstat)) & PHASE)
1846 && RD_HARPOON((ioport + hp_scsisig)) ==
1847 (SCSI_BSY | SCSI_REQ | SCSI_CD | SCSI_MSG |
1848 SCSI_IOBIT))) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001850 /*
1851 The additional loop exit condition above detects a timing problem
1852 with the revision D/E harpoon chips. The caller should reset the
1853 host adapter to recover when 0xFE is returned.
1854 */
1855 if (!
1856 (RDW_HARPOON((ioport + hp_intstat)) &
1857 (BUS_FREE | RSEL))) {
1858 MENABLE_INT(ioport);
1859 return 0xFE;
1860 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001862 WRW_HARPOON((ioport + hp_intstat),
1863 (BUS_FREE | ITAR_DISC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001865 ((struct sccb_card *)pCurrCard)->globalFlags |=
1866 F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001868 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001870 else if (hp_int & RSEL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001872 WRW_HARPOON((ioport + hp_intstat),
1873 (PROG_HLT | RSEL | PHASE | BUS_FREE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001875 if (RDW_HARPOON((ioport + hp_intstat)) & ITAR_DISC) {
1876 if (((struct sccb_card *)pCurrCard)->
1877 globalFlags & F_HOST_XFER_ACT) {
1878 FPT_phaseChkFifo(ioport, thisCard);
1879 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001880
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001881 if (RD_HARPOON(ioport + hp_gp_reg_1) ==
1882 SMSAVE_DATA_PTR) {
1883 WR_HARPOON(ioport + hp_gp_reg_1, 0x00);
1884 currSCCB->Sccb_XferState |=
1885 F_NO_DATA_YET;
1886 currSCCB->Sccb_savedATC =
1887 currSCCB->Sccb_ATC;
1888 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001889
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001890 WRW_HARPOON((ioport + hp_intstat),
1891 (BUS_FREE | ITAR_DISC));
1892 currSCCB->Sccb_scsistat = DISCONNECT_ST;
1893 FPT_queueDisconnect(currSCCB, thisCard);
1894 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001895
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001896 FPT_sres(ioport, thisCard,
1897 ((struct sccb_card *)pCurrCard));
1898 FPT_phaseDecode(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001899
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001900 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001902 else if ((hp_int & IDO_STRT) && (!(hp_int & BUS_FREE))) {
1903
1904 WRW_HARPOON((ioport + hp_intstat),
1905 (IDO_STRT | XFER_CNT_0));
1906 FPT_phaseDecode(ioport, thisCard);
1907
1908 }
1909
1910 else if ((hp_int & IUNKWN) || (hp_int & PROG_HLT)) {
1911 WRW_HARPOON((ioport + hp_intstat),
1912 (PHASE | IUNKWN | PROG_HLT));
1913 if ((RD_HARPOON(ioport + hp_prgmcnt_0) & (unsigned char)
1914 0x3f) < (unsigned char)SELCHK) {
1915 FPT_phaseDecode(ioport, thisCard);
1916 } else {
1917 /* Harpoon problem some SCSI target device respond to selection
1918 with short BUSY pulse (<400ns) this will make the Harpoon is not able
1919 to latch the correct Target ID into reg. x53.
1920 The work around require to correct this reg. But when write to this
1921 reg. (0x53) also increment the FIFO write addr reg (0x6f), thus we
1922 need to read this reg first then restore it later. After update to 0x53 */
1923
1924 i = (unsigned
1925 char)(RD_HARPOON(ioport + hp_fifowrite));
1926 target =
1927 (unsigned
1928 char)(RD_HARPOON(ioport + hp_gp_reg_3));
1929 WR_HARPOON(ioport + hp_xfer_pad,
1930 (unsigned char)ID_UNLOCK);
1931 WR_HARPOON(ioport + hp_select_id,
1932 (unsigned char)(target | target <<
1933 4));
1934 WR_HARPOON(ioport + hp_xfer_pad,
1935 (unsigned char)0x00);
1936 WR_HARPOON(ioport + hp_fifowrite, i);
1937 WR_HARPOON(ioport + hp_autostart_3,
1938 (AUTO_IMMED + TAG_STRT));
1939 }
1940 }
1941
1942 else if (hp_int & XFER_CNT_0) {
1943
1944 WRW_HARPOON((ioport + hp_intstat), XFER_CNT_0);
1945
1946 FPT_schkdd(ioport, thisCard);
1947
1948 }
1949
1950 else if (hp_int & BUS_FREE) {
1951
1952 WRW_HARPOON((ioport + hp_intstat), BUS_FREE);
1953
1954 if (((struct sccb_card *)pCurrCard)->
1955 globalFlags & F_HOST_XFER_ACT) {
1956
1957 FPT_hostDataXferAbort(ioport, thisCard,
1958 currSCCB);
1959 }
1960
1961 FPT_phaseBusFree(ioport, thisCard);
1962 }
1963
1964 else if (hp_int & ITICKLE) {
1965
1966 WRW_HARPOON((ioport + hp_intstat), ITICKLE);
1967 ((struct sccb_card *)pCurrCard)->globalFlags |=
1968 F_NEW_SCCB_CMD;
1969 }
1970
1971 if (((struct sccb_card *)pCurrCard)->
1972 globalFlags & F_NEW_SCCB_CMD) {
1973
1974 ((struct sccb_card *)pCurrCard)->globalFlags &=
1975 ~F_NEW_SCCB_CMD;
1976
1977 if (((struct sccb_card *)pCurrCard)->currentSCCB ==
1978 NULL) {
1979
1980 FPT_queueSearchSelect(((struct sccb_card *)
1981 pCurrCard), thisCard);
1982 }
1983
1984 if (((struct sccb_card *)pCurrCard)->currentSCCB !=
1985 NULL) {
1986 ((struct sccb_card *)pCurrCard)->globalFlags &=
1987 ~F_NEW_SCCB_CMD;
1988 FPT_ssel(ioport, thisCard);
1989 }
1990
1991 break;
1992
1993 }
1994
1995 } /*end while */
1996
1997 MENABLE_INT(ioport);
1998
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001999 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000}
2001
2002/*---------------------------------------------------------------------
2003 *
2004 * Function: Sccb_bad_isr
2005 *
2006 * Description: Some type of interrupt has occurred which is slightly
2007 * out of the ordinary. We will now decode it fully, in
2008 * this routine. This is broken up in an attempt to save
2009 * processing time.
2010 *
2011 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002012static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port,
2013 unsigned char p_card,
2014 struct sccb_card *pCurrCard,
2015 unsigned short p_int)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002017 unsigned char temp, ScamFlg;
2018 struct sccb_mgr_tar_info *currTar_Info;
2019 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002021 if (RD_HARPOON(p_port + hp_ext_status) &
2022 (BM_FORCE_OFF | PCI_DEV_TMOUT | BM_PARITY_ERR | PIO_OVERRUN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002024 if (pCurrCard->globalFlags & F_HOST_XFER_ACT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002025
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002026 FPT_hostDataXferAbort(p_port, p_card,
2027 pCurrCard->currentSCCB);
2028 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002029
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002030 if (RD_HARPOON(p_port + hp_pci_stat_cfg) & REC_MASTER_ABORT)
2031 {
2032 WR_HARPOON(p_port + hp_pci_stat_cfg,
2033 (RD_HARPOON(p_port + hp_pci_stat_cfg) &
2034 ~REC_MASTER_ABORT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002035
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002036 WR_HARPOON(p_port + hp_host_blk_cnt, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002038 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002039
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002040 if (pCurrCard->currentSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002042 if (!pCurrCard->currentSCCB->HostStatus)
2043 pCurrCard->currentSCCB->HostStatus =
2044 SCCB_BM_ERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002046 FPT_sxfrp(p_port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002048 temp = (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
2049 (EXT_ARB_ACK | SCSI_TERM_ENA_H));
2050 WR_HARPOON(p_port + hp_ee_ctrl,
2051 ((unsigned char)temp | SEE_MS | SEE_CS));
2052 WR_HARPOON(p_port + hp_ee_ctrl, temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002053
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002054 if (!
2055 (RDW_HARPOON((p_port + hp_intstat)) &
2056 (BUS_FREE | RESET))) {
2057 FPT_phaseDecode(p_port, p_card);
2058 }
2059 }
2060 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002061
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002062 else if (p_int & RESET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002064 WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
2065 WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
2066 if (pCurrCard->currentSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002067
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002068 if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002070 FPT_hostDataXferAbort(p_port, p_card,
2071 pCurrCard->currentSCCB);
2072 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002073
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002074 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002076 FPT_sresb(p_port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002078 while (RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST) {
2079 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002080
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002081 pCurrNvRam = pCurrCard->pNvRamInfo;
2082 if (pCurrNvRam) {
2083 ScamFlg = pCurrNvRam->niScamConf;
2084 } else {
2085 ScamFlg =
2086 (unsigned char)FPT_utilEERead(p_port,
2087 SCAM_CONFIG / 2);
2088 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002089
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002090 FPT_XbowInit(p_port, ScamFlg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002091
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002092 FPT_scini(p_card, pCurrCard->ourId, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002094 return 0xFF;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002095 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002096
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002097 else if (p_int & FIFO) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002099 WRW_HARPOON((p_port + hp_intstat), FIFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002100
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002101 if (pCurrCard->currentSCCB != NULL)
2102 FPT_sxfrp(p_port, p_card);
2103 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002104
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002105 else if (p_int & TIMEOUT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002107 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002108
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002109 WRW_HARPOON((p_port + hp_intstat),
2110 (PROG_HLT | TIMEOUT | SEL | BUS_FREE | PHASE |
2111 IUNKWN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002113 pCurrCard->currentSCCB->HostStatus = SCCB_SELECTION_TIMEOUT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002115 currTar_Info =
2116 &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
2117 if ((pCurrCard->globalFlags & F_CONLUN_IO)
2118 && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
2119 TAG_Q_TRYING))
2120 currTar_Info->TarLUNBusy[pCurrCard->currentSCCB->Lun] =
2121 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002123 currTar_Info->TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002125 if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
2126 currTar_Info->TarSyncCtrl = 0;
2127 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2128 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002129
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002130 if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
2131 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2132 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002134 FPT_sssyncv(p_port, pCurrCard->currentSCCB->TargID, NARROW_SCSI,
2135 currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002137 FPT_queueCmdComplete(pCurrCard, pCurrCard->currentSCCB, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002138
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002139 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002141 else if (p_int & SCAM_SEL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002143 FPT_scarb(p_port, LEVEL2_TAR);
2144 FPT_scsel(p_port);
2145 FPT_scasid(p_card, p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002146
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002147 FPT_scbusf(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002149 WRW_HARPOON((p_port + hp_intstat), SCAM_SEL);
2150 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002152 return 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153}
2154
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155/*---------------------------------------------------------------------
2156 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157 * Function: SccbMgrTableInit
2158 *
2159 * Description: Initialize all Sccb manager data structures.
2160 *
2161 *---------------------------------------------------------------------*/
2162
James Bottomley 47b5d692005-04-24 02:38:05 -05002163static void FPT_SccbMgrTableInitAll()
Linus Torvalds1da177e2005-04-16 15:20:36 -07002164{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002165 unsigned char thisCard;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002167 for (thisCard = 0; thisCard < MAX_CARDS; thisCard++) {
2168 FPT_SccbMgrTableInitCard(&FPT_BL_Card[thisCard], thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002170 FPT_BL_Card[thisCard].ioPort = 0x00;
2171 FPT_BL_Card[thisCard].cardInfo = NULL;
2172 FPT_BL_Card[thisCard].cardIndex = 0xFF;
2173 FPT_BL_Card[thisCard].ourId = 0x00;
2174 FPT_BL_Card[thisCard].pNvRamInfo = NULL;
2175 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176}
2177
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178/*---------------------------------------------------------------------
2179 *
2180 * Function: SccbMgrTableInit
2181 *
2182 * Description: Initialize all Sccb manager data structures.
2183 *
2184 *---------------------------------------------------------------------*/
2185
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002186static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard,
2187 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002189 unsigned char scsiID, qtag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002191 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002192 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193 }
2194
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002195 for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
2196 FPT_sccbMgrTbl[p_card][scsiID].TarStatus = 0;
2197 FPT_sccbMgrTbl[p_card][scsiID].TarEEValue = 0;
2198 FPT_SccbMgrTableInitTarget(p_card, scsiID);
2199 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002201 pCurrCard->scanIndex = 0x00;
2202 pCurrCard->currentSCCB = NULL;
2203 pCurrCard->globalFlags = 0x00;
2204 pCurrCard->cmdCounter = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205 pCurrCard->tagQ_Lst = 0x01;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002206 pCurrCard->discQCount = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207
2208}
2209
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210/*---------------------------------------------------------------------
2211 *
2212 * Function: SccbMgrTableInit
2213 *
2214 * Description: Initialize all Sccb manager data structures.
2215 *
2216 *---------------------------------------------------------------------*/
2217
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002218static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
2219 unsigned char target)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220{
2221
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08002222 unsigned char lun, qtag;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002223 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224
James Bottomley 47b5d692005-04-24 02:38:05 -05002225 currTar_Info = &FPT_sccbMgrTbl[p_card][target];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226
2227 currTar_Info->TarSelQ_Cnt = 0;
2228 currTar_Info->TarSyncCtrl = 0;
2229
2230 currTar_Info->TarSelQ_Head = NULL;
2231 currTar_Info->TarSelQ_Tail = NULL;
2232 currTar_Info->TarTagQ_Cnt = 0;
James Bottomley 47b5d692005-04-24 02:38:05 -05002233 currTar_Info->TarLUN_CA = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002235 for (lun = 0; lun < MAX_LUN; lun++) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002236 currTar_Info->TarLUNBusy[lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237 currTar_Info->LunDiscQ_Idx[lun] = 0;
2238 }
2239
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002240 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
2241 if (FPT_BL_Card[p_card].discQ_Tbl[qtag] != NULL) {
2242 if (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
2243 target) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002244 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
2245 FPT_BL_Card[p_card].discQCount--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246 }
2247 }
2248 }
2249}
2250
Linus Torvalds1da177e2005-04-16 15:20:36 -07002251/*---------------------------------------------------------------------
2252 *
2253 * Function: sfetm
2254 *
2255 * Description: Read in a message byte from the SCSI bus, and check
2256 * for a parity error.
2257 *
2258 *---------------------------------------------------------------------*/
2259
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002260static unsigned char FPT_sfm(unsigned long port, struct sccb *pCurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261{
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08002262 unsigned char message;
Alexey Dobriyanc823fee2006-03-08 00:14:25 -08002263 unsigned short TimeOutLoop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264
2265 TimeOutLoop = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002266 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2267 (TimeOutLoop++ < 20000)) {
2268 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002270 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002272 message = RD_HARPOON(port + hp_scsidata_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002274 WR_HARPOON(port + hp_scsisig, SCSI_ACK + S_MSGI_PH);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275
2276 if (TimeOutLoop > 20000)
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002277 message = 0x00; /* force message byte = 0 if Time Out on Req */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002279 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
2280 (RD_HARPOON(port + hp_addstat) & SCSI_PAR_ERR)) {
2281 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2282 WR_HARPOON(port + hp_xferstat, 0);
2283 WR_HARPOON(port + hp_fiforead, 0);
2284 WR_HARPOON(port + hp_fifowrite, 0);
2285 if (pCurrSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286 pCurrSCCB->Sccb_scsimsg = SMPARITY;
2287 }
2288 message = 0x00;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002289 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290 ACCEPT_MSG_ATN(port);
2291 TimeOutLoop = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002292 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2293 (TimeOutLoop++ < 20000)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002295 if (TimeOutLoop > 20000) {
2296 WRW_HARPOON((port + hp_intstat), PARITY);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002297 return message;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002299 if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) !=
2300 S_MSGI_PH) {
2301 WRW_HARPOON((port + hp_intstat), PARITY);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002302 return message;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002303 }
2304 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002306 RD_HARPOON(port + hp_scsidata_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002308 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002310 } while (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311
2312 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002313 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2314 WR_HARPOON(port + hp_xferstat, 0);
2315 WR_HARPOON(port + hp_fiforead, 0);
2316 WR_HARPOON(port + hp_fifowrite, 0);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002317 return message;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318}
2319
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320/*---------------------------------------------------------------------
2321 *
James Bottomley 47b5d692005-04-24 02:38:05 -05002322 * Function: FPT_ssel
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323 *
2324 * Description: Load up automation and select target device.
2325 *
2326 *---------------------------------------------------------------------*/
2327
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08002328static void FPT_ssel(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329{
2330
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002331 unsigned char auto_loaded, i, target, *theCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002333 unsigned long cdb_reg;
2334 struct sccb_card *CurrCard;
2335 struct sccb *currSCCB;
2336 struct sccb_mgr_tar_info *currTar_Info;
2337 unsigned char lastTag, lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002339 CurrCard = &FPT_BL_Card[p_card];
2340 currSCCB = CurrCard->currentSCCB;
2341 target = currSCCB->TargID;
2342 currTar_Info = &FPT_sccbMgrTbl[p_card][target];
2343 lastTag = CurrCard->tagQ_Lst;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002345 ARAM_ACCESS(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002346
2347 if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
2348 currSCCB->ControlByte &= ~F_USE_CMD_Q;
2349
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002350 if (((CurrCard->globalFlags & F_CONLUN_IO) &&
2351 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002353 lun = currSCCB->Lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 else
2355 lun = 0;
2356
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002357 if (CurrCard->globalFlags & F_TAG_STARTED) {
2358 if (!(currSCCB->ControlByte & F_USE_CMD_Q)) {
2359 if ((currTar_Info->TarLUN_CA == 0)
2360 && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
2361 == TAG_Q_TRYING)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002363 if (currTar_Info->TarTagQ_Cnt != 0) {
2364 currTar_Info->TarLUNBusy[lun] = 1;
2365 FPT_queueSelectFail(CurrCard, p_card);
2366 SGRAM_ACCESS(port);
2367 return;
2368 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002370 else {
2371 currTar_Info->TarLUNBusy[lun] = 1;
2372 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002374 }
2375 /*End non-tagged */
2376 else {
2377 currTar_Info->TarLUNBusy[lun] = 1;
2378 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002380 }
2381 /*!Use cmd Q Tagged */
2382 else {
2383 if (currTar_Info->TarLUN_CA == 1) {
2384 FPT_queueSelectFail(CurrCard, p_card);
2385 SGRAM_ACCESS(port);
2386 return;
2387 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388
James Bottomley 47b5d692005-04-24 02:38:05 -05002389 currTar_Info->TarLUNBusy[lun] = 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002390
2391 } /*else use cmd Q tagged */
2392
2393 }
2394 /*if glob tagged started */
2395 else {
2396 currTar_Info->TarLUNBusy[lun] = 1;
2397 }
2398
2399 if ((((CurrCard->globalFlags & F_CONLUN_IO) &&
2400 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
2401 || (!(currSCCB->ControlByte & F_USE_CMD_Q)))) {
2402 if (CurrCard->discQCount >= QUEUE_DEPTH) {
2403 currTar_Info->TarLUNBusy[lun] = 1;
2404 FPT_queueSelectFail(CurrCard, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405 SGRAM_ACCESS(port);
2406 return;
2407 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002408 for (i = 1; i < QUEUE_DEPTH; i++) {
2409 if (++lastTag >= QUEUE_DEPTH)
2410 lastTag = 1;
2411 if (CurrCard->discQ_Tbl[lastTag] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412 CurrCard->tagQ_Lst = lastTag;
2413 currTar_Info->LunDiscQ_Idx[lun] = lastTag;
2414 CurrCard->discQ_Tbl[lastTag] = currSCCB;
2415 CurrCard->discQCount++;
2416 break;
2417 }
2418 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002419 if (i == QUEUE_DEPTH) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002420 currTar_Info->TarLUNBusy[lun] = 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002421 FPT_queueSelectFail(CurrCard, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422 SGRAM_ACCESS(port);
2423 return;
2424 }
2425 }
2426
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002427 auto_loaded = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002429 WR_HARPOON(port + hp_select_id, target);
2430 WR_HARPOON(port + hp_gp_reg_3, target); /* Use by new automation logic */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002432 if (currSCCB->OperationCode == RESET_COMMAND) {
2433 WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
2434 (currSCCB->
2435 Sccb_idmsg & ~DISC_PRIV)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002437 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + NP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002439 currSCCB->Sccb_scsimsg = SMDEV_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002441 WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
2442 auto_loaded = 1;
2443 currSCCB->Sccb_scsistat = SELECT_BDR_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002445 if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
2446 currTar_Info->TarSyncCtrl = 0;
2447 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448 }
2449
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002450 if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
2451 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2452 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002454 FPT_sssyncv(port, target, NARROW_SCSI, currTar_Info);
2455 FPT_SccbMgrTableInitTarget(p_card, target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002457 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002459 else if (currSCCB->Sccb_scsistat == ABORT_ST) {
2460 WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
2461 (currSCCB->
2462 Sccb_idmsg & ~DISC_PRIV)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002464 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002466 WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT +
2467 (((unsigned
2468 char)(currSCCB->
2469 ControlByte &
2470 TAG_TYPE_MASK)
2471 >> 6) | (unsigned char)
2472 0x20)));
2473 WRW_HARPOON((port + SYNC_MSGS + 2),
2474 (MPM_OP + AMSG_OUT + currSCCB->Sccb_tag));
2475 WRW_HARPOON((port + SYNC_MSGS + 4), (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002477 WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
2478 auto_loaded = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002480 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002482 else if (!(currTar_Info->TarStatus & WIDE_NEGOCIATED)) {
2483 auto_loaded = FPT_siwidn(port, p_card);
2484 currSCCB->Sccb_scsistat = SELECT_WN_ST;
2485 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002487 else if (!((currTar_Info->TarStatus & TAR_SYNC_MASK)
2488 == SYNC_SUPPORTED)) {
2489 auto_loaded = FPT_sisyncn(port, p_card, 0);
2490 currSCCB->Sccb_scsistat = SELECT_SN_ST;
2491 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002493 if (!auto_loaded) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002495 if (currSCCB->ControlByte & F_USE_CMD_Q) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002497 CurrCard->globalFlags |= F_TAG_STARTED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002499 if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
2500 == TAG_Q_REJECT) {
2501 currSCCB->ControlByte &= ~F_USE_CMD_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002503 /* Fix up the start instruction with a jump to
2504 Non-Tag-CMD handling */
2505 WRW_HARPOON((port + ID_MSG_STRT),
2506 BRH_OP + ALWAYS + NTCMD);
2507
2508 WRW_HARPOON((port + NON_TAG_ID_MSG),
2509 (MPM_OP + AMSG_OUT +
2510 currSCCB->Sccb_idmsg));
2511
2512 WR_HARPOON(port + hp_autostart_3,
2513 (SELECT + SELCHK_STRT));
2514
2515 /* Setup our STATE so we know what happend when
2516 the wheels fall off. */
2517 currSCCB->Sccb_scsistat = SELECT_ST;
2518
2519 currTar_Info->TarLUNBusy[lun] = 1;
2520 }
2521
2522 else {
2523 WRW_HARPOON((port + ID_MSG_STRT),
2524 (MPM_OP + AMSG_OUT +
2525 currSCCB->Sccb_idmsg));
2526
2527 WRW_HARPOON((port + ID_MSG_STRT + 2),
2528 (MPM_OP + AMSG_OUT +
2529 (((unsigned char)(currSCCB->
2530 ControlByte &
2531 TAG_TYPE_MASK)
2532 >> 6) | (unsigned char)0x20)));
2533
2534 for (i = 1; i < QUEUE_DEPTH; i++) {
2535 if (++lastTag >= QUEUE_DEPTH)
2536 lastTag = 1;
2537 if (CurrCard->discQ_Tbl[lastTag] ==
2538 NULL) {
2539 WRW_HARPOON((port +
2540 ID_MSG_STRT + 6),
2541 (MPM_OP + AMSG_OUT +
2542 lastTag));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543 CurrCard->tagQ_Lst = lastTag;
2544 currSCCB->Sccb_tag = lastTag;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002545 CurrCard->discQ_Tbl[lastTag] =
2546 currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547 CurrCard->discQCount++;
2548 break;
2549 }
2550 }
2551
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002552 if (i == QUEUE_DEPTH) {
2553 currTar_Info->TarLUNBusy[lun] = 1;
2554 FPT_queueSelectFail(CurrCard, p_card);
2555 SGRAM_ACCESS(port);
2556 return;
2557 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002559 currSCCB->Sccb_scsistat = SELECT_Q_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002561 WR_HARPOON(port + hp_autostart_3,
2562 (SELECT + SELCHK_STRT));
2563 }
2564 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002566 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002568 WRW_HARPOON((port + ID_MSG_STRT),
2569 BRH_OP + ALWAYS + NTCMD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002571 WRW_HARPOON((port + NON_TAG_ID_MSG),
2572 (MPM_OP + AMSG_OUT + currSCCB->Sccb_idmsg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002574 currSCCB->Sccb_scsistat = SELECT_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002575
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002576 WR_HARPOON(port + hp_autostart_3,
2577 (SELECT + SELCHK_STRT));
2578 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002580 theCCB = (unsigned char *)&currSCCB->Cdb[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002582 cdb_reg = port + CMD_STRT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002584 for (i = 0; i < currSCCB->CdbLength; i++) {
2585 WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + *theCCB));
2586 cdb_reg += 2;
2587 theCCB++;
2588 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002590 if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
2591 WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002593 }
2594 /* auto_loaded */
2595 WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
2596 WR_HARPOON(port + hp_xferstat, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002598 WRW_HARPOON((port + hp_intstat), (PROG_HLT | TIMEOUT | SEL | BUS_FREE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002600 WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002602 if (!(currSCCB->Sccb_MGRFlags & F_DEV_SELECTED)) {
2603 WR_HARPOON(port + hp_scsictrl_0,
2604 (SEL_TAR | ENA_ATN | ENA_RESEL | ENA_SCAM_SEL));
2605 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08002607/* auto_loaded = (RD_HARPOON(port+hp_autostart_3) & (unsigned char)0x1F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608 auto_loaded |= AUTO_IMMED; */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002609 auto_loaded = AUTO_IMMED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002611 DISABLE_AUTO(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002613 WR_HARPOON(port + hp_autostart_3, auto_loaded);
2614 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002616 SGRAM_ACCESS(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617}
2618
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619/*---------------------------------------------------------------------
2620 *
James Bottomley 47b5d692005-04-24 02:38:05 -05002621 * Function: FPT_sres
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622 *
2623 * Description: Hookup the correct CCB and handle the incoming messages.
2624 *
2625 *---------------------------------------------------------------------*/
2626
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002627static void FPT_sres(unsigned long port, unsigned char p_card,
2628 struct sccb_card *pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629{
2630
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002631 unsigned char our_target, message, lun = 0, tag, msgRetryCount;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002633 struct sccb_mgr_tar_info *currTar_Info;
2634 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002636 if (pCurrCard->currentSCCB != NULL) {
2637 currTar_Info =
2638 &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639 DISABLE_AUTO(port);
2640
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002641 WR_HARPOON((port + hp_scsictrl_0), (ENA_RESEL | ENA_SCAM_SEL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642
2643 currSCCB = pCurrCard->currentSCCB;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002644 if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2646 currSCCB->Sccb_scsistat = BUS_FREE_ST;
2647 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002648 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2650 currSCCB->Sccb_scsistat = BUS_FREE_ST;
2651 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002652 if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
2653 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
2654 TAG_Q_TRYING))) {
2655 currTar_Info->TarLUNBusy[currSCCB->Lun] = 0;
2656 if (currSCCB->Sccb_scsistat != ABORT_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002657 pCurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002658 pCurrCard->discQ_Tbl[currTar_Info->
2659 LunDiscQ_Idx[currSCCB->
2660 Lun]]
2661 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002663 } else {
2664 currTar_Info->TarLUNBusy[0] = 0;
2665 if (currSCCB->Sccb_tag) {
2666 if (currSCCB->Sccb_scsistat != ABORT_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667 pCurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002668 pCurrCard->discQ_Tbl[currSCCB->
2669 Sccb_tag] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002671 } else {
2672 if (currSCCB->Sccb_scsistat != ABORT_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673 pCurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002674 pCurrCard->discQ_Tbl[currTar_Info->
2675 LunDiscQ_Idx[0]] =
2676 NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002677 }
2678 }
2679 }
2680
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002681 FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682 }
2683
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002684 WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002686 our_target = (unsigned char)(RD_HARPOON(port + hp_select_id) >> 4);
James Bottomley 47b5d692005-04-24 02:38:05 -05002687 currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689 msgRetryCount = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002690 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691
James Bottomley 47b5d692005-04-24 02:38:05 -05002692 currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693 tag = 0;
2694
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002695 while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
2696 if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002698 WRW_HARPOON((port + hp_intstat), PHASE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699 return;
2700 }
2701 }
2702
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002703 WRW_HARPOON((port + hp_intstat), PHASE);
2704 if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002706 message = FPT_sfm(port, pCurrCard->currentSCCB);
2707 if (message) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002709 if (message <= (0x80 | LUN_MASK)) {
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08002710 lun = message & (unsigned char)LUN_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002711
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002712 if ((currTar_Info->
2713 TarStatus & TAR_TAG_Q_MASK) ==
2714 TAG_Q_TRYING) {
2715 if (currTar_Info->TarTagQ_Cnt !=
2716 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002718 if (!
2719 (currTar_Info->
2720 TarLUN_CA)) {
2721 ACCEPT_MSG(port); /*Release the ACK for ID msg. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002723 message =
2724 FPT_sfm
2725 (port,
2726 pCurrCard->
2727 currentSCCB);
2728 if (message) {
2729 ACCEPT_MSG
2730 (port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731 }
2732
2733 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002734 message
2735 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002737 if (message !=
2738 0) {
2739 tag =
2740 FPT_sfm
2741 (port,
2742 pCurrCard->
2743 currentSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002744
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002745 if (!
2746 (tag))
2747 message
2748 =
2749 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750 }
2751
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002752 }
2753 /*C.A. exists! */
2754 }
2755 /*End Q cnt != 0 */
2756 }
2757 /*End Tag cmds supported! */
2758 }
2759 /*End valid ID message. */
2760 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761
2762 ACCEPT_MSG_ATN(port);
2763 }
2764
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002765 }
2766 /* End good id message. */
2767 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768
James Bottomley 47b5d692005-04-24 02:38:05 -05002769 message = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002771 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002772 ACCEPT_MSG_ATN(port);
2773
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002774 while (!
2775 (RDW_HARPOON((port + hp_intstat)) &
2776 (PHASE | RESET))
2777 && !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
2778 && (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002779
2780 return;
2781 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002782
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002783 if (message == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002784 msgRetryCount++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002785 if (msgRetryCount == 1) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002786 FPT_SendMsg(port, SMPARITY);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002787 } else {
James Bottomley 47b5d692005-04-24 02:38:05 -05002788 FPT_SendMsg(port, SMDEV_RESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002790 FPT_sssyncv(port, our_target, NARROW_SCSI,
2791 currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002793 if (FPT_sccbMgrTbl[p_card][our_target].
2794 TarEEValue & EE_SYNC_MASK) {
2795
2796 FPT_sccbMgrTbl[p_card][our_target].
2797 TarStatus &= ~TAR_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798
2799 }
2800
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002801 if (FPT_sccbMgrTbl[p_card][our_target].
2802 TarEEValue & EE_WIDE_SCSI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002804 FPT_sccbMgrTbl[p_card][our_target].
2805 TarStatus &= ~TAR_WIDE_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002806 }
2807
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002808 FPT_queueFlushTargSccb(p_card, our_target,
2809 SCCB_COMPLETE);
2810 FPT_SccbMgrTableInitTarget(p_card, our_target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002811 return;
2812 }
2813 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002814 } while (message == 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002815
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002816 if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
2817 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002818 currTar_Info->TarLUNBusy[lun] = 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002819 pCurrCard->currentSCCB =
2820 pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[lun]];
2821 if (pCurrCard->currentSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002823 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824 ACCEPT_MSG_ATN(port);
2825 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002826 } else {
James Bottomley 47b5d692005-04-24 02:38:05 -05002827 currTar_Info->TarLUNBusy[0] = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002828
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002829 if (tag) {
2830 if (pCurrCard->discQ_Tbl[tag] != NULL) {
2831 pCurrCard->currentSCCB =
2832 pCurrCard->discQ_Tbl[tag];
2833 currTar_Info->TarTagQ_Cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002835 } else {
2836 ACCEPT_MSG_ATN(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002838 } else {
2839 pCurrCard->currentSCCB =
2840 pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]];
2841 if (pCurrCard->currentSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002843 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002844 ACCEPT_MSG_ATN(port);
2845 }
2846 }
2847 }
2848
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002849 if (pCurrCard->currentSCCB != NULL) {
2850 if (pCurrCard->currentSCCB->Sccb_scsistat == ABORT_ST) {
2851 /* During Abort Tag command, the target could have got re-selected
2852 and completed the command. Check the select Q and remove the CCB
2853 if it is in the Select Q */
James Bottomley 47b5d692005-04-24 02:38:05 -05002854 FPT_queueFindSccb(pCurrCard->currentSCCB, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855 }
2856 }
2857
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002858 while (!(RDW_HARPOON((port + hp_intstat)) & (PHASE | RESET)) &&
2859 !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ) &&
2860 (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002861}
2862
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08002863static void FPT_SendMsg(unsigned long port, unsigned char message)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002864{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002865 while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
2866 if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002868 WRW_HARPOON((port + hp_intstat), PHASE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002869 return;
2870 }
2871 }
2872
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002873 WRW_HARPOON((port + hp_intstat), PHASE);
2874 if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGO_PH) {
2875 WRW_HARPOON((port + hp_intstat),
2876 (BUS_FREE | PHASE | XFER_CNT_0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002877
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002878 WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002879
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002880 WR_HARPOON(port + hp_scsidata_0, message);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002882 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883
2884 ACCEPT_MSG(port);
2885
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002886 WR_HARPOON(port + hp_portctrl_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887
2888 if ((message == SMABORT) || (message == SMDEV_RESET) ||
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002889 (message == SMABORT_TAG)) {
2890 while (!
2891 (RDW_HARPOON((port + hp_intstat)) &
2892 (BUS_FREE | PHASE))) {
2893 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002894
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002895 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
2896 WRW_HARPOON((port + hp_intstat), BUS_FREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002897 }
2898 }
2899 }
2900}
2901
2902/*---------------------------------------------------------------------
2903 *
James Bottomley 47b5d692005-04-24 02:38:05 -05002904 * Function: FPT_sdecm
Linus Torvalds1da177e2005-04-16 15:20:36 -07002905 *
2906 * Description: Determine the proper responce to the message from the
2907 * target device.
2908 *
2909 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002910static void FPT_sdecm(unsigned char message, unsigned long port,
2911 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002912{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002913 struct sccb *currSCCB;
2914 struct sccb_card *CurrCard;
2915 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916
James Bottomley 47b5d692005-04-24 02:38:05 -05002917 CurrCard = &FPT_BL_Card[p_card];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002918 currSCCB = CurrCard->currentSCCB;
2919
James Bottomley 47b5d692005-04-24 02:38:05 -05002920 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002922 if (message == SMREST_DATA_PTR) {
2923 if (!(currSCCB->Sccb_XferState & F_NO_DATA_YET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002924 currSCCB->Sccb_ATC = currSCCB->Sccb_savedATC;
2925
James Bottomley 47b5d692005-04-24 02:38:05 -05002926 FPT_hostDataXferRestart(currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002927 }
2928
2929 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002930 WR_HARPOON(port + hp_autostart_1,
2931 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002932 }
2933
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002934 else if (message == SMCMD_COMP) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002935
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002936 if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
2937 currTar_Info->TarStatus &=
2938 ~(unsigned char)TAR_TAG_Q_MASK;
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08002939 currTar_Info->TarStatus |= (unsigned char)TAG_Q_REJECT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940 }
2941
2942 ACCEPT_MSG(port);
2943
2944 }
2945
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002946 else if ((message == SMNO_OP) || (message >= SMIDENT)
2947 || (message == SMINIT_RECOVERY) || (message == SMREL_RECOVERY)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002948
2949 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002950 WR_HARPOON(port + hp_autostart_1,
2951 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002952 }
2953
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002954 else if (message == SMREJECT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002955
2956 if ((currSCCB->Sccb_scsistat == SELECT_SN_ST) ||
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002957 (currSCCB->Sccb_scsistat == SELECT_WN_ST) ||
2958 ((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)
2959 || ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) ==
2960 TAG_Q_TRYING))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002961 {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002962 WRW_HARPOON((port + hp_intstat), BUS_FREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002963
2964 ACCEPT_MSG(port);
2965
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002966 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2967 (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002968 {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002969 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002971 if (currSCCB->Lun == 0x00) {
2972 if ((currSCCB->Sccb_scsistat == SELECT_SN_ST)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002973
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002974 currTar_Info->TarStatus |=
2975 (unsigned char)SYNC_SUPPORTED;
2976
2977 currTar_Info->TarEEValue &=
2978 ~EE_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002979 }
2980
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002981 else if ((currSCCB->Sccb_scsistat ==
2982 SELECT_WN_ST)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002984 currTar_Info->TarStatus =
2985 (currTar_Info->
2986 TarStatus & ~WIDE_ENABLED) |
2987 WIDE_NEGOCIATED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002988
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002989 currTar_Info->TarEEValue &=
2990 ~EE_WIDE_SCSI;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991
2992 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002994 else if ((currTar_Info->
2995 TarStatus & TAR_TAG_Q_MASK) ==
2996 TAG_Q_TRYING) {
2997 currTar_Info->TarStatus =
2998 (currTar_Info->
2999 TarStatus & ~(unsigned char)
3000 TAR_TAG_Q_MASK) | TAG_Q_REJECT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001
3002 currSCCB->ControlByte &= ~F_USE_CMD_Q;
3003 CurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003004 CurrCard->discQ_Tbl[currSCCB->
3005 Sccb_tag] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006 currSCCB->Sccb_tag = 0x00;
3007
3008 }
3009 }
3010
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003011 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003012
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003013 if (currSCCB->Lun == 0x00) {
3014 WRW_HARPOON((port + hp_intstat),
3015 BUS_FREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003016 CurrCard->globalFlags |= F_NEW_SCCB_CMD;
3017 }
3018 }
3019
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003020 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003021
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003022 if ((CurrCard->globalFlags & F_CONLUN_IO) &&
3023 ((currTar_Info->
3024 TarStatus & TAR_TAG_Q_MASK) !=
3025 TAG_Q_TRYING))
3026 currTar_Info->TarLUNBusy[currSCCB->
3027 Lun] = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028 else
James Bottomley 47b5d692005-04-24 02:38:05 -05003029 currTar_Info->TarLUNBusy[0] = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003031 currSCCB->ControlByte &=
3032 ~(unsigned char)F_USE_CMD_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003034 WR_HARPOON(port + hp_autostart_1,
3035 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003036
3037 }
3038 }
3039
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003040 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041 ACCEPT_MSG(port);
3042
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003043 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
3044 (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003045 {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003046 }
3047
3048 if (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)) {
3049 WR_HARPOON(port + hp_autostart_1,
3050 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003051 }
3052 }
3053 }
3054
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003055 else if (message == SMEXT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003056
3057 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003058 FPT_shandem(port, p_card, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059 }
3060
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003061 else if (message == SMIGNORWR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003062
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003063 ACCEPT_MSG(port); /* ACK the RESIDUE MSG */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003064
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003065 message = FPT_sfm(port, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003067 if (currSCCB->Sccb_scsimsg != SMPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003068 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003069 WR_HARPOON(port + hp_autostart_1,
3070 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071 }
3072
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003073 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003074
3075 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
3076 currSCCB->Sccb_scsimsg = SMREJECT;
3077
3078 ACCEPT_MSG_ATN(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003079 WR_HARPOON(port + hp_autostart_1,
3080 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081 }
3082}
3083
Linus Torvalds1da177e2005-04-16 15:20:36 -07003084/*---------------------------------------------------------------------
3085 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003086 * Function: FPT_shandem
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087 *
3088 * Description: Decide what to do with the extended message.
3089 *
3090 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003091static void FPT_shandem(unsigned long port, unsigned char p_card,
3092 struct sccb *pCurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003093{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003094 unsigned char length, message;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003096 length = FPT_sfm(port, pCurrSCCB);
3097 if (length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003098
3099 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003100 message = FPT_sfm(port, pCurrSCCB);
3101 if (message) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003103 if (message == SMSYNC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003105 if (length == 0x03) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003106
3107 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003108 FPT_stsyncn(port, p_card);
3109 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110
3111 pCurrSCCB->Sccb_scsimsg = SMREJECT;
3112 ACCEPT_MSG_ATN(port);
3113 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003114 } else if (message == SMWDTR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003115
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003116 if (length == 0x02) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003117
3118 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003119 FPT_stwidn(port, p_card);
3120 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003121
3122 pCurrSCCB->Sccb_scsimsg = SMREJECT;
3123 ACCEPT_MSG_ATN(port);
3124
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003125 WR_HARPOON(port + hp_autostart_1,
3126 (AUTO_IMMED +
3127 DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003129 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003130
3131 pCurrSCCB->Sccb_scsimsg = SMREJECT;
3132 ACCEPT_MSG_ATN(port);
3133
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003134 WR_HARPOON(port + hp_autostart_1,
3135 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003137 } else {
3138 if (pCurrSCCB->Sccb_scsimsg != SMPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003140 WR_HARPOON(port + hp_autostart_1,
3141 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003142 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003143 } else {
3144 if (pCurrSCCB->Sccb_scsimsg == SMPARITY)
3145 WR_HARPOON(port + hp_autostart_1,
3146 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003147 }
3148}
3149
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150/*---------------------------------------------------------------------
3151 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003152 * Function: FPT_sisyncn
Linus Torvalds1da177e2005-04-16 15:20:36 -07003153 *
3154 * Description: Read in a message byte from the SCSI bus, and check
3155 * for a parity error.
3156 *
3157 *---------------------------------------------------------------------*/
3158
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003159static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card,
3160 unsigned char syncFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003161{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003162 struct sccb *currSCCB;
3163 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003165 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3166 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003168 if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003169
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003170 WRW_HARPOON((port + ID_MSG_STRT),
3171 (MPM_OP + AMSG_OUT +
3172 (currSCCB->
3173 Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003175 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003177 WRW_HARPOON((port + SYNC_MSGS + 0),
3178 (MPM_OP + AMSG_OUT + SMEXT));
3179 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
3180 WRW_HARPOON((port + SYNC_MSGS + 4),
3181 (MPM_OP + AMSG_OUT + SMSYNC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003182
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003183 if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003184
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003185 WRW_HARPOON((port + SYNC_MSGS + 6),
3186 (MPM_OP + AMSG_OUT + 12));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003188 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
3189 EE_SYNC_10MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003190
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003191 WRW_HARPOON((port + SYNC_MSGS + 6),
3192 (MPM_OP + AMSG_OUT + 25));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003193
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003194 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
3195 EE_SYNC_5MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003196
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003197 WRW_HARPOON((port + SYNC_MSGS + 6),
3198 (MPM_OP + AMSG_OUT + 50));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003199
Linus Torvalds1da177e2005-04-16 15:20:36 -07003200 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003201 WRW_HARPOON((port + SYNC_MSGS + 6),
3202 (MPM_OP + AMSG_OUT + 00));
3203
3204 WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
3205 WRW_HARPOON((port + SYNC_MSGS + 10),
3206 (MPM_OP + AMSG_OUT + DEFAULT_OFFSET));
3207 WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
3208
3209 if (syncFlag == 0) {
3210 WR_HARPOON(port + hp_autostart_3,
3211 (SELECT + SELCHK_STRT));
3212 currTar_Info->TarStatus =
3213 ((currTar_Info->
3214 TarStatus & ~(unsigned char)TAR_SYNC_MASK) |
3215 (unsigned char)SYNC_TRYING);
3216 } else {
3217 WR_HARPOON(port + hp_autostart_3,
3218 (AUTO_IMMED + CMD_ONLY_STRT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003219 }
3220
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08003221 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003222 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003223
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003224 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003225
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003226 currTar_Info->TarStatus |= (unsigned char)SYNC_SUPPORTED;
3227 currTar_Info->TarEEValue &= ~EE_SYNC_MASK;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08003228 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003229 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003230}
3231
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232/*---------------------------------------------------------------------
3233 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003234 * Function: FPT_stsyncn
Linus Torvalds1da177e2005-04-16 15:20:36 -07003235 *
3236 * Description: The has sent us a Sync Nego message so handle it as
3237 * necessary.
3238 *
3239 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08003240static void FPT_stsyncn(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003241{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003242 unsigned char sync_msg, offset, sync_reg, our_sync_msg;
3243 struct sccb *currSCCB;
3244 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003245
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003246 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3247 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003248
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003249 sync_msg = FPT_sfm(port, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003250
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003251 if ((sync_msg == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3252 WR_HARPOON(port + hp_autostart_1,
3253 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003254 return;
3255 }
3256
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003257 ACCEPT_MSG(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003258
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003259 offset = FPT_sfm(port, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003261 if ((offset == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3262 WR_HARPOON(port + hp_autostart_1,
3263 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003264 return;
3265 }
3266
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003267 if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003268
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003269 our_sync_msg = 12; /* Setup our Message to 20mb/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003270
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003271 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_10MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003272
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003273 our_sync_msg = 25; /* Setup our Message to 10mb/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003274
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003275 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_5MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003276
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003277 our_sync_msg = 50; /* Setup our Message to 5mb/s */
3278 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003279
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003280 our_sync_msg = 0; /* Message = Async */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003281
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003282 if (sync_msg < our_sync_msg) {
3283 sync_msg = our_sync_msg; /*if faster, then set to max. */
3284 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003285
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003286 if (offset == ASYNC)
3287 sync_msg = ASYNC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003288
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003289 if (offset > MAX_OFFSET)
3290 offset = MAX_OFFSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003291
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003292 sync_reg = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003293
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003294 if (sync_msg > 12)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003295
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003296 sync_reg = 0x20; /* Use 10MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003297
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003298 if (sync_msg > 25)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003300 sync_reg = 0x40; /* Use 6.6MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003301
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003302 if (sync_msg > 38)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003303
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003304 sync_reg = 0x60; /* Use 5MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003305
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003306 if (sync_msg > 50)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003307
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003308 sync_reg = 0x80; /* Use 4MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003309
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003310 if (sync_msg > 62)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003311
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003312 sync_reg = 0xA0; /* Use 3.33MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003313
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003314 if (sync_msg > 75)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003315
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003316 sync_reg = 0xC0; /* Use 2.85MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003317
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003318 if (sync_msg > 87)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003319
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003320 sync_reg = 0xE0; /* Use 2.5MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003321
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003322 if (sync_msg > 100) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003323
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003324 sync_reg = 0x00; /* Use ASYNC */
3325 offset = 0x00;
3326 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003327
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003328 if (currTar_Info->TarStatus & WIDE_ENABLED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003329
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003330 sync_reg |= offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003331
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003332 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003333
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003334 sync_reg |= (offset | NARROW_SCSI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003335
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003336 FPT_sssyncv(port, currSCCB->TargID, sync_reg, currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003337
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003338 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003339
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003340 ACCEPT_MSG(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003341
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003342 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3343 ~(unsigned char)TAR_SYNC_MASK) |
3344 (unsigned char)SYNC_SUPPORTED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003345
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003346 WR_HARPOON(port + hp_autostart_1,
3347 (AUTO_IMMED + DISCONNECT_START));
3348 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003349
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003350 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003351
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003352 ACCEPT_MSG_ATN(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003354 FPT_sisyncr(port, sync_msg, offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003355
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003356 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3357 ~(unsigned char)TAR_SYNC_MASK) |
3358 (unsigned char)SYNC_SUPPORTED);
3359 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003360}
3361
Linus Torvalds1da177e2005-04-16 15:20:36 -07003362/*---------------------------------------------------------------------
3363 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003364 * Function: FPT_sisyncr
Linus Torvalds1da177e2005-04-16 15:20:36 -07003365 *
3366 * Description: Answer the targets sync message.
3367 *
3368 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003369static void FPT_sisyncr(unsigned long port, unsigned char sync_pulse,
3370 unsigned char offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003371{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003372 ARAM_ACCESS(port);
3373 WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT));
3374 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
3375 WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMSYNC));
3376 WRW_HARPOON((port + SYNC_MSGS + 6), (MPM_OP + AMSG_OUT + sync_pulse));
3377 WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
3378 WRW_HARPOON((port + SYNC_MSGS + 10), (MPM_OP + AMSG_OUT + offset));
3379 WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
3380 SGRAM_ACCESS(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003382 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3383 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003384
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003385 WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003386
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003387 while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
3388 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003389}
3390
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391/*---------------------------------------------------------------------
3392 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003393 * Function: FPT_siwidn
Linus Torvalds1da177e2005-04-16 15:20:36 -07003394 *
3395 * Description: Read in a message byte from the SCSI bus, and check
3396 * for a parity error.
3397 *
3398 *---------------------------------------------------------------------*/
3399
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08003400static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003402 struct sccb *currSCCB;
3403 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003404
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003405 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3406 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003407
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003408 if (!((currTar_Info->TarStatus & TAR_WIDE_MASK) == WIDE_NEGOCIATED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003409
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003410 WRW_HARPOON((port + ID_MSG_STRT),
3411 (MPM_OP + AMSG_OUT +
3412 (currSCCB->
3413 Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003414
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003415 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003416
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003417 WRW_HARPOON((port + SYNC_MSGS + 0),
3418 (MPM_OP + AMSG_OUT + SMEXT));
3419 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
3420 WRW_HARPOON((port + SYNC_MSGS + 4),
3421 (MPM_OP + AMSG_OUT + SMWDTR));
3422 WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
3423 WRW_HARPOON((port + SYNC_MSGS + 8),
3424 (MPM_OP + AMSG_OUT + SM16BIT));
3425 WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003426
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003427 WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003428
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003429 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3430 ~(unsigned char)TAR_WIDE_MASK) |
3431 (unsigned char)WIDE_ENABLED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003432
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08003433 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003434 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003435
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003436 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003437
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003438 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3439 ~(unsigned char)TAR_WIDE_MASK) |
3440 WIDE_NEGOCIATED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003441
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003442 currTar_Info->TarEEValue &= ~EE_WIDE_SCSI;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08003443 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003444 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003445}
3446
Linus Torvalds1da177e2005-04-16 15:20:36 -07003447/*---------------------------------------------------------------------
3448 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003449 * Function: FPT_stwidn
Linus Torvalds1da177e2005-04-16 15:20:36 -07003450 *
3451 * Description: The has sent us a Wide Nego message so handle it as
3452 * necessary.
3453 *
3454 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08003455static void FPT_stwidn(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003456{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003457 unsigned char width;
3458 struct sccb *currSCCB;
3459 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003461 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3462 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003463
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003464 width = FPT_sfm(port, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003465
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003466 if ((width == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3467 WR_HARPOON(port + hp_autostart_1,
3468 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469 return;
3470 }
3471
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003472 if (!(currTar_Info->TarEEValue & EE_WIDE_SCSI))
3473 width = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003474
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003475 if (width) {
3476 currTar_Info->TarStatus |= WIDE_ENABLED;
3477 width = 0;
3478 } else {
3479 width = NARROW_SCSI;
3480 currTar_Info->TarStatus &= ~WIDE_ENABLED;
3481 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003482
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003483 FPT_sssyncv(port, currSCCB->TargID, width, currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003484
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003485 if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003486
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003487 currTar_Info->TarStatus |= WIDE_NEGOCIATED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003488
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003489 if (!
3490 ((currTar_Info->TarStatus & TAR_SYNC_MASK) ==
3491 SYNC_SUPPORTED)) {
3492 ACCEPT_MSG_ATN(port);
3493 ARAM_ACCESS(port);
3494 FPT_sisyncn(port, p_card, 1);
3495 currSCCB->Sccb_scsistat = SELECT_SN_ST;
3496 SGRAM_ACCESS(port);
3497 } else {
3498 ACCEPT_MSG(port);
3499 WR_HARPOON(port + hp_autostart_1,
3500 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003501 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003502 }
3503
3504 else {
3505
3506 ACCEPT_MSG_ATN(port);
3507
3508 if (currTar_Info->TarEEValue & EE_WIDE_SCSI)
3509 width = SM16BIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003510 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003511 width = SM8BIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003512
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003513 FPT_siwidr(port, width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003514
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003515 currTar_Info->TarStatus |= (WIDE_NEGOCIATED | WIDE_ENABLED);
3516 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003517}
3518
Linus Torvalds1da177e2005-04-16 15:20:36 -07003519/*---------------------------------------------------------------------
3520 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003521 * Function: FPT_siwidr
Linus Torvalds1da177e2005-04-16 15:20:36 -07003522 *
3523 * Description: Answer the targets Wide nego message.
3524 *
3525 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08003526static void FPT_siwidr(unsigned long port, unsigned char width)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003527{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003528 ARAM_ACCESS(port);
3529 WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT));
3530 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
3531 WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMWDTR));
3532 WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
3533 WRW_HARPOON((port + SYNC_MSGS + 8), (MPM_OP + AMSG_OUT + width));
3534 WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
3535 SGRAM_ACCESS(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003536
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003537 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3538 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003540 WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003541
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003542 while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
3543 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003544}
3545
Linus Torvalds1da177e2005-04-16 15:20:36 -07003546/*---------------------------------------------------------------------
3547 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003548 * Function: FPT_sssyncv
Linus Torvalds1da177e2005-04-16 15:20:36 -07003549 *
3550 * Description: Write the desired value to the Sync Register for the
3551 * ID specified.
3552 *
3553 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003554static void FPT_sssyncv(unsigned long p_port, unsigned char p_id,
3555 unsigned char p_sync_value,
3556 struct sccb_mgr_tar_info *currTar_Info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003557{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003558 unsigned char index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003559
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003560 index = p_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003561
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003562 switch (index) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003563
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003564 case 0:
3565 index = 12; /* hp_synctarg_0 */
3566 break;
3567 case 1:
3568 index = 13; /* hp_synctarg_1 */
3569 break;
3570 case 2:
3571 index = 14; /* hp_synctarg_2 */
3572 break;
3573 case 3:
3574 index = 15; /* hp_synctarg_3 */
3575 break;
3576 case 4:
3577 index = 8; /* hp_synctarg_4 */
3578 break;
3579 case 5:
3580 index = 9; /* hp_synctarg_5 */
3581 break;
3582 case 6:
3583 index = 10; /* hp_synctarg_6 */
3584 break;
3585 case 7:
3586 index = 11; /* hp_synctarg_7 */
3587 break;
3588 case 8:
3589 index = 4; /* hp_synctarg_8 */
3590 break;
3591 case 9:
3592 index = 5; /* hp_synctarg_9 */
3593 break;
3594 case 10:
3595 index = 6; /* hp_synctarg_10 */
3596 break;
3597 case 11:
3598 index = 7; /* hp_synctarg_11 */
3599 break;
3600 case 12:
3601 index = 0; /* hp_synctarg_12 */
3602 break;
3603 case 13:
3604 index = 1; /* hp_synctarg_13 */
3605 break;
3606 case 14:
3607 index = 2; /* hp_synctarg_14 */
3608 break;
3609 case 15:
3610 index = 3; /* hp_synctarg_15 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003611
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003612 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003613
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003614 WR_HARPOON(p_port + hp_synctarg_base + index, p_sync_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003615
3616 currTar_Info->TarSyncCtrl = p_sync_value;
3617}
3618
Linus Torvalds1da177e2005-04-16 15:20:36 -07003619/*---------------------------------------------------------------------
3620 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003621 * Function: FPT_sresb
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622 *
3623 * Description: Reset the desired card's SCSI bus.
3624 *
3625 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08003626static void FPT_sresb(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003627{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003628 unsigned char scsiID, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003629
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003630 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003632 WR_HARPOON(port + hp_page_ctrl,
3633 (RD_HARPOON(port + hp_page_ctrl) | G_INT_DISABLE));
3634 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003636 WR_HARPOON(port + hp_scsictrl_0, SCSI_RST);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003637
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003638 scsiID = RD_HARPOON(port + hp_seltimeout);
3639 WR_HARPOON(port + hp_seltimeout, TO_5ms);
3640 WRW_HARPOON((port + hp_intstat), TIMEOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003641
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003642 WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT | START_TO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003643
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003644 while (!(RDW_HARPOON((port + hp_intstat)) & TIMEOUT)) {
3645 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003646
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003647 WR_HARPOON(port + hp_seltimeout, scsiID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003648
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003649 WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003650
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003651 FPT_Wait(port, TO_5ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003652
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003653 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003654
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003655 WR_HARPOON(port + hp_int_mask, (RD_HARPOON(port + hp_int_mask) | 0x00));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003656
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003657 for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
3658 currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003659
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003660 if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
3661 currTar_Info->TarSyncCtrl = 0;
3662 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
3663 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003664
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003665 if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
3666 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
3667 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003668
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003669 FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003670
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003671 FPT_SccbMgrTableInitTarget(p_card, scsiID);
3672 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003673
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003674 FPT_BL_Card[p_card].scanIndex = 0x00;
3675 FPT_BL_Card[p_card].currentSCCB = NULL;
3676 FPT_BL_Card[p_card].globalFlags &= ~(F_TAG_STARTED | F_HOST_XFER_ACT
3677 | F_NEW_SCCB_CMD);
3678 FPT_BL_Card[p_card].cmdCounter = 0x00;
James Bottomley 47b5d692005-04-24 02:38:05 -05003679 FPT_BL_Card[p_card].discQCount = 0x00;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003680 FPT_BL_Card[p_card].tagQ_Lst = 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003681
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003682 for (i = 0; i < QUEUE_DEPTH; i++)
James Bottomley 47b5d692005-04-24 02:38:05 -05003683 FPT_BL_Card[p_card].discQ_Tbl[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003684
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003685 WR_HARPOON(port + hp_page_ctrl,
3686 (RD_HARPOON(port + hp_page_ctrl) & ~G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003687
3688}
3689
3690/*---------------------------------------------------------------------
3691 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003692 * Function: FPT_ssenss
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693 *
3694 * Description: Setup for the Auto Sense command.
3695 *
3696 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003697static void FPT_ssenss(struct sccb_card *pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003698{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003699 unsigned char i;
3700 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003701
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003702 currSCCB = pCurrCard->currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003703
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003704 currSCCB->Save_CdbLen = currSCCB->CdbLength;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003705
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003706 for (i = 0; i < 6; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003708 currSCCB->Save_Cdb[i] = currSCCB->Cdb[i];
3709 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003710
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003711 currSCCB->CdbLength = SIX_BYTE_CMD;
3712 currSCCB->Cdb[0] = SCSI_REQUEST_SENSE;
3713 currSCCB->Cdb[1] = currSCCB->Cdb[1] & (unsigned char)0xE0; /*Keep LUN. */
3714 currSCCB->Cdb[2] = 0x00;
3715 currSCCB->Cdb[3] = 0x00;
3716 currSCCB->Cdb[4] = currSCCB->RequestSenseLength;
3717 currSCCB->Cdb[5] = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003718
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003719 currSCCB->Sccb_XferCnt = (unsigned long)currSCCB->RequestSenseLength;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003720
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003721 currSCCB->Sccb_ATC = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003722
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003723 currSCCB->Sccb_XferState |= F_AUTO_SENSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003724
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003725 currSCCB->Sccb_XferState &= ~F_SG_XFER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003726
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003727 currSCCB->Sccb_idmsg = currSCCB->Sccb_idmsg & ~(unsigned char)DISC_PRIV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003728
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003729 currSCCB->ControlByte = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003730
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003731 currSCCB->Sccb_MGRFlags &= F_STATUSLOADED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003732}
3733
Linus Torvalds1da177e2005-04-16 15:20:36 -07003734/*---------------------------------------------------------------------
3735 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003736 * Function: FPT_sxfrp
Linus Torvalds1da177e2005-04-16 15:20:36 -07003737 *
3738 * Description: Transfer data into the bit bucket until the device
3739 * decides to switch phase.
3740 *
3741 *---------------------------------------------------------------------*/
3742
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08003743static void FPT_sxfrp(unsigned long p_port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003744{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003745 unsigned char curr_phz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003746
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003747 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003748
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003749 if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003750
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003751 FPT_hostDataXferAbort(p_port, p_card,
3752 FPT_BL_Card[p_card].currentSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003753
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003754 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003755
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003756 /* If the Automation handled the end of the transfer then do not
3757 match the phase or we will get out of sync with the ISR. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003758
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003759 if (RDW_HARPOON((p_port + hp_intstat)) &
3760 (BUS_FREE | XFER_CNT_0 | AUTO_INT))
3761 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003762
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003763 WR_HARPOON(p_port + hp_xfercnt_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003764
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003765 curr_phz = RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003766
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003767 WRW_HARPOON((p_port + hp_intstat), XFER_CNT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003768
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003769 WR_HARPOON(p_port + hp_scsisig, curr_phz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003770
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003771 while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET)) &&
3772 (curr_phz ==
3773 (RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ)))
3774 {
3775 if (curr_phz & (unsigned char)SCSI_IOBIT) {
3776 WR_HARPOON(p_port + hp_portctrl_0,
3777 (SCSI_PORT | HOST_PORT | SCSI_INBIT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003778
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003779 if (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
3780 RD_HARPOON(p_port + hp_fifodata_0);
3781 }
3782 } else {
3783 WR_HARPOON(p_port + hp_portctrl_0,
3784 (SCSI_PORT | HOST_PORT | HOST_WRT));
3785 if (RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY) {
3786 WR_HARPOON(p_port + hp_fifodata_0, 0xFA);
3787 }
3788 }
3789 } /* End of While loop for padding data I/O phase */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003790
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003791 while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
3792 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ)
3793 break;
3794 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003795
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003796 WR_HARPOON(p_port + hp_portctrl_0,
3797 (SCSI_PORT | HOST_PORT | SCSI_INBIT));
3798 while (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
3799 RD_HARPOON(p_port + hp_fifodata_0);
3800 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003802 if (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
3803 WR_HARPOON(p_port + hp_autostart_0,
3804 (AUTO_IMMED + DISCONNECT_START));
3805 while (!(RDW_HARPOON((p_port + hp_intstat)) & AUTO_INT)) {
3806 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003807
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003808 if (RDW_HARPOON((p_port + hp_intstat)) &
3809 (ICMD_COMP | ITAR_DISC))
3810 while (!
3811 (RDW_HARPOON((p_port + hp_intstat)) &
3812 (BUS_FREE | RSEL))) ;
3813 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814}
3815
Linus Torvalds1da177e2005-04-16 15:20:36 -07003816/*---------------------------------------------------------------------
3817 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003818 * Function: FPT_schkdd
Linus Torvalds1da177e2005-04-16 15:20:36 -07003819 *
3820 * Description: Make sure data has been flushed from both FIFOs and abort
3821 * the operations if necessary.
3822 *
3823 *---------------------------------------------------------------------*/
3824
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08003825static void FPT_schkdd(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003826{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003827 unsigned short TimeOutLoop;
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08003828 unsigned char sPhase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003829
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003830 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003831
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003832 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003833
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003834 if ((currSCCB->Sccb_scsistat != DATA_OUT_ST) &&
3835 (currSCCB->Sccb_scsistat != DATA_IN_ST)) {
3836 return;
3837 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003839 if (currSCCB->Sccb_XferState & F_ODD_BALL_CNT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003840
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003841 currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003842
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003843 currSCCB->Sccb_XferCnt = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003844
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003845 currSCCB->Sccb_XferState &= ~F_ODD_BALL_CNT;
3846 WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
3847 WR_HARPOON(port + hp_xferstat, 0x00);
3848 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003849
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003850 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003851
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003852 currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003853
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003854 currSCCB->Sccb_XferCnt = 0;
3855 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003857 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
3858 (currSCCB->HostStatus == SCCB_COMPLETE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003859
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003860 currSCCB->HostStatus = SCCB_PARITY_ERR;
3861 WRW_HARPOON((port + hp_intstat), PARITY);
3862 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003863
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003864 FPT_hostDataXferAbort(port, p_card, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003866 while (RD_HARPOON(port + hp_scsisig) & SCSI_ACK) {
3867 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003868
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003869 TimeOutLoop = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003870
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003871 while (RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY) {
3872 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
3873 return;
3874 }
3875 if (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) {
3876 break;
3877 }
3878 if (RDW_HARPOON((port + hp_intstat)) & RESET) {
3879 return;
3880 }
3881 if ((RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
3882 || (TimeOutLoop++ > 0x3000))
3883 break;
3884 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003885
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003886 sPhase = RD_HARPOON(port + hp_scsisig) & (SCSI_BSY | S_SCSI_PHZ);
3887 if ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) ||
3888 (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) ||
3889 (sPhase == (SCSI_BSY | S_DATAO_PH)) ||
3890 (sPhase == (SCSI_BSY | S_DATAI_PH))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003891
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003892 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003893
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003894 if (!(currSCCB->Sccb_XferState & F_ALL_XFERRED)) {
3895 if (currSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
3896 FPT_phaseDataIn(port, p_card);
3897 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003898
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003899 else {
3900 FPT_phaseDataOut(port, p_card);
3901 }
3902 } else {
3903 FPT_sxfrp(port, p_card);
3904 if (!(RDW_HARPOON((port + hp_intstat)) &
3905 (BUS_FREE | ICMD_COMP | ITAR_DISC | RESET))) {
3906 WRW_HARPOON((port + hp_intstat), AUTO_INT);
3907 FPT_phaseDecode(port, p_card);
3908 }
3909 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003910
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003911 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003912
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003913 else {
3914 WR_HARPOON(port + hp_portctrl_0, 0x00);
3915 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916}
3917
Linus Torvalds1da177e2005-04-16 15:20:36 -07003918/*---------------------------------------------------------------------
3919 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003920 * Function: FPT_sinits
Linus Torvalds1da177e2005-04-16 15:20:36 -07003921 *
3922 * Description: Setup SCCB manager fields in this SCCB.
3923 *
3924 *---------------------------------------------------------------------*/
3925
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003926static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003928 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003930 if ((p_sccb->TargID > MAX_SCSI_TAR) || (p_sccb->Lun > MAX_LUN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003931 return;
3932 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003933 currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003935 p_sccb->Sccb_XferState = 0x00;
3936 p_sccb->Sccb_XferCnt = p_sccb->DataLength;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003937
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003938 if ((p_sccb->OperationCode == SCATTER_GATHER_COMMAND) ||
3939 (p_sccb->OperationCode == RESIDUAL_SG_COMMAND)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003941 p_sccb->Sccb_SGoffset = 0;
3942 p_sccb->Sccb_XferState = F_SG_XFER;
3943 p_sccb->Sccb_XferCnt = 0x00;
3944 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003945
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003946 if (p_sccb->DataLength == 0x00)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003947
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003948 p_sccb->Sccb_XferState |= F_ALL_XFERRED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003949
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003950 if (p_sccb->ControlByte & F_USE_CMD_Q) {
3951 if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
3952 p_sccb->ControlByte &= ~F_USE_CMD_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003953
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003954 else
3955 currTar_Info->TarStatus |= TAG_Q_TRYING;
3956 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003957
3958/* For !single SCSI device in system & device allow Disconnect
3959 or command is tag_q type then send Cmd with Disconnect Enable
3960 else send Cmd with Disconnect Disable */
3961
3962/*
James Bottomley 47b5d692005-04-24 02:38:05 -05003963 if (((!(FPT_BL_Card[p_card].globalFlags & F_SINGLE_DEVICE)) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07003964 (currTar_Info->TarStatus & TAR_ALLOW_DISC)) ||
3965 (currTar_Info->TarStatus & TAG_Q_TRYING)) {
3966*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003967 if ((currTar_Info->TarStatus & TAR_ALLOW_DISC) ||
3968 (currTar_Info->TarStatus & TAG_Q_TRYING)) {
3969 p_sccb->Sccb_idmsg =
3970 (unsigned char)(SMIDENT | DISC_PRIV) | p_sccb->Lun;
3971 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003973 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003975 p_sccb->Sccb_idmsg = (unsigned char)SMIDENT | p_sccb->Lun;
3976 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003977
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003978 p_sccb->HostStatus = 0x00;
3979 p_sccb->TargetStatus = 0x00;
3980 p_sccb->Sccb_tag = 0x00;
3981 p_sccb->Sccb_MGRFlags = 0x00;
3982 p_sccb->Sccb_sgseg = 0x00;
3983 p_sccb->Sccb_ATC = 0x00;
3984 p_sccb->Sccb_savedATC = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003985/*
3986 p_sccb->SccbVirtDataPtr = 0x00;
3987 p_sccb->Sccb_forwardlink = NULL;
3988 p_sccb->Sccb_backlink = NULL;
3989 */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003990 p_sccb->Sccb_scsistat = BUS_FREE_ST;
3991 p_sccb->SccbStatus = SCCB_IN_PROCESS;
3992 p_sccb->Sccb_scsimsg = SMNO_OP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003993
3994}
3995
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996/*---------------------------------------------------------------------
3997 *
3998 * Function: Phase Decode
3999 *
4000 * Description: Determine the phase and call the appropriate function.
4001 *
4002 *---------------------------------------------------------------------*/
4003
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004004static void FPT_phaseDecode(unsigned long p_port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004005{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004006 unsigned char phase_ref;
4007 void (*phase) (unsigned long, unsigned char);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004008
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004009 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004010
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004011 phase_ref =
4012 (unsigned char)(RD_HARPOON(p_port + hp_scsisig) & S_SCSI_PHZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004014 phase = FPT_s_PhaseTbl[phase_ref];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004015
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004016 (*phase) (p_port, p_card); /* Call the correct phase func */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004017}
4018
Linus Torvalds1da177e2005-04-16 15:20:36 -07004019/*---------------------------------------------------------------------
4020 *
4021 * Function: Data Out Phase
4022 *
4023 * Description: Start up both the BusMaster and Xbow.
4024 *
4025 *---------------------------------------------------------------------*/
4026
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004027static void FPT_phaseDataOut(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028{
4029
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004030 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004032 currSCCB = FPT_BL_Card[p_card].currentSCCB;
4033 if (currSCCB == NULL) {
4034 return; /* Exit if No SCCB record */
4035 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004036
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004037 currSCCB->Sccb_scsistat = DATA_OUT_ST;
4038 currSCCB->Sccb_XferState &= ~(F_HOST_XFER_DIR | F_NO_DATA_YET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004039
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004040 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004042 WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004043
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004044 WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004045
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004046 FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004047
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004048 if (currSCCB->Sccb_XferCnt == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004049
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004050 if ((currSCCB->ControlByte & SCCB_DATA_XFER_OUT) &&
4051 (currSCCB->HostStatus == SCCB_COMPLETE))
4052 currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004053
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004054 FPT_sxfrp(port, p_card);
4055 if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
4056 FPT_phaseDecode(port, p_card);
4057 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004058}
4059
Linus Torvalds1da177e2005-04-16 15:20:36 -07004060/*---------------------------------------------------------------------
4061 *
4062 * Function: Data In Phase
4063 *
4064 * Description: Startup the BusMaster and the XBOW.
4065 *
4066 *---------------------------------------------------------------------*/
4067
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004068static void FPT_phaseDataIn(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069{
4070
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004071 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004072
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004073 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004074
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004075 if (currSCCB == NULL) {
4076 return; /* Exit if No SCCB record */
4077 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004079 currSCCB->Sccb_scsistat = DATA_IN_ST;
4080 currSCCB->Sccb_XferState |= F_HOST_XFER_DIR;
4081 currSCCB->Sccb_XferState &= ~F_NO_DATA_YET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004082
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004083 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004084
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004085 WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004086
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004087 WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004088
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004089 FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004090
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004091 if (currSCCB->Sccb_XferCnt == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004092
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004093 if ((currSCCB->ControlByte & SCCB_DATA_XFER_IN) &&
4094 (currSCCB->HostStatus == SCCB_COMPLETE))
4095 currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004096
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004097 FPT_sxfrp(port, p_card);
4098 if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
4099 FPT_phaseDecode(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004100
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004101 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004102}
4103
4104/*---------------------------------------------------------------------
4105 *
4106 * Function: Command Phase
4107 *
4108 * Description: Load the CDB into the automation and start it up.
4109 *
4110 *---------------------------------------------------------------------*/
4111
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004112static void FPT_phaseCommand(unsigned long p_port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004114 struct sccb *currSCCB;
4115 unsigned long cdb_reg;
4116 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004117
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004118 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004119
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004120 if (currSCCB->OperationCode == RESET_COMMAND) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004121
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004122 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4123 currSCCB->CdbLength = SIX_BYTE_CMD;
4124 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004125
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004126 WR_HARPOON(p_port + hp_scsisig, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004127
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004128 ARAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004129
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004130 cdb_reg = p_port + CMD_STRT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004131
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004132 for (i = 0; i < currSCCB->CdbLength; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004133
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004134 if (currSCCB->OperationCode == RESET_COMMAND)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004135
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004136 WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + 0x00));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004138 else
4139 WRW_HARPOON(cdb_reg,
4140 (MPM_OP + ACOMMAND + currSCCB->Cdb[i]));
4141 cdb_reg += 2;
4142 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004144 if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
4145 WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004147 WR_HARPOON(p_port + hp_portctrl_0, (SCSI_PORT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004148
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004149 currSCCB->Sccb_scsistat = COMMAND_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004150
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004151 WR_HARPOON(p_port + hp_autostart_3, (AUTO_IMMED | CMD_ONLY_STRT));
4152 SGRAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004153}
4154
Linus Torvalds1da177e2005-04-16 15:20:36 -07004155/*---------------------------------------------------------------------
4156 *
4157 * Function: Status phase
4158 *
4159 * Description: Bring in the status and command complete message bytes
4160 *
4161 *---------------------------------------------------------------------*/
4162
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004163static void FPT_phaseStatus(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004164{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004165 /* Start-up the automation to finish off this command and let the
4166 isr handle the interrupt for command complete when it comes in.
4167 We could wait here for the interrupt to be generated?
4168 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004169
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004170 WR_HARPOON(port + hp_scsisig, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004171
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004172 WR_HARPOON(port + hp_autostart_0, (AUTO_IMMED + END_DATA_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173}
4174
Linus Torvalds1da177e2005-04-16 15:20:36 -07004175/*---------------------------------------------------------------------
4176 *
4177 * Function: Phase Message Out
4178 *
4179 * Description: Send out our message (if we have one) and handle whatever
4180 * else is involed.
4181 *
4182 *---------------------------------------------------------------------*/
4183
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004184static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004185{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004186 unsigned char message, scsiID;
4187 struct sccb *currSCCB;
4188 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004189
James Bottomley 47b5d692005-04-24 02:38:05 -05004190 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004191
4192 if (currSCCB != NULL) {
4193
4194 message = currSCCB->Sccb_scsimsg;
4195 scsiID = currSCCB->TargID;
4196
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004197 if (message == SMDEV_RESET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004198
James Bottomley 47b5d692005-04-24 02:38:05 -05004199 currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004200 currTar_Info->TarSyncCtrl = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004201 FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004202
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004203 if (FPT_sccbMgrTbl[p_card][scsiID].
4204 TarEEValue & EE_SYNC_MASK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004205
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004206 FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
4207 ~TAR_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004208
4209 }
4210
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004211 if (FPT_sccbMgrTbl[p_card][scsiID].
4212 TarEEValue & EE_WIDE_SCSI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004213
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004214 FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
4215 ~TAR_WIDE_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004216 }
4217
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004218 FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
4219 FPT_SccbMgrTableInitTarget(p_card, scsiID);
4220 } else if (currSCCB->Sccb_scsistat == ABORT_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004221 currSCCB->HostStatus = SCCB_COMPLETE;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004222 if (FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] !=
4223 NULL) {
4224 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4225 Sccb_tag] = NULL;
James Bottomley 47b5d692005-04-24 02:38:05 -05004226 FPT_sccbMgrTbl[p_card][scsiID].TarTagQ_Cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004227 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004228
Linus Torvalds1da177e2005-04-16 15:20:36 -07004229 }
4230
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004231 else if (currSCCB->Sccb_scsistat < COMMAND_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004232
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004233 if (message == SMNO_OP) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004234 currSCCB->Sccb_MGRFlags |= F_DEV_SELECTED;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004235
4236 FPT_ssel(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004237 return;
4238 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004239 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004240
4241 if (message == SMABORT)
4242
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004243 FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004244 }
4245
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004246 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004247 message = SMABORT;
4248 }
4249
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004250 WRW_HARPOON((port + hp_intstat), (BUS_FREE | PHASE | XFER_CNT_0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004251
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004252 WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004253
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004254 WR_HARPOON(port + hp_scsidata_0, message);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004255
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004256 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004257
4258 ACCEPT_MSG(port);
4259
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004260 WR_HARPOON(port + hp_portctrl_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004261
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004262 if ((message == SMABORT) || (message == SMDEV_RESET) ||
4263 (message == SMABORT_TAG)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004264
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004265 while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | PHASE))) {
4266 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004267
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004268 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
4269 WRW_HARPOON((port + hp_intstat), BUS_FREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004270
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004271 if (currSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004272
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004273 if ((FPT_BL_Card[p_card].
4274 globalFlags & F_CONLUN_IO)
4275 &&
4276 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4277 TarStatus & TAR_TAG_Q_MASK) !=
4278 TAG_Q_TRYING))
4279 FPT_sccbMgrTbl[p_card][currSCCB->
4280 TargID].
4281 TarLUNBusy[currSCCB->Lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004282 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004283 FPT_sccbMgrTbl[p_card][currSCCB->
4284 TargID].
4285 TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004286
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004287 FPT_queueCmdComplete(&FPT_BL_Card[p_card],
4288 currSCCB, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004289 }
4290
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004291 else {
4292 FPT_BL_Card[p_card].globalFlags |=
4293 F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004294 }
4295 }
4296
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004297 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004298
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004299 FPT_sxfrp(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004300 }
4301 }
4302
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004303 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004304
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004305 if (message == SMPARITY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004306 currSCCB->Sccb_scsimsg = SMNO_OP;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004307 WR_HARPOON(port + hp_autostart_1,
4308 (AUTO_IMMED + DISCONNECT_START));
4309 } else {
4310 FPT_sxfrp(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004311 }
4312 }
4313}
4314
Linus Torvalds1da177e2005-04-16 15:20:36 -07004315/*---------------------------------------------------------------------
4316 *
4317 * Function: Message In phase
4318 *
4319 * Description: Bring in the message and determine what to do with it.
4320 *
4321 *---------------------------------------------------------------------*/
4322
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004323static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004324{
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08004325 unsigned char message;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004326 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004327
James Bottomley 47b5d692005-04-24 02:38:05 -05004328 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004329
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004330 if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004331
James Bottomley 47b5d692005-04-24 02:38:05 -05004332 FPT_phaseChkFifo(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004333 }
4334
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004335 message = RD_HARPOON(port + hp_scsidata_0);
4336 if ((message == SMDISC) || (message == SMSAVE_DATA_PTR)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004338 WR_HARPOON(port + hp_autostart_1,
4339 (AUTO_IMMED + END_DATA_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004340
4341 }
4342
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004343 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004344
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004345 message = FPT_sfm(port, currSCCB);
4346 if (message) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004348 FPT_sdecm(message, port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004349
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004350 } else {
4351 if (currSCCB->Sccb_scsimsg != SMPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004352 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004353 WR_HARPOON(port + hp_autostart_1,
4354 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004355 }
4356 }
4357
4358}
4359
Linus Torvalds1da177e2005-04-16 15:20:36 -07004360/*---------------------------------------------------------------------
4361 *
4362 * Function: Illegal phase
4363 *
4364 * Description: Target switched to some illegal phase, so all we can do
4365 * is report an error back to the host (if that is possible)
4366 * and send an ABORT message to the misbehaving target.
4367 *
4368 *---------------------------------------------------------------------*/
4369
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004370static void FPT_phaseIllegal(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004371{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004372 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004373
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004374 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004375
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004376 WR_HARPOON(port + hp_scsisig, RD_HARPOON(port + hp_scsisig));
4377 if (currSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004378
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004379 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4380 currSCCB->Sccb_scsistat = ABORT_ST;
4381 currSCCB->Sccb_scsimsg = SMABORT;
4382 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004383
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004384 ACCEPT_MSG_ATN(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004385}
4386
Linus Torvalds1da177e2005-04-16 15:20:36 -07004387/*---------------------------------------------------------------------
4388 *
4389 * Function: Phase Check FIFO
4390 *
4391 * Description: Make sure data has been flushed from both FIFOs and abort
4392 * the operations if necessary.
4393 *
4394 *---------------------------------------------------------------------*/
4395
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004396static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004397{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004398 unsigned long xfercnt;
4399 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004400
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004401 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004402
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004403 if (currSCCB->Sccb_scsistat == DATA_IN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004404
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004405 while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) &&
4406 (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)) {
4407 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004408
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004409 if (!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) {
4410 currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004411
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004412 currSCCB->Sccb_XferCnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004413
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004414 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
4415 (currSCCB->HostStatus == SCCB_COMPLETE)) {
4416 currSCCB->HostStatus = SCCB_PARITY_ERR;
4417 WRW_HARPOON((port + hp_intstat), PARITY);
4418 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004419
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004420 FPT_hostDataXferAbort(port, p_card, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004421
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004422 FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004423
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004424 while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY))
4425 && (RD_HARPOON(port + hp_ext_status) &
4426 BM_CMD_BUSY)) {
4427 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004428
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004429 }
4430 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004431
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004432 /*End Data In specific code. */
4433 GET_XFER_CNT(port, xfercnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004434
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004435 WR_HARPOON(port + hp_xfercnt_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004436
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004437 WR_HARPOON(port + hp_portctrl_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004438
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004439 currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - xfercnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004440
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004441 currSCCB->Sccb_XferCnt = xfercnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004443 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
4444 (currSCCB->HostStatus == SCCB_COMPLETE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004445
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004446 currSCCB->HostStatus = SCCB_PARITY_ERR;
4447 WRW_HARPOON((port + hp_intstat), PARITY);
4448 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004449
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004450 FPT_hostDataXferAbort(port, p_card, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004451
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004452 WR_HARPOON(port + hp_fifowrite, 0x00);
4453 WR_HARPOON(port + hp_fiforead, 0x00);
4454 WR_HARPOON(port + hp_xferstat, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004455
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004456 WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004457}
4458
Linus Torvalds1da177e2005-04-16 15:20:36 -07004459/*---------------------------------------------------------------------
4460 *
4461 * Function: Phase Bus Free
4462 *
4463 * Description: We just went bus free so figure out if it was
4464 * because of command complete or from a disconnect.
4465 *
4466 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004467static void FPT_phaseBusFree(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004468{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004469 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004470
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004471 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004472
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004473 if (currSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004474
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004475 DISABLE_AUTO(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004476
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004477 if (currSCCB->OperationCode == RESET_COMMAND) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004478
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004479 if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4480 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4481 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4482 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4483 TarLUNBusy[currSCCB->Lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004484 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004485 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4486 TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004487
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004488 FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
4489 p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004490
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004491 FPT_queueSearchSelect(&FPT_BL_Card[p_card], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004492
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004493 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004494
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004495 else if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
4496 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4497 (unsigned char)SYNC_SUPPORTED;
4498 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4499 ~EE_SYNC_MASK;
4500 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004501
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004502 else if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
4503 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
4504 (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4505 TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004506
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004507 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4508 ~EE_WIDE_SCSI;
4509 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004510
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004511 else if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
4512 /* Make sure this is not a phony BUS_FREE. If we were
4513 reselected or if BUSY is NOT on then this is a
4514 valid BUS FREE. SRR Wednesday, 5/10/1995. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004515
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004516 if ((!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ||
4517 (RDW_HARPOON((port + hp_intstat)) & RSEL)) {
4518 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4519 TarStatus &= ~TAR_TAG_Q_MASK;
4520 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4521 TarStatus |= TAG_Q_REJECT;
4522 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004523
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004524 else {
4525 return;
4526 }
4527 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004528
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004529 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004530
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004531 currSCCB->Sccb_scsistat = BUS_FREE_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004532
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004533 if (!currSCCB->HostStatus) {
4534 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4535 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004536
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004537 if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4538 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4539 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4540 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4541 TarLUNBusy[currSCCB->Lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004542 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004543 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4544 TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004545
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004546 FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
4547 p_card);
4548 return;
4549 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004550
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004551 FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004552
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004553 } /*end if !=null */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004554}
4555
Linus Torvalds1da177e2005-04-16 15:20:36 -07004556/*---------------------------------------------------------------------
4557 *
4558 * Function: Auto Load Default Map
4559 *
4560 * Description: Load the Automation RAM with the defualt map values.
4561 *
4562 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004563static void FPT_autoLoadDefaultMap(unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004564{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004565 unsigned long map_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004566
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004567 ARAM_ACCESS(p_port);
4568 map_addr = p_port + hp_aramBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004569
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004570 WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0xC0)); /*ID MESSAGE */
4571 map_addr += 2;
4572 WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x20)); /*SIMPLE TAG QUEUEING MSG */
4573 map_addr += 2;
4574 WRW_HARPOON(map_addr, RAT_OP); /*RESET ATTENTION */
4575 map_addr += 2;
4576 WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x00)); /*TAG ID MSG */
4577 map_addr += 2;
4578 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 0 */
4579 map_addr += 2;
4580 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 1 */
4581 map_addr += 2;
4582 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 2 */
4583 map_addr += 2;
4584 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 3 */
4585 map_addr += 2;
4586 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 4 */
4587 map_addr += 2;
4588 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 5 */
4589 map_addr += 2;
4590 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 6 */
4591 map_addr += 2;
4592 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 7 */
4593 map_addr += 2;
4594 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 8 */
4595 map_addr += 2;
4596 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 9 */
4597 map_addr += 2;
4598 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 10 */
4599 map_addr += 2;
4600 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 11 */
4601 map_addr += 2;
4602 WRW_HARPOON(map_addr, (CPE_OP + ADATA_OUT + DINT)); /*JUMP IF DATA OUT */
4603 map_addr += 2;
4604 WRW_HARPOON(map_addr, (TCB_OP + FIFO_0 + DI)); /*JUMP IF NO DATA IN FIFO */
4605 map_addr += 2; /*This means AYNC DATA IN */
4606 WRW_HARPOON(map_addr, (SSI_OP + SSI_IDO_STRT)); /*STOP AND INTERRUPT */
4607 map_addr += 2;
4608 WRW_HARPOON(map_addr, (CPE_OP + ADATA_IN + DINT)); /*JUMP IF NOT DATA IN PHZ */
4609 map_addr += 2;
4610 WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST)); /*IF NOT MSG IN CHECK 4 DATA IN */
4611 map_addr += 2;
4612 WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x02)); /*SAVE DATA PTR MSG? */
4613 map_addr += 2;
4614 WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + DC)); /*GO CHECK FOR DISCONNECT MSG */
4615 map_addr += 2;
4616 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR1)); /*SAVE DATA PTRS MSG */
4617 map_addr += 2;
4618 WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST)); /*IF NOT MSG IN CHECK DATA IN */
4619 map_addr += 2;
4620 WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x04)); /*DISCONNECT MSG? */
4621 map_addr += 2;
4622 WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + UNKNWN)); /*UKNKNOWN MSG */
4623 map_addr += 2;
4624 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET)); /*XFER DISCONNECT MSG */
4625 map_addr += 2;
4626 WRW_HARPOON(map_addr, (SSI_OP + SSI_ITAR_DISC)); /*STOP AND INTERRUPT */
4627 map_addr += 2;
4628 WRW_HARPOON(map_addr, (CPN_OP + ASTATUS + UNKNWN)); /*JUMP IF NOT STATUS PHZ. */
4629 map_addr += 2;
4630 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR0)); /*GET STATUS BYTE */
4631 map_addr += 2;
4632 WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + CC)); /*ERROR IF NOT MSG IN PHZ */
4633 map_addr += 2;
4634 WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x00)); /*CHECK FOR CMD COMPLETE MSG. */
4635 map_addr += 2;
4636 WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + CC)); /*ERROR IF NOT CMD COMPLETE MSG. */
4637 map_addr += 2;
4638 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET)); /*GET CMD COMPLETE MSG */
4639 map_addr += 2;
4640 WRW_HARPOON(map_addr, (SSI_OP + SSI_ICMD_COMP)); /*END OF COMMAND */
4641 map_addr += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004642
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004643 WRW_HARPOON(map_addr, (SSI_OP + SSI_IUNKWN)); /*RECEIVED UNKNOWN MSG BYTE */
4644 map_addr += 2;
4645 WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */
4646 map_addr += 2;
4647 WRW_HARPOON(map_addr, (SSI_OP + SSI_ITICKLE)); /*BIOS Tickled the Mgr */
4648 map_addr += 2;
4649 WRW_HARPOON(map_addr, (SSI_OP + SSI_IRFAIL)); /*EXPECTED ID/TAG MESSAGES AND */
4650 map_addr += 2; /* DIDN'T GET ONE */
4651 WRW_HARPOON(map_addr, (CRR_OP + AR3 + S_IDREG)); /* comp SCSI SEL ID & AR3 */
4652 map_addr += 2;
4653 WRW_HARPOON(map_addr, (BRH_OP + EQUAL + 0x00)); /*SEL ID OK then Conti. */
4654 map_addr += 2;
4655 WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004656
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004657 SGRAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004658}
4659
4660/*---------------------------------------------------------------------
4661 *
4662 * Function: Auto Command Complete
4663 *
4664 * Description: Post command back to host and find another command
4665 * to execute.
4666 *
4667 *---------------------------------------------------------------------*/
4668
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004669static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004670{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004671 struct sccb *currSCCB;
4672 unsigned char status_byte;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004673
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004674 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004675
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004676 status_byte = RD_HARPOON(p_port + hp_gp_reg_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004677
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004678 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004679
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004680 if (status_byte != SSGOOD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004681
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004682 if (status_byte == SSQ_FULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004683
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004684 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4685 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4686 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4687 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4688 TarLUNBusy[currSCCB->Lun] = 1;
4689 if (FPT_BL_Card[p_card].discQCount != 0)
James Bottomley 47b5d692005-04-24 02:38:05 -05004690 FPT_BL_Card[p_card].discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004691 FPT_BL_Card[p_card].
4692 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4693 [currSCCB->TargID].
4694 LunDiscQ_Idx[currSCCB->Lun]] =
4695 NULL;
4696 } else {
4697 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4698 TarLUNBusy[0] = 1;
4699 if (currSCCB->Sccb_tag) {
4700 if (FPT_BL_Card[p_card].discQCount != 0)
4701 FPT_BL_Card[p_card].
4702 discQCount--;
4703 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4704 Sccb_tag]
4705 = NULL;
4706 } else {
4707 if (FPT_BL_Card[p_card].discQCount != 0)
4708 FPT_BL_Card[p_card].
4709 discQCount--;
4710 FPT_BL_Card[p_card].
4711 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4712 [currSCCB->TargID].
4713 LunDiscQ_Idx[0]] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004714 }
4715 }
4716
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004717 currSCCB->Sccb_MGRFlags |= F_STATUSLOADED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004718
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004719 FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004720
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004721 return;
4722 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004723
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004724 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
4725 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4726 (unsigned char)SYNC_SUPPORTED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004727
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004728 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4729 ~EE_SYNC_MASK;
4730 FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004731
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004732 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4733 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4734 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4735 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4736 TarLUNBusy[currSCCB->Lun] = 1;
4737 if (FPT_BL_Card[p_card].discQCount != 0)
James Bottomley 47b5d692005-04-24 02:38:05 -05004738 FPT_BL_Card[p_card].discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004739 FPT_BL_Card[p_card].
4740 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4741 [currSCCB->TargID].
4742 LunDiscQ_Idx[currSCCB->Lun]] =
4743 NULL;
4744 } else {
4745 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4746 TarLUNBusy[0] = 1;
4747 if (currSCCB->Sccb_tag) {
4748 if (FPT_BL_Card[p_card].discQCount != 0)
4749 FPT_BL_Card[p_card].
4750 discQCount--;
4751 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4752 Sccb_tag]
4753 = NULL;
4754 } else {
4755 if (FPT_BL_Card[p_card].discQCount != 0)
4756 FPT_BL_Card[p_card].
4757 discQCount--;
4758 FPT_BL_Card[p_card].
4759 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4760 [currSCCB->TargID].
4761 LunDiscQ_Idx[0]] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004762 }
4763 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004764 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004765
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004766 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004767
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004768 if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004769
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004770 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
4771 (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4772 TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004773
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004774 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4775 ~EE_WIDE_SCSI;
4776 FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004777
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004778 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4779 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4780 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4781 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4782 TarLUNBusy[currSCCB->Lun] = 1;
4783 if (FPT_BL_Card[p_card].discQCount != 0)
James Bottomley 47b5d692005-04-24 02:38:05 -05004784 FPT_BL_Card[p_card].discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004785 FPT_BL_Card[p_card].
4786 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4787 [currSCCB->TargID].
4788 LunDiscQ_Idx[currSCCB->Lun]] =
4789 NULL;
4790 } else {
4791 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4792 TarLUNBusy[0] = 1;
4793 if (currSCCB->Sccb_tag) {
4794 if (FPT_BL_Card[p_card].discQCount != 0)
4795 FPT_BL_Card[p_card].
4796 discQCount--;
4797 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4798 Sccb_tag]
4799 = NULL;
4800 } else {
4801 if (FPT_BL_Card[p_card].discQCount != 0)
4802 FPT_BL_Card[p_card].
4803 discQCount--;
4804 FPT_BL_Card[p_card].
4805 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4806 [currSCCB->TargID].
4807 LunDiscQ_Idx[0]] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004808 }
4809 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004810 return;
4811
4812 }
4813
4814 if (status_byte == SSCHECK) {
4815 if (FPT_BL_Card[p_card].globalFlags & F_DO_RENEGO) {
4816 if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4817 TarEEValue & EE_SYNC_MASK) {
4818 FPT_sccbMgrTbl[p_card][currSCCB->
4819 TargID].
4820 TarStatus &= ~TAR_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004821 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004822 if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4823 TarEEValue & EE_WIDE_SCSI) {
4824 FPT_sccbMgrTbl[p_card][currSCCB->
4825 TargID].
4826 TarStatus &= ~TAR_WIDE_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004827 }
4828 }
4829 }
4830
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004831 if (!(currSCCB->Sccb_XferState & F_AUTO_SENSE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004832
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004833 currSCCB->SccbStatus = SCCB_ERROR;
4834 currSCCB->TargetStatus = status_byte;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004835
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004836 if (status_byte == SSCHECK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004837
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004838 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4839 TarLUN_CA = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004840
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004841 if (currSCCB->RequestSenseLength !=
4842 NO_AUTO_REQUEST_SENSE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004843
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004844 if (currSCCB->RequestSenseLength == 0)
4845 currSCCB->RequestSenseLength =
4846 14;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004847
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004848 FPT_ssenss(&FPT_BL_Card[p_card]);
4849 FPT_BL_Card[p_card].globalFlags |=
4850 F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004851
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004852 if (((FPT_BL_Card[p_card].
4853 globalFlags & F_CONLUN_IO)
4854 &&
4855 ((FPT_sccbMgrTbl[p_card]
4856 [currSCCB->TargID].
4857 TarStatus & TAR_TAG_Q_MASK) !=
4858 TAG_Q_TRYING))) {
4859 FPT_sccbMgrTbl[p_card]
4860 [currSCCB->TargID].
4861 TarLUNBusy[currSCCB->Lun] =
4862 1;
4863 if (FPT_BL_Card[p_card].
4864 discQCount != 0)
4865 FPT_BL_Card[p_card].
4866 discQCount--;
4867 FPT_BL_Card[p_card].
4868 discQ_Tbl[FPT_sccbMgrTbl
4869 [p_card]
4870 [currSCCB->
4871 TargID].
4872 LunDiscQ_Idx
4873 [currSCCB->Lun]] =
4874 NULL;
4875 } else {
4876 FPT_sccbMgrTbl[p_card]
4877 [currSCCB->TargID].
4878 TarLUNBusy[0] = 1;
4879 if (currSCCB->Sccb_tag) {
4880 if (FPT_BL_Card[p_card].
4881 discQCount != 0)
4882 FPT_BL_Card
4883 [p_card].
4884 discQCount--;
4885 FPT_BL_Card[p_card].
4886 discQ_Tbl[currSCCB->
4887 Sccb_tag]
4888 = NULL;
4889 } else {
4890 if (FPT_BL_Card[p_card].
4891 discQCount != 0)
4892 FPT_BL_Card
4893 [p_card].
4894 discQCount--;
4895 FPT_BL_Card[p_card].
4896 discQ_Tbl
4897 [FPT_sccbMgrTbl
4898 [p_card][currSCCB->
4899 TargID].
4900 LunDiscQ_Idx[0]] =
4901 NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004902 }
4903 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004904 return;
4905 }
4906 }
4907 }
4908 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004909
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004910 if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4911 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4912 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4913 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->
4914 Lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004915 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004916 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004917
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004918 FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004919}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004920
4921#define SHORT_WAIT 0x0000000F
4922#define LONG_WAIT 0x0000FFFFL
4923
Linus Torvalds1da177e2005-04-16 15:20:36 -07004924/*---------------------------------------------------------------------
4925 *
4926 * Function: Data Transfer Processor
4927 *
4928 * Description: This routine performs two tasks.
4929 * (1) Start data transfer by calling HOST_DATA_XFER_START
4930 * function. Once data transfer is started, (2) Depends
4931 * on the type of data transfer mode Scatter/Gather mode
4932 * or NON Scatter/Gather mode. In NON Scatter/Gather mode,
4933 * this routine checks Sccb_MGRFlag (F_HOST_XFER_ACT bit) for
4934 * data transfer done. In Scatter/Gather mode, this routine
4935 * checks bus master command complete and dual rank busy
4936 * bit to keep chaining SC transfer command. Similarly,
4937 * in Scatter/Gather mode, it checks Sccb_MGRFlag
4938 * (F_HOST_XFER_ACT bit) for data transfer done.
4939 *
4940 *---------------------------------------------------------------------*/
4941
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004942static void FPT_dataXferProcessor(unsigned long port,
4943 struct sccb_card *pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004944{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004945 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004946
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004947 currSCCB = pCurrCard->currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004948
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004949 if (currSCCB->Sccb_XferState & F_SG_XFER) {
4950 if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
4951 {
4952 currSCCB->Sccb_sgseg += (unsigned char)SG_BUF_CNT;
4953 currSCCB->Sccb_SGoffset = 0x00;
4954 }
4955 pCurrCard->globalFlags |= F_HOST_XFER_ACT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004956
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004957 FPT_busMstrSGDataXferStart(port, currSCCB);
4958 }
4959
4960 else {
4961 if (!(pCurrCard->globalFlags & F_HOST_XFER_ACT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004962 pCurrCard->globalFlags |= F_HOST_XFER_ACT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004963
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004964 FPT_busMstrDataXferStart(port, currSCCB);
4965 }
4966 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004967}
4968
Linus Torvalds1da177e2005-04-16 15:20:36 -07004969/*---------------------------------------------------------------------
4970 *
4971 * Function: BusMaster Scatter Gather Data Transfer Start
4972 *
4973 * Description:
4974 *
4975 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004976static void FPT_busMstrSGDataXferStart(unsigned long p_port,
4977 struct sccb *pcurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004978{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004979 unsigned long count, addr, tmpSGCnt;
4980 unsigned int sg_index;
4981 unsigned char sg_count, i;
4982 unsigned long reg_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004983
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004984 if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004985
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004986 count = ((unsigned long)HOST_RD_CMD) << 24;
4987 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004988
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004989 else {
4990 count = ((unsigned long)HOST_WRT_CMD) << 24;
4991 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004992
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004993 sg_count = 0;
4994 tmpSGCnt = 0;
4995 sg_index = pcurrSCCB->Sccb_sgseg;
4996 reg_offset = hp_aramBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004997
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004998 i = (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
4999 ~(SGRAM_ARAM | SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005000
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005001 WR_HARPOON(p_port + hp_page_ctrl, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005002
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005003 while ((sg_count < (unsigned char)SG_BUF_CNT) &&
5004 ((unsigned long)(sg_index * (unsigned int)SG_ELEMENT_SIZE) <
5005 pcurrSCCB->DataLength)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005006
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005007 tmpSGCnt += *(((unsigned long *)pcurrSCCB->DataPointer) +
5008 (sg_index * 2));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005009
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005010 count |= *(((unsigned long *)pcurrSCCB->DataPointer) +
5011 (sg_index * 2));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005012
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005013 addr = *(((unsigned long *)pcurrSCCB->DataPointer) +
5014 ((sg_index * 2) + 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005015
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005016 if ((!sg_count) && (pcurrSCCB->Sccb_SGoffset)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005017
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005018 addr +=
5019 ((count & 0x00FFFFFFL) - pcurrSCCB->Sccb_SGoffset);
5020 count =
5021 (count & 0xFF000000L) | pcurrSCCB->Sccb_SGoffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005022
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005023 tmpSGCnt = count & 0x00FFFFFFL;
5024 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005025
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005026 WR_HARP32(p_port, reg_offset, addr);
5027 reg_offset += 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005028
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005029 WR_HARP32(p_port, reg_offset, count);
5030 reg_offset += 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005031
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005032 count &= 0xFF000000L;
5033 sg_index++;
5034 sg_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005035
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005036 } /*End While */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005037
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005038 pcurrSCCB->Sccb_XferCnt = tmpSGCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005039
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005040 WR_HARPOON(p_port + hp_sg_addr, (sg_count << 4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005041
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005042 if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005043
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005044 WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005045
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005046 WR_HARPOON(p_port + hp_portctrl_0,
5047 (DMA_PORT | SCSI_PORT | SCSI_INBIT));
5048 WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
5049 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005050
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005051 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005052
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005053 if ((!(RD_HARPOON(p_port + hp_synctarg_0) & NARROW_SCSI)) &&
5054 (tmpSGCnt & 0x000000001)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005055
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005056 pcurrSCCB->Sccb_XferState |= F_ODD_BALL_CNT;
5057 tmpSGCnt--;
5058 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005059
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005060 WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005061
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005062 WR_HARPOON(p_port + hp_portctrl_0,
5063 (SCSI_PORT | DMA_PORT | DMA_RD));
5064 WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
5065 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005066
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005067 WR_HARPOON(p_port + hp_page_ctrl, (unsigned char)(i | SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005068
5069}
5070
Linus Torvalds1da177e2005-04-16 15:20:36 -07005071/*---------------------------------------------------------------------
5072 *
5073 * Function: BusMaster Data Transfer Start
5074 *
5075 * Description:
5076 *
5077 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005078static void FPT_busMstrDataXferStart(unsigned long p_port,
5079 struct sccb *pcurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005080{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005081 unsigned long addr, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005082
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005083 if (!(pcurrSCCB->Sccb_XferState & F_AUTO_SENSE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005084
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005085 count = pcurrSCCB->Sccb_XferCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005086
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005087 addr =
5088 (unsigned long)pcurrSCCB->DataPointer + pcurrSCCB->Sccb_ATC;
5089 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005090
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005091 else {
5092 addr = pcurrSCCB->SensePointer;
5093 count = pcurrSCCB->RequestSenseLength;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005094
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005095 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005096
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005097 HP_SETUP_ADDR_CNT(p_port, addr, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005098
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005099 if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005100
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005101 WR_HARPOON(p_port + hp_portctrl_0,
5102 (DMA_PORT | SCSI_PORT | SCSI_INBIT));
5103 WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005104
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005105 WR_HARPOON(p_port + hp_xfer_cmd,
5106 (XFER_DMA_HOST | XFER_HOST_AUTO | XFER_DMA_8BIT));
5107 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005108
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005109 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005110
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005111 WR_HARPOON(p_port + hp_portctrl_0,
5112 (SCSI_PORT | DMA_PORT | DMA_RD));
5113 WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005114
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005115 WR_HARPOON(p_port + hp_xfer_cmd,
5116 (XFER_HOST_DMA | XFER_HOST_AUTO | XFER_DMA_8BIT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005117
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005118 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005119}
5120
Linus Torvalds1da177e2005-04-16 15:20:36 -07005121/*---------------------------------------------------------------------
5122 *
5123 * Function: BusMaster Timeout Handler
5124 *
5125 * Description: This function is called after a bus master command busy time
5126 * out is detected. This routines issue halt state machine
5127 * with a software time out for command busy. If command busy
5128 * is still asserted at the end of the time out, it issues
5129 * hard abort with another software time out. It hard abort
5130 * command busy is also time out, it'll just give up.
5131 *
5132 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08005133static unsigned char FPT_busMstrTimeOut(unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005134{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005135 unsigned long timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005136
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005137 timeout = LONG_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005138
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005139 WR_HARPOON(p_port + hp_sys_ctrl, HALT_MACH);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005140
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005141 while ((!(RD_HARPOON(p_port + hp_ext_status) & CMD_ABORTED))
5142 && timeout--) {
5143 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005144
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005145 if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
5146 WR_HARPOON(p_port + hp_sys_ctrl, HARD_ABORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005147
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005148 timeout = LONG_WAIT;
5149 while ((RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY)
5150 && timeout--) {
5151 }
5152 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005153
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005154 RD_HARPOON(p_port + hp_int_status); /*Clear command complete */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005155
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005156 if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005157 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005158 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005159
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005160 else {
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005161 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005162 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005163}
5164
Linus Torvalds1da177e2005-04-16 15:20:36 -07005165/*---------------------------------------------------------------------
5166 *
5167 * Function: Host Data Transfer Abort
5168 *
5169 * Description: Abort any in progress transfer.
5170 *
5171 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005172static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card,
5173 struct sccb *pCurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005174{
5175
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005176 unsigned long timeout;
5177 unsigned long remain_cnt;
5178 unsigned int sg_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005179
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005180 FPT_BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005181
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005182 if (pCurrSCCB->Sccb_XferState & F_AUTO_SENSE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005183
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005184 if (!(RD_HARPOON(port + hp_int_status) & INT_CMD_COMPL)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005185
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005186 WR_HARPOON(port + hp_bm_ctrl,
5187 (RD_HARPOON(port + hp_bm_ctrl) |
5188 FLUSH_XFER_CNTR));
5189 timeout = LONG_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005190
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005191 while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
5192 && timeout--) {
5193 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005194
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005195 WR_HARPOON(port + hp_bm_ctrl,
5196 (RD_HARPOON(port + hp_bm_ctrl) &
5197 ~FLUSH_XFER_CNTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005198
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005199 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005200
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005201 if (FPT_busMstrTimeOut(port)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005202
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005203 if (pCurrSCCB->HostStatus == 0x00)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005204
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005205 pCurrSCCB->HostStatus =
5206 SCCB_BM_ERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005207
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005208 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005209
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005210 if (RD_HARPOON(port + hp_int_status) &
5211 INT_EXT_STATUS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005212
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005213 if (RD_HARPOON(port + hp_ext_status) &
5214 BAD_EXT_STATUS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005215
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005216 if (pCurrSCCB->HostStatus ==
5217 0x00)
5218 {
5219 pCurrSCCB->HostStatus =
5220 SCCB_BM_ERR;
5221 }
5222 }
5223 }
5224 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005225
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005226 else if (pCurrSCCB->Sccb_XferCnt) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005227
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005228 if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005229
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005230 WR_HARPOON(port + hp_page_ctrl,
5231 (RD_HARPOON(port + hp_page_ctrl) &
5232 ~SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005233
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005234 WR_HARPOON(port + hp_sg_addr, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005235
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005236 sg_ptr = pCurrSCCB->Sccb_sgseg + SG_BUF_CNT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005237
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005238 if (sg_ptr >
5239 (unsigned int)(pCurrSCCB->DataLength /
5240 SG_ELEMENT_SIZE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005241
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005242 sg_ptr =
5243 (unsigned int)(pCurrSCCB->DataLength /
5244 SG_ELEMENT_SIZE);
5245 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005246
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005247 remain_cnt = pCurrSCCB->Sccb_XferCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005248
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005249 while (remain_cnt < 0x01000000L) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005250
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005251 sg_ptr--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005252
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005253 if (remain_cnt >
5254 (unsigned
5255 long)(*(((unsigned long *)pCurrSCCB->
5256 DataPointer) + (sg_ptr * 2)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005257
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005258 remain_cnt -=
5259 (unsigned
5260 long)(*(((unsigned long *)
5261 pCurrSCCB->DataPointer) +
5262 (sg_ptr * 2)));
5263 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005264
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005265 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005266
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005267 break;
5268 }
5269 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005270
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005271 if (remain_cnt < 0x01000000L) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005272
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005273 pCurrSCCB->Sccb_SGoffset = remain_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005274
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005275 pCurrSCCB->Sccb_sgseg = (unsigned short)sg_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005276
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005277 if ((unsigned long)(sg_ptr * SG_ELEMENT_SIZE) ==
5278 pCurrSCCB->DataLength && (remain_cnt == 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005279
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005280 pCurrSCCB->Sccb_XferState |=
5281 F_ALL_XFERRED;
5282 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005283
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005284 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005285
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005286 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005287
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005288 pCurrSCCB->HostStatus =
5289 SCCB_GROSS_FW_ERR;
5290 }
5291 }
5292 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005293
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005294 if (!(pCurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005295
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005296 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005297
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005298 FPT_busMstrTimeOut(port);
5299 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005300
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005301 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005302
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005303 if (RD_HARPOON(port + hp_int_status) &
5304 INT_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005305
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005306 if (RD_HARPOON(port + hp_ext_status) &
5307 BAD_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005308
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005309 if (pCurrSCCB->HostStatus ==
5310 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005311
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005312 pCurrSCCB->HostStatus =
5313 SCCB_BM_ERR;
5314 }
5315 }
5316 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005317
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005318 }
5319 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005320
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005321 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005322
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005323 if ((RD_HARPOON(port + hp_fifo_cnt)) >= BM_THRESHOLD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005324
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005325 timeout = SHORT_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005326
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005327 while ((RD_HARPOON(port + hp_ext_status) &
5328 BM_CMD_BUSY)
5329 && ((RD_HARPOON(port + hp_fifo_cnt)) >=
5330 BM_THRESHOLD) && timeout--) {
5331 }
5332 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005333
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005334 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005335
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005336 WR_HARPOON(port + hp_bm_ctrl,
5337 (RD_HARPOON(port + hp_bm_ctrl) |
5338 FLUSH_XFER_CNTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005339
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005340 timeout = LONG_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005341
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005342 while ((RD_HARPOON(port + hp_ext_status) &
5343 BM_CMD_BUSY) && timeout--) {
5344 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005345
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005346 WR_HARPOON(port + hp_bm_ctrl,
5347 (RD_HARPOON(port + hp_bm_ctrl) &
5348 ~FLUSH_XFER_CNTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005349
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005350 if (RD_HARPOON(port + hp_ext_status) &
5351 BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005352
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005353 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005354
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005355 pCurrSCCB->HostStatus =
5356 SCCB_BM_ERR;
5357 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005358
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005359 FPT_busMstrTimeOut(port);
5360 }
5361 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005362
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005363 if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005364
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005365 if (RD_HARPOON(port + hp_ext_status) &
5366 BAD_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005367
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005368 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005369
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005370 pCurrSCCB->HostStatus =
5371 SCCB_BM_ERR;
5372 }
5373 }
5374 }
5375 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005376
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005377 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005378
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005379 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005380
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005381 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005382
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005383 timeout = LONG_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005384
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005385 while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
5386 && timeout--) {
5387 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005388
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005389 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005390
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005391 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005392
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005393 pCurrSCCB->HostStatus = SCCB_BM_ERR;
5394 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005395
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005396 FPT_busMstrTimeOut(port);
5397 }
5398 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005399
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005400 if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005401
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005402 if (RD_HARPOON(port + hp_ext_status) & BAD_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005403
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005404 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005405
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005406 pCurrSCCB->HostStatus = SCCB_BM_ERR;
5407 }
5408 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005409
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005410 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005411
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005412 if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005413
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005414 WR_HARPOON(port + hp_page_ctrl,
5415 (RD_HARPOON(port + hp_page_ctrl) &
5416 ~SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005417
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005418 WR_HARPOON(port + hp_sg_addr, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005419
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005420 pCurrSCCB->Sccb_sgseg += SG_BUF_CNT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005421
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005422 pCurrSCCB->Sccb_SGoffset = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005423
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005424 if ((unsigned long)(pCurrSCCB->Sccb_sgseg *
5425 SG_ELEMENT_SIZE) >=
5426 pCurrSCCB->DataLength) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005427
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005428 pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005429
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005430 pCurrSCCB->Sccb_sgseg =
5431 (unsigned short)(pCurrSCCB->DataLength /
5432 SG_ELEMENT_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005433
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005434 }
5435 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005436
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005437 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005438
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005439 if (!(pCurrSCCB->Sccb_XferState & F_AUTO_SENSE))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005440
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005441 pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
5442 }
5443 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005444
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005445 WR_HARPOON(port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005446}
5447
Linus Torvalds1da177e2005-04-16 15:20:36 -07005448/*---------------------------------------------------------------------
5449 *
5450 * Function: Host Data Transfer Restart
5451 *
5452 * Description: Reset the available count due to a restore data
5453 * pointers message.
5454 *
5455 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005456static void FPT_hostDataXferRestart(struct sccb *currSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005457{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005458 unsigned long data_count;
5459 unsigned int sg_index;
5460 unsigned long *sg_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005461
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005462 if (currSCCB->Sccb_XferState & F_SG_XFER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005463
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005464 currSCCB->Sccb_XferCnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005465
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005466 sg_index = 0xffff; /*Index by long words into sg list. */
5467 data_count = 0; /*Running count of SG xfer counts. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005468
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005469 sg_ptr = (unsigned long *)currSCCB->DataPointer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005470
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005471 while (data_count < currSCCB->Sccb_ATC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005472
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005473 sg_index++;
5474 data_count += *(sg_ptr + (sg_index * 2));
5475 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005476
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005477 if (data_count == currSCCB->Sccb_ATC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005478
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005479 currSCCB->Sccb_SGoffset = 0;
5480 sg_index++;
5481 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005482
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005483 else {
5484 currSCCB->Sccb_SGoffset =
5485 data_count - currSCCB->Sccb_ATC;
5486 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005487
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005488 currSCCB->Sccb_sgseg = (unsigned short)sg_index;
5489 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005490
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005491 else {
5492 currSCCB->Sccb_XferCnt =
5493 currSCCB->DataLength - currSCCB->Sccb_ATC;
5494 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005495}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005496
Linus Torvalds1da177e2005-04-16 15:20:36 -07005497/*---------------------------------------------------------------------
5498 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005499 * Function: FPT_scini
Linus Torvalds1da177e2005-04-16 15:20:36 -07005500 *
5501 * Description: Setup all data structures necessary for SCAM selection.
5502 *
5503 *---------------------------------------------------------------------*/
5504
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005505static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
5506 unsigned char p_power_up)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005507{
5508
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005509 unsigned char loser, assigned_id;
5510 unsigned long p_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005511
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005512 unsigned char i, k, ScamFlg;
5513 struct sccb_card *currCard;
5514 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005515
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005516 currCard = &FPT_BL_Card[p_card];
5517 p_port = currCard->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005518 pCurrNvRam = currCard->pNvRamInfo;
5519
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005520 if (pCurrNvRam) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005521 ScamFlg = pCurrNvRam->niScamConf;
5522 i = pCurrNvRam->niSysConf;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005523 } else {
5524 ScamFlg =
5525 (unsigned char)FPT_utilEERead(p_port, SCAM_CONFIG / 2);
5526 i = (unsigned
5527 char)(FPT_utilEERead(p_port, (SYSTEM_CONFIG / 2)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005528 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005529 if (!(i & 0x02)) /* check if reset bus in AutoSCSI parameter set */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005530 return;
5531
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005532 FPT_inisci(p_card, p_port, p_our_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005533
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005534 /* Force to wait 1 sec after SCSI bus reset. Some SCAM device FW
5535 too slow to return to SCAM selection */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005536
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005537 /* if (p_power_up)
5538 FPT_Wait1Second(p_port);
5539 else
5540 FPT_Wait(p_port, TO_250ms); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005541
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005542 FPT_Wait1Second(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005543
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005544 if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2)) {
5545 while (!(FPT_scarb(p_port, INIT_SELTD))) {
5546 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005547
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005548 FPT_scsel(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005549
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005550 do {
5551 FPT_scxferc(p_port, SYNC_PTRN);
5552 FPT_scxferc(p_port, DOM_MSTR);
5553 loser =
5554 FPT_scsendi(p_port,
5555 &FPT_scamInfo[p_our_id].id_string[0]);
5556 } while (loser == 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005557
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005558 FPT_scbusf(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005559
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005560 if ((p_power_up) && (!loser)) {
5561 FPT_sresb(p_port, p_card);
5562 FPT_Wait(p_port, TO_250ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005563
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005564 while (!(FPT_scarb(p_port, INIT_SELTD))) {
5565 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005566
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005567 FPT_scsel(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005568
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005569 do {
5570 FPT_scxferc(p_port, SYNC_PTRN);
5571 FPT_scxferc(p_port, DOM_MSTR);
5572 loser =
5573 FPT_scsendi(p_port,
5574 &FPT_scamInfo[p_our_id].
5575 id_string[0]);
5576 } while (loser == 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005577
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005578 FPT_scbusf(p_port);
5579 }
5580 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005581
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005582 else {
5583 loser = 0;
5584 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005585
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005586 if (!loser) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005587
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005588 FPT_scamInfo[p_our_id].state = ID_ASSIGNED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005589
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005590 if (ScamFlg & SCAM_ENABLED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005591
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005592 for (i = 0; i < MAX_SCSI_TAR; i++) {
5593 if ((FPT_scamInfo[i].state == ID_UNASSIGNED) ||
5594 (FPT_scamInfo[i].state == ID_UNUSED)) {
5595 if (FPT_scsell(p_port, i)) {
5596 FPT_scamInfo[i].state = LEGACY;
5597 if ((FPT_scamInfo[i].
5598 id_string[0] != 0xFF)
5599 || (FPT_scamInfo[i].
5600 id_string[1] != 0xFA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005601
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005602 FPT_scamInfo[i].
5603 id_string[0] = 0xFF;
5604 FPT_scamInfo[i].
5605 id_string[1] = 0xFA;
5606 if (pCurrNvRam == NULL)
5607 currCard->
5608 globalFlags
5609 |=
5610 F_UPDATE_EEPROM;
5611 }
5612 }
5613 }
5614 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005615
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005616 FPT_sresb(p_port, p_card);
5617 FPT_Wait1Second(p_port);
5618 while (!(FPT_scarb(p_port, INIT_SELTD))) {
5619 }
5620 FPT_scsel(p_port);
5621 FPT_scasid(p_card, p_port);
5622 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005623
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005624 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005625
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005626 else if ((loser) && (ScamFlg & SCAM_ENABLED)) {
5627 FPT_scamInfo[p_our_id].id_string[0] = SLV_TYPE_CODE0;
5628 assigned_id = 0;
5629 FPT_scwtsel(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005630
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005631 do {
5632 while (FPT_scxferc(p_port, 0x00) != SYNC_PTRN) {
5633 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005634
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005635 i = FPT_scxferc(p_port, 0x00);
5636 if (i == ASSIGN_ID) {
5637 if (!
5638 (FPT_scsendi
5639 (p_port,
5640 &FPT_scamInfo[p_our_id].id_string[0]))) {
5641 i = FPT_scxferc(p_port, 0x00);
5642 if (FPT_scvalq(i)) {
5643 k = FPT_scxferc(p_port, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005644
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005645 if (FPT_scvalq(k)) {
5646 currCard->ourId =
5647 ((unsigned char)(i
5648 <<
5649 3)
5650 +
5651 (k &
5652 (unsigned char)7))
5653 & (unsigned char)
5654 0x3F;
5655 FPT_inisci(p_card,
5656 p_port,
5657 p_our_id);
5658 FPT_scamInfo[currCard->
5659 ourId].
5660 state = ID_ASSIGNED;
5661 FPT_scamInfo[currCard->
5662 ourId].
5663 id_string[0]
5664 = SLV_TYPE_CODE0;
5665 assigned_id = 1;
5666 }
5667 }
5668 }
5669 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005670
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005671 else if (i == SET_P_FLAG) {
5672 if (!(FPT_scsendi(p_port,
5673 &FPT_scamInfo[p_our_id].
5674 id_string[0])))
5675 FPT_scamInfo[p_our_id].id_string[0] |=
5676 0x80;
5677 }
5678 } while (!assigned_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005679
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005680 while (FPT_scxferc(p_port, 0x00) != CFG_CMPLT) {
5681 }
5682 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005683
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005684 if (ScamFlg & SCAM_ENABLED) {
5685 FPT_scbusf(p_port);
5686 if (currCard->globalFlags & F_UPDATE_EEPROM) {
5687 FPT_scsavdi(p_card, p_port);
5688 currCard->globalFlags &= ~F_UPDATE_EEPROM;
5689 }
5690 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005691
Linus Torvalds1da177e2005-04-16 15:20:36 -07005692/*
5693 for (i=0,k=0; i < MAX_SCSI_TAR; i++)
5694 {
James Bottomley 47b5d692005-04-24 02:38:05 -05005695 if ((FPT_scamInfo[i].state == ID_ASSIGNED) ||
5696 (FPT_scamInfo[i].state == LEGACY))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005697 k++;
5698 }
5699
5700 if (k==2)
5701 currCard->globalFlags |= F_SINGLE_DEVICE;
5702 else
5703 currCard->globalFlags &= ~F_SINGLE_DEVICE;
5704*/
5705}
5706
Linus Torvalds1da177e2005-04-16 15:20:36 -07005707/*---------------------------------------------------------------------
5708 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005709 * Function: FPT_scarb
Linus Torvalds1da177e2005-04-16 15:20:36 -07005710 *
5711 * Description: Gain control of the bus and wait SCAM select time (250ms)
5712 *
5713 *---------------------------------------------------------------------*/
5714
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08005715static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005716{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005717 if (p_sel_type == INIT_SELTD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005718
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005719 while (RD_HARPOON(p_port + hp_scsisig) & (SCSI_SEL | SCSI_BSY)) {
5720 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005721
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005722 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005723 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005724
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005725 if (RD_HARPOON(p_port + hp_scsidata_0) != 00)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005726 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005727
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005728 WR_HARPOON(p_port + hp_scsisig,
5729 (RD_HARPOON(p_port + hp_scsisig) | SCSI_BSY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005730
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005731 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005732
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005733 WR_HARPOON(p_port + hp_scsisig,
5734 (RD_HARPOON(p_port + hp_scsisig) &
5735 ~SCSI_BSY));
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005736 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005737 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005738
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005739 WR_HARPOON(p_port + hp_scsisig,
5740 (RD_HARPOON(p_port + hp_scsisig) | SCSI_SEL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005741
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005742 if (RD_HARPOON(p_port + hp_scsidata_0) != 00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005743
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005744 WR_HARPOON(p_port + hp_scsisig,
5745 (RD_HARPOON(p_port + hp_scsisig) &
5746 ~(SCSI_BSY | SCSI_SEL)));
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005747 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005748 }
5749 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005750
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005751 WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
5752 & ~ACTdeassert));
5753 WR_HARPOON(p_port + hp_scsireset, SCAM_EN);
5754 WR_HARPOON(p_port + hp_scsidata_0, 0x00);
5755 WR_HARPOON(p_port + hp_scsidata_1, 0x00);
5756 WR_HARPOON(p_port + hp_portctrl_0, SCSI_BUS_EN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005757
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005758 WR_HARPOON(p_port + hp_scsisig,
5759 (RD_HARPOON(p_port + hp_scsisig) | SCSI_MSG));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005760
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005761 WR_HARPOON(p_port + hp_scsisig, (RD_HARPOON(p_port + hp_scsisig)
5762 & ~SCSI_BSY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005763
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005764 FPT_Wait(p_port, TO_250ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005765
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005766 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005767}
5768
Linus Torvalds1da177e2005-04-16 15:20:36 -07005769/*---------------------------------------------------------------------
5770 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005771 * Function: FPT_scbusf
Linus Torvalds1da177e2005-04-16 15:20:36 -07005772 *
5773 * Description: Release the SCSI bus and disable SCAM selection.
5774 *
5775 *---------------------------------------------------------------------*/
5776
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08005777static void FPT_scbusf(unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005778{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005779 WR_HARPOON(p_port + hp_page_ctrl,
5780 (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005781
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005782 WR_HARPOON(p_port + hp_scsidata_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005783
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005784 WR_HARPOON(p_port + hp_portctrl_0, (RD_HARPOON(p_port + hp_portctrl_0)
5785 & ~SCSI_BUS_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005786
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005787 WR_HARPOON(p_port + hp_scsisig, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005788
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005789 WR_HARPOON(p_port + hp_scsireset, (RD_HARPOON(p_port + hp_scsireset)
5790 & ~SCAM_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005791
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005792 WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
5793 | ACTdeassert));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005794
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005795 WRW_HARPOON((p_port + hp_intstat), (BUS_FREE | AUTO_INT | SCAM_SEL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005796
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005797 WR_HARPOON(p_port + hp_page_ctrl,
5798 (RD_HARPOON(p_port + hp_page_ctrl) & ~G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005799}
5800
Linus Torvalds1da177e2005-04-16 15:20:36 -07005801/*---------------------------------------------------------------------
5802 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005803 * Function: FPT_scasid
Linus Torvalds1da177e2005-04-16 15:20:36 -07005804 *
5805 * Description: Assign an ID to all the SCAM devices.
5806 *
5807 *---------------------------------------------------------------------*/
5808
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08005809static void FPT_scasid(unsigned char p_card, unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005810{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005811 unsigned char temp_id_string[ID_STRING_LENGTH];
Linus Torvalds1da177e2005-04-16 15:20:36 -07005812
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005813 unsigned char i, k, scam_id;
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08005814 unsigned char crcBytes[3];
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005815 struct nvram_info *pCurrNvRam;
5816 unsigned short *pCrcBytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005817
James Bottomley 47b5d692005-04-24 02:38:05 -05005818 pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005819
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005820 i = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005821
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005822 while (!i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005823
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005824 for (k = 0; k < ID_STRING_LENGTH; k++) {
5825 temp_id_string[k] = (unsigned char)0x00;
5826 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005827
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005828 FPT_scxferc(p_port, SYNC_PTRN);
5829 FPT_scxferc(p_port, ASSIGN_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005830
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005831 if (!(FPT_sciso(p_port, &temp_id_string[0]))) {
5832 if (pCurrNvRam) {
Alexey Dobriyanfd1e29e2006-03-08 00:14:27 -08005833 pCrcBytes = (unsigned short *)&crcBytes[0];
James Bottomley 47b5d692005-04-24 02:38:05 -05005834 *pCrcBytes = FPT_CalcCrc16(&temp_id_string[0]);
5835 crcBytes[2] = FPT_CalcLrc(&temp_id_string[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005836 temp_id_string[1] = crcBytes[2];
5837 temp_id_string[2] = crcBytes[0];
5838 temp_id_string[3] = crcBytes[1];
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005839 for (k = 4; k < ID_STRING_LENGTH; k++)
5840 temp_id_string[k] = (unsigned char)0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005841 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005842 i = FPT_scmachid(p_card, temp_id_string);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005843
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005844 if (i == CLR_PRIORITY) {
5845 FPT_scxferc(p_port, MISC_CODE);
5846 FPT_scxferc(p_port, CLR_P_FLAG);
5847 i = 0; /*Not the last ID yet. */
5848 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005849
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005850 else if (i != NO_ID_AVAIL) {
5851 if (i < 8)
5852 FPT_scxferc(p_port, ID_0_7);
5853 else
5854 FPT_scxferc(p_port, ID_8_F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005855
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005856 scam_id = (i & (unsigned char)0x07);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005857
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005858 for (k = 1; k < 0x08; k <<= 1)
5859 if (!(k & i))
5860 scam_id += 0x08; /*Count number of zeros in DB0-3. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005861
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005862 FPT_scxferc(p_port, scam_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005863
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005864 i = 0; /*Not the last ID yet. */
5865 }
5866 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005867
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005868 else {
5869 i = 1;
5870 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005871
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005872 } /*End while */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005873
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005874 FPT_scxferc(p_port, SYNC_PTRN);
5875 FPT_scxferc(p_port, CFG_CMPLT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005876}
5877
Linus Torvalds1da177e2005-04-16 15:20:36 -07005878/*---------------------------------------------------------------------
5879 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005880 * Function: FPT_scsel
Linus Torvalds1da177e2005-04-16 15:20:36 -07005881 *
5882 * Description: Select all the SCAM devices.
5883 *
5884 *---------------------------------------------------------------------*/
5885
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08005886static void FPT_scsel(unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005887{
5888
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005889 WR_HARPOON(p_port + hp_scsisig, SCSI_SEL);
5890 FPT_scwiros(p_port, SCSI_MSG);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005891
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005892 WR_HARPOON(p_port + hp_scsisig, (SCSI_SEL | SCSI_BSY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005893
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005894 WR_HARPOON(p_port + hp_scsisig,
5895 (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5896 WR_HARPOON(p_port + hp_scsidata_0,
5897 (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) |
5898 (unsigned char)(BIT(7) + BIT(6))));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005899
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005900 WR_HARPOON(p_port + hp_scsisig, (SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5901 FPT_scwiros(p_port, SCSI_SEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005902
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005903 WR_HARPOON(p_port + hp_scsidata_0,
5904 (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) &
5905 ~(unsigned char)BIT(6)));
5906 FPT_scwirod(p_port, BIT(6));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005907
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005908 WR_HARPOON(p_port + hp_scsisig,
5909 (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005910}
5911
Linus Torvalds1da177e2005-04-16 15:20:36 -07005912/*---------------------------------------------------------------------
5913 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005914 * Function: FPT_scxferc
Linus Torvalds1da177e2005-04-16 15:20:36 -07005915 *
5916 * Description: Handshake the p_data (DB4-0) across the bus.
5917 *
5918 *---------------------------------------------------------------------*/
5919
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08005920static unsigned char FPT_scxferc(unsigned long p_port, unsigned char p_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005921{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005922 unsigned char curr_data, ret_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005923
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005924 curr_data = p_data | BIT(7) | BIT(5); /*Start with DB7 & DB5 asserted. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005925
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005926 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005927
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005928 curr_data &= ~BIT(7);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005929
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005930 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005931
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005932 FPT_scwirod(p_port, BIT(7)); /*Wait for DB7 to be released. */
5933 while (!(RD_HARPOON(p_port + hp_scsidata_0) & BIT(5))) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005934
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005935 ret_data = (RD_HARPOON(p_port + hp_scsidata_0) & (unsigned char)0x1F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005936
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005937 curr_data |= BIT(6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005938
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005939 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005940
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005941 curr_data &= ~BIT(5);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005942
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005943 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005944
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005945 FPT_scwirod(p_port, BIT(5)); /*Wait for DB5 to be released. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005946
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005947 curr_data &= ~(BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0)); /*Release data bits */
5948 curr_data |= BIT(7);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005949
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005950 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005951
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005952 curr_data &= ~BIT(6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005953
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005954 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005955
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005956 FPT_scwirod(p_port, BIT(6)); /*Wait for DB6 to be released. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005957
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005958 return ret_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005959}
5960
Linus Torvalds1da177e2005-04-16 15:20:36 -07005961/*---------------------------------------------------------------------
5962 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005963 * Function: FPT_scsendi
Linus Torvalds1da177e2005-04-16 15:20:36 -07005964 *
5965 * Description: Transfer our Identification string to determine if we
5966 * will be the dominant master.
5967 *
5968 *---------------------------------------------------------------------*/
5969
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005970static unsigned char FPT_scsendi(unsigned long p_port,
5971 unsigned char p_id_string[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07005972{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005973 unsigned char ret_data, byte_cnt, bit_cnt, defer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005974
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005975 defer = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005976
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005977 for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005978
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005979 for (bit_cnt = 0x80; bit_cnt != 0; bit_cnt >>= 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005980
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005981 if (defer)
5982 ret_data = FPT_scxferc(p_port, 00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005983
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005984 else if (p_id_string[byte_cnt] & bit_cnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005985
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005986 ret_data = FPT_scxferc(p_port, 02);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005987
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005988 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005989
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005990 ret_data = FPT_scxferc(p_port, 01);
5991 if (ret_data & 02)
5992 defer = 1;
5993 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005994
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005995 if ((ret_data & 0x1C) == 0x10)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005996 return 0x00; /*End of isolation stage, we won! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005997
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005998 if (ret_data & 0x1C)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005999 return 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006000
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006001 if ((defer) && (!(ret_data & 0x1F)))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006002 return 0x01; /*End of isolation stage, we lost. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006003
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006004 } /*bit loop */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006005
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006006 } /*byte loop */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006007
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006008 if (defer)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006009 return 0x01; /*We lost */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006010 else
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006011 return 0; /*We WON! Yeeessss! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006012}
6013
Linus Torvalds1da177e2005-04-16 15:20:36 -07006014/*---------------------------------------------------------------------
6015 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006016 * Function: FPT_sciso
Linus Torvalds1da177e2005-04-16 15:20:36 -07006017 *
6018 * Description: Transfer the Identification string.
6019 *
6020 *---------------------------------------------------------------------*/
6021
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006022static unsigned char FPT_sciso(unsigned long p_port,
6023 unsigned char p_id_string[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07006024{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006025 unsigned char ret_data, the_data, byte_cnt, bit_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006026
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006027 the_data = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006028
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006029 for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006030
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006031 for (bit_cnt = 0; bit_cnt < 8; bit_cnt++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006032
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006033 ret_data = FPT_scxferc(p_port, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006034
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006035 if (ret_data & 0xFC)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006036 return 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006037
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006038 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006039
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006040 the_data <<= 1;
6041 if (ret_data & BIT(1)) {
6042 the_data |= 1;
6043 }
6044 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006045
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006046 if ((ret_data & 0x1F) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006047/*
6048 if(bit_cnt != 0 || bit_cnt != 8)
6049 {
6050 byte_cnt = 0;
6051 bit_cnt = 0;
James Bottomley 47b5d692005-04-24 02:38:05 -05006052 FPT_scxferc(p_port, SYNC_PTRN);
6053 FPT_scxferc(p_port, ASSIGN_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006054 continue;
6055 }
6056*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006057 if (byte_cnt)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006058 return 0x00;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006059 else
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006060 return 0xFF;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006061 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006062
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006063 } /*bit loop */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006064
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006065 p_id_string[byte_cnt] = the_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006066
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006067 } /*byte loop */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006068
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006069 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006070}
6071
Linus Torvalds1da177e2005-04-16 15:20:36 -07006072/*---------------------------------------------------------------------
6073 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006074 * Function: FPT_scwirod
Linus Torvalds1da177e2005-04-16 15:20:36 -07006075 *
6076 * Description: Sample the SCSI data bus making sure the signal has been
6077 * deasserted for the correct number of consecutive samples.
6078 *
6079 *---------------------------------------------------------------------*/
6080
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08006081static void FPT_scwirod(unsigned long p_port, unsigned char p_data_bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006082{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006083 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006084
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006085 i = 0;
6086 while (i < MAX_SCSI_TAR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006087
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006088 if (RD_HARPOON(p_port + hp_scsidata_0) & p_data_bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006089
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006090 i = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006091
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006092 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07006093
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006094 i++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006095
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006096 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006097}
6098
Linus Torvalds1da177e2005-04-16 15:20:36 -07006099/*---------------------------------------------------------------------
6100 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006101 * Function: FPT_scwiros
Linus Torvalds1da177e2005-04-16 15:20:36 -07006102 *
6103 * Description: Sample the SCSI Signal lines making sure the signal has been
6104 * deasserted for the correct number of consecutive samples.
6105 *
6106 *---------------------------------------------------------------------*/
6107
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08006108static void FPT_scwiros(unsigned long p_port, unsigned char p_data_bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006109{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006110 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006111
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006112 i = 0;
6113 while (i < MAX_SCSI_TAR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006114
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006115 if (RD_HARPOON(p_port + hp_scsisig) & p_data_bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006116
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006117 i = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006118
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006119 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07006120
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006121 i++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006122
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006123 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006124}
6125
Linus Torvalds1da177e2005-04-16 15:20:36 -07006126/*---------------------------------------------------------------------
6127 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006128 * Function: FPT_scvalq
Linus Torvalds1da177e2005-04-16 15:20:36 -07006129 *
6130 * Description: Make sure we received a valid data byte.
6131 *
6132 *---------------------------------------------------------------------*/
6133
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08006134static unsigned char FPT_scvalq(unsigned char p_quintet)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006135{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006136 unsigned char count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006137
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006138 for (count = 1; count < 0x08; count <<= 1) {
6139 if (!(p_quintet & count))
6140 p_quintet -= 0x80;
6141 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006142
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006143 if (p_quintet & 0x18)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006144 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006145
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006146 else
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006147 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006148}
6149
Linus Torvalds1da177e2005-04-16 15:20:36 -07006150/*---------------------------------------------------------------------
6151 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006152 * Function: FPT_scsell
Linus Torvalds1da177e2005-04-16 15:20:36 -07006153 *
6154 * Description: Select the specified device ID using a selection timeout
6155 * less than 4ms. If somebody responds then it is a legacy
6156 * drive and this ID must be marked as such.
6157 *
6158 *---------------------------------------------------------------------*/
6159
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08006160static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006161{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006162 unsigned long i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006163
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006164 WR_HARPOON(p_port + hp_page_ctrl,
6165 (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006166
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006167 ARAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006168
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006169 WR_HARPOON(p_port + hp_addstat,
6170 (RD_HARPOON(p_port + hp_addstat) | SCAM_TIMER));
6171 WR_HARPOON(p_port + hp_seltimeout, TO_4ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006172
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006173 for (i = p_port + CMD_STRT; i < p_port + CMD_STRT + 12; i += 2) {
6174 WRW_HARPOON(i, (MPM_OP + ACOMMAND));
6175 }
6176 WRW_HARPOON(i, (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006177
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006178 WRW_HARPOON((p_port + hp_intstat),
6179 (RESET | TIMEOUT | SEL | BUS_FREE | AUTO_INT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006180
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006181 WR_HARPOON(p_port + hp_select_id, targ_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006182
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006183 WR_HARPOON(p_port + hp_portctrl_0, SCSI_PORT);
6184 WR_HARPOON(p_port + hp_autostart_3, (SELECT | CMD_ONLY_STRT));
6185 WR_HARPOON(p_port + hp_scsictrl_0, (SEL_TAR | ENA_RESEL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006186
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006187 while (!(RDW_HARPOON((p_port + hp_intstat)) &
6188 (RESET | PROG_HLT | TIMEOUT | AUTO_INT))) {
6189 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006190
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006191 if (RDW_HARPOON((p_port + hp_intstat)) & RESET)
6192 FPT_Wait(p_port, TO_250ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006193
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006194 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006195
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006196 WR_HARPOON(p_port + hp_addstat,
6197 (RD_HARPOON(p_port + hp_addstat) & ~SCAM_TIMER));
6198 WR_HARPOON(p_port + hp_seltimeout, TO_290ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006199
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006200 SGRAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006201
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006202 if (RDW_HARPOON((p_port + hp_intstat)) & (RESET | TIMEOUT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006203
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006204 WRW_HARPOON((p_port + hp_intstat),
6205 (RESET | TIMEOUT | SEL | BUS_FREE | PHASE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006206
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006207 WR_HARPOON(p_port + hp_page_ctrl,
6208 (RD_HARPOON(p_port + hp_page_ctrl) &
6209 ~G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006210
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006211 return 0; /*No legacy device */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006212 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006213
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006214 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006215
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006216 while (!(RDW_HARPOON((p_port + hp_intstat)) & BUS_FREE)) {
6217 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ) {
6218 WR_HARPOON(p_port + hp_scsisig,
6219 (SCSI_ACK + S_ILL_PH));
6220 ACCEPT_MSG(p_port);
6221 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006222 }
6223
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006224 WRW_HARPOON((p_port + hp_intstat), CLR_ALL_INT_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006225
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006226 WR_HARPOON(p_port + hp_page_ctrl,
6227 (RD_HARPOON(p_port + hp_page_ctrl) &
6228 ~G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006229
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006230 return 1; /*Found one of them oldies! */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006231 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006232}
6233
Linus Torvalds1da177e2005-04-16 15:20:36 -07006234/*---------------------------------------------------------------------
6235 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006236 * Function: FPT_scwtsel
Linus Torvalds1da177e2005-04-16 15:20:36 -07006237 *
6238 * Description: Wait to be selected by another SCAM initiator.
6239 *
6240 *---------------------------------------------------------------------*/
6241
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08006242static void FPT_scwtsel(unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006243{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006244 while (!(RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL)) {
6245 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006246}
6247
Linus Torvalds1da177e2005-04-16 15:20:36 -07006248/*---------------------------------------------------------------------
6249 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006250 * Function: FPT_inisci
Linus Torvalds1da177e2005-04-16 15:20:36 -07006251 *
6252 * Description: Setup the data Structure with the info from the EEPROM.
6253 *
6254 *---------------------------------------------------------------------*/
6255
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006256static void FPT_inisci(unsigned char p_card, unsigned long p_port,
6257 unsigned char p_our_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006258{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006259 unsigned char i, k, max_id;
6260 unsigned short ee_data;
6261 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006262
James Bottomley 47b5d692005-04-24 02:38:05 -05006263 pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006264
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006265 if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6266 max_id = 0x08;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006267
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006268 else
6269 max_id = 0x10;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006270
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006271 if (pCurrNvRam) {
6272 for (i = 0; i < max_id; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006273
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006274 for (k = 0; k < 4; k++)
6275 FPT_scamInfo[i].id_string[k] =
6276 pCurrNvRam->niScamTbl[i][k];
6277 for (k = 4; k < ID_STRING_LENGTH; k++)
6278 FPT_scamInfo[i].id_string[k] =
6279 (unsigned char)0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006280
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006281 if (FPT_scamInfo[i].id_string[0] == 0x00)
6282 FPT_scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */
6283 else
6284 FPT_scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006285
6286 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006287 } else {
6288 for (i = 0; i < max_id; i++) {
6289 for (k = 0; k < ID_STRING_LENGTH; k += 2) {
6290 ee_data =
6291 FPT_utilEERead(p_port,
6292 (unsigned
6293 short)((EE_SCAMBASE / 2) +
6294 (unsigned short)(i *
6295 ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
6296 FPT_scamInfo[i].id_string[k] =
6297 (unsigned char)ee_data;
6298 ee_data >>= 8;
6299 FPT_scamInfo[i].id_string[k + 1] =
6300 (unsigned char)ee_data;
6301 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006302
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006303 if ((FPT_scamInfo[i].id_string[0] == 0x00) ||
6304 (FPT_scamInfo[i].id_string[0] == 0xFF))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006305
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006306 FPT_scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006307
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006308 else
6309 FPT_scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006310
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006311 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006312 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006313 for (k = 0; k < ID_STRING_LENGTH; k++)
James Bottomley 47b5d692005-04-24 02:38:05 -05006314 FPT_scamInfo[p_our_id].id_string[k] = FPT_scamHAString[k];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006315
6316}
6317
6318/*---------------------------------------------------------------------
6319 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006320 * Function: FPT_scmachid
Linus Torvalds1da177e2005-04-16 15:20:36 -07006321 *
6322 * Description: Match the Device ID string with our values stored in
6323 * the EEPROM.
6324 *
6325 *---------------------------------------------------------------------*/
6326
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006327static unsigned char FPT_scmachid(unsigned char p_card,
6328 unsigned char p_id_string[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07006329{
6330
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006331 unsigned char i, k, match;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006332
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006333 for (i = 0; i < MAX_SCSI_TAR; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006334
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006335 match = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006336
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006337 for (k = 0; k < ID_STRING_LENGTH; k++) {
6338 if (p_id_string[k] != FPT_scamInfo[i].id_string[k])
6339 match = 0;
6340 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006341
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006342 if (match) {
6343 FPT_scamInfo[i].state = ID_ASSIGNED;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006344 return i;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006345 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006346
Linus Torvalds1da177e2005-04-16 15:20:36 -07006347 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006348
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006349 if (p_id_string[0] & BIT(5))
6350 i = 8;
6351 else
6352 i = MAX_SCSI_TAR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006353
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006354 if (((p_id_string[0] & 0x06) == 0x02)
6355 || ((p_id_string[0] & 0x06) == 0x04))
6356 match = p_id_string[1] & (unsigned char)0x1F;
6357 else
6358 match = 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006359
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006360 while (i > 0) {
6361 i--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006362
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006363 if (FPT_scamInfo[match].state == ID_UNUSED) {
6364 for (k = 0; k < ID_STRING_LENGTH; k++) {
6365 FPT_scamInfo[match].id_string[k] =
6366 p_id_string[k];
6367 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006368
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006369 FPT_scamInfo[match].state = ID_ASSIGNED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006370
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006371 if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
6372 FPT_BL_Card[p_card].globalFlags |=
6373 F_UPDATE_EEPROM;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006374 return match;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006375
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006376 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006377
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006378 match--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006379
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006380 if (match == 0xFF) {
6381 if (p_id_string[0] & BIT(5))
6382 match = 7;
6383 else
6384 match = MAX_SCSI_TAR - 1;
6385 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006386 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006387
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006388 if (p_id_string[0] & BIT(7)) {
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006389 return CLR_PRIORITY;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006390 }
6391
6392 if (p_id_string[0] & BIT(5))
6393 i = 8;
6394 else
6395 i = MAX_SCSI_TAR;
6396
6397 if (((p_id_string[0] & 0x06) == 0x02)
6398 || ((p_id_string[0] & 0x06) == 0x04))
6399 match = p_id_string[1] & (unsigned char)0x1F;
6400 else
6401 match = 7;
6402
6403 while (i > 0) {
6404
6405 i--;
6406
6407 if (FPT_scamInfo[match].state == ID_UNASSIGNED) {
6408 for (k = 0; k < ID_STRING_LENGTH; k++) {
6409 FPT_scamInfo[match].id_string[k] =
6410 p_id_string[k];
6411 }
6412
6413 FPT_scamInfo[match].id_string[0] |= BIT(7);
6414 FPT_scamInfo[match].state = ID_ASSIGNED;
6415 if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
6416 FPT_BL_Card[p_card].globalFlags |=
6417 F_UPDATE_EEPROM;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006418 return match;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006419
6420 }
6421
6422 match--;
6423
6424 if (match == 0xFF) {
6425 if (p_id_string[0] & BIT(5))
6426 match = 7;
6427 else
6428 match = MAX_SCSI_TAR - 1;
6429 }
6430 }
6431
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006432 return NO_ID_AVAIL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006433}
6434
Linus Torvalds1da177e2005-04-16 15:20:36 -07006435/*---------------------------------------------------------------------
6436 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006437 * Function: FPT_scsavdi
Linus Torvalds1da177e2005-04-16 15:20:36 -07006438 *
6439 * Description: Save off the device SCAM ID strings.
6440 *
6441 *---------------------------------------------------------------------*/
6442
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08006443static void FPT_scsavdi(unsigned char p_card, unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006444{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006445 unsigned char i, k, max_id;
6446 unsigned short ee_data, sum_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006447
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006448 sum_data = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006449
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006450 for (i = 1; i < EE_SCAMBASE / 2; i++) {
6451 sum_data += FPT_utilEERead(p_port, i);
6452 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006453
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006454 FPT_utilEEWriteOnOff(p_port, 1); /* Enable write access to the EEPROM */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006455
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006456 if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6457 max_id = 0x08;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006458
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006459 else
6460 max_id = 0x10;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006461
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006462 for (i = 0; i < max_id; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006463
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006464 for (k = 0; k < ID_STRING_LENGTH; k += 2) {
6465 ee_data = FPT_scamInfo[i].id_string[k + 1];
6466 ee_data <<= 8;
6467 ee_data |= FPT_scamInfo[i].id_string[k];
6468 sum_data += ee_data;
6469 FPT_utilEEWrite(p_port, ee_data,
6470 (unsigned short)((EE_SCAMBASE / 2) +
6471 (unsigned short)(i *
6472 ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
6473 }
6474 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006475
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006476 FPT_utilEEWrite(p_port, sum_data, EEPROM_CHECK_SUM / 2);
6477 FPT_utilEEWriteOnOff(p_port, 0); /* Turn off write access */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006478}
Linus Torvalds1da177e2005-04-16 15:20:36 -07006479
6480/*---------------------------------------------------------------------
6481 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006482 * Function: FPT_XbowInit
Linus Torvalds1da177e2005-04-16 15:20:36 -07006483 *
6484 * Description: Setup the Xbow for normal operation.
6485 *
6486 *---------------------------------------------------------------------*/
6487
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08006488static void FPT_XbowInit(unsigned long port, unsigned char ScamFlg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006489{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006490 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006491
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006492 i = RD_HARPOON(port + hp_page_ctrl);
6493 WR_HARPOON(port + hp_page_ctrl, (unsigned char)(i | G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006494
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006495 WR_HARPOON(port + hp_scsireset, 0x00);
6496 WR_HARPOON(port + hp_portctrl_1, HOST_MODE8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006497
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006498 WR_HARPOON(port + hp_scsireset, (DMA_RESET | HPSCSI_RESET | PROG_RESET |
6499 FIFO_CLR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006500
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006501 WR_HARPOON(port + hp_scsireset, SCSI_INI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006502
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006503 WR_HARPOON(port + hp_clkctrl_0, CLKCTRL_DEFAULT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006504
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006505 WR_HARPOON(port + hp_scsisig, 0x00); /* Clear any signals we might */
6506 WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006507
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006508 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006509
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006510 FPT_default_intena = RESET | RSEL | PROG_HLT | TIMEOUT |
6511 BUS_FREE | XFER_CNT_0 | AUTO_INT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006512
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006513 if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2))
James Bottomley 47b5d692005-04-24 02:38:05 -05006514 FPT_default_intena |= SCAM_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006515
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006516 WRW_HARPOON((port + hp_intena), FPT_default_intena);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006517
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006518 WR_HARPOON(port + hp_seltimeout, TO_290ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006519
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006520 /* Turn on SCSI_MODE8 for narrow cards to fix the
6521 strapping issue with the DUAL CHANNEL card */
6522 if (RD_HARPOON(port + hp_page_ctrl) & NARROW_SCSI_CARD)
6523 WR_HARPOON(port + hp_addstat, SCSI_MODE8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006524
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006525 WR_HARPOON(port + hp_page_ctrl, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006526
6527}
6528
Linus Torvalds1da177e2005-04-16 15:20:36 -07006529/*---------------------------------------------------------------------
6530 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006531 * Function: FPT_BusMasterInit
Linus Torvalds1da177e2005-04-16 15:20:36 -07006532 *
6533 * Description: Initialize the BusMaster for normal operations.
6534 *
6535 *---------------------------------------------------------------------*/
6536
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08006537static void FPT_BusMasterInit(unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006538{
6539
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006540 WR_HARPOON(p_port + hp_sys_ctrl, DRVR_RST);
6541 WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006542
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006543 WR_HARPOON(p_port + hp_host_blk_cnt, XFER_BLK64);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006544
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006545 WR_HARPOON(p_port + hp_bm_ctrl, (BMCTRL_DEFAULT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006546
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006547 WR_HARPOON(p_port + hp_ee_ctrl, (SCSI_TERM_ENA_H));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006548
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006549 RD_HARPOON(p_port + hp_int_status); /*Clear interrupts. */
6550 WR_HARPOON(p_port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
6551 WR_HARPOON(p_port + hp_page_ctrl, (RD_HARPOON(p_port + hp_page_ctrl) &
6552 ~SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006553}
6554
Linus Torvalds1da177e2005-04-16 15:20:36 -07006555/*---------------------------------------------------------------------
6556 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006557 * Function: FPT_DiagEEPROM
Linus Torvalds1da177e2005-04-16 15:20:36 -07006558 *
6559 * Description: Verfiy checksum and 'Key' and initialize the EEPROM if
6560 * necessary.
6561 *
6562 *---------------------------------------------------------------------*/
6563
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08006564static void FPT_DiagEEPROM(unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006565{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006566 unsigned short index, temp, max_wd_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006567
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006568 if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6569 max_wd_cnt = EEPROM_WD_CNT;
6570 else
6571 max_wd_cnt = EEPROM_WD_CNT * 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006572
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006573 temp = FPT_utilEERead(p_port, FW_SIGNATURE / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006574
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006575 if (temp == 0x4641) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006576
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006577 for (index = 2; index < max_wd_cnt; index++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006578
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006579 temp += FPT_utilEERead(p_port, index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006580
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006581 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006582
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006583 if (temp == FPT_utilEERead(p_port, EEPROM_CHECK_SUM / 2)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006584
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006585 return; /*EEPROM is Okay so return now! */
6586 }
6587 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006588
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006589 FPT_utilEEWriteOnOff(p_port, (unsigned char)1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006590
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006591 for (index = 0; index < max_wd_cnt; index++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006592
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006593 FPT_utilEEWrite(p_port, 0x0000, index);
6594 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006595
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006596 temp = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006597
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006598 FPT_utilEEWrite(p_port, 0x4641, FW_SIGNATURE / 2);
6599 temp += 0x4641;
6600 FPT_utilEEWrite(p_port, 0x3920, MODEL_NUMB_0 / 2);
6601 temp += 0x3920;
6602 FPT_utilEEWrite(p_port, 0x3033, MODEL_NUMB_2 / 2);
6603 temp += 0x3033;
6604 FPT_utilEEWrite(p_port, 0x2020, MODEL_NUMB_4 / 2);
6605 temp += 0x2020;
6606 FPT_utilEEWrite(p_port, 0x70D3, SYSTEM_CONFIG / 2);
6607 temp += 0x70D3;
6608 FPT_utilEEWrite(p_port, 0x0010, BIOS_CONFIG / 2);
6609 temp += 0x0010;
6610 FPT_utilEEWrite(p_port, 0x0003, SCAM_CONFIG / 2);
6611 temp += 0x0003;
6612 FPT_utilEEWrite(p_port, 0x0007, ADAPTER_SCSI_ID / 2);
6613 temp += 0x0007;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006614
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006615 FPT_utilEEWrite(p_port, 0x0000, IGNORE_B_SCAN / 2);
6616 temp += 0x0000;
6617 FPT_utilEEWrite(p_port, 0x0000, SEND_START_ENA / 2);
6618 temp += 0x0000;
6619 FPT_utilEEWrite(p_port, 0x0000, DEVICE_ENABLE / 2);
6620 temp += 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006621
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006622 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL01 / 2);
6623 temp += 0x4242;
6624 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL23 / 2);
6625 temp += 0x4242;
6626 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL45 / 2);
6627 temp += 0x4242;
6628 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL67 / 2);
6629 temp += 0x4242;
6630 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL89 / 2);
6631 temp += 0x4242;
6632 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLab / 2);
6633 temp += 0x4242;
6634 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLcd / 2);
6635 temp += 0x4242;
6636 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLef / 2);
6637 temp += 0x4242;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006638
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006639 FPT_utilEEWrite(p_port, 0x6C46, 64 / 2); /*PRODUCT ID */
6640 temp += 0x6C46;
6641 FPT_utilEEWrite(p_port, 0x7361, 66 / 2); /* FlashPoint LT */
6642 temp += 0x7361;
6643 FPT_utilEEWrite(p_port, 0x5068, 68 / 2);
6644 temp += 0x5068;
6645 FPT_utilEEWrite(p_port, 0x696F, 70 / 2);
6646 temp += 0x696F;
6647 FPT_utilEEWrite(p_port, 0x746E, 72 / 2);
6648 temp += 0x746E;
6649 FPT_utilEEWrite(p_port, 0x4C20, 74 / 2);
6650 temp += 0x4C20;
6651 FPT_utilEEWrite(p_port, 0x2054, 76 / 2);
6652 temp += 0x2054;
6653 FPT_utilEEWrite(p_port, 0x2020, 78 / 2);
6654 temp += 0x2020;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006655
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006656 index = ((EE_SCAMBASE / 2) + (7 * 16));
6657 FPT_utilEEWrite(p_port, (0x0700 + TYPE_CODE0), index);
6658 temp += (0x0700 + TYPE_CODE0);
6659 index++;
6660 FPT_utilEEWrite(p_port, 0x5542, index); /*Vendor ID code */
6661 temp += 0x5542; /* BUSLOGIC */
6662 index++;
6663 FPT_utilEEWrite(p_port, 0x4C53, index);
6664 temp += 0x4C53;
6665 index++;
6666 FPT_utilEEWrite(p_port, 0x474F, index);
6667 temp += 0x474F;
6668 index++;
6669 FPT_utilEEWrite(p_port, 0x4349, index);
6670 temp += 0x4349;
6671 index++;
6672 FPT_utilEEWrite(p_port, 0x5442, index); /*Vendor unique code */
6673 temp += 0x5442; /* BT- 930 */
6674 index++;
6675 FPT_utilEEWrite(p_port, 0x202D, index);
6676 temp += 0x202D;
6677 index++;
6678 FPT_utilEEWrite(p_port, 0x3339, index);
6679 temp += 0x3339;
6680 index++; /*Serial # */
6681 FPT_utilEEWrite(p_port, 0x2030, index); /* 01234567 */
6682 temp += 0x2030;
6683 index++;
6684 FPT_utilEEWrite(p_port, 0x5453, index);
6685 temp += 0x5453;
6686 index++;
6687 FPT_utilEEWrite(p_port, 0x5645, index);
6688 temp += 0x5645;
6689 index++;
6690 FPT_utilEEWrite(p_port, 0x2045, index);
6691 temp += 0x2045;
6692 index++;
6693 FPT_utilEEWrite(p_port, 0x202F, index);
6694 temp += 0x202F;
6695 index++;
6696 FPT_utilEEWrite(p_port, 0x4F4A, index);
6697 temp += 0x4F4A;
6698 index++;
6699 FPT_utilEEWrite(p_port, 0x204E, index);
6700 temp += 0x204E;
6701 index++;
6702 FPT_utilEEWrite(p_port, 0x3539, index);
6703 temp += 0x3539;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006704
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006705 FPT_utilEEWrite(p_port, temp, EEPROM_CHECK_SUM / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006706
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006707 FPT_utilEEWriteOnOff(p_port, (unsigned char)0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006708
6709}
6710
Linus Torvalds1da177e2005-04-16 15:20:36 -07006711/*---------------------------------------------------------------------
6712 *
6713 * Function: Queue Search Select
6714 *
6715 * Description: Try to find a new command to execute.
6716 *
6717 *---------------------------------------------------------------------*/
6718
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006719static void FPT_queueSearchSelect(struct sccb_card *pCurrCard,
6720 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006721{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006722 unsigned char scan_ptr, lun;
6723 struct sccb_mgr_tar_info *currTar_Info;
6724 struct sccb *pOldSccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006725
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006726 scan_ptr = pCurrCard->scanIndex;
6727 do {
James Bottomley 47b5d692005-04-24 02:38:05 -05006728 currTar_Info = &FPT_sccbMgrTbl[p_card][scan_ptr];
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006729 if ((pCurrCard->globalFlags & F_CONLUN_IO) &&
6730 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
6731 TAG_Q_TRYING)) {
6732 if (currTar_Info->TarSelQ_Cnt != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006733
6734 scan_ptr++;
6735 if (scan_ptr == MAX_SCSI_TAR)
6736 scan_ptr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006737
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006738 for (lun = 0; lun < MAX_LUN; lun++) {
6739 if (currTar_Info->TarLUNBusy[lun] == 0) {
6740
6741 pCurrCard->currentSCCB =
6742 currTar_Info->TarSelQ_Head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006743 pOldSccb = NULL;
6744
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006745 while ((pCurrCard->
6746 currentSCCB != NULL)
6747 && (lun !=
6748 pCurrCard->
6749 currentSCCB->Lun)) {
6750 pOldSccb =
6751 pCurrCard->
6752 currentSCCB;
6753 pCurrCard->currentSCCB =
6754 (struct sccb
6755 *)(pCurrCard->
6756 currentSCCB)->
6757 Sccb_forwardlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006758 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006759 if (pCurrCard->currentSCCB ==
6760 NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006761 continue;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006762 if (pOldSccb != NULL) {
6763 pOldSccb->
6764 Sccb_forwardlink =
6765 (struct sccb
6766 *)(pCurrCard->
6767 currentSCCB)->
6768 Sccb_forwardlink;
6769 pOldSccb->
6770 Sccb_backlink =
6771 (struct sccb
6772 *)(pCurrCard->
6773 currentSCCB)->
6774 Sccb_backlink;
6775 currTar_Info->
6776 TarSelQ_Cnt--;
6777 } else {
6778 currTar_Info->
6779 TarSelQ_Head =
6780 (struct sccb
6781 *)(pCurrCard->
6782 currentSCCB)->
6783 Sccb_forwardlink;
6784
6785 if (currTar_Info->
6786 TarSelQ_Head ==
6787 NULL) {
6788 currTar_Info->
6789 TarSelQ_Tail
6790 = NULL;
6791 currTar_Info->
6792 TarSelQ_Cnt
6793 = 0;
6794 } else {
6795 currTar_Info->
6796 TarSelQ_Cnt--;
6797 currTar_Info->
6798 TarSelQ_Head->
6799 Sccb_backlink
6800 =
6801 (struct sccb
6802 *)NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006803 }
6804 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006805 pCurrCard->scanIndex = scan_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006806
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006807 pCurrCard->globalFlags |=
6808 F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006809
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006810 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006811 }
6812 }
6813 }
6814
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006815 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006816 scan_ptr++;
6817 if (scan_ptr == MAX_SCSI_TAR) {
6818 scan_ptr = 0;
6819 }
6820 }
6821
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006822 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006823 if ((currTar_Info->TarSelQ_Cnt != 0) &&
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006824 (currTar_Info->TarLUNBusy[0] == 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006825
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006826 pCurrCard->currentSCCB =
6827 currTar_Info->TarSelQ_Head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006828
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006829 currTar_Info->TarSelQ_Head =
6830 (struct sccb *)(pCurrCard->currentSCCB)->
6831 Sccb_forwardlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006832
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006833 if (currTar_Info->TarSelQ_Head == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006834 currTar_Info->TarSelQ_Tail = NULL;
6835 currTar_Info->TarSelQ_Cnt = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006836 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006837 currTar_Info->TarSelQ_Cnt--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006838 currTar_Info->TarSelQ_Head->
6839 Sccb_backlink = (struct sccb *)NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006840 }
6841
6842 scan_ptr++;
6843 if (scan_ptr == MAX_SCSI_TAR)
6844 scan_ptr = 0;
6845
6846 pCurrCard->scanIndex = scan_ptr;
6847
6848 pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
6849
6850 break;
6851 }
6852
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006853 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006854 scan_ptr++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006855 if (scan_ptr == MAX_SCSI_TAR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006856 scan_ptr = 0;
6857 }
6858 }
6859 }
6860 } while (scan_ptr != pCurrCard->scanIndex);
6861}
6862
Linus Torvalds1da177e2005-04-16 15:20:36 -07006863/*---------------------------------------------------------------------
6864 *
6865 * Function: Queue Select Fail
6866 *
6867 * Description: Add the current SCCB to the head of the Queue.
6868 *
6869 *---------------------------------------------------------------------*/
6870
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006871static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
6872 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006873{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006874 unsigned char thisTarg;
6875 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006876
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006877 if (pCurrCard->currentSCCB != NULL) {
6878 thisTarg =
6879 (unsigned char)(((struct sccb *)(pCurrCard->currentSCCB))->
6880 TargID);
6881 currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006882
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006883 pCurrCard->currentSCCB->Sccb_backlink = (struct sccb *)NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006884
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006885 pCurrCard->currentSCCB->Sccb_forwardlink =
6886 currTar_Info->TarSelQ_Head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006887
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006888 if (currTar_Info->TarSelQ_Cnt == 0) {
6889 currTar_Info->TarSelQ_Tail = pCurrCard->currentSCCB;
6890 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006891
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006892 else {
6893 currTar_Info->TarSelQ_Head->Sccb_backlink =
6894 pCurrCard->currentSCCB;
6895 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006896
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006897 currTar_Info->TarSelQ_Head = pCurrCard->currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006898
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006899 pCurrCard->currentSCCB = NULL;
6900 currTar_Info->TarSelQ_Cnt++;
6901 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006902}
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006903
Linus Torvalds1da177e2005-04-16 15:20:36 -07006904/*---------------------------------------------------------------------
6905 *
6906 * Function: Queue Command Complete
6907 *
6908 * Description: Call the callback function with the current SCCB.
6909 *
6910 *---------------------------------------------------------------------*/
6911
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006912static void FPT_queueCmdComplete(struct sccb_card *pCurrCard,
6913 struct sccb *p_sccb, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006914{
6915
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006916 unsigned char i, SCSIcmd;
6917 CALL_BK_FN callback;
6918 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006919
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006920 SCSIcmd = p_sccb->Cdb[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006921
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006922 if (!(p_sccb->Sccb_XferState & F_ALL_XFERRED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006923
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006924 if ((p_sccb->
6925 ControlByte & (SCCB_DATA_XFER_OUT | SCCB_DATA_XFER_IN))
6926 && (p_sccb->HostStatus == SCCB_COMPLETE)
6927 && (p_sccb->TargetStatus != SSCHECK))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006928
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006929 if ((SCSIcmd == SCSI_READ) ||
6930 (SCSIcmd == SCSI_WRITE) ||
6931 (SCSIcmd == SCSI_READ_EXTENDED) ||
6932 (SCSIcmd == SCSI_WRITE_EXTENDED) ||
6933 (SCSIcmd == SCSI_WRITE_AND_VERIFY) ||
6934 (SCSIcmd == SCSI_START_STOP_UNIT) ||
6935 (pCurrCard->globalFlags & F_NO_FILTER)
6936 )
6937 p_sccb->HostStatus = SCCB_DATA_UNDER_RUN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006938 }
6939
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006940 if (p_sccb->SccbStatus == SCCB_IN_PROCESS) {
6941 if (p_sccb->HostStatus || p_sccb->TargetStatus)
6942 p_sccb->SccbStatus = SCCB_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006943 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006944 p_sccb->SccbStatus = SCCB_SUCCESS;
6945 }
6946
6947 if (p_sccb->Sccb_XferState & F_AUTO_SENSE) {
6948
6949 p_sccb->CdbLength = p_sccb->Save_CdbLen;
6950 for (i = 0; i < 6; i++) {
6951 p_sccb->Cdb[i] = p_sccb->Save_Cdb[i];
6952 }
6953 }
6954
6955 if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) ||
6956 (p_sccb->OperationCode == RESIDUAL_COMMAND)) {
6957
6958 FPT_utilUpdateResidual(p_sccb);
6959 }
6960
6961 pCurrCard->cmdCounter--;
6962 if (!pCurrCard->cmdCounter) {
6963
6964 if (pCurrCard->globalFlags & F_GREEN_PC) {
6965 WR_HARPOON(pCurrCard->ioPort + hp_clkctrl_0,
6966 (PWR_DWN | CLKCTRL_DEFAULT));
6967 WR_HARPOON(pCurrCard->ioPort + hp_sys_ctrl, STOP_CLK);
6968 }
6969
6970 WR_HARPOON(pCurrCard->ioPort + hp_semaphore,
6971 (RD_HARPOON(pCurrCard->ioPort + hp_semaphore) &
6972 ~SCCB_MGR_ACTIVE));
6973
6974 }
6975
6976 if (pCurrCard->discQCount != 0) {
6977 currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
6978 if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
6979 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
6980 TAG_Q_TRYING))) {
6981 pCurrCard->discQCount--;
6982 pCurrCard->discQ_Tbl[currTar_Info->
6983 LunDiscQ_Idx[p_sccb->Lun]] = NULL;
6984 } else {
6985 if (p_sccb->Sccb_tag) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006986 pCurrCard->discQCount--;
6987 pCurrCard->discQ_Tbl[p_sccb->Sccb_tag] = NULL;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006988 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006989 pCurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006990 pCurrCard->discQ_Tbl[currTar_Info->
6991 LunDiscQ_Idx[0]] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006992 }
6993 }
6994
6995 }
6996
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006997 callback = (CALL_BK_FN) p_sccb->SccbCallback;
6998 callback(p_sccb);
6999 pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
7000 pCurrCard->currentSCCB = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007001}
Linus Torvalds1da177e2005-04-16 15:20:36 -07007002
Linus Torvalds1da177e2005-04-16 15:20:36 -07007003/*---------------------------------------------------------------------
7004 *
7005 * Function: Queue Disconnect
7006 *
7007 * Description: Add SCCB to our disconnect array.
7008 *
7009 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007010static void FPT_queueDisconnect(struct sccb *p_sccb, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007011{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007012 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007013
James Bottomley 47b5d692005-04-24 02:38:05 -05007014 currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007015
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007016 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
7017 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
7018 FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
7019 LunDiscQ_Idx[p_sccb->Lun]] =
7020 p_sccb;
7021 } else {
7022 if (p_sccb->Sccb_tag) {
7023 FPT_BL_Card[p_card].discQ_Tbl[p_sccb->Sccb_tag] =
7024 p_sccb;
7025 FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarLUNBusy[0] =
7026 0;
James Bottomley 47b5d692005-04-24 02:38:05 -05007027 FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarTagQ_Cnt++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007028 } else {
7029 FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
7030 LunDiscQ_Idx[0]] = p_sccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007031 }
7032 }
James Bottomley 47b5d692005-04-24 02:38:05 -05007033 FPT_BL_Card[p_card].currentSCCB = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007034}
7035
Linus Torvalds1da177e2005-04-16 15:20:36 -07007036/*---------------------------------------------------------------------
7037 *
7038 * Function: Queue Flush SCCB
7039 *
7040 * Description: Flush all SCCB's back to the host driver for this target.
7041 *
7042 *---------------------------------------------------------------------*/
7043
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007044static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007045{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007046 unsigned char qtag, thisTarg;
7047 struct sccb *currSCCB;
7048 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007049
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007050 currSCCB = FPT_BL_Card[p_card].currentSCCB;
7051 if (currSCCB != NULL) {
7052 thisTarg = (unsigned char)currSCCB->TargID;
7053 currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007054
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007055 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007056
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007057 if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
7058 (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
7059 thisTarg)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007060
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007061 FPT_BL_Card[p_card].discQ_Tbl[qtag]->
7062 HostStatus = (unsigned char)error_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007063
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007064 FPT_queueCmdComplete(&FPT_BL_Card[p_card],
7065 FPT_BL_Card[p_card].
7066 discQ_Tbl[qtag], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007067
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007068 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
7069 currTar_Info->TarTagQ_Cnt--;
7070
7071 }
7072 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007073 }
7074
7075}
7076
7077/*---------------------------------------------------------------------
7078 *
7079 * Function: Queue Flush Target SCCB
7080 *
7081 * Description: Flush all SCCB's back to the host driver for this target.
7082 *
7083 *---------------------------------------------------------------------*/
7084
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007085static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
7086 unsigned char error_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007087{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007088 unsigned char qtag;
7089 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007090
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007091 currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007092
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007093 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007094
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007095 if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
7096 (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007097
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007098 FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus =
7099 (unsigned char)error_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007100
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007101 FPT_queueCmdComplete(&FPT_BL_Card[p_card],
7102 FPT_BL_Card[p_card].
7103 discQ_Tbl[qtag], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007104
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007105 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
7106 currTar_Info->TarTagQ_Cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007107
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007108 }
7109 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007110
7111}
7112
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007113static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007114{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007115 struct sccb_mgr_tar_info *currTar_Info;
7116 currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007117
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007118 p_SCCB->Sccb_forwardlink = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007119
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007120 p_SCCB->Sccb_backlink = currTar_Info->TarSelQ_Tail;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007121
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007122 if (currTar_Info->TarSelQ_Cnt == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007123
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007124 currTar_Info->TarSelQ_Head = p_SCCB;
7125 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007126
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007127 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007128
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007129 currTar_Info->TarSelQ_Tail->Sccb_forwardlink = p_SCCB;
7130 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007131
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007132 currTar_Info->TarSelQ_Tail = p_SCCB;
7133 currTar_Info->TarSelQ_Cnt++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007134}
7135
Linus Torvalds1da177e2005-04-16 15:20:36 -07007136/*---------------------------------------------------------------------
7137 *
7138 * Function: Queue Find SCCB
7139 *
7140 * Description: Search the target select Queue for this SCCB, and
7141 * remove it if found.
7142 *
7143 *---------------------------------------------------------------------*/
7144
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007145static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB,
7146 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007147{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007148 struct sccb *q_ptr;
7149 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007150
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007151 currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007152
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007153 q_ptr = currTar_Info->TarSelQ_Head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007154
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007155 while (q_ptr != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007156
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007157 if (q_ptr == p_SCCB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007158
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007159 if (currTar_Info->TarSelQ_Head == q_ptr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007160
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007161 currTar_Info->TarSelQ_Head =
7162 q_ptr->Sccb_forwardlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007163 }
7164
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007165 if (currTar_Info->TarSelQ_Tail == q_ptr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007166
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007167 currTar_Info->TarSelQ_Tail =
7168 q_ptr->Sccb_backlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007169 }
7170
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007171 if (q_ptr->Sccb_forwardlink != NULL) {
7172 q_ptr->Sccb_forwardlink->Sccb_backlink =
7173 q_ptr->Sccb_backlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007174 }
7175
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007176 if (q_ptr->Sccb_backlink != NULL) {
7177 q_ptr->Sccb_backlink->Sccb_forwardlink =
7178 q_ptr->Sccb_forwardlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007179 }
7180
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007181 currTar_Info->TarSelQ_Cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007182
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007183 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007184 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007185
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007186 else {
7187 q_ptr = q_ptr->Sccb_forwardlink;
7188 }
7189 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007190
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007191 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007192
7193}
7194
Linus Torvalds1da177e2005-04-16 15:20:36 -07007195/*---------------------------------------------------------------------
7196 *
7197 * Function: Utility Update Residual Count
7198 *
7199 * Description: Update the XferCnt to the remaining byte count.
7200 * If we transferred all the data then just write zero.
7201 * If Non-SG transfer then report Total Cnt - Actual Transfer
7202 * Cnt. For SG transfers add the count fields of all
7203 * remaining SG elements, as well as any partial remaining
7204 * element.
7205 *
7206 *---------------------------------------------------------------------*/
7207
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007208static void FPT_utilUpdateResidual(struct sccb *p_SCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007209{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007210 unsigned long partial_cnt;
7211 unsigned int sg_index;
7212 unsigned long *sg_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007213
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007214 if (p_SCCB->Sccb_XferState & F_ALL_XFERRED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007215
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007216 p_SCCB->DataLength = 0x0000;
7217 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007218
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007219 else if (p_SCCB->Sccb_XferState & F_SG_XFER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007220
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007221 partial_cnt = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007222
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007223 sg_index = p_SCCB->Sccb_sgseg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007224
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007225 sg_ptr = (unsigned long *)p_SCCB->DataPointer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007226
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007227 if (p_SCCB->Sccb_SGoffset) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007228
7229 partial_cnt = p_SCCB->Sccb_SGoffset;
7230 sg_index++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007231 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007232
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007233 while (((unsigned long)sg_index *
7234 (unsigned long)SG_ELEMENT_SIZE) < p_SCCB->DataLength) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007235
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007236 partial_cnt += *(sg_ptr + (sg_index * 2));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007237 sg_index++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007238 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007239
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007240 p_SCCB->DataLength = partial_cnt;
7241 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007242
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007243 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007244
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007245 p_SCCB->DataLength -= p_SCCB->Sccb_ATC;
7246 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007247}
7248
Linus Torvalds1da177e2005-04-16 15:20:36 -07007249/*---------------------------------------------------------------------
7250 *
7251 * Function: Wait 1 Second
7252 *
7253 * Description: Wait for 1 second.
7254 *
7255 *---------------------------------------------------------------------*/
7256
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08007257static void FPT_Wait1Second(unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007258{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007259 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007260
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007261 for (i = 0; i < 4; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007262
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007263 FPT_Wait(p_port, TO_250ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007264
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007265 if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
7266 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007267
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007268 if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
7269 break;
7270 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007271}
7272
Linus Torvalds1da177e2005-04-16 15:20:36 -07007273/*---------------------------------------------------------------------
7274 *
James Bottomley 47b5d692005-04-24 02:38:05 -05007275 * Function: FPT_Wait
Linus Torvalds1da177e2005-04-16 15:20:36 -07007276 *
7277 * Description: Wait the desired delay.
7278 *
7279 *---------------------------------------------------------------------*/
7280
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08007281static void FPT_Wait(unsigned long p_port, unsigned char p_delay)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007282{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007283 unsigned char old_timer;
7284 unsigned char green_flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007285
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007286 old_timer = RD_HARPOON(p_port + hp_seltimeout);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007287
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007288 green_flag = RD_HARPOON(p_port + hp_clkctrl_0);
7289 WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007290
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007291 WR_HARPOON(p_port + hp_seltimeout, p_delay);
7292 WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
7293 WRW_HARPOON((p_port + hp_intena), (FPT_default_intena & ~TIMEOUT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007294
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007295 WR_HARPOON(p_port + hp_portctrl_0,
7296 (RD_HARPOON(p_port + hp_portctrl_0) | START_TO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007297
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007298 while (!(RDW_HARPOON((p_port + hp_intstat)) & TIMEOUT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007299
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007300 if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
7301 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007302
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007303 if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
7304 break;
7305 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007306
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007307 WR_HARPOON(p_port + hp_portctrl_0,
7308 (RD_HARPOON(p_port + hp_portctrl_0) & ~START_TO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007309
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007310 WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
7311 WRW_HARPOON((p_port + hp_intena), FPT_default_intena);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007312
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007313 WR_HARPOON(p_port + hp_clkctrl_0, green_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007314
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007315 WR_HARPOON(p_port + hp_seltimeout, old_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007316}
7317
Linus Torvalds1da177e2005-04-16 15:20:36 -07007318/*---------------------------------------------------------------------
7319 *
7320 * Function: Enable/Disable Write to EEPROM
7321 *
7322 * Description: The EEPROM must first be enabled for writes
7323 * A total of 9 clocks are needed.
7324 *
7325 *---------------------------------------------------------------------*/
7326
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007327static void FPT_utilEEWriteOnOff(unsigned long p_port, unsigned char p_mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007328{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007329 unsigned char ee_value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007330
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007331 ee_value =
7332 (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
7333 (EXT_ARB_ACK | SCSI_TERM_ENA_H));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007334
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007335 if (p_mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007336
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007337 FPT_utilEESendCmdAddr(p_port, EWEN, EWEN_ADDR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007338
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007339 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07007340
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007341 FPT_utilEESendCmdAddr(p_port, EWDS, EWDS_ADDR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007342
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007343 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */
7344 WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /*Turn off Master Select */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007345}
7346
Linus Torvalds1da177e2005-04-16 15:20:36 -07007347/*---------------------------------------------------------------------
7348 *
7349 * Function: Write EEPROM
7350 *
7351 * Description: Write a word to the EEPROM at the specified
7352 * address.
7353 *
7354 *---------------------------------------------------------------------*/
7355
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007356static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data,
7357 unsigned short ee_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007358{
7359
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007360 unsigned char ee_value;
7361 unsigned short i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007362
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007363 ee_value =
7364 (unsigned
7365 char)((RD_HARPOON(p_port + hp_ee_ctrl) &
7366 (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007367
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007368 FPT_utilEESendCmdAddr(p_port, EE_WRITE, ee_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007369
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007370 ee_value |= (SEE_MS + SEE_CS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007371
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007372 for (i = 0x8000; i != 0; i >>= 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007373
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007374 if (i & ee_data)
7375 ee_value |= SEE_DO;
7376 else
7377 ee_value &= ~SEE_DO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007378
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007379 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7380 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7381 ee_value |= SEE_CLK; /* Clock data! */
7382 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7383 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7384 ee_value &= ~SEE_CLK;
7385 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7386 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7387 }
7388 ee_value &= (EXT_ARB_ACK | SCSI_TERM_ENA_H);
7389 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007390
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007391 FPT_Wait(p_port, TO_10ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007392
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007393 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS | SEE_CS)); /* Set CS to EEPROM */
7394 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /* Turn off CS */
7395 WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /* Turn off Master Select */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007396}
7397
7398/*---------------------------------------------------------------------
7399 *
7400 * Function: Read EEPROM
7401 *
7402 * Description: Read a word from the EEPROM at the desired
7403 * address.
7404 *
7405 *---------------------------------------------------------------------*/
7406
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007407static unsigned short FPT_utilEERead(unsigned long p_port,
7408 unsigned short ee_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007409{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007410 unsigned short i, ee_data1, ee_data2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007411
7412 i = 0;
James Bottomley 47b5d692005-04-24 02:38:05 -05007413 ee_data1 = FPT_utilEEReadOrg(p_port, ee_addr);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007414 do {
James Bottomley 47b5d692005-04-24 02:38:05 -05007415 ee_data2 = FPT_utilEEReadOrg(p_port, ee_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007416
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007417 if (ee_data1 == ee_data2)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007418 return ee_data1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007419
7420 ee_data1 = ee_data2;
7421 i++;
7422
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007423 } while (i < 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007424
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007425 return ee_data1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007426}
7427
7428/*---------------------------------------------------------------------
7429 *
7430 * Function: Read EEPROM Original
7431 *
7432 * Description: Read a word from the EEPROM at the desired
7433 * address.
7434 *
7435 *---------------------------------------------------------------------*/
7436
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007437static unsigned short FPT_utilEEReadOrg(unsigned long p_port,
7438 unsigned short ee_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007439{
7440
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007441 unsigned char ee_value;
7442 unsigned short i, ee_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007443
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007444 ee_value =
7445 (unsigned
7446 char)((RD_HARPOON(p_port + hp_ee_ctrl) &
7447 (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007448
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007449 FPT_utilEESendCmdAddr(p_port, EE_READ, ee_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007450
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007451 ee_value |= (SEE_MS + SEE_CS);
7452 ee_data = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007453
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007454 for (i = 1; i <= 16; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007455
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007456 ee_value |= SEE_CLK; /* Clock data! */
7457 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7458 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7459 ee_value &= ~SEE_CLK;
7460 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7461 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007462
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007463 ee_data <<= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007464
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007465 if (RD_HARPOON(p_port + hp_ee_ctrl) & SEE_DI)
7466 ee_data |= 1;
7467 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007468
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007469 ee_value &= ~(SEE_MS + SEE_CS);
7470 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */
7471 WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /*Turn off Master Select */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007472
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007473 return ee_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007474}
7475
Linus Torvalds1da177e2005-04-16 15:20:36 -07007476/*---------------------------------------------------------------------
7477 *
7478 * Function: Send EE command and Address to the EEPROM
7479 *
7480 * Description: Transfers the correct command and sends the address
7481 * to the eeprom.
7482 *
7483 *---------------------------------------------------------------------*/
7484
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007485static void FPT_utilEESendCmdAddr(unsigned long p_port, unsigned char ee_cmd,
7486 unsigned short ee_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007487{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007488 unsigned char ee_value;
7489 unsigned char narrow_flg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007490
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007491 unsigned short i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007492
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007493 narrow_flg =
7494 (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
7495 NARROW_SCSI_CARD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007496
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007497 ee_value = SEE_MS;
7498 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007499
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007500 ee_value |= SEE_CS; /* Set CS to EEPROM */
7501 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007502
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007503 for (i = 0x04; i != 0; i >>= 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007504
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007505 if (i & ee_cmd)
7506 ee_value |= SEE_DO;
7507 else
7508 ee_value &= ~SEE_DO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007509
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007510 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7511 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7512 ee_value |= SEE_CLK; /* Clock data! */
7513 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7514 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7515 ee_value &= ~SEE_CLK;
7516 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7517 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7518 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007519
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007520 if (narrow_flg)
7521 i = 0x0080;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007522
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007523 else
7524 i = 0x0200;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007525
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007526 while (i != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007527
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007528 if (i & ee_addr)
7529 ee_value |= SEE_DO;
7530 else
7531 ee_value &= ~SEE_DO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007532
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007533 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7534 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7535 ee_value |= SEE_CLK; /* Clock data! */
7536 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7537 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7538 ee_value &= ~SEE_CLK;
7539 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7540 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007541
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007542 i >>= 1;
7543 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007544}
7545
Alexey Dobriyanc823fee2006-03-08 00:14:25 -08007546static unsigned short FPT_CalcCrc16(unsigned char buffer[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07007547{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007548 unsigned short crc = 0;
7549 int i, j;
7550 unsigned short ch;
7551 for (i = 0; i < ID_STRING_LENGTH; i++) {
7552 ch = (unsigned short)buffer[i];
7553 for (j = 0; j < 8; j++) {
7554 if ((crc ^ ch) & 1)
7555 crc = (crc >> 1) ^ CRCMASK;
7556 else
7557 crc >>= 1;
7558 ch >>= 1;
7559 }
7560 }
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007561 return crc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007562}
7563
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08007564static unsigned char FPT_CalcLrc(unsigned char buffer[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07007565{
7566 int i;
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08007567 unsigned char lrc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007568 lrc = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007569 for (i = 0; i < ID_STRING_LENGTH; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007570 lrc ^= buffer[i];
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007571 return lrc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007572}
7573
Linus Torvalds1da177e2005-04-16 15:20:36 -07007574/*
7575 The following inline definitions avoid type conflicts.
7576*/
7577
7578static inline unsigned char
7579FlashPoint__ProbeHostAdapter(struct FlashPoint_Info *FlashPointInfo)
7580{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007581 return FlashPoint_ProbeHostAdapter((struct sccb_mgr_info *)
7582 FlashPointInfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007583}
7584
Linus Torvalds1da177e2005-04-16 15:20:36 -07007585static inline FlashPoint_CardHandle_T
7586FlashPoint__HardwareResetHostAdapter(struct FlashPoint_Info *FlashPointInfo)
7587{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007588 return FlashPoint_HardwareResetHostAdapter((struct sccb_mgr_info *)
7589 FlashPointInfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007590}
7591
7592static inline void
7593FlashPoint__ReleaseHostAdapter(FlashPoint_CardHandle_T CardHandle)
7594{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007595 FlashPoint_ReleaseHostAdapter(CardHandle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007596}
7597
Linus Torvalds1da177e2005-04-16 15:20:36 -07007598static inline void
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007599FlashPoint__StartCCB(FlashPoint_CardHandle_T CardHandle,
7600 struct BusLogic_CCB *CCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007601{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007602 FlashPoint_StartCCB(CardHandle, (struct sccb *)CCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007603}
7604
Linus Torvalds1da177e2005-04-16 15:20:36 -07007605static inline void
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007606FlashPoint__AbortCCB(FlashPoint_CardHandle_T CardHandle,
7607 struct BusLogic_CCB *CCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007608{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007609 FlashPoint_AbortCCB(CardHandle, (struct sccb *)CCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007610}
7611
Linus Torvalds1da177e2005-04-16 15:20:36 -07007612static inline boolean
7613FlashPoint__InterruptPending(FlashPoint_CardHandle_T CardHandle)
7614{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007615 return FlashPoint_InterruptPending(CardHandle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007616}
7617
Linus Torvalds1da177e2005-04-16 15:20:36 -07007618static inline int
7619FlashPoint__HandleInterrupt(FlashPoint_CardHandle_T CardHandle)
7620{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007621 return FlashPoint_HandleInterrupt(CardHandle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007622}
7623
Linus Torvalds1da177e2005-04-16 15:20:36 -07007624#define FlashPoint_ProbeHostAdapter FlashPoint__ProbeHostAdapter
7625#define FlashPoint_HardwareResetHostAdapter FlashPoint__HardwareResetHostAdapter
7626#define FlashPoint_ReleaseHostAdapter FlashPoint__ReleaseHostAdapter
7627#define FlashPoint_StartCCB FlashPoint__StartCCB
7628#define FlashPoint_AbortCCB FlashPoint__AbortCCB
7629#define FlashPoint_InterruptPending FlashPoint__InterruptPending
7630#define FlashPoint_HandleInterrupt FlashPoint__HandleInterrupt
7631
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007632#else /* CONFIG_SCSI_OMIT_FLASHPOINT */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007633
7634/*
7635 Define prototypes for the FlashPoint SCCB Manager Functions.
7636*/
7637
7638extern unsigned char FlashPoint_ProbeHostAdapter(struct FlashPoint_Info *);
7639extern FlashPoint_CardHandle_T
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007640FlashPoint_HardwareResetHostAdapter(struct FlashPoint_Info *);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007641extern void FlashPoint_StartCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *);
7642extern int FlashPoint_AbortCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *);
7643extern boolean FlashPoint_InterruptPending(FlashPoint_CardHandle_T);
7644extern int FlashPoint_HandleInterrupt(FlashPoint_CardHandle_T);
7645extern void FlashPoint_ReleaseHostAdapter(FlashPoint_CardHandle_T);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007646
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007647#endif /* CONFIG_SCSI_OMIT_FLASHPOINT */