blob: 90297205006370d5541fa2a55ea2527ee01713a5 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2
3 FlashPoint.c -- FlashPoint SCCB Manager for Linux
4
5 This file contains the FlashPoint SCCB Manager from BusLogic's FlashPoint
6 Driver Developer's Kit, with minor modifications by Leonard N. Zubkoff for
7 Linux compatibility. It was provided by BusLogic in the form of 16 separate
8 source files, which would have unnecessarily cluttered the scsi directory, so
9 the individual files have been combined into this single file.
10
11 Copyright 1995-1996 by Mylex Corporation. All Rights Reserved
12
13 This file is available under both the GNU General Public License
14 and a BSD-style copyright; see LICENSE.FlashPoint for details.
15
16*/
17
Linus Torvalds1da177e2005-04-16 15:20:36 -070018
Matthew Wilcox78b4b052008-03-13 06:55:08 -060019#ifdef CONFIG_SCSI_FLASHPOINT
Linus Torvalds1da177e2005-04-16 15:20:36 -070020
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#define MAX_CARDS 8
22#undef BUSTYPE_PCI
23
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#define CRCMASK 0xA001
25
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#define FAILURE 0xFFFFFFFFL
27
Alexey Dobriyan69eb2ea2006-03-08 00:14:29 -080028struct sccb;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -080029typedef void (*CALL_BK_FN) (struct sccb *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070030
Alexey Dobriyan7f101662006-03-08 00:14:30 -080031struct sccb_mgr_info {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -080032 unsigned long si_baseaddr;
33 unsigned char si_present;
34 unsigned char si_intvect;
35 unsigned char si_id;
36 unsigned char si_lun;
37 unsigned short si_fw_revision;
38 unsigned short si_per_targ_init_sync;
39 unsigned short si_per_targ_fast_nego;
40 unsigned short si_per_targ_ultra_nego;
41 unsigned short si_per_targ_no_disc;
42 unsigned short si_per_targ_wide_nego;
43 unsigned short si_flags;
44 unsigned char si_card_family;
45 unsigned char si_bustype;
46 unsigned char si_card_model[3];
47 unsigned char si_relative_cardnum;
48 unsigned char si_reserved[4];
49 unsigned long si_OS_reserved;
50 unsigned char si_XlatInfo[4];
51 unsigned long si_reserved2[5];
52 unsigned long si_secondary_range;
Alexey Dobriyan7f101662006-03-08 00:14:30 -080053};
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
James Bottomley 47b5d692005-04-24 02:38:05 -050055#define SCSI_PARITY_ENA 0x0001
56#define LOW_BYTE_TERM 0x0010
57#define HIGH_BYTE_TERM 0x0020
58#define BUSTYPE_PCI 0x3
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
60#define SUPPORT_16TAR_32LUN 0x0002
61#define SOFT_RESET 0x0004
62#define EXTENDED_TRANSLATION 0x0008
63#define POST_ALL_UNDERRRUNS 0x0040
64#define FLAG_SCAM_ENABLED 0x0080
65#define FLAG_SCAM_LEVEL2 0x0100
66
Linus Torvalds1da177e2005-04-16 15:20:36 -070067#define HARPOON_FAMILY 0x02
68
Alexey Dobriyan323579882006-01-15 02:12:54 +010069/* SCCB struct used for both SCCB and UCB manager compiles!
Linus Torvalds1da177e2005-04-16 15:20:36 -070070 * The UCB Manager treats the SCCB as it's 'native hardware structure'
71 */
72
Linus Torvalds1da177e2005-04-16 15:20:36 -070073#pragma pack(1)
Alexey Dobriyan69eb2ea2006-03-08 00:14:29 -080074struct sccb {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -080075 unsigned char OperationCode;
76 unsigned char ControlByte;
77 unsigned char CdbLength;
78 unsigned char RequestSenseLength;
79 unsigned long DataLength;
80 unsigned long DataPointer;
81 unsigned char CcbRes[2];
82 unsigned char HostStatus;
83 unsigned char TargetStatus;
84 unsigned char TargID;
85 unsigned char Lun;
86 unsigned char Cdb[12];
87 unsigned char CcbRes1;
88 unsigned char Reserved1;
89 unsigned long Reserved2;
90 unsigned long SensePointer;
Linus Torvalds1da177e2005-04-16 15:20:36 -070091
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -080092 CALL_BK_FN SccbCallback; /* VOID (*SccbCallback)(); */
93 unsigned long SccbIOPort; /* Identifies board base port */
94 unsigned char SccbStatus;
95 unsigned char SCCBRes2;
96 unsigned short SccbOSFlags;
Linus Torvalds1da177e2005-04-16 15:20:36 -070097
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -080098 unsigned long Sccb_XferCnt; /* actual transfer count */
99 unsigned long Sccb_ATC;
100 unsigned long SccbVirtDataPtr; /* virtual addr for OS/2 */
101 unsigned long Sccb_res1;
102 unsigned short Sccb_MGRFlags;
103 unsigned short Sccb_sgseg;
104 unsigned char Sccb_scsimsg; /* identify msg for selection */
105 unsigned char Sccb_tag;
106 unsigned char Sccb_scsistat;
107 unsigned char Sccb_idmsg; /* image of last msg in */
108 struct sccb *Sccb_forwardlink;
109 struct sccb *Sccb_backlink;
110 unsigned long Sccb_savedATC;
111 unsigned char Save_Cdb[6];
112 unsigned char Save_CdbLen;
113 unsigned char Sccb_XferState;
114 unsigned long Sccb_SGoffset;
115};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116
117#pragma pack()
118
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119#define SCATTER_GATHER_COMMAND 0x02
120#define RESIDUAL_COMMAND 0x03
121#define RESIDUAL_SG_COMMAND 0x04
122#define RESET_COMMAND 0x81
123
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800124#define F_USE_CMD_Q 0x20 /*Inidcates TAGGED command. */
125#define TAG_TYPE_MASK 0xC0 /*Type of tag msg to send. */
126#define SCCB_DATA_XFER_OUT 0x10 /* Write */
127#define SCCB_DATA_XFER_IN 0x08 /* Read */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800129#define NO_AUTO_REQUEST_SENSE 0x01 /* No Request Sense Buffer */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800131#define BUS_FREE_ST 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132#define SELECT_ST 1
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800133#define SELECT_BDR_ST 2 /* Select w\ Bus Device Reset */
134#define SELECT_SN_ST 3 /* Select w\ Sync Nego */
135#define SELECT_WN_ST 4 /* Select w\ Wide Data Nego */
136#define SELECT_Q_ST 5 /* Select w\ Tagged Q'ing */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137#define COMMAND_ST 6
138#define DATA_OUT_ST 7
139#define DATA_IN_ST 8
140#define DISCONNECT_ST 9
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141#define ABORT_ST 11
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143#define F_HOST_XFER_DIR 0x01
144#define F_ALL_XFERRED 0x02
145#define F_SG_XFER 0x04
146#define F_AUTO_SENSE 0x08
147#define F_ODD_BALL_CNT 0x10
148#define F_NO_DATA_YET 0x80
149
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150#define F_STATUSLOADED 0x01
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151#define F_DEV_SELECTED 0x04
152
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800153#define SCCB_COMPLETE 0x00 /* SCCB completed without error */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154#define SCCB_DATA_UNDER_RUN 0x0C
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800155#define SCCB_SELECTION_TIMEOUT 0x11 /* Set SCSI selection timed out */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156#define SCCB_DATA_OVER_RUN 0x12
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800157#define SCCB_PHASE_SEQUENCE_FAIL 0x14 /* Target bus phase sequence failure */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700158
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800159#define SCCB_GROSS_FW_ERR 0x27 /* Major problem! */
160#define SCCB_BM_ERR 0x30 /* BusMaster error. */
161#define SCCB_PARITY_ERR 0x34 /* SCSI parity error */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162
163#define SCCB_IN_PROCESS 0x00
164#define SCCB_SUCCESS 0x01
165#define SCCB_ABORT 0x02
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166#define SCCB_ERROR 0x04
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168#define ORION_FW_REV 3110
169
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800170#define QUEUE_DEPTH 254+1 /*1 for Normal disconnect 32 for Q'ing. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800172#define MAX_MB_CARDS 4 /* Max. no of cards suppoerted on Mother Board */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700173
James Bottomley 47b5d692005-04-24 02:38:05 -0500174#define MAX_SCSI_TAR 16
175#define MAX_LUN 32
176#define LUN_MASK 0x1f
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800178#define SG_BUF_CNT 16 /*Number of prefetched elements. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800180#define SG_ELEMENT_SIZE 8 /*Eight byte per element. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181
Alexey Dobriyanad0e1d92006-03-08 00:14:28 -0800182#define RD_HARPOON(ioport) inb((u32)ioport)
183#define RDW_HARPOON(ioport) inw((u32)ioport)
184#define RD_HARP32(ioport,offset,data) (data = inl((u32)(ioport + offset)))
185#define WR_HARPOON(ioport,val) outb((u8) val, (u32)ioport)
186#define WRW_HARPOON(ioport,val) outw((u16)val, (u32)ioport)
187#define WR_HARP32(ioport,offset,data) outl(data, (u32)(ioport + offset))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189#define TAR_SYNC_MASK (BIT(7)+BIT(6))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190#define SYNC_TRYING BIT(6)
191#define SYNC_SUPPORTED (BIT(7)+BIT(6))
192
193#define TAR_WIDE_MASK (BIT(5)+BIT(4))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194#define WIDE_ENABLED BIT(4)
195#define WIDE_NEGOCIATED BIT(5)
196
197#define TAR_TAG_Q_MASK (BIT(3)+BIT(2))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198#define TAG_Q_TRYING BIT(2)
199#define TAG_Q_REJECT BIT(3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200
201#define TAR_ALLOW_DISC BIT(0)
202
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203#define EE_SYNC_MASK (BIT(0)+BIT(1))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204#define EE_SYNC_5MB BIT(0)
205#define EE_SYNC_10MB BIT(1)
206#define EE_SYNC_20MB (BIT(0)+BIT(1))
207
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208#define EE_WIDE_SCSI BIT(7)
209
Alexey Dobriyanf31dc0cd2006-03-08 00:14:31 -0800210struct sccb_mgr_tar_info {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800212 struct sccb *TarSelQ_Head;
213 struct sccb *TarSelQ_Tail;
214 unsigned char TarLUN_CA; /*Contingent Allgiance */
215 unsigned char TarTagQ_Cnt;
216 unsigned char TarSelQ_Cnt;
217 unsigned char TarStatus;
218 unsigned char TarEEValue;
219 unsigned char TarSyncCtrl;
220 unsigned char TarReserved[2]; /* for alignment */
221 unsigned char LunDiscQ_Idx[MAX_LUN];
222 unsigned char TarLUNBusy[MAX_LUN];
Alexey Dobriyanf31dc0cd2006-03-08 00:14:31 -0800223};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224
Alexey Dobriyan68d0c1a2006-03-08 00:14:33 -0800225struct nvram_info {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800226 unsigned char niModel; /* Model No. of card */
227 unsigned char niCardNo; /* Card no. */
228 unsigned long niBaseAddr; /* Port Address of card */
229 unsigned char niSysConf; /* Adapter Configuration byte - Byte 16 of eeprom map */
230 unsigned char niScsiConf; /* SCSI Configuration byte - Byte 17 of eeprom map */
231 unsigned char niScamConf; /* SCAM Configuration byte - Byte 20 of eeprom map */
232 unsigned char niAdapId; /* Host Adapter ID - Byte 24 of eerpom map */
233 unsigned char niSyncTbl[MAX_SCSI_TAR / 2]; /* Sync/Wide byte of targets */
234 unsigned char niScamTbl[MAX_SCSI_TAR][4]; /* Compressed Scam name string of Targets */
Alexey Dobriyan68d0c1a2006-03-08 00:14:33 -0800235};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237#define MODEL_LT 1
238#define MODEL_DL 2
239#define MODEL_LW 3
240#define MODEL_DW 4
241
Alexey Dobriyan13e68512006-03-08 00:14:34 -0800242struct sccb_card {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800243 struct sccb *currentSCCB;
244 struct sccb_mgr_info *cardInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800246 unsigned long ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800248 unsigned short cmdCounter;
249 unsigned char discQCount;
250 unsigned char tagQ_Lst;
251 unsigned char cardIndex;
252 unsigned char scanIndex;
253 unsigned char globalFlags;
254 unsigned char ourId;
255 struct nvram_info *pNvRamInfo;
256 struct sccb *discQ_Tbl[QUEUE_DEPTH];
257
Alexey Dobriyan13e68512006-03-08 00:14:34 -0800258};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260#define F_TAG_STARTED 0x01
261#define F_CONLUN_IO 0x02
262#define F_DO_RENEGO 0x04
263#define F_NO_FILTER 0x08
264#define F_GREEN_PC 0x10
265#define F_HOST_XFER_ACT 0x20
266#define F_NEW_SCCB_CMD 0x40
267#define F_UPDATE_EEPROM 0x80
268
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269#define ID_STRING_LENGTH 32
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800270#define TYPE_CODE0 0x63 /*Level2 Mstr (bits 7-6), */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800272#define SLV_TYPE_CODE0 0xA3 /*Priority Bit set (bits 7-6), */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273
274#define ASSIGN_ID 0x00
275#define SET_P_FLAG 0x01
276#define CFG_CMPLT 0x03
277#define DOM_MSTR 0x0F
278#define SYNC_PTRN 0x1F
279
280#define ID_0_7 0x18
281#define ID_8_F 0x11
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282#define MISC_CODE 0x14
283#define CLR_P_FLAG 0x18
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285#define INIT_SELTD 0x01
286#define LEVEL2_TAR 0x02
287
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800288enum scam_id_st { ID0, ID1, ID2, ID3, ID4, ID5, ID6, ID7, ID8, ID9, ID10, ID11,
289 ID12,
290 ID13, ID14, ID15, ID_UNUSED, ID_UNASSIGNED, ID_ASSIGNED, LEGACY,
291 CLR_PRIORITY, NO_ID_AVAIL
292};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293
294typedef struct SCCBscam_info {
295
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800296 unsigned char id_string[ID_STRING_LENGTH];
297 enum scam_id_st state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800299} SCCBSCAM_INFO;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301#define SCSI_REQUEST_SENSE 0x03
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302#define SCSI_READ 0x08
303#define SCSI_WRITE 0x0A
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304#define SCSI_START_STOP_UNIT 0x1B
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305#define SCSI_READ_EXTENDED 0x28
306#define SCSI_WRITE_EXTENDED 0x2A
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307#define SCSI_WRITE_AND_VERIFY 0x2E
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309#define SSGOOD 0x00
310#define SSCHECK 0x02
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311#define SSQ_FULL 0x28
312
Linus Torvalds1da177e2005-04-16 15:20:36 -0700313#define SMCMD_COMP 0x00
314#define SMEXT 0x01
315#define SMSAVE_DATA_PTR 0x02
316#define SMREST_DATA_PTR 0x03
317#define SMDISC 0x04
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318#define SMABORT 0x06
319#define SMREJECT 0x07
320#define SMNO_OP 0x08
321#define SMPARITY 0x09
322#define SMDEV_RESET 0x0C
323#define SMABORT_TAG 0x0D
324#define SMINIT_RECOVERY 0x0F
325#define SMREL_RECOVERY 0x10
326
327#define SMIDENT 0x80
328#define DISC_PRIV 0x40
329
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330#define SMSYNC 0x01
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331#define SMWDTR 0x03
332#define SM8BIT 0x00
333#define SM16BIT 0x01
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800334#define SMIGNORWR 0x23 /* Ignore Wide Residue */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335
336#define SIX_BYTE_CMD 0x06
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337#define TWELVE_BYTE_CMD 0x0C
338
339#define ASYNC 0x00
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800340#define MAX_OFFSET 0x0F /* Maxbyteoffset for Sync Xfers */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341
342#define EEPROM_WD_CNT 256
343
344#define EEPROM_CHECK_SUM 0
345#define FW_SIGNATURE 2
346#define MODEL_NUMB_0 4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347#define MODEL_NUMB_2 6
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348#define MODEL_NUMB_4 8
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349#define SYSTEM_CONFIG 16
350#define SCSI_CONFIG 17
351#define BIOS_CONFIG 18
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352#define SCAM_CONFIG 20
353#define ADAPTER_SCSI_ID 24
354
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355#define IGNORE_B_SCAN 32
356#define SEND_START_ENA 34
357#define DEVICE_ENABLE 36
358
359#define SYNC_RATE_TBL 38
360#define SYNC_RATE_TBL01 38
361#define SYNC_RATE_TBL23 40
362#define SYNC_RATE_TBL45 42
363#define SYNC_RATE_TBL67 44
364#define SYNC_RATE_TBL89 46
365#define SYNC_RATE_TBLab 48
366#define SYNC_RATE_TBLcd 50
367#define SYNC_RATE_TBLef 52
368
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800369#define EE_SCAMBASE 256
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800371#define SCAM_ENABLED BIT(2)
372#define SCAM_LEVEL2 BIT(3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373
Jiri Slaby1cafc302007-10-18 23:40:36 -0700374#define RENEGO_ENA BIT(10)
375#define CONNIO_ENA BIT(11)
376#define GREEN_PC_ENA BIT(12)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800378#define AUTO_RATE_00 00
379#define AUTO_RATE_05 01
380#define AUTO_RATE_10 02
381#define AUTO_RATE_20 03
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800383#define WIDE_NEGO_BIT BIT(7)
384#define DISC_ENABLE_BIT BIT(6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800386#define hp_vendor_id_0 0x00 /* LSB */
387#define ORION_VEND_0 0x4B
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800389#define hp_vendor_id_1 0x01 /* MSB */
390#define ORION_VEND_1 0x10
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800392#define hp_device_id_0 0x02 /* LSB */
393#define ORION_DEV_0 0x30
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800395#define hp_device_id_1 0x03 /* MSB */
396#define ORION_DEV_1 0x81
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397
398 /* Sub Vendor ID and Sub Device ID only available in
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800399 Harpoon Version 2 and higher */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800401#define hp_sub_device_id_0 0x06 /* LSB */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800403#define hp_semaphore 0x0C
404#define SCCB_MGR_ACTIVE BIT(0)
405#define TICKLE_ME BIT(1)
406#define SCCB_MGR_PRESENT BIT(3)
407#define BIOS_IN_USE BIT(4)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800409#define hp_sys_ctrl 0x0F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800411#define STOP_CLK BIT(0) /*Turn off BusMaster Clock */
412#define DRVR_RST BIT(1) /*Firmware Reset to 80C15 chip */
413#define HALT_MACH BIT(3) /*Halt State Machine */
414#define HARD_ABORT BIT(4) /*Hard Abort */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800416#define hp_host_blk_cnt 0x13
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800418#define XFER_BLK64 0x06 /* 1 1 0 64 byte per block */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800420#define BM_THRESHOLD 0x40 /* PCI mode can only xfer 16 bytes */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800422#define hp_int_mask 0x17
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800424#define INT_CMD_COMPL BIT(0) /* DMA command complete */
425#define INT_EXT_STATUS BIT(1) /* Extended Status Set */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800427#define hp_xfer_cnt_lo 0x18
428#define hp_xfer_cnt_hi 0x1A
429#define hp_xfer_cmd 0x1B
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800431#define XFER_HOST_DMA 0x00 /* 0 0 0 Transfer Host -> DMA */
432#define XFER_DMA_HOST 0x01 /* 0 0 1 Transfer DMA -> Host */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800434#define XFER_HOST_AUTO 0x00 /* 0 0 Auto Transfer Size */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800436#define XFER_DMA_8BIT 0x20 /* 0 1 8 BIT Transfer Size */
Alexey Dobriyan85ae97d82006-03-08 00:14:22 -0800437
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800438#define DISABLE_INT BIT(7) /*Do not interrupt at end of cmd. */
Alexey Dobriyan85ae97d82006-03-08 00:14:22 -0800439
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800440#define HOST_WRT_CMD ((DISABLE_INT + XFER_HOST_DMA + XFER_HOST_AUTO + XFER_DMA_8BIT))
441#define HOST_RD_CMD ((DISABLE_INT + XFER_DMA_HOST + XFER_HOST_AUTO + XFER_DMA_8BIT))
Alexey Dobriyan85ae97d82006-03-08 00:14:22 -0800442
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800443#define hp_host_addr_lo 0x1C
444#define hp_host_addr_hmi 0x1E
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800446#define hp_ee_ctrl 0x22
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800448#define EXT_ARB_ACK BIT(7)
449#define SCSI_TERM_ENA_H BIT(6) /* SCSI high byte terminator */
450#define SEE_MS BIT(5)
451#define SEE_CS BIT(3)
452#define SEE_CLK BIT(2)
453#define SEE_DO BIT(1)
454#define SEE_DI BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800456#define EE_READ 0x06
457#define EE_WRITE 0x05
458#define EWEN 0x04
459#define EWEN_ADDR 0x03C0
460#define EWDS 0x04
461#define EWDS_ADDR 0x0000
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800463#define hp_bm_ctrl 0x26
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800465#define SCSI_TERM_ENA_L BIT(0) /*Enable/Disable external terminators */
466#define FLUSH_XFER_CNTR BIT(1) /*Flush transfer counter */
467#define FORCE1_XFER BIT(5) /*Always xfer one byte in byte mode */
468#define FAST_SINGLE BIT(6) /*?? */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800470#define BMCTRL_DEFAULT (FORCE1_XFER|FAST_SINGLE|SCSI_TERM_ENA_L)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800472#define hp_sg_addr 0x28
473#define hp_page_ctrl 0x29
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800475#define SCATTER_EN BIT(0)
476#define SGRAM_ARAM BIT(1)
477#define G_INT_DISABLE BIT(3) /* Enable/Disable all Interrupts */
478#define NARROW_SCSI_CARD BIT(4) /* NARROW/WIDE SCSI config pin */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800480#define hp_pci_stat_cfg 0x2D
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800482#define REC_MASTER_ABORT BIT(5) /*received Master abort */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800484#define hp_rev_num 0x33
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800486#define hp_stack_data 0x34
487#define hp_stack_addr 0x35
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800489#define hp_ext_status 0x36
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800491#define BM_FORCE_OFF BIT(0) /*Bus Master is forced to get off */
492#define PCI_TGT_ABORT BIT(0) /*PCI bus master transaction aborted */
493#define PCI_DEV_TMOUT BIT(1) /*PCI Device Time out */
494#define CMD_ABORTED BIT(4) /*Command aborted */
495#define BM_PARITY_ERR BIT(5) /*parity error on data received */
496#define PIO_OVERRUN BIT(6) /*Slave data overrun */
497#define BM_CMD_BUSY BIT(7) /*Bus master transfer command busy */
498#define BAD_EXT_STATUS (BM_FORCE_OFF | PCI_DEV_TMOUT | CMD_ABORTED | \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 BM_PARITY_ERR | PIO_OVERRUN)
500
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800501#define hp_int_status 0x37
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800503#define EXT_STATUS_ON BIT(1) /*Extended status is valid */
504#define SCSI_INTERRUPT BIT(2) /*Global indication of a SCSI int. */
505#define INT_ASSERTED BIT(5) /* */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800507#define hp_fifo_cnt 0x38
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800509#define hp_intena 0x40
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510
Jiri Slaby1cafc302007-10-18 23:40:36 -0700511#define RESET BIT(7)
512#define PROG_HLT BIT(6)
513#define PARITY BIT(5)
514#define FIFO BIT(4)
515#define SEL BIT(3)
516#define SCAM_SEL BIT(2)
517#define RSEL BIT(1)
518#define TIMEOUT BIT(0)
519#define BUS_FREE BIT(15)
520#define XFER_CNT_0 BIT(14)
521#define PHASE BIT(13)
522#define IUNKWN BIT(12)
523#define ICMD_COMP BIT(11)
524#define ITICKLE BIT(10)
525#define IDO_STRT BIT(9)
526#define ITAR_DISC BIT(8)
527#define AUTO_INT (BIT(12)+BIT(11)+BIT(10)+BIT(9)+BIT(8))
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800528#define CLR_ALL_INT 0xFFFF
529#define CLR_ALL_INT_1 0xFF00
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800531#define hp_intstat 0x42
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800533#define hp_scsisig 0x44
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800535#define SCSI_SEL BIT(7)
536#define SCSI_BSY BIT(6)
537#define SCSI_REQ BIT(5)
538#define SCSI_ACK BIT(4)
539#define SCSI_ATN BIT(3)
540#define SCSI_CD BIT(2)
541#define SCSI_MSG BIT(1)
542#define SCSI_IOBIT BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800544#define S_SCSI_PHZ (BIT(2)+BIT(1)+BIT(0))
545#define S_MSGO_PH (BIT(2)+BIT(1) )
546#define S_MSGI_PH (BIT(2)+BIT(1)+BIT(0))
547#define S_DATAI_PH ( BIT(0))
548#define S_DATAO_PH 0x00
549#define S_ILL_PH ( BIT(1) )
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800551#define hp_scsictrl_0 0x45
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800553#define SEL_TAR BIT(6)
554#define ENA_ATN BIT(4)
555#define ENA_RESEL BIT(2)
556#define SCSI_RST BIT(1)
557#define ENA_SCAM_SEL BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800559#define hp_portctrl_0 0x46
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800561#define SCSI_PORT BIT(7)
562#define SCSI_INBIT BIT(6)
563#define DMA_PORT BIT(5)
564#define DMA_RD BIT(4)
565#define HOST_PORT BIT(3)
566#define HOST_WRT BIT(2)
567#define SCSI_BUS_EN BIT(1)
568#define START_TO BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800570#define hp_scsireset 0x47
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800572#define SCSI_INI BIT(6)
573#define SCAM_EN BIT(5)
574#define DMA_RESET BIT(3)
575#define HPSCSI_RESET BIT(2)
576#define PROG_RESET BIT(1)
577#define FIFO_CLR BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800579#define hp_xfercnt_0 0x48
580#define hp_xfercnt_2 0x4A
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800582#define hp_fifodata_0 0x4C
583#define hp_addstat 0x4E
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800585#define SCAM_TIMER BIT(7)
586#define SCSI_MODE8 BIT(3)
587#define SCSI_PAR_ERR BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800589#define hp_prgmcnt_0 0x4F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800591#define hp_selfid_0 0x50
592#define hp_selfid_1 0x51
593#define hp_arb_id 0x52
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800595#define hp_select_id 0x53
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800597#define hp_synctarg_base 0x54
598#define hp_synctarg_12 0x54
599#define hp_synctarg_13 0x55
600#define hp_synctarg_14 0x56
601#define hp_synctarg_15 0x57
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800603#define hp_synctarg_8 0x58
604#define hp_synctarg_9 0x59
605#define hp_synctarg_10 0x5A
606#define hp_synctarg_11 0x5B
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800608#define hp_synctarg_4 0x5C
609#define hp_synctarg_5 0x5D
610#define hp_synctarg_6 0x5E
611#define hp_synctarg_7 0x5F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800613#define hp_synctarg_0 0x60
614#define hp_synctarg_1 0x61
615#define hp_synctarg_2 0x62
616#define hp_synctarg_3 0x63
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800618#define NARROW_SCSI BIT(4)
619#define DEFAULT_OFFSET 0x0F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800621#define hp_autostart_0 0x64
622#define hp_autostart_1 0x65
623#define hp_autostart_3 0x67
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800625#define AUTO_IMMED BIT(5)
626#define SELECT BIT(6)
627#define END_DATA (BIT(7)+BIT(6))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800629#define hp_gp_reg_0 0x68
630#define hp_gp_reg_1 0x69
631#define hp_gp_reg_3 0x6B
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800633#define hp_seltimeout 0x6C
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800635#define TO_4ms 0x67 /* 3.9959ms */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800637#define TO_5ms 0x03 /* 4.9152ms */
638#define TO_10ms 0x07 /* 11.xxxms */
639#define TO_250ms 0x99 /* 250.68ms */
640#define TO_290ms 0xB1 /* 289.99ms */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800642#define hp_clkctrl_0 0x6D
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800644#define PWR_DWN BIT(6)
645#define ACTdeassert BIT(4)
646#define CLK_40MHZ (BIT(1) + BIT(0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800648#define CLKCTRL_DEFAULT (ACTdeassert | CLK_40MHZ)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800650#define hp_fiforead 0x6E
651#define hp_fifowrite 0x6F
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800653#define hp_offsetctr 0x70
654#define hp_xferstat 0x71
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800656#define FIFO_EMPTY BIT(6)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800658#define hp_portctrl_1 0x72
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800660#define CHK_SCSI_P BIT(3)
661#define HOST_MODE8 BIT(0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800663#define hp_xfer_pad 0x73
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800665#define ID_UNLOCK BIT(3)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800667#define hp_scsidata_0 0x74
668#define hp_scsidata_1 0x75
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800670#define hp_aramBase 0x80
671#define BIOS_DATA_OFFSET 0x60
672#define BIOS_RELATIVE_CARD 0x64
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673
Jiri Slaby1cafc302007-10-18 23:40:36 -0700674#define AR3 (BIT(9) + BIT(8))
675#define SDATA BIT(10)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676
Jiri Slaby1cafc302007-10-18 23:40:36 -0700677#define CRD_OP BIT(11) /* Cmp Reg. w/ Data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678
Jiri Slaby1cafc302007-10-18 23:40:36 -0700679#define CRR_OP BIT(12) /* Cmp Reg. w. Reg. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680
Jiri Slaby1cafc302007-10-18 23:40:36 -0700681#define CPE_OP (BIT(14)+BIT(11)) /* Cmp SCSI phs & Branch EQ */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682
Jiri Slaby1cafc302007-10-18 23:40:36 -0700683#define CPN_OP (BIT(14)+BIT(12)) /* Cmp SCSI phs & Branch NOT EQ */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800685#define ADATA_OUT 0x00
Jiri Slaby1cafc302007-10-18 23:40:36 -0700686#define ADATA_IN BIT(8)
687#define ACOMMAND BIT(10)
688#define ASTATUS (BIT(10)+BIT(8))
689#define AMSG_OUT (BIT(10)+BIT(9))
690#define AMSG_IN (BIT(10)+BIT(9)+BIT(8))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691
Jiri Slaby1cafc302007-10-18 23:40:36 -0700692#define BRH_OP BIT(13) /* Branch */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800694#define ALWAYS 0x00
Jiri Slaby1cafc302007-10-18 23:40:36 -0700695#define EQUAL BIT(8)
696#define NOT_EQ BIT(9)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697
Jiri Slaby1cafc302007-10-18 23:40:36 -0700698#define TCB_OP (BIT(13)+BIT(11)) /* Test condition & branch */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699
Jiri Slaby1cafc302007-10-18 23:40:36 -0700700#define FIFO_0 BIT(10)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701
Jiri Slaby1cafc302007-10-18 23:40:36 -0700702#define MPM_OP BIT(15) /* Match phase and move data */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703
Jiri Slaby1cafc302007-10-18 23:40:36 -0700704#define MRR_OP BIT(14) /* Move DReg. to Reg. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800706#define S_IDREG (BIT(2)+BIT(1)+BIT(0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800708#define D_AR0 0x00
709#define D_AR1 BIT(0)
710#define D_BUCKET (BIT(2) + BIT(1) + BIT(0))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711
Jiri Slaby1cafc302007-10-18 23:40:36 -0700712#define RAT_OP (BIT(14)+BIT(13)+BIT(11))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713
Jiri Slaby1cafc302007-10-18 23:40:36 -0700714#define SSI_OP (BIT(15)+BIT(11))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800716#define SSI_ITAR_DISC (ITAR_DISC >> 8)
717#define SSI_IDO_STRT (IDO_STRT >> 8)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800719#define SSI_ICMD_COMP (ICMD_COMP >> 8)
720#define SSI_ITICKLE (ITICKLE >> 8)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800722#define SSI_IUNKWN (IUNKWN >> 8)
723#define SSI_INO_CC (IUNKWN >> 8)
724#define SSI_IRFAIL (IUNKWN >> 8)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800726#define NP 0x10 /*Next Phase */
727#define NTCMD 0x02 /*Non- Tagged Command start */
728#define CMDPZ 0x04 /*Command phase */
729#define DINT 0x12 /*Data Out/In interrupt */
730#define DI 0x13 /*Data Out */
731#define DC 0x19 /*Disconnect Message */
732#define ST 0x1D /*Status Phase */
733#define UNKNWN 0x24 /*Unknown bus action */
734#define CC 0x25 /*Command Completion failure */
735#define TICK 0x26 /*New target reselected us. */
736#define SELCHK 0x28 /*Select & Check SCSI ID latch reg */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800738#define ID_MSG_STRT hp_aramBase + 0x00
739#define NON_TAG_ID_MSG hp_aramBase + 0x06
740#define CMD_STRT hp_aramBase + 0x08
741#define SYNC_MSGS hp_aramBase + 0x08
Alexey Dobriyan85ae97d82006-03-08 00:14:22 -0800742
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800743#define TAG_STRT 0x00
744#define DISCONNECT_START 0x10/2
745#define END_DATA_START 0x14/2
746#define CMD_ONLY_STRT CMDPZ/2
747#define SELCHK_STRT SELCHK/2
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748
749#define GET_XFER_CNT(port, xfercnt) {RD_HARP32(port,hp_xfercnt_0,xfercnt); xfercnt &= 0xFFFFFF;}
750/* #define GET_XFER_CNT(port, xfercnt) (xfercnt = RD_HARPOON(port+hp_xfercnt_2), \
751 xfercnt <<= 16,\
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800752 xfercnt |= RDW_HARPOON((unsigned short)(port+hp_xfercnt_0)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 */
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800754#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 -0700755 addr >>= 16,\
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800756 WRW_HARPOON((port+hp_host_addr_hmi), (unsigned short)(addr & 0x0000FFFFL)),\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757 WR_HARP32(port,hp_xfercnt_0,count),\
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800758 WRW_HARPOON((port+hp_xfer_cnt_lo), (unsigned short)(count & 0x0000FFFFL)),\
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 count >>= 16,\
760 WR_HARPOON(port+hp_xfer_cnt_hi, (count & 0xFF)))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761
762#define ACCEPT_MSG(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
763 WR_HARPOON(port+hp_scsisig, S_ILL_PH);}
764
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765#define ACCEPT_MSG_ATN(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
766 WR_HARPOON(port+hp_scsisig, (S_ILL_PH|SCSI_ATN));}
767
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768#define DISABLE_AUTO(port) (WR_HARPOON(port+hp_scsireset, PROG_RESET),\
769 WR_HARPOON(port+hp_scsireset, 0x00))
770
771#define ARAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
772 (RD_HARPOON(p_port+hp_page_ctrl) | SGRAM_ARAM)))
773
774#define SGRAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
775 (RD_HARPOON(p_port+hp_page_ctrl) & ~SGRAM_ARAM)))
776
777#define MDISABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
778 (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE)))
779
780#define MENABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
781 (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE)))
782
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800783static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card,
784 unsigned char syncFlag);
785static void FPT_ssel(unsigned long port, unsigned char p_card);
786static void FPT_sres(unsigned long port, unsigned char p_card,
787 struct sccb_card *pCurrCard);
788static void FPT_shandem(unsigned long port, unsigned char p_card,
789 struct sccb *pCurrSCCB);
790static void FPT_stsyncn(unsigned long port, unsigned char p_card);
791static void FPT_sisyncr(unsigned long port, unsigned char sync_pulse,
792 unsigned char offset);
793static void FPT_sssyncv(unsigned long p_port, unsigned char p_id,
794 unsigned char p_sync_value,
795 struct sccb_mgr_tar_info *currTar_Info);
796static void FPT_sresb(unsigned long port, unsigned char p_card);
797static void FPT_sxfrp(unsigned long p_port, unsigned char p_card);
798static void FPT_schkdd(unsigned long port, unsigned char p_card);
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -0800799static unsigned char FPT_RdStack(unsigned long port, unsigned char index);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800800static void FPT_WrStack(unsigned long portBase, unsigned char index,
801 unsigned char data);
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -0800802static unsigned char FPT_ChkIfChipInitialized(unsigned long ioPort);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -0800804static void FPT_SendMsg(unsigned long port, unsigned char message);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800805static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
806 unsigned char error_code);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800808static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card);
809static void FPT_RNVRamData(struct nvram_info *pNvRamInfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -0800811static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800812static void FPT_stwidn(unsigned long port, unsigned char p_card);
813static void FPT_siwidr(unsigned long port, unsigned char width);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800815static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
816 unsigned char p_card);
817static void FPT_queueDisconnect(struct sccb *p_SCCB, unsigned char p_card);
818static void FPT_queueCmdComplete(struct sccb_card *pCurrCard,
819 struct sccb *p_SCCB, unsigned char p_card);
820static void FPT_queueSearchSelect(struct sccb_card *pCurrCard,
Alexey Dobriyandb038cf2006-03-08 00:14:24 -0800821 unsigned char p_card);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800822static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code);
823static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char card);
824static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB,
825 unsigned char p_card);
826static void FPT_utilUpdateResidual(struct sccb *p_SCCB);
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800827static unsigned short FPT_CalcCrc16(unsigned char buffer[]);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800828static unsigned char FPT_CalcLrc(unsigned char buffer[]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800830static void FPT_Wait1Second(unsigned long p_port);
831static void FPT_Wait(unsigned long p_port, unsigned char p_delay);
832static void FPT_utilEEWriteOnOff(unsigned long p_port, unsigned char p_mode);
833static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data,
834 unsigned short ee_addr);
835static unsigned short FPT_utilEERead(unsigned long p_port,
836 unsigned short ee_addr);
837static unsigned short FPT_utilEEReadOrg(unsigned long p_port,
838 unsigned short ee_addr);
839static void FPT_utilEESendCmdAddr(unsigned long p_port, unsigned char ee_cmd,
840 unsigned short ee_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800842static void FPT_phaseDataOut(unsigned long port, unsigned char p_card);
843static void FPT_phaseDataIn(unsigned long port, unsigned char p_card);
844static void FPT_phaseCommand(unsigned long port, unsigned char p_card);
845static void FPT_phaseStatus(unsigned long port, unsigned char p_card);
846static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card);
847static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card);
848static void FPT_phaseIllegal(unsigned long port, unsigned char p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800850static void FPT_phaseDecode(unsigned long port, unsigned char p_card);
851static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card);
852static void FPT_phaseBusFree(unsigned long p_port, unsigned char p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800854static void FPT_XbowInit(unsigned long port, unsigned char scamFlg);
855static void FPT_BusMasterInit(unsigned long p_port);
856static void FPT_DiagEEPROM(unsigned long p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800858static void FPT_dataXferProcessor(unsigned long port,
859 struct sccb_card *pCurrCard);
860static void FPT_busMstrSGDataXferStart(unsigned long port,
861 struct sccb *pCurrSCCB);
862static void FPT_busMstrDataXferStart(unsigned long port,
863 struct sccb *pCurrSCCB);
864static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card,
865 struct sccb *pCurrSCCB);
866static void FPT_hostDataXferRestart(struct sccb *currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800868static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port,
869 unsigned char p_card,
870 struct sccb_card *pCurrCard,
871 unsigned short p_int);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800873static void FPT_SccbMgrTableInitAll(void);
874static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard,
875 unsigned char p_card);
876static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
877 unsigned char target);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800879static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
880 unsigned char p_power_up);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800882static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type);
883static void FPT_scbusf(unsigned long p_port);
884static void FPT_scsel(unsigned long p_port);
885static void FPT_scasid(unsigned char p_card, unsigned long p_port);
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -0800886static unsigned char FPT_scxferc(unsigned long p_port, unsigned char p_data);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800887static unsigned char FPT_scsendi(unsigned long p_port,
888 unsigned char p_id_string[]);
889static unsigned char FPT_sciso(unsigned long p_port,
890 unsigned char p_id_string[]);
891static void FPT_scwirod(unsigned long p_port, unsigned char p_data_bit);
892static void FPT_scwiros(unsigned long p_port, unsigned char p_data_bit);
Alexey Dobriyandb038cf2006-03-08 00:14:24 -0800893static unsigned char FPT_scvalq(unsigned char p_quintet);
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -0800894static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800895static void FPT_scwtsel(unsigned long p_port);
896static void FPT_inisci(unsigned char p_card, unsigned long p_port,
897 unsigned char p_our_id);
898static void FPT_scsavdi(unsigned char p_card, unsigned long p_port);
899static unsigned char FPT_scmachid(unsigned char p_card,
900 unsigned char p_id_string[]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800902static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card);
903static void FPT_autoLoadDefaultMap(unsigned long p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800905static struct sccb_mgr_tar_info FPT_sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] =
906 { {{0}} };
907static struct sccb_card FPT_BL_Card[MAX_CARDS] = { {0} };
908static SCCBSCAM_INFO FPT_scamInfo[MAX_SCSI_TAR] = { {{0}} };
909static struct nvram_info FPT_nvRamInfo[MAX_MB_CARDS] = { {0} };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910
Alexey Dobriyandb038cf2006-03-08 00:14:24 -0800911static unsigned char FPT_mbCards = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800912static unsigned char FPT_scamHAString[] =
913 { 0x63, 0x07, 'B', 'U', 'S', 'L', 'O', 'G', 'I', 'C',
914 ' ', 'B', 'T', '-', '9', '3', '0',
915 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
916 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
917};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918
Alexey Dobriyanc823fee2006-03-08 00:14:25 -0800919static unsigned short FPT_default_intena = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800921static void (*FPT_s_PhaseTbl[8]) (unsigned long, unsigned char) = {
9220};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923
924/*---------------------------------------------------------------------
925 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -0800926 * Function: FlashPoint_ProbeHostAdapter
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 *
928 * Description: Setup and/or Search for cards and return info to caller.
929 *
930 *---------------------------------------------------------------------*/
931
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800932static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800934 static unsigned char first_time = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800936 unsigned char i, j, id, ScamFlg;
937 unsigned short temp, temp2, temp3, temp4, temp5, temp6;
938 unsigned long ioport;
939 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800941 ioport = pCardInfo->si_baseaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800943 if (RD_HARPOON(ioport + hp_vendor_id_0) != ORION_VEND_0)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800944 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800946 if ((RD_HARPOON(ioport + hp_vendor_id_1) != ORION_VEND_1))
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_device_id_0) != ORION_DEV_0))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800950 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800952 if ((RD_HARPOON(ioport + hp_device_id_1) != ORION_DEV_1))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800953 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800955 if (RD_HARPOON(ioport + hp_rev_num) != 0x0f) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956
957/* For new Harpoon then check for sub_device ID LSB
958 the bits(0-3) must be all ZERO for compatible with
959 current version of SCCBMgr, else skip this Harpoon
960 device. */
961
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800962 if (RD_HARPOON(ioport + hp_sub_device_id_0) & 0x0f)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800963 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 }
965
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800966 if (first_time) {
967 FPT_SccbMgrTableInitAll();
968 first_time = 0;
James Bottomley 47b5d692005-04-24 02:38:05 -0500969 FPT_mbCards = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800970 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800972 if (FPT_RdStack(ioport, 0) != 0x00) {
973 if (FPT_ChkIfChipInitialized(ioport) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 pCurrNvRam = NULL;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800975 WR_HARPOON(ioport + hp_semaphore, 0x00);
976 FPT_XbowInit(ioport, 0); /*Must Init the SCSI before attempting */
James Bottomley 47b5d692005-04-24 02:38:05 -0500977 FPT_DiagEEPROM(ioport);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800978 } else {
979 if (FPT_mbCards < MAX_MB_CARDS) {
James Bottomley 47b5d692005-04-24 02:38:05 -0500980 pCurrNvRam = &FPT_nvRamInfo[FPT_mbCards];
981 FPT_mbCards++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 pCurrNvRam->niBaseAddr = ioport;
James Bottomley 47b5d692005-04-24 02:38:05 -0500983 FPT_RNVRamData(pCurrNvRam);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800984 } else
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -0800985 return (int)FAILURE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800987 } else
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 pCurrNvRam = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800990 WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT);
991 WR_HARPOON(ioport + hp_sys_ctrl, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800993 if (pCurrNvRam)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 pCardInfo->si_id = pCurrNvRam->niAdapId;
995 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -0800996 pCardInfo->si_id =
997 (unsigned
998 char)(FPT_utilEERead(ioport,
999 (ADAPTER_SCSI_ID /
1000 2)) & (unsigned char)0x0FF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001002 pCardInfo->si_lun = 0x00;
1003 pCardInfo->si_fw_revision = ORION_FW_REV;
1004 temp2 = 0x0000;
1005 temp3 = 0x0000;
1006 temp4 = 0x0000;
1007 temp5 = 0x0000;
1008 temp6 = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001010 for (id = 0; id < (16 / 2); id++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001012 if (pCurrNvRam) {
1013 temp = (unsigned short)pCurrNvRam->niSyncTbl[id];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001015 (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
1016 } else
1017 temp =
1018 FPT_utilEERead(ioport,
1019 (unsigned short)((SYNC_RATE_TBL / 2)
1020 + id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001022 for (i = 0; i < 2; temp >>= 8, i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001024 temp2 >>= 1;
1025 temp3 >>= 1;
1026 temp4 >>= 1;
1027 temp5 >>= 1;
1028 temp6 >>= 1;
1029 switch (temp & 0x3) {
1030 case AUTO_RATE_20: /* Synchronous, 20 mega-transfers/second */
1031 temp6 |= 0x8000; /* Fall through */
1032 case AUTO_RATE_10: /* Synchronous, 10 mega-transfers/second */
1033 temp5 |= 0x8000; /* Fall through */
1034 case AUTO_RATE_05: /* Synchronous, 5 mega-transfers/second */
1035 temp2 |= 0x8000; /* Fall through */
1036 case AUTO_RATE_00: /* Asynchronous */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 break;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001038 }
1039
1040 if (temp & DISC_ENABLE_BIT)
1041 temp3 |= 0x8000;
1042
1043 if (temp & WIDE_NEGO_BIT)
1044 temp4 |= 0x8000;
1045
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 }
1048
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001049 pCardInfo->si_per_targ_init_sync = temp2;
1050 pCardInfo->si_per_targ_no_disc = temp3;
1051 pCardInfo->si_per_targ_wide_nego = temp4;
1052 pCardInfo->si_per_targ_fast_nego = temp5;
1053 pCardInfo->si_per_targ_ultra_nego = temp6;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001055 if (pCurrNvRam)
1056 i = pCurrNvRam->niSysConf;
1057 else
1058 i = (unsigned
1059 char)(FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001061 if (pCurrNvRam)
1062 ScamFlg = pCurrNvRam->niScamConf;
1063 else
1064 ScamFlg =
1065 (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001067 pCardInfo->si_flags = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001069 if (i & 0x01)
1070 pCardInfo->si_flags |= SCSI_PARITY_ENA;
1071
1072 if (!(i & 0x02))
1073 pCardInfo->si_flags |= SOFT_RESET;
1074
1075 if (i & 0x10)
1076 pCardInfo->si_flags |= EXTENDED_TRANSLATION;
1077
1078 if (ScamFlg & SCAM_ENABLED)
1079 pCardInfo->si_flags |= FLAG_SCAM_ENABLED;
1080
1081 if (ScamFlg & SCAM_LEVEL2)
1082 pCardInfo->si_flags |= FLAG_SCAM_LEVEL2;
1083
1084 j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
1085 if (i & 0x04) {
1086 j |= SCSI_TERM_ENA_L;
1087 }
1088 WR_HARPOON(ioport + hp_bm_ctrl, j);
1089
1090 j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
1091 if (i & 0x08) {
1092 j |= SCSI_TERM_ENA_H;
1093 }
1094 WR_HARPOON(ioport + hp_ee_ctrl, j);
1095
1096 if (!(RD_HARPOON(ioport + hp_page_ctrl) & NARROW_SCSI_CARD))
1097
1098 pCardInfo->si_flags |= SUPPORT_16TAR_32LUN;
1099
1100 pCardInfo->si_card_family = HARPOON_FAMILY;
1101 pCardInfo->si_bustype = BUSTYPE_PCI;
1102
1103 if (pCurrNvRam) {
1104 pCardInfo->si_card_model[0] = '9';
1105 switch (pCurrNvRam->niModel & 0x0f) {
1106 case MODEL_LT:
1107 pCardInfo->si_card_model[1] = '3';
1108 pCardInfo->si_card_model[2] = '0';
1109 break;
1110 case MODEL_LW:
1111 pCardInfo->si_card_model[1] = '5';
1112 pCardInfo->si_card_model[2] = '0';
1113 break;
1114 case MODEL_DL:
1115 pCardInfo->si_card_model[1] = '3';
1116 pCardInfo->si_card_model[2] = '2';
1117 break;
1118 case MODEL_DW:
1119 pCardInfo->si_card_model[1] = '5';
1120 pCardInfo->si_card_model[2] = '2';
1121 break;
1122 }
1123 } else {
1124 temp = FPT_utilEERead(ioport, (MODEL_NUMB_0 / 2));
1125 pCardInfo->si_card_model[0] = (unsigned char)(temp >> 8);
1126 temp = FPT_utilEERead(ioport, (MODEL_NUMB_2 / 2));
1127
1128 pCardInfo->si_card_model[1] = (unsigned char)(temp & 0x00FF);
1129 pCardInfo->si_card_model[2] = (unsigned char)(temp >> 8);
1130 }
1131
1132 if (pCardInfo->si_card_model[1] == '3') {
1133 if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
1134 pCardInfo->si_flags |= LOW_BYTE_TERM;
1135 } else if (pCardInfo->si_card_model[2] == '0') {
1136 temp = RD_HARPOON(ioport + hp_xfer_pad);
1137 WR_HARPOON(ioport + hp_xfer_pad, (temp & ~BIT(4)));
1138 if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
1139 pCardInfo->si_flags |= LOW_BYTE_TERM;
1140 WR_HARPOON(ioport + hp_xfer_pad, (temp | BIT(4)));
1141 if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
1142 pCardInfo->si_flags |= HIGH_BYTE_TERM;
1143 WR_HARPOON(ioport + hp_xfer_pad, temp);
1144 } else {
1145 temp = RD_HARPOON(ioport + hp_ee_ctrl);
1146 temp2 = RD_HARPOON(ioport + hp_xfer_pad);
1147 WR_HARPOON(ioport + hp_ee_ctrl, (temp | SEE_CS));
1148 WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4)));
1149 temp3 = 0;
1150 for (i = 0; i < 8; i++) {
1151 temp3 <<= 1;
1152 if (!(RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7)))
1153 temp3 |= 1;
1154 WR_HARPOON(ioport + hp_xfer_pad, (temp2 & ~BIT(4)));
1155 WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4)));
1156 }
1157 WR_HARPOON(ioport + hp_ee_ctrl, temp);
1158 WR_HARPOON(ioport + hp_xfer_pad, temp2);
1159 if (!(temp3 & BIT(7)))
1160 pCardInfo->si_flags |= LOW_BYTE_TERM;
1161 if (!(temp3 & BIT(6)))
1162 pCardInfo->si_flags |= HIGH_BYTE_TERM;
1163 }
1164
1165 ARAM_ACCESS(ioport);
1166
1167 for (i = 0; i < 4; i++) {
1168
1169 pCardInfo->si_XlatInfo[i] =
1170 RD_HARPOON(ioport + hp_aramBase + BIOS_DATA_OFFSET + i);
1171 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172
1173 /* return with -1 if no sort, else return with
1174 logical card number sorted by BIOS (zero-based) */
1175
1176 pCardInfo->si_relative_cardnum =
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001177 (unsigned
1178 char)(RD_HARPOON(ioport + hp_aramBase + BIOS_RELATIVE_CARD) - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001180 SGRAM_ACCESS(ioport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001182 FPT_s_PhaseTbl[0] = FPT_phaseDataOut;
1183 FPT_s_PhaseTbl[1] = FPT_phaseDataIn;
1184 FPT_s_PhaseTbl[2] = FPT_phaseIllegal;
1185 FPT_s_PhaseTbl[3] = FPT_phaseIllegal;
1186 FPT_s_PhaseTbl[4] = FPT_phaseCommand;
1187 FPT_s_PhaseTbl[5] = FPT_phaseStatus;
1188 FPT_s_PhaseTbl[6] = FPT_phaseMsgOut;
1189 FPT_s_PhaseTbl[7] = FPT_phaseMsgIn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001191 pCardInfo->si_present = 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001193 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001194}
1195
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196/*---------------------------------------------------------------------
1197 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001198 * Function: FlashPoint_HardwareResetHostAdapter
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199 *
1200 * Description: Setup adapter for normal operation (hard reset).
1201 *
1202 *---------------------------------------------------------------------*/
1203
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001204static unsigned long FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info
1205 *pCardInfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001207 struct sccb_card *CurrCard = NULL;
1208 struct nvram_info *pCurrNvRam;
1209 unsigned char i, j, thisCard, ScamFlg;
1210 unsigned short temp, sync_bit_map, id;
1211 unsigned long ioport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001213 ioport = pCardInfo->si_baseaddr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001215 for (thisCard = 0; thisCard <= MAX_CARDS; thisCard++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001217 if (thisCard == MAX_CARDS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001219 return FAILURE;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001220 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001222 if (FPT_BL_Card[thisCard].ioPort == ioport) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001224 CurrCard = &FPT_BL_Card[thisCard];
1225 FPT_SccbMgrTableInitCard(CurrCard, thisCard);
1226 break;
1227 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001229 else if (FPT_BL_Card[thisCard].ioPort == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001231 FPT_BL_Card[thisCard].ioPort = ioport;
1232 CurrCard = &FPT_BL_Card[thisCard];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001234 if (FPT_mbCards)
1235 for (i = 0; i < FPT_mbCards; i++) {
1236 if (CurrCard->ioPort ==
1237 FPT_nvRamInfo[i].niBaseAddr)
1238 CurrCard->pNvRamInfo =
1239 &FPT_nvRamInfo[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001241 FPT_SccbMgrTableInitCard(CurrCard, thisCard);
1242 CurrCard->cardIndex = thisCard;
1243 CurrCard->cardInfo = pCardInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001245 break;
1246 }
1247 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248
1249 pCurrNvRam = CurrCard->pNvRamInfo;
1250
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001251 if (pCurrNvRam) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 ScamFlg = pCurrNvRam->niScamConf;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001253 } else {
1254 ScamFlg =
1255 (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 }
1257
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001258 FPT_BusMasterInit(ioport);
1259 FPT_XbowInit(ioport, ScamFlg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001261 FPT_autoLoadDefaultMap(ioport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001263 for (i = 0, id = 0x01; i != pCardInfo->si_id; i++, id <<= 1) {
1264 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001266 WR_HARPOON(ioport + hp_selfid_0, id);
1267 WR_HARPOON(ioport + hp_selfid_1, 0x00);
1268 WR_HARPOON(ioport + hp_arb_id, pCardInfo->si_id);
1269 CurrCard->ourId = pCardInfo->si_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001271 i = (unsigned char)pCardInfo->si_flags;
1272 if (i & SCSI_PARITY_ENA)
1273 WR_HARPOON(ioport + hp_portctrl_1, (HOST_MODE8 | CHK_SCSI_P));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001275 j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
1276 if (i & LOW_BYTE_TERM)
1277 j |= SCSI_TERM_ENA_L;
1278 WR_HARPOON(ioport + hp_bm_ctrl, j);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001280 j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
1281 if (i & HIGH_BYTE_TERM)
1282 j |= SCSI_TERM_ENA_H;
1283 WR_HARPOON(ioport + hp_ee_ctrl, j);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001285 if (!(pCardInfo->si_flags & SOFT_RESET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001287 FPT_sresb(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001289 FPT_scini(thisCard, pCardInfo->si_id, 0);
1290 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001292 if (pCardInfo->si_flags & POST_ALL_UNDERRRUNS)
1293 CurrCard->globalFlags |= F_NO_FILTER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001295 if (pCurrNvRam) {
1296 if (pCurrNvRam->niSysConf & 0x10)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297 CurrCard->globalFlags |= F_GREEN_PC;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001298 } else {
1299 if (FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)) & GREEN_PC_ENA)
1300 CurrCard->globalFlags |= F_GREEN_PC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 }
1302
1303 /* Set global flag to indicate Re-Negotiation to be done on all
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001304 ckeck condition */
1305 if (pCurrNvRam) {
1306 if (pCurrNvRam->niScsiConf & 0x04)
1307 CurrCard->globalFlags |= F_DO_RENEGO;
1308 } else {
1309 if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & RENEGO_ENA)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 CurrCard->globalFlags |= F_DO_RENEGO;
1311 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001313 if (pCurrNvRam) {
1314 if (pCurrNvRam->niScsiConf & 0x08)
1315 CurrCard->globalFlags |= F_CONLUN_IO;
1316 } else {
1317 if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & CONNIO_ENA)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 CurrCard->globalFlags |= F_CONLUN_IO;
1319 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001320
1321 temp = pCardInfo->si_per_targ_no_disc;
1322
1323 for (i = 0, id = 1; i < MAX_SCSI_TAR; i++, id <<= 1) {
1324
1325 if (temp & id)
1326 FPT_sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 }
1328
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001329 sync_bit_map = 0x0001;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001331 for (id = 0; id < (MAX_SCSI_TAR / 2); id++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001333 if (pCurrNvRam) {
1334 temp = (unsigned short)pCurrNvRam->niSyncTbl[id];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001336 (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
1337 } else
1338 temp =
1339 FPT_utilEERead(ioport,
1340 (unsigned short)((SYNC_RATE_TBL / 2)
1341 + id));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001343 for (i = 0; i < 2; temp >>= 8, i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001345 if (pCardInfo->si_per_targ_init_sync & sync_bit_map) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001347 FPT_sccbMgrTbl[thisCard][id * 2 +
1348 i].TarEEValue =
1349 (unsigned char)temp;
1350 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001352 else {
1353 FPT_sccbMgrTbl[thisCard][id * 2 +
1354 i].TarStatus |=
1355 SYNC_SUPPORTED;
1356 FPT_sccbMgrTbl[thisCard][id * 2 +
1357 i].TarEEValue =
1358 (unsigned char)(temp & ~EE_SYNC_MASK);
1359 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361/* if ((pCardInfo->si_per_targ_wide_nego & sync_bit_map) ||
1362 (id*2+i >= 8)){
1363*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001364 if (pCardInfo->si_per_targ_wide_nego & sync_bit_map) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001366 FPT_sccbMgrTbl[thisCard][id * 2 +
1367 i].TarEEValue |=
1368 EE_WIDE_SCSI;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001370 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001372 else { /* NARROW SCSI */
1373 FPT_sccbMgrTbl[thisCard][id * 2 +
1374 i].TarStatus |=
1375 WIDE_NEGOCIATED;
1376 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001378 sync_bit_map <<= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001380 }
1381 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001383 WR_HARPOON((ioport + hp_semaphore),
1384 (unsigned char)(RD_HARPOON((ioport + hp_semaphore)) |
1385 SCCB_MGR_PRESENT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001387 return (unsigned long)CurrCard;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388}
1389
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08001390static void FlashPoint_ReleaseHostAdapter(unsigned long pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391{
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08001392 unsigned char i;
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08001393 unsigned long portBase;
1394 unsigned long regOffset;
1395 unsigned long scamData;
1396 unsigned long *pScamTbl;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001397 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001399 pCurrNvRam = ((struct sccb_card *)pCurrCard)->pNvRamInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001401 if (pCurrNvRam) {
James Bottomley 47b5d692005-04-24 02:38:05 -05001402 FPT_WrStack(pCurrNvRam->niBaseAddr, 0, pCurrNvRam->niModel);
1403 FPT_WrStack(pCurrNvRam->niBaseAddr, 1, pCurrNvRam->niSysConf);
1404 FPT_WrStack(pCurrNvRam->niBaseAddr, 2, pCurrNvRam->niScsiConf);
1405 FPT_WrStack(pCurrNvRam->niBaseAddr, 3, pCurrNvRam->niScamConf);
1406 FPT_WrStack(pCurrNvRam->niBaseAddr, 4, pCurrNvRam->niAdapId);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001408 for (i = 0; i < MAX_SCSI_TAR / 2; i++)
1409 FPT_WrStack(pCurrNvRam->niBaseAddr,
1410 (unsigned char)(i + 5),
1411 pCurrNvRam->niSyncTbl[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412
1413 portBase = pCurrNvRam->niBaseAddr;
1414
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001415 for (i = 0; i < MAX_SCSI_TAR; i++) {
1416 regOffset = hp_aramBase + 64 + i * 4;
1417 pScamTbl = (unsigned long *)&pCurrNvRam->niScamTbl[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 scamData = *pScamTbl;
1419 WR_HARP32(portBase, regOffset, scamData);
1420 }
1421
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001422 } else {
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001423 FPT_WrStack(((struct sccb_card *)pCurrCard)->ioPort, 0, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 }
1425}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001427static void FPT_RNVRamData(struct nvram_info *pNvRamInfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428{
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08001429 unsigned char i;
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08001430 unsigned long portBase;
1431 unsigned long regOffset;
1432 unsigned long scamData;
1433 unsigned long *pScamTbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001435 pNvRamInfo->niModel = FPT_RdStack(pNvRamInfo->niBaseAddr, 0);
1436 pNvRamInfo->niSysConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 1);
James Bottomley 47b5d692005-04-24 02:38:05 -05001437 pNvRamInfo->niScsiConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 2);
1438 pNvRamInfo->niScamConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 3);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001439 pNvRamInfo->niAdapId = FPT_RdStack(pNvRamInfo->niBaseAddr, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001441 for (i = 0; i < MAX_SCSI_TAR / 2; i++)
1442 pNvRamInfo->niSyncTbl[i] =
1443 FPT_RdStack(pNvRamInfo->niBaseAddr, (unsigned char)(i + 5));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
1445 portBase = pNvRamInfo->niBaseAddr;
1446
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001447 for (i = 0; i < MAX_SCSI_TAR; i++) {
1448 regOffset = hp_aramBase + 64 + i * 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 RD_HARP32(portBase, regOffset, scamData);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001450 pScamTbl = (unsigned long *)&pNvRamInfo->niScamTbl[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451 *pScamTbl = scamData;
1452 }
1453
1454}
1455
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08001456static unsigned char FPT_RdStack(unsigned long portBase, unsigned char index)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457{
1458 WR_HARPOON(portBase + hp_stack_addr, index);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001459 return RD_HARPOON(portBase + hp_stack_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460}
1461
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001462static void FPT_WrStack(unsigned long portBase, unsigned char index,
1463 unsigned char data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464{
1465 WR_HARPOON(portBase + hp_stack_addr, index);
1466 WR_HARPOON(portBase + hp_stack_data, data);
1467}
1468
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08001469static unsigned char FPT_ChkIfChipInitialized(unsigned long ioPort)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001471 if ((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != FPT_RdStack(ioPort, 4))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001472 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001473 if ((RD_HARPOON(ioPort + hp_clkctrl_0) & CLKCTRL_DEFAULT)
1474 != CLKCTRL_DEFAULT)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001475 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001476 if ((RD_HARPOON(ioPort + hp_seltimeout) == TO_250ms) ||
1477 (RD_HARPOON(ioPort + hp_seltimeout) == TO_290ms))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001478 return 1;
1479 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480
1481}
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001482
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483/*---------------------------------------------------------------------
1484 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001485 * Function: FlashPoint_StartCCB
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486 *
1487 * Description: Start a command pointed to by p_Sccb. When the
1488 * command is completed it will be returned via the
1489 * callback function.
1490 *
1491 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001492static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb *p_Sccb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001494 unsigned long ioport;
1495 unsigned char thisCard, lun;
1496 struct sccb *pSaveSccb;
1497 CALL_BK_FN callback;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001499 thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
1500 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501
Adrian Bunk1377d8d2008-04-23 12:51:10 +03001502 if ((p_Sccb->TargID >= MAX_SCSI_TAR) || (p_Sccb->Lun >= MAX_LUN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 p_Sccb->HostStatus = SCCB_COMPLETE;
1505 p_Sccb->SccbStatus = SCCB_ERROR;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001506 callback = (CALL_BK_FN) p_Sccb->SccbCallback;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507 if (callback)
1508 callback(p_Sccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 return;
1511 }
1512
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001513 FPT_sinits(p_Sccb, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001515 if (!((struct sccb_card *)pCurrCard)->cmdCounter) {
1516 WR_HARPOON(ioport + hp_semaphore,
1517 (RD_HARPOON(ioport + hp_semaphore)
1518 | SCCB_MGR_ACTIVE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001520 if (((struct sccb_card *)pCurrCard)->globalFlags & F_GREEN_PC) {
1521 WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT);
1522 WR_HARPOON(ioport + hp_sys_ctrl, 0x00);
1523 }
1524 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001526 ((struct sccb_card *)pCurrCard)->cmdCounter++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001528 if (RD_HARPOON(ioport + hp_semaphore) & BIOS_IN_USE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001530 WR_HARPOON(ioport + hp_semaphore,
1531 (RD_HARPOON(ioport + hp_semaphore)
1532 | TICKLE_ME));
1533 if (p_Sccb->OperationCode == RESET_COMMAND) {
1534 pSaveSccb =
1535 ((struct sccb_card *)pCurrCard)->currentSCCB;
1536 ((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb;
1537 FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
1538 ((struct sccb_card *)pCurrCard)->currentSCCB =
1539 pSaveSccb;
1540 } else {
1541 FPT_queueAddSccb(p_Sccb, thisCard);
1542 }
1543 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001545 else if ((RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001547 if (p_Sccb->OperationCode == RESET_COMMAND) {
1548 pSaveSccb =
1549 ((struct sccb_card *)pCurrCard)->currentSCCB;
1550 ((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb;
1551 FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
1552 ((struct sccb_card *)pCurrCard)->currentSCCB =
1553 pSaveSccb;
1554 } else {
1555 FPT_queueAddSccb(p_Sccb, thisCard);
1556 }
1557 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001559 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001561 MDISABLE_INT(ioport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001563 if ((((struct sccb_card *)pCurrCard)->globalFlags & F_CONLUN_IO)
1564 &&
1565 ((FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].
1566 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567 lun = p_Sccb->Lun;
1568 else
1569 lun = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001570 if ((((struct sccb_card *)pCurrCard)->currentSCCB == NULL) &&
1571 (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarSelQ_Cnt == 0)
1572 && (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarLUNBusy[lun]
1573 == 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001575 ((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb;
1576 FPT_ssel(p_Sccb->SccbIOPort, thisCard);
1577 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001579 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001581 if (p_Sccb->OperationCode == RESET_COMMAND) {
1582 pSaveSccb =
1583 ((struct sccb_card *)pCurrCard)->
1584 currentSCCB;
1585 ((struct sccb_card *)pCurrCard)->currentSCCB =
1586 p_Sccb;
1587 FPT_queueSelectFail(&FPT_BL_Card[thisCard],
1588 thisCard);
1589 ((struct sccb_card *)pCurrCard)->currentSCCB =
1590 pSaveSccb;
1591 } else {
1592 FPT_queueAddSccb(p_Sccb, thisCard);
1593 }
1594 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001596 MENABLE_INT(ioport);
1597 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599}
1600
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601/*---------------------------------------------------------------------
1602 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001603 * Function: FlashPoint_AbortCCB
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604 *
1605 * Description: Abort the command pointed to by p_Sccb. When the
1606 * command is completed it will be returned via the
1607 * callback function.
1608 *
1609 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001610static int FlashPoint_AbortCCB(unsigned long pCurrCard, struct sccb *p_Sccb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611{
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08001612 unsigned long ioport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08001614 unsigned char thisCard;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 CALL_BK_FN callback;
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08001616 unsigned char TID;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001617 struct sccb *pSaveSCCB;
1618 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001620 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001622 thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001624 if (!(RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001626 if (FPT_queueFindSccb(p_Sccb, thisCard)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001628 ((struct sccb_card *)pCurrCard)->cmdCounter--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629
Alexey Dobriyan13e68512006-03-08 00:14:34 -08001630 if (!((struct sccb_card *)pCurrCard)->cmdCounter)
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001631 WR_HARPOON(ioport + hp_semaphore,
1632 (RD_HARPOON(ioport + hp_semaphore)
1633 & (unsigned
1634 char)(~(SCCB_MGR_ACTIVE |
1635 TICKLE_ME))));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637 p_Sccb->SccbStatus = SCCB_ABORT;
1638 callback = p_Sccb->SccbCallback;
1639 callback(p_Sccb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001641 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642 }
1643
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001644 else {
1645 if (((struct sccb_card *)pCurrCard)->currentSCCB ==
1646 p_Sccb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647 p_Sccb->SccbStatus = SCCB_ABORT;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001648 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649
1650 }
1651
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001652 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653
1654 TID = p_Sccb->TargID;
1655
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001656 if (p_Sccb->Sccb_tag) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 MDISABLE_INT(ioport);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001658 if (((struct sccb_card *)pCurrCard)->
1659 discQ_Tbl[p_Sccb->Sccb_tag] ==
1660 p_Sccb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 p_Sccb->SccbStatus = SCCB_ABORT;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001662 p_Sccb->Sccb_scsistat =
1663 ABORT_ST;
1664 p_Sccb->Sccb_scsimsg =
1665 SMABORT_TAG;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001667 if (((struct sccb_card *)
1668 pCurrCard)->currentSCCB ==
1669 NULL) {
1670 ((struct sccb_card *)
1671 pCurrCard)->
1672 currentSCCB = p_Sccb;
1673 FPT_ssel(ioport,
1674 thisCard);
1675 } else {
1676 pSaveSCCB =
1677 ((struct sccb_card
1678 *)pCurrCard)->
1679 currentSCCB;
1680 ((struct sccb_card *)
1681 pCurrCard)->
1682 currentSCCB = p_Sccb;
1683 FPT_queueSelectFail((struct sccb_card *)pCurrCard, thisCard);
1684 ((struct sccb_card *)
1685 pCurrCard)->
1686 currentSCCB = pSaveSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687 }
1688 }
1689 MENABLE_INT(ioport);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001690 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001691 } else {
1692 currTar_Info =
1693 &FPT_sccbMgrTbl[thisCard][p_Sccb->
1694 TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001696 if (FPT_BL_Card[thisCard].
1697 discQ_Tbl[currTar_Info->
1698 LunDiscQ_Idx[p_Sccb->Lun]]
1699 == p_Sccb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 p_Sccb->SccbStatus = SCCB_ABORT;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001701 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 }
1703 }
1704 }
1705 }
1706 }
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001707 return -1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708}
1709
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710/*---------------------------------------------------------------------
1711 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001712 * Function: FlashPoint_InterruptPending
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713 *
1714 * Description: Do a quick check to determine if there is a pending
1715 * interrupt for this card and disable the IRQ Pin if so.
1716 *
1717 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08001718static unsigned char FlashPoint_InterruptPending(unsigned long pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001720 unsigned long ioport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001722 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001724 if (RD_HARPOON(ioport + hp_int_status) & INT_ASSERTED) {
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001725 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001726 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001728 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001730 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731}
1732
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733/*---------------------------------------------------------------------
1734 *
Alexey Dobriyand8b6b8b2006-03-08 00:14:23 -08001735 * Function: FlashPoint_HandleInterrupt
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 *
1737 * Description: This is our entry point when an interrupt is generated
1738 * by the card and the upper level driver passes it on to
1739 * us.
1740 *
1741 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08001742static int FlashPoint_HandleInterrupt(unsigned long pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001743{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001744 struct sccb *currSCCB;
1745 unsigned char thisCard, result, bm_status, bm_int_st;
1746 unsigned short hp_int;
1747 unsigned char i, target;
1748 unsigned long ioport;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001750 thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
1751 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001753 MDISABLE_INT(ioport);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001755 if ((bm_int_st = RD_HARPOON(ioport + hp_int_status)) & EXT_STATUS_ON)
1756 bm_status =
1757 RD_HARPOON(ioport +
1758 hp_ext_status) & (unsigned char)BAD_EXT_STATUS;
1759 else
1760 bm_status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001761
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001762 WR_HARPOON(ioport + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001764 while ((hp_int =
1765 RDW_HARPOON((ioport +
1766 hp_intstat)) & FPT_default_intena) | bm_status) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001768 currSCCB = ((struct sccb_card *)pCurrCard)->currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001770 if (hp_int & (FIFO | TIMEOUT | RESET | SCAM_SEL) || bm_status) {
1771 result =
1772 FPT_SccbMgr_bad_isr(ioport, thisCard,
1773 ((struct sccb_card *)pCurrCard),
1774 hp_int);
1775 WRW_HARPOON((ioport + hp_intstat),
1776 (FIFO | TIMEOUT | RESET | SCAM_SEL));
1777 bm_status = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001779 if (result) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001781 MENABLE_INT(ioport);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001782 return result;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001783 }
1784 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001786 else if (hp_int & ICMD_COMP) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001788 if (!(hp_int & BUS_FREE)) {
1789 /* Wait for the BusFree before starting a new command. We
1790 must also check for being reselected since the BusFree
1791 may not show up if another device reselects us in 1.5us or
1792 less. SRR Wednesday, 3/8/1995.
1793 */
1794 while (!
1795 (RDW_HARPOON((ioport + hp_intstat)) &
1796 (BUS_FREE | RSEL))) ;
1797 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001799 if (((struct sccb_card *)pCurrCard)->
1800 globalFlags & F_HOST_XFER_ACT)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001802 FPT_phaseChkFifo(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001803
1804/* WRW_HARPOON((ioport+hp_intstat),
1805 (BUS_FREE | ICMD_COMP | ITAR_DISC | XFER_CNT_0));
1806 */
1807
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001808 WRW_HARPOON((ioport + hp_intstat), CLR_ALL_INT_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001810 FPT_autoCmdCmplt(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001811
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001812 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001814 else if (hp_int & ITAR_DISC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001816 if (((struct sccb_card *)pCurrCard)->
1817 globalFlags & F_HOST_XFER_ACT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001819 FPT_phaseChkFifo(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001820
Linus Torvalds1da177e2005-04-16 15:20:36 -07001821 }
1822
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001823 if (RD_HARPOON(ioport + hp_gp_reg_1) == SMSAVE_DATA_PTR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001825 WR_HARPOON(ioport + hp_gp_reg_1, 0x00);
1826 currSCCB->Sccb_XferState |= F_NO_DATA_YET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001828 currSCCB->Sccb_savedATC = currSCCB->Sccb_ATC;
1829 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001830
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001831 currSCCB->Sccb_scsistat = DISCONNECT_ST;
1832 FPT_queueDisconnect(currSCCB, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001834 /* Wait for the BusFree before starting a new command. We
1835 must also check for being reselected since the BusFree
1836 may not show up if another device reselects us in 1.5us or
1837 less. SRR Wednesday, 3/8/1995.
1838 */
1839 while (!
1840 (RDW_HARPOON((ioport + hp_intstat)) &
1841 (BUS_FREE | RSEL))
1842 && !((RDW_HARPOON((ioport + hp_intstat)) & PHASE)
1843 && RD_HARPOON((ioport + hp_scsisig)) ==
1844 (SCSI_BSY | SCSI_REQ | SCSI_CD | SCSI_MSG |
1845 SCSI_IOBIT))) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001847 /*
1848 The additional loop exit condition above detects a timing problem
1849 with the revision D/E harpoon chips. The caller should reset the
1850 host adapter to recover when 0xFE is returned.
1851 */
1852 if (!
1853 (RDW_HARPOON((ioport + hp_intstat)) &
1854 (BUS_FREE | RSEL))) {
1855 MENABLE_INT(ioport);
1856 return 0xFE;
1857 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001859 WRW_HARPOON((ioport + hp_intstat),
1860 (BUS_FREE | ITAR_DISC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001861
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001862 ((struct sccb_card *)pCurrCard)->globalFlags |=
1863 F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001865 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001867 else if (hp_int & RSEL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001868
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001869 WRW_HARPOON((ioport + hp_intstat),
1870 (PROG_HLT | RSEL | PHASE | BUS_FREE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001871
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001872 if (RDW_HARPOON((ioport + hp_intstat)) & ITAR_DISC) {
1873 if (((struct sccb_card *)pCurrCard)->
1874 globalFlags & F_HOST_XFER_ACT) {
1875 FPT_phaseChkFifo(ioport, thisCard);
1876 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001878 if (RD_HARPOON(ioport + hp_gp_reg_1) ==
1879 SMSAVE_DATA_PTR) {
1880 WR_HARPOON(ioport + hp_gp_reg_1, 0x00);
1881 currSCCB->Sccb_XferState |=
1882 F_NO_DATA_YET;
1883 currSCCB->Sccb_savedATC =
1884 currSCCB->Sccb_ATC;
1885 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001887 WRW_HARPOON((ioport + hp_intstat),
1888 (BUS_FREE | ITAR_DISC));
1889 currSCCB->Sccb_scsistat = DISCONNECT_ST;
1890 FPT_queueDisconnect(currSCCB, thisCard);
1891 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001892
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001893 FPT_sres(ioport, thisCard,
1894 ((struct sccb_card *)pCurrCard));
1895 FPT_phaseDecode(ioport, thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001897 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001898
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08001899 else if ((hp_int & IDO_STRT) && (!(hp_int & BUS_FREE))) {
1900
1901 WRW_HARPOON((ioport + hp_intstat),
1902 (IDO_STRT | XFER_CNT_0));
1903 FPT_phaseDecode(ioport, thisCard);
1904
1905 }
1906
1907 else if ((hp_int & IUNKWN) || (hp_int & PROG_HLT)) {
1908 WRW_HARPOON((ioport + hp_intstat),
1909 (PHASE | IUNKWN | PROG_HLT));
1910 if ((RD_HARPOON(ioport + hp_prgmcnt_0) & (unsigned char)
1911 0x3f) < (unsigned char)SELCHK) {
1912 FPT_phaseDecode(ioport, thisCard);
1913 } else {
1914 /* Harpoon problem some SCSI target device respond to selection
1915 with short BUSY pulse (<400ns) this will make the Harpoon is not able
1916 to latch the correct Target ID into reg. x53.
1917 The work around require to correct this reg. But when write to this
1918 reg. (0x53) also increment the FIFO write addr reg (0x6f), thus we
1919 need to read this reg first then restore it later. After update to 0x53 */
1920
1921 i = (unsigned
1922 char)(RD_HARPOON(ioport + hp_fifowrite));
1923 target =
1924 (unsigned
1925 char)(RD_HARPOON(ioport + hp_gp_reg_3));
1926 WR_HARPOON(ioport + hp_xfer_pad,
1927 (unsigned char)ID_UNLOCK);
1928 WR_HARPOON(ioport + hp_select_id,
1929 (unsigned char)(target | target <<
1930 4));
1931 WR_HARPOON(ioport + hp_xfer_pad,
1932 (unsigned char)0x00);
1933 WR_HARPOON(ioport + hp_fifowrite, i);
1934 WR_HARPOON(ioport + hp_autostart_3,
1935 (AUTO_IMMED + TAG_STRT));
1936 }
1937 }
1938
1939 else if (hp_int & XFER_CNT_0) {
1940
1941 WRW_HARPOON((ioport + hp_intstat), XFER_CNT_0);
1942
1943 FPT_schkdd(ioport, thisCard);
1944
1945 }
1946
1947 else if (hp_int & BUS_FREE) {
1948
1949 WRW_HARPOON((ioport + hp_intstat), BUS_FREE);
1950
1951 if (((struct sccb_card *)pCurrCard)->
1952 globalFlags & F_HOST_XFER_ACT) {
1953
1954 FPT_hostDataXferAbort(ioport, thisCard,
1955 currSCCB);
1956 }
1957
1958 FPT_phaseBusFree(ioport, thisCard);
1959 }
1960
1961 else if (hp_int & ITICKLE) {
1962
1963 WRW_HARPOON((ioport + hp_intstat), ITICKLE);
1964 ((struct sccb_card *)pCurrCard)->globalFlags |=
1965 F_NEW_SCCB_CMD;
1966 }
1967
1968 if (((struct sccb_card *)pCurrCard)->
1969 globalFlags & F_NEW_SCCB_CMD) {
1970
1971 ((struct sccb_card *)pCurrCard)->globalFlags &=
1972 ~F_NEW_SCCB_CMD;
1973
1974 if (((struct sccb_card *)pCurrCard)->currentSCCB ==
1975 NULL) {
1976
1977 FPT_queueSearchSelect(((struct sccb_card *)
1978 pCurrCard), thisCard);
1979 }
1980
1981 if (((struct sccb_card *)pCurrCard)->currentSCCB !=
1982 NULL) {
1983 ((struct sccb_card *)pCurrCard)->globalFlags &=
1984 ~F_NEW_SCCB_CMD;
1985 FPT_ssel(ioport, thisCard);
1986 }
1987
1988 break;
1989
1990 }
1991
1992 } /*end while */
1993
1994 MENABLE_INT(ioport);
1995
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08001996 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997}
1998
1999/*---------------------------------------------------------------------
2000 *
2001 * Function: Sccb_bad_isr
2002 *
2003 * Description: Some type of interrupt has occurred which is slightly
2004 * out of the ordinary. We will now decode it fully, in
2005 * this routine. This is broken up in an attempt to save
2006 * processing time.
2007 *
2008 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002009static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port,
2010 unsigned char p_card,
2011 struct sccb_card *pCurrCard,
2012 unsigned short p_int)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002013{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002014 unsigned char temp, ScamFlg;
2015 struct sccb_mgr_tar_info *currTar_Info;
2016 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002017
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002018 if (RD_HARPOON(p_port + hp_ext_status) &
2019 (BM_FORCE_OFF | PCI_DEV_TMOUT | BM_PARITY_ERR | PIO_OVERRUN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002020
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002021 if (pCurrCard->globalFlags & F_HOST_XFER_ACT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002023 FPT_hostDataXferAbort(p_port, p_card,
2024 pCurrCard->currentSCCB);
2025 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002027 if (RD_HARPOON(p_port + hp_pci_stat_cfg) & REC_MASTER_ABORT)
2028 {
2029 WR_HARPOON(p_port + hp_pci_stat_cfg,
2030 (RD_HARPOON(p_port + hp_pci_stat_cfg) &
2031 ~REC_MASTER_ABORT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002032
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002033 WR_HARPOON(p_port + hp_host_blk_cnt, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002034
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002035 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002037 if (pCurrCard->currentSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002039 if (!pCurrCard->currentSCCB->HostStatus)
2040 pCurrCard->currentSCCB->HostStatus =
2041 SCCB_BM_ERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002042
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002043 FPT_sxfrp(p_port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002045 temp = (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
2046 (EXT_ARB_ACK | SCSI_TERM_ENA_H));
2047 WR_HARPOON(p_port + hp_ee_ctrl,
2048 ((unsigned char)temp | SEE_MS | SEE_CS));
2049 WR_HARPOON(p_port + hp_ee_ctrl, temp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002050
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002051 if (!
2052 (RDW_HARPOON((p_port + hp_intstat)) &
2053 (BUS_FREE | RESET))) {
2054 FPT_phaseDecode(p_port, p_card);
2055 }
2056 }
2057 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002059 else if (p_int & RESET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002060
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002061 WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
2062 WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
2063 if (pCurrCard->currentSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002064
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002065 if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002066
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002067 FPT_hostDataXferAbort(p_port, p_card,
2068 pCurrCard->currentSCCB);
2069 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002070
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002071 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002072
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002073 FPT_sresb(p_port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002074
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002075 while (RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST) {
2076 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002077
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002078 pCurrNvRam = pCurrCard->pNvRamInfo;
2079 if (pCurrNvRam) {
2080 ScamFlg = pCurrNvRam->niScamConf;
2081 } else {
2082 ScamFlg =
2083 (unsigned char)FPT_utilEERead(p_port,
2084 SCAM_CONFIG / 2);
2085 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002087 FPT_XbowInit(p_port, ScamFlg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002089 FPT_scini(p_card, pCurrCard->ourId, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002091 return 0xFF;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002092 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002094 else if (p_int & FIFO) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002096 WRW_HARPOON((p_port + hp_intstat), FIFO);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002097
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002098 if (pCurrCard->currentSCCB != NULL)
2099 FPT_sxfrp(p_port, p_card);
2100 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002101
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002102 else if (p_int & TIMEOUT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002104 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002106 WRW_HARPOON((p_port + hp_intstat),
2107 (PROG_HLT | TIMEOUT | SEL | BUS_FREE | PHASE |
2108 IUNKWN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002109
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002110 pCurrCard->currentSCCB->HostStatus = SCCB_SELECTION_TIMEOUT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002111
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002112 currTar_Info =
2113 &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
2114 if ((pCurrCard->globalFlags & F_CONLUN_IO)
2115 && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
2116 TAG_Q_TRYING))
2117 currTar_Info->TarLUNBusy[pCurrCard->currentSCCB->Lun] =
2118 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002119 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002120 currTar_Info->TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002121
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002122 if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
2123 currTar_Info->TarSyncCtrl = 0;
2124 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2125 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002127 if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
2128 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2129 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002131 FPT_sssyncv(p_port, pCurrCard->currentSCCB->TargID, NARROW_SCSI,
2132 currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002134 FPT_queueCmdComplete(pCurrCard, pCurrCard->currentSCCB, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002135
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002136 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002137
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002138 else if (p_int & SCAM_SEL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002139
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002140 FPT_scarb(p_port, LEVEL2_TAR);
2141 FPT_scsel(p_port);
2142 FPT_scasid(p_card, p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002144 FPT_scbusf(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002146 WRW_HARPOON((p_port + hp_intstat), SCAM_SEL);
2147 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002149 return 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150}
2151
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152/*---------------------------------------------------------------------
2153 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154 * Function: SccbMgrTableInit
2155 *
2156 * Description: Initialize all Sccb manager data structures.
2157 *
2158 *---------------------------------------------------------------------*/
2159
James Bottomley 47b5d692005-04-24 02:38:05 -05002160static void FPT_SccbMgrTableInitAll()
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002162 unsigned char thisCard;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002164 for (thisCard = 0; thisCard < MAX_CARDS; thisCard++) {
2165 FPT_SccbMgrTableInitCard(&FPT_BL_Card[thisCard], thisCard);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002167 FPT_BL_Card[thisCard].ioPort = 0x00;
2168 FPT_BL_Card[thisCard].cardInfo = NULL;
2169 FPT_BL_Card[thisCard].cardIndex = 0xFF;
2170 FPT_BL_Card[thisCard].ourId = 0x00;
2171 FPT_BL_Card[thisCard].pNvRamInfo = NULL;
2172 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173}
2174
Linus Torvalds1da177e2005-04-16 15:20:36 -07002175/*---------------------------------------------------------------------
2176 *
2177 * Function: SccbMgrTableInit
2178 *
2179 * Description: Initialize all Sccb manager data structures.
2180 *
2181 *---------------------------------------------------------------------*/
2182
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002183static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard,
2184 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002186 unsigned char scsiID, qtag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002188 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002189 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190 }
2191
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002192 for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
2193 FPT_sccbMgrTbl[p_card][scsiID].TarStatus = 0;
2194 FPT_sccbMgrTbl[p_card][scsiID].TarEEValue = 0;
2195 FPT_SccbMgrTableInitTarget(p_card, scsiID);
2196 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002198 pCurrCard->scanIndex = 0x00;
2199 pCurrCard->currentSCCB = NULL;
2200 pCurrCard->globalFlags = 0x00;
2201 pCurrCard->cmdCounter = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202 pCurrCard->tagQ_Lst = 0x01;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002203 pCurrCard->discQCount = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204
2205}
2206
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207/*---------------------------------------------------------------------
2208 *
2209 * Function: SccbMgrTableInit
2210 *
2211 * Description: Initialize all Sccb manager data structures.
2212 *
2213 *---------------------------------------------------------------------*/
2214
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002215static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
2216 unsigned char target)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217{
2218
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08002219 unsigned char lun, qtag;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002220 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221
James Bottomley 47b5d692005-04-24 02:38:05 -05002222 currTar_Info = &FPT_sccbMgrTbl[p_card][target];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002223
2224 currTar_Info->TarSelQ_Cnt = 0;
2225 currTar_Info->TarSyncCtrl = 0;
2226
2227 currTar_Info->TarSelQ_Head = NULL;
2228 currTar_Info->TarSelQ_Tail = NULL;
2229 currTar_Info->TarTagQ_Cnt = 0;
James Bottomley 47b5d692005-04-24 02:38:05 -05002230 currTar_Info->TarLUN_CA = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002232 for (lun = 0; lun < MAX_LUN; lun++) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002233 currTar_Info->TarLUNBusy[lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234 currTar_Info->LunDiscQ_Idx[lun] = 0;
2235 }
2236
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002237 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
2238 if (FPT_BL_Card[p_card].discQ_Tbl[qtag] != NULL) {
2239 if (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
2240 target) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002241 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
2242 FPT_BL_Card[p_card].discQCount--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 }
2244 }
2245 }
2246}
2247
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248/*---------------------------------------------------------------------
2249 *
2250 * Function: sfetm
2251 *
2252 * Description: Read in a message byte from the SCSI bus, and check
2253 * for a parity error.
2254 *
2255 *---------------------------------------------------------------------*/
2256
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002257static unsigned char FPT_sfm(unsigned long port, struct sccb *pCurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258{
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08002259 unsigned char message;
Alexey Dobriyanc823fee2006-03-08 00:14:25 -08002260 unsigned short TimeOutLoop;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261
2262 TimeOutLoop = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002263 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2264 (TimeOutLoop++ < 20000)) {
2265 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002267 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002268
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002269 message = RD_HARPOON(port + hp_scsidata_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002271 WR_HARPOON(port + hp_scsisig, SCSI_ACK + S_MSGI_PH);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272
2273 if (TimeOutLoop > 20000)
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002274 message = 0x00; /* force message byte = 0 if Time Out on Req */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002276 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
2277 (RD_HARPOON(port + hp_addstat) & SCSI_PAR_ERR)) {
2278 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2279 WR_HARPOON(port + hp_xferstat, 0);
2280 WR_HARPOON(port + hp_fiforead, 0);
2281 WR_HARPOON(port + hp_fifowrite, 0);
2282 if (pCurrSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283 pCurrSCCB->Sccb_scsimsg = SMPARITY;
2284 }
2285 message = 0x00;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002286 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287 ACCEPT_MSG_ATN(port);
2288 TimeOutLoop = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002289 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2290 (TimeOutLoop++ < 20000)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002292 if (TimeOutLoop > 20000) {
2293 WRW_HARPOON((port + hp_intstat), PARITY);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002294 return message;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002296 if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) !=
2297 S_MSGI_PH) {
2298 WRW_HARPOON((port + hp_intstat), PARITY);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002299 return message;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002300 }
2301 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002303 RD_HARPOON(port + hp_scsidata_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002305 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002307 } while (1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308
2309 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002310 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2311 WR_HARPOON(port + hp_xferstat, 0);
2312 WR_HARPOON(port + hp_fiforead, 0);
2313 WR_HARPOON(port + hp_fifowrite, 0);
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08002314 return message;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315}
2316
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317/*---------------------------------------------------------------------
2318 *
James Bottomley 47b5d692005-04-24 02:38:05 -05002319 * Function: FPT_ssel
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320 *
2321 * Description: Load up automation and select target device.
2322 *
2323 *---------------------------------------------------------------------*/
2324
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08002325static void FPT_ssel(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326{
2327
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002328 unsigned char auto_loaded, i, target, *theCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002330 unsigned long cdb_reg;
2331 struct sccb_card *CurrCard;
2332 struct sccb *currSCCB;
2333 struct sccb_mgr_tar_info *currTar_Info;
2334 unsigned char lastTag, lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002336 CurrCard = &FPT_BL_Card[p_card];
2337 currSCCB = CurrCard->currentSCCB;
2338 target = currSCCB->TargID;
2339 currTar_Info = &FPT_sccbMgrTbl[p_card][target];
2340 lastTag = CurrCard->tagQ_Lst;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002342 ARAM_ACCESS(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343
2344 if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
2345 currSCCB->ControlByte &= ~F_USE_CMD_Q;
2346
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002347 if (((CurrCard->globalFlags & F_CONLUN_IO) &&
2348 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002349
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002350 lun = currSCCB->Lun;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351 else
2352 lun = 0;
2353
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002354 if (CurrCard->globalFlags & F_TAG_STARTED) {
2355 if (!(currSCCB->ControlByte & F_USE_CMD_Q)) {
2356 if ((currTar_Info->TarLUN_CA == 0)
2357 && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
2358 == TAG_Q_TRYING)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002360 if (currTar_Info->TarTagQ_Cnt != 0) {
2361 currTar_Info->TarLUNBusy[lun] = 1;
2362 FPT_queueSelectFail(CurrCard, p_card);
2363 SGRAM_ACCESS(port);
2364 return;
2365 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002367 else {
2368 currTar_Info->TarLUNBusy[lun] = 1;
2369 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002371 }
2372 /*End non-tagged */
2373 else {
2374 currTar_Info->TarLUNBusy[lun] = 1;
2375 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002377 }
2378 /*!Use cmd Q Tagged */
2379 else {
2380 if (currTar_Info->TarLUN_CA == 1) {
2381 FPT_queueSelectFail(CurrCard, p_card);
2382 SGRAM_ACCESS(port);
2383 return;
2384 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385
James Bottomley 47b5d692005-04-24 02:38:05 -05002386 currTar_Info->TarLUNBusy[lun] = 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002387
2388 } /*else use cmd Q tagged */
2389
2390 }
2391 /*if glob tagged started */
2392 else {
2393 currTar_Info->TarLUNBusy[lun] = 1;
2394 }
2395
2396 if ((((CurrCard->globalFlags & F_CONLUN_IO) &&
2397 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
2398 || (!(currSCCB->ControlByte & F_USE_CMD_Q)))) {
2399 if (CurrCard->discQCount >= QUEUE_DEPTH) {
2400 currTar_Info->TarLUNBusy[lun] = 1;
2401 FPT_queueSelectFail(CurrCard, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 SGRAM_ACCESS(port);
2403 return;
2404 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002405 for (i = 1; i < QUEUE_DEPTH; i++) {
2406 if (++lastTag >= QUEUE_DEPTH)
2407 lastTag = 1;
2408 if (CurrCard->discQ_Tbl[lastTag] == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409 CurrCard->tagQ_Lst = lastTag;
2410 currTar_Info->LunDiscQ_Idx[lun] = lastTag;
2411 CurrCard->discQ_Tbl[lastTag] = currSCCB;
2412 CurrCard->discQCount++;
2413 break;
2414 }
2415 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002416 if (i == QUEUE_DEPTH) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002417 currTar_Info->TarLUNBusy[lun] = 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002418 FPT_queueSelectFail(CurrCard, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419 SGRAM_ACCESS(port);
2420 return;
2421 }
2422 }
2423
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002424 auto_loaded = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002426 WR_HARPOON(port + hp_select_id, target);
2427 WR_HARPOON(port + hp_gp_reg_3, target); /* Use by new automation logic */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002429 if (currSCCB->OperationCode == RESET_COMMAND) {
2430 WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
2431 (currSCCB->
2432 Sccb_idmsg & ~DISC_PRIV)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002434 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + NP);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002436 currSCCB->Sccb_scsimsg = SMDEV_RESET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002438 WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
2439 auto_loaded = 1;
2440 currSCCB->Sccb_scsistat = SELECT_BDR_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002442 if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
2443 currTar_Info->TarSyncCtrl = 0;
2444 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445 }
2446
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002447 if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
2448 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2449 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002451 FPT_sssyncv(port, target, NARROW_SCSI, currTar_Info);
2452 FPT_SccbMgrTableInitTarget(p_card, target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002454 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002456 else if (currSCCB->Sccb_scsistat == ABORT_ST) {
2457 WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
2458 (currSCCB->
2459 Sccb_idmsg & ~DISC_PRIV)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002461 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002463 WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT +
2464 (((unsigned
2465 char)(currSCCB->
2466 ControlByte &
2467 TAG_TYPE_MASK)
2468 >> 6) | (unsigned char)
2469 0x20)));
2470 WRW_HARPOON((port + SYNC_MSGS + 2),
2471 (MPM_OP + AMSG_OUT + currSCCB->Sccb_tag));
2472 WRW_HARPOON((port + SYNC_MSGS + 4), (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002473
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002474 WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
2475 auto_loaded = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002477 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002479 else if (!(currTar_Info->TarStatus & WIDE_NEGOCIATED)) {
2480 auto_loaded = FPT_siwidn(port, p_card);
2481 currSCCB->Sccb_scsistat = SELECT_WN_ST;
2482 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002484 else if (!((currTar_Info->TarStatus & TAR_SYNC_MASK)
2485 == SYNC_SUPPORTED)) {
2486 auto_loaded = FPT_sisyncn(port, p_card, 0);
2487 currSCCB->Sccb_scsistat = SELECT_SN_ST;
2488 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002490 if (!auto_loaded) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002491
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002492 if (currSCCB->ControlByte & F_USE_CMD_Q) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002494 CurrCard->globalFlags |= F_TAG_STARTED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002496 if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
2497 == TAG_Q_REJECT) {
2498 currSCCB->ControlByte &= ~F_USE_CMD_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002500 /* Fix up the start instruction with a jump to
2501 Non-Tag-CMD handling */
2502 WRW_HARPOON((port + ID_MSG_STRT),
2503 BRH_OP + ALWAYS + NTCMD);
2504
2505 WRW_HARPOON((port + NON_TAG_ID_MSG),
2506 (MPM_OP + AMSG_OUT +
2507 currSCCB->Sccb_idmsg));
2508
2509 WR_HARPOON(port + hp_autostart_3,
2510 (SELECT + SELCHK_STRT));
2511
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002512 /* Setup our STATE so we know what happened when
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002513 the wheels fall off. */
2514 currSCCB->Sccb_scsistat = SELECT_ST;
2515
2516 currTar_Info->TarLUNBusy[lun] = 1;
2517 }
2518
2519 else {
2520 WRW_HARPOON((port + ID_MSG_STRT),
2521 (MPM_OP + AMSG_OUT +
2522 currSCCB->Sccb_idmsg));
2523
2524 WRW_HARPOON((port + ID_MSG_STRT + 2),
2525 (MPM_OP + AMSG_OUT +
2526 (((unsigned char)(currSCCB->
2527 ControlByte &
2528 TAG_TYPE_MASK)
2529 >> 6) | (unsigned char)0x20)));
2530
2531 for (i = 1; i < QUEUE_DEPTH; i++) {
2532 if (++lastTag >= QUEUE_DEPTH)
2533 lastTag = 1;
2534 if (CurrCard->discQ_Tbl[lastTag] ==
2535 NULL) {
2536 WRW_HARPOON((port +
2537 ID_MSG_STRT + 6),
2538 (MPM_OP + AMSG_OUT +
2539 lastTag));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540 CurrCard->tagQ_Lst = lastTag;
2541 currSCCB->Sccb_tag = lastTag;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002542 CurrCard->discQ_Tbl[lastTag] =
2543 currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544 CurrCard->discQCount++;
2545 break;
2546 }
2547 }
2548
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002549 if (i == QUEUE_DEPTH) {
2550 currTar_Info->TarLUNBusy[lun] = 1;
2551 FPT_queueSelectFail(CurrCard, p_card);
2552 SGRAM_ACCESS(port);
2553 return;
2554 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002556 currSCCB->Sccb_scsistat = SELECT_Q_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002558 WR_HARPOON(port + hp_autostart_3,
2559 (SELECT + SELCHK_STRT));
2560 }
2561 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002562
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002563 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002565 WRW_HARPOON((port + ID_MSG_STRT),
2566 BRH_OP + ALWAYS + NTCMD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002568 WRW_HARPOON((port + NON_TAG_ID_MSG),
2569 (MPM_OP + AMSG_OUT + currSCCB->Sccb_idmsg));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002571 currSCCB->Sccb_scsistat = SELECT_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002573 WR_HARPOON(port + hp_autostart_3,
2574 (SELECT + SELCHK_STRT));
2575 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002577 theCCB = (unsigned char *)&currSCCB->Cdb[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002579 cdb_reg = port + CMD_STRT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002581 for (i = 0; i < currSCCB->CdbLength; i++) {
2582 WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + *theCCB));
2583 cdb_reg += 2;
2584 theCCB++;
2585 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002587 if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
2588 WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002590 }
2591 /* auto_loaded */
2592 WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
2593 WR_HARPOON(port + hp_xferstat, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002595 WRW_HARPOON((port + hp_intstat), (PROG_HLT | TIMEOUT | SEL | BUS_FREE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002597 WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002599 if (!(currSCCB->Sccb_MGRFlags & F_DEV_SELECTED)) {
2600 WR_HARPOON(port + hp_scsictrl_0,
2601 (SEL_TAR | ENA_ATN | ENA_RESEL | ENA_SCAM_SEL));
2602 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08002604/* auto_loaded = (RD_HARPOON(port+hp_autostart_3) & (unsigned char)0x1F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605 auto_loaded |= AUTO_IMMED; */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002606 auto_loaded = AUTO_IMMED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002607
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002608 DISABLE_AUTO(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002609
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002610 WR_HARPOON(port + hp_autostart_3, auto_loaded);
2611 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002613 SGRAM_ACCESS(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614}
2615
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616/*---------------------------------------------------------------------
2617 *
James Bottomley 47b5d692005-04-24 02:38:05 -05002618 * Function: FPT_sres
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619 *
2620 * Description: Hookup the correct CCB and handle the incoming messages.
2621 *
2622 *---------------------------------------------------------------------*/
2623
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002624static void FPT_sres(unsigned long port, unsigned char p_card,
2625 struct sccb_card *pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626{
2627
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002628 unsigned char our_target, message, lun = 0, tag, msgRetryCount;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002630 struct sccb_mgr_tar_info *currTar_Info;
2631 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002633 if (pCurrCard->currentSCCB != NULL) {
2634 currTar_Info =
2635 &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636 DISABLE_AUTO(port);
2637
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002638 WR_HARPOON((port + hp_scsictrl_0), (ENA_RESEL | ENA_SCAM_SEL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639
2640 currSCCB = pCurrCard->currentSCCB;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002641 if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2643 currSCCB->Sccb_scsistat = BUS_FREE_ST;
2644 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002645 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2647 currSCCB->Sccb_scsistat = BUS_FREE_ST;
2648 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002649 if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
2650 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
2651 TAG_Q_TRYING))) {
2652 currTar_Info->TarLUNBusy[currSCCB->Lun] = 0;
2653 if (currSCCB->Sccb_scsistat != ABORT_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002654 pCurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002655 pCurrCard->discQ_Tbl[currTar_Info->
2656 LunDiscQ_Idx[currSCCB->
2657 Lun]]
2658 = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002660 } else {
2661 currTar_Info->TarLUNBusy[0] = 0;
2662 if (currSCCB->Sccb_tag) {
2663 if (currSCCB->Sccb_scsistat != ABORT_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664 pCurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002665 pCurrCard->discQ_Tbl[currSCCB->
2666 Sccb_tag] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002668 } else {
2669 if (currSCCB->Sccb_scsistat != ABORT_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670 pCurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002671 pCurrCard->discQ_Tbl[currTar_Info->
2672 LunDiscQ_Idx[0]] =
2673 NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674 }
2675 }
2676 }
2677
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002678 FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679 }
2680
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002681 WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002683 our_target = (unsigned char)(RD_HARPOON(port + hp_select_id) >> 4);
James Bottomley 47b5d692005-04-24 02:38:05 -05002684 currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686 msgRetryCount = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002687 do {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688
James Bottomley 47b5d692005-04-24 02:38:05 -05002689 currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690 tag = 0;
2691
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002692 while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
2693 if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002695 WRW_HARPOON((port + hp_intstat), PHASE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696 return;
2697 }
2698 }
2699
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002700 WRW_HARPOON((port + hp_intstat), PHASE);
2701 if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002703 message = FPT_sfm(port, pCurrCard->currentSCCB);
2704 if (message) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002706 if (message <= (0x80 | LUN_MASK)) {
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08002707 lun = message & (unsigned char)LUN_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002709 if ((currTar_Info->
2710 TarStatus & TAR_TAG_Q_MASK) ==
2711 TAG_Q_TRYING) {
2712 if (currTar_Info->TarTagQ_Cnt !=
2713 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002715 if (!
2716 (currTar_Info->
2717 TarLUN_CA)) {
2718 ACCEPT_MSG(port); /*Release the ACK for ID msg. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002720 message =
2721 FPT_sfm
2722 (port,
2723 pCurrCard->
2724 currentSCCB);
2725 if (message) {
2726 ACCEPT_MSG
2727 (port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728 }
2729
2730 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002731 message
2732 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002734 if (message !=
2735 0) {
2736 tag =
2737 FPT_sfm
2738 (port,
2739 pCurrCard->
2740 currentSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002741
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002742 if (!
2743 (tag))
2744 message
2745 =
2746 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747 }
2748
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002749 }
2750 /*C.A. exists! */
2751 }
2752 /*End Q cnt != 0 */
2753 }
2754 /*End Tag cmds supported! */
2755 }
2756 /*End valid ID message. */
2757 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758
2759 ACCEPT_MSG_ATN(port);
2760 }
2761
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002762 }
2763 /* End good id message. */
2764 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765
James Bottomley 47b5d692005-04-24 02:38:05 -05002766 message = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002768 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769 ACCEPT_MSG_ATN(port);
2770
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002771 while (!
2772 (RDW_HARPOON((port + hp_intstat)) &
2773 (PHASE | RESET))
2774 && !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
2775 && (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002776
2777 return;
2778 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002779
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002780 if (message == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781 msgRetryCount++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002782 if (msgRetryCount == 1) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002783 FPT_SendMsg(port, SMPARITY);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002784 } else {
James Bottomley 47b5d692005-04-24 02:38:05 -05002785 FPT_SendMsg(port, SMDEV_RESET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002786
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002787 FPT_sssyncv(port, our_target, NARROW_SCSI,
2788 currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002790 if (FPT_sccbMgrTbl[p_card][our_target].
2791 TarEEValue & EE_SYNC_MASK) {
2792
2793 FPT_sccbMgrTbl[p_card][our_target].
2794 TarStatus &= ~TAR_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795
2796 }
2797
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002798 if (FPT_sccbMgrTbl[p_card][our_target].
2799 TarEEValue & EE_WIDE_SCSI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002801 FPT_sccbMgrTbl[p_card][our_target].
2802 TarStatus &= ~TAR_WIDE_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803 }
2804
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002805 FPT_queueFlushTargSccb(p_card, our_target,
2806 SCCB_COMPLETE);
2807 FPT_SccbMgrTableInitTarget(p_card, our_target);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808 return;
2809 }
2810 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002811 } while (message == 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002813 if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
2814 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
James Bottomley 47b5d692005-04-24 02:38:05 -05002815 currTar_Info->TarLUNBusy[lun] = 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002816 pCurrCard->currentSCCB =
2817 pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[lun]];
2818 if (pCurrCard->currentSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002820 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821 ACCEPT_MSG_ATN(port);
2822 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002823 } else {
James Bottomley 47b5d692005-04-24 02:38:05 -05002824 currTar_Info->TarLUNBusy[0] = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002825
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002826 if (tag) {
2827 if (pCurrCard->discQ_Tbl[tag] != NULL) {
2828 pCurrCard->currentSCCB =
2829 pCurrCard->discQ_Tbl[tag];
2830 currTar_Info->TarTagQ_Cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002832 } else {
2833 ACCEPT_MSG_ATN(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002835 } else {
2836 pCurrCard->currentSCCB =
2837 pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]];
2838 if (pCurrCard->currentSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002839 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002840 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841 ACCEPT_MSG_ATN(port);
2842 }
2843 }
2844 }
2845
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002846 if (pCurrCard->currentSCCB != NULL) {
2847 if (pCurrCard->currentSCCB->Sccb_scsistat == ABORT_ST) {
2848 /* During Abort Tag command, the target could have got re-selected
2849 and completed the command. Check the select Q and remove the CCB
2850 if it is in the Select Q */
James Bottomley 47b5d692005-04-24 02:38:05 -05002851 FPT_queueFindSccb(pCurrCard->currentSCCB, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002852 }
2853 }
2854
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002855 while (!(RDW_HARPOON((port + hp_intstat)) & (PHASE | RESET)) &&
2856 !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ) &&
2857 (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002858}
2859
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08002860static void FPT_SendMsg(unsigned long port, unsigned char message)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002861{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002862 while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
2863 if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002864
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002865 WRW_HARPOON((port + hp_intstat), PHASE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002866 return;
2867 }
2868 }
2869
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002870 WRW_HARPOON((port + hp_intstat), PHASE);
2871 if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGO_PH) {
2872 WRW_HARPOON((port + hp_intstat),
2873 (BUS_FREE | PHASE | XFER_CNT_0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002875 WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002876
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002877 WR_HARPOON(port + hp_scsidata_0, message);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002878
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002879 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002880
2881 ACCEPT_MSG(port);
2882
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002883 WR_HARPOON(port + hp_portctrl_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002884
2885 if ((message == SMABORT) || (message == SMDEV_RESET) ||
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002886 (message == SMABORT_TAG)) {
2887 while (!
2888 (RDW_HARPOON((port + hp_intstat)) &
2889 (BUS_FREE | PHASE))) {
2890 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002891
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002892 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
2893 WRW_HARPOON((port + hp_intstat), BUS_FREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002894 }
2895 }
2896 }
2897}
2898
2899/*---------------------------------------------------------------------
2900 *
James Bottomley 47b5d692005-04-24 02:38:05 -05002901 * Function: FPT_sdecm
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902 *
Lucas De Marchi25985ed2011-03-30 22:57:33 -03002903 * Description: Determine the proper response to the message from the
Linus Torvalds1da177e2005-04-16 15:20:36 -07002904 * target device.
2905 *
2906 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002907static void FPT_sdecm(unsigned char message, unsigned long port,
2908 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002909{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002910 struct sccb *currSCCB;
2911 struct sccb_card *CurrCard;
2912 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002913
James Bottomley 47b5d692005-04-24 02:38:05 -05002914 CurrCard = &FPT_BL_Card[p_card];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002915 currSCCB = CurrCard->currentSCCB;
2916
James Bottomley 47b5d692005-04-24 02:38:05 -05002917 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002918
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002919 if (message == SMREST_DATA_PTR) {
2920 if (!(currSCCB->Sccb_XferState & F_NO_DATA_YET)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921 currSCCB->Sccb_ATC = currSCCB->Sccb_savedATC;
2922
James Bottomley 47b5d692005-04-24 02:38:05 -05002923 FPT_hostDataXferRestart(currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002924 }
2925
2926 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002927 WR_HARPOON(port + hp_autostart_1,
2928 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002929 }
2930
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002931 else if (message == SMCMD_COMP) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002932
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002933 if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
2934 currTar_Info->TarStatus &=
2935 ~(unsigned char)TAR_TAG_Q_MASK;
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08002936 currTar_Info->TarStatus |= (unsigned char)TAG_Q_REJECT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002937 }
2938
2939 ACCEPT_MSG(port);
2940
2941 }
2942
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002943 else if ((message == SMNO_OP) || (message >= SMIDENT)
2944 || (message == SMINIT_RECOVERY) || (message == SMREL_RECOVERY)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002945
2946 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002947 WR_HARPOON(port + hp_autostart_1,
2948 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002949 }
2950
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002951 else if (message == SMREJECT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002952
2953 if ((currSCCB->Sccb_scsistat == SELECT_SN_ST) ||
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002954 (currSCCB->Sccb_scsistat == SELECT_WN_ST) ||
2955 ((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)
2956 || ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) ==
2957 TAG_Q_TRYING))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002958 {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002959 WRW_HARPOON((port + hp_intstat), BUS_FREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002960
2961 ACCEPT_MSG(port);
2962
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002963 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2964 (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002965 {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002966 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002967
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002968 if (currSCCB->Lun == 0x00) {
2969 if ((currSCCB->Sccb_scsistat == SELECT_SN_ST)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002970
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002971 currTar_Info->TarStatus |=
2972 (unsigned char)SYNC_SUPPORTED;
2973
2974 currTar_Info->TarEEValue &=
2975 ~EE_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002976 }
2977
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002978 else if ((currSCCB->Sccb_scsistat ==
2979 SELECT_WN_ST)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002980
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002981 currTar_Info->TarStatus =
2982 (currTar_Info->
2983 TarStatus & ~WIDE_ENABLED) |
2984 WIDE_NEGOCIATED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002986 currTar_Info->TarEEValue &=
2987 ~EE_WIDE_SCSI;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002988
2989 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002990
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08002991 else if ((currTar_Info->
2992 TarStatus & TAR_TAG_Q_MASK) ==
2993 TAG_Q_TRYING) {
2994 currTar_Info->TarStatus =
2995 (currTar_Info->
2996 TarStatus & ~(unsigned char)
2997 TAR_TAG_Q_MASK) | TAG_Q_REJECT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002998
2999 currSCCB->ControlByte &= ~F_USE_CMD_Q;
3000 CurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003001 CurrCard->discQ_Tbl[currSCCB->
3002 Sccb_tag] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003 currSCCB->Sccb_tag = 0x00;
3004
3005 }
3006 }
3007
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003008 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003010 if (currSCCB->Lun == 0x00) {
3011 WRW_HARPOON((port + hp_intstat),
3012 BUS_FREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013 CurrCard->globalFlags |= F_NEW_SCCB_CMD;
3014 }
3015 }
3016
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003017 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003018
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003019 if ((CurrCard->globalFlags & F_CONLUN_IO) &&
3020 ((currTar_Info->
3021 TarStatus & TAR_TAG_Q_MASK) !=
3022 TAG_Q_TRYING))
3023 currTar_Info->TarLUNBusy[currSCCB->
3024 Lun] = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003025 else
James Bottomley 47b5d692005-04-24 02:38:05 -05003026 currTar_Info->TarLUNBusy[0] = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003027
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003028 currSCCB->ControlByte &=
3029 ~(unsigned char)F_USE_CMD_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003031 WR_HARPOON(port + hp_autostart_1,
3032 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033
3034 }
3035 }
3036
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003037 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038 ACCEPT_MSG(port);
3039
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003040 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
3041 (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003042 {
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003043 }
3044
3045 if (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)) {
3046 WR_HARPOON(port + hp_autostart_1,
3047 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003048 }
3049 }
3050 }
3051
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003052 else if (message == SMEXT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053
3054 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003055 FPT_shandem(port, p_card, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003056 }
3057
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003058 else if (message == SMIGNORWR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003060 ACCEPT_MSG(port); /* ACK the RESIDUE MSG */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003061
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003062 message = FPT_sfm(port, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003063
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003064 if (currSCCB->Sccb_scsimsg != SMPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003066 WR_HARPOON(port + hp_autostart_1,
3067 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003068 }
3069
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003070 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071
3072 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
3073 currSCCB->Sccb_scsimsg = SMREJECT;
3074
3075 ACCEPT_MSG_ATN(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003076 WR_HARPOON(port + hp_autostart_1,
3077 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078 }
3079}
3080
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081/*---------------------------------------------------------------------
3082 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003083 * Function: FPT_shandem
Linus Torvalds1da177e2005-04-16 15:20:36 -07003084 *
3085 * Description: Decide what to do with the extended message.
3086 *
3087 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003088static void FPT_shandem(unsigned long port, unsigned char p_card,
3089 struct sccb *pCurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003090{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003091 unsigned char length, message;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003092
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003093 length = FPT_sfm(port, pCurrSCCB);
3094 if (length) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095
3096 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003097 message = FPT_sfm(port, pCurrSCCB);
3098 if (message) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003099
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003100 if (message == SMSYNC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003101
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003102 if (length == 0x03) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103
3104 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003105 FPT_stsyncn(port, p_card);
3106 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107
3108 pCurrSCCB->Sccb_scsimsg = SMREJECT;
3109 ACCEPT_MSG_ATN(port);
3110 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003111 } else if (message == SMWDTR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003112
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003113 if (length == 0x02) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003114
3115 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003116 FPT_stwidn(port, p_card);
3117 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003118
3119 pCurrSCCB->Sccb_scsimsg = SMREJECT;
3120 ACCEPT_MSG_ATN(port);
3121
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003122 WR_HARPOON(port + hp_autostart_1,
3123 (AUTO_IMMED +
3124 DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003125 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003126 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127
3128 pCurrSCCB->Sccb_scsimsg = SMREJECT;
3129 ACCEPT_MSG_ATN(port);
3130
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003131 WR_HARPOON(port + hp_autostart_1,
3132 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003134 } else {
3135 if (pCurrSCCB->Sccb_scsimsg != SMPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003137 WR_HARPOON(port + hp_autostart_1,
3138 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003140 } else {
3141 if (pCurrSCCB->Sccb_scsimsg == SMPARITY)
3142 WR_HARPOON(port + hp_autostart_1,
3143 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144 }
3145}
3146
Linus Torvalds1da177e2005-04-16 15:20:36 -07003147/*---------------------------------------------------------------------
3148 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003149 * Function: FPT_sisyncn
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150 *
3151 * Description: Read in a message byte from the SCSI bus, and check
3152 * for a parity error.
3153 *
3154 *---------------------------------------------------------------------*/
3155
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003156static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card,
3157 unsigned char syncFlag)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003158{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003159 struct sccb *currSCCB;
3160 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003161
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003162 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3163 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003165 if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003166
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003167 WRW_HARPOON((port + ID_MSG_STRT),
3168 (MPM_OP + AMSG_OUT +
3169 (currSCCB->
3170 Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003171
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003172 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003173
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003174 WRW_HARPOON((port + SYNC_MSGS + 0),
3175 (MPM_OP + AMSG_OUT + SMEXT));
3176 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
3177 WRW_HARPOON((port + SYNC_MSGS + 4),
3178 (MPM_OP + AMSG_OUT + SMSYNC));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003179
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003180 if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003181
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003182 WRW_HARPOON((port + SYNC_MSGS + 6),
3183 (MPM_OP + AMSG_OUT + 12));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003184
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003185 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
3186 EE_SYNC_10MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003188 WRW_HARPOON((port + SYNC_MSGS + 6),
3189 (MPM_OP + AMSG_OUT + 25));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003190
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003191 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
3192 EE_SYNC_5MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003193
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003194 WRW_HARPOON((port + SYNC_MSGS + 6),
3195 (MPM_OP + AMSG_OUT + 50));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003196
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003198 WRW_HARPOON((port + SYNC_MSGS + 6),
3199 (MPM_OP + AMSG_OUT + 00));
3200
3201 WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
3202 WRW_HARPOON((port + SYNC_MSGS + 10),
3203 (MPM_OP + AMSG_OUT + DEFAULT_OFFSET));
3204 WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
3205
3206 if (syncFlag == 0) {
3207 WR_HARPOON(port + hp_autostart_3,
3208 (SELECT + SELCHK_STRT));
3209 currTar_Info->TarStatus =
3210 ((currTar_Info->
3211 TarStatus & ~(unsigned char)TAR_SYNC_MASK) |
3212 (unsigned char)SYNC_TRYING);
3213 } else {
3214 WR_HARPOON(port + hp_autostart_3,
3215 (AUTO_IMMED + CMD_ONLY_STRT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003216 }
3217
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08003218 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003219 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003220
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003221 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003222
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003223 currTar_Info->TarStatus |= (unsigned char)SYNC_SUPPORTED;
3224 currTar_Info->TarEEValue &= ~EE_SYNC_MASK;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08003225 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003226 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227}
3228
Linus Torvalds1da177e2005-04-16 15:20:36 -07003229/*---------------------------------------------------------------------
3230 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003231 * Function: FPT_stsyncn
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232 *
3233 * Description: The has sent us a Sync Nego message so handle it as
3234 * necessary.
3235 *
3236 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08003237static void FPT_stsyncn(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003238{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003239 unsigned char sync_msg, offset, sync_reg, our_sync_msg;
3240 struct sccb *currSCCB;
3241 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003242
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003243 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3244 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003245
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003246 sync_msg = FPT_sfm(port, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003247
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003248 if ((sync_msg == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3249 WR_HARPOON(port + hp_autostart_1,
3250 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003251 return;
3252 }
3253
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003254 ACCEPT_MSG(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003255
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003256 offset = FPT_sfm(port, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003257
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003258 if ((offset == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3259 WR_HARPOON(port + hp_autostart_1,
3260 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003261 return;
3262 }
3263
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003264 if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003265
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003266 our_sync_msg = 12; /* Setup our Message to 20mb/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003267
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003268 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_10MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003270 our_sync_msg = 25; /* Setup our Message to 10mb/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003271
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003272 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_5MB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003274 our_sync_msg = 50; /* Setup our Message to 5mb/s */
3275 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003276
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003277 our_sync_msg = 0; /* Message = Async */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003278
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003279 if (sync_msg < our_sync_msg) {
3280 sync_msg = our_sync_msg; /*if faster, then set to max. */
3281 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003282
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003283 if (offset == ASYNC)
3284 sync_msg = ASYNC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003285
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003286 if (offset > MAX_OFFSET)
3287 offset = MAX_OFFSET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003288
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003289 sync_reg = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003290
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003291 if (sync_msg > 12)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003292
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003293 sync_reg = 0x20; /* Use 10MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003294
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003295 if (sync_msg > 25)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003296
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003297 sync_reg = 0x40; /* Use 6.6MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003298
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003299 if (sync_msg > 38)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003300
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003301 sync_reg = 0x60; /* Use 5MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003302
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003303 if (sync_msg > 50)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003304
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003305 sync_reg = 0x80; /* Use 4MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003306
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003307 if (sync_msg > 62)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003308
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003309 sync_reg = 0xA0; /* Use 3.33MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003310
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003311 if (sync_msg > 75)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003312
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003313 sync_reg = 0xC0; /* Use 2.85MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003314
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003315 if (sync_msg > 87)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003316
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003317 sync_reg = 0xE0; /* Use 2.5MB/s */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003318
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003319 if (sync_msg > 100) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003320
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003321 sync_reg = 0x00; /* Use ASYNC */
3322 offset = 0x00;
3323 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003324
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003325 if (currTar_Info->TarStatus & WIDE_ENABLED)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003326
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003327 sync_reg |= offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003328
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003329 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003330
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003331 sync_reg |= (offset | NARROW_SCSI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003332
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003333 FPT_sssyncv(port, currSCCB->TargID, sync_reg, currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003334
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003335 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003336
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003337 ACCEPT_MSG(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003338
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003339 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3340 ~(unsigned char)TAR_SYNC_MASK) |
3341 (unsigned char)SYNC_SUPPORTED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003342
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003343 WR_HARPOON(port + hp_autostart_1,
3344 (AUTO_IMMED + DISCONNECT_START));
3345 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003346
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003347 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003348
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003349 ACCEPT_MSG_ATN(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003350
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003351 FPT_sisyncr(port, sync_msg, offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003352
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003353 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3354 ~(unsigned char)TAR_SYNC_MASK) |
3355 (unsigned char)SYNC_SUPPORTED);
3356 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003357}
3358
Linus Torvalds1da177e2005-04-16 15:20:36 -07003359/*---------------------------------------------------------------------
3360 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003361 * Function: FPT_sisyncr
Linus Torvalds1da177e2005-04-16 15:20:36 -07003362 *
3363 * Description: Answer the targets sync message.
3364 *
3365 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003366static void FPT_sisyncr(unsigned long port, unsigned char sync_pulse,
3367 unsigned char offset)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003369 ARAM_ACCESS(port);
3370 WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT));
3371 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
3372 WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMSYNC));
3373 WRW_HARPOON((port + SYNC_MSGS + 6), (MPM_OP + AMSG_OUT + sync_pulse));
3374 WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
3375 WRW_HARPOON((port + SYNC_MSGS + 10), (MPM_OP + AMSG_OUT + offset));
3376 WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
3377 SGRAM_ACCESS(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003378
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003379 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3380 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003382 WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003383
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003384 while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
3385 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003386}
3387
Linus Torvalds1da177e2005-04-16 15:20:36 -07003388/*---------------------------------------------------------------------
3389 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003390 * Function: FPT_siwidn
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391 *
3392 * Description: Read in a message byte from the SCSI bus, and check
3393 * for a parity error.
3394 *
3395 *---------------------------------------------------------------------*/
3396
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08003397static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003398{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003399 struct sccb *currSCCB;
3400 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003401
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003402 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3403 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003404
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003405 if (!((currTar_Info->TarStatus & TAR_WIDE_MASK) == WIDE_NEGOCIATED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003406
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003407 WRW_HARPOON((port + ID_MSG_STRT),
3408 (MPM_OP + AMSG_OUT +
3409 (currSCCB->
3410 Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003411
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003412 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003413
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003414 WRW_HARPOON((port + SYNC_MSGS + 0),
3415 (MPM_OP + AMSG_OUT + SMEXT));
3416 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
3417 WRW_HARPOON((port + SYNC_MSGS + 4),
3418 (MPM_OP + AMSG_OUT + SMWDTR));
3419 WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
3420 WRW_HARPOON((port + SYNC_MSGS + 8),
3421 (MPM_OP + AMSG_OUT + SM16BIT));
3422 WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003423
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003424 WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003425
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003426 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3427 ~(unsigned char)TAR_WIDE_MASK) |
3428 (unsigned char)WIDE_ENABLED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003429
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08003430 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003431 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003432
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003433 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003434
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003435 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3436 ~(unsigned char)TAR_WIDE_MASK) |
3437 WIDE_NEGOCIATED);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003438
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003439 currTar_Info->TarEEValue &= ~EE_WIDE_SCSI;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08003440 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003441 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003442}
3443
Linus Torvalds1da177e2005-04-16 15:20:36 -07003444/*---------------------------------------------------------------------
3445 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003446 * Function: FPT_stwidn
Linus Torvalds1da177e2005-04-16 15:20:36 -07003447 *
3448 * Description: The has sent us a Wide Nego message so handle it as
3449 * necessary.
3450 *
3451 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08003452static void FPT_stwidn(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003453{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003454 unsigned char width;
3455 struct sccb *currSCCB;
3456 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003457
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003458 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3459 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003461 width = FPT_sfm(port, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003462
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003463 if ((width == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3464 WR_HARPOON(port + hp_autostart_1,
3465 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003466 return;
3467 }
3468
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003469 if (!(currTar_Info->TarEEValue & EE_WIDE_SCSI))
3470 width = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003471
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003472 if (width) {
3473 currTar_Info->TarStatus |= WIDE_ENABLED;
3474 width = 0;
3475 } else {
3476 width = NARROW_SCSI;
3477 currTar_Info->TarStatus &= ~WIDE_ENABLED;
3478 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003479
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003480 FPT_sssyncv(port, currSCCB->TargID, width, currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003481
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003482 if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003483
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003484 currTar_Info->TarStatus |= WIDE_NEGOCIATED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003485
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003486 if (!
3487 ((currTar_Info->TarStatus & TAR_SYNC_MASK) ==
3488 SYNC_SUPPORTED)) {
3489 ACCEPT_MSG_ATN(port);
3490 ARAM_ACCESS(port);
3491 FPT_sisyncn(port, p_card, 1);
3492 currSCCB->Sccb_scsistat = SELECT_SN_ST;
3493 SGRAM_ACCESS(port);
3494 } else {
3495 ACCEPT_MSG(port);
3496 WR_HARPOON(port + hp_autostart_1,
3497 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003498 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003499 }
3500
3501 else {
3502
3503 ACCEPT_MSG_ATN(port);
3504
3505 if (currTar_Info->TarEEValue & EE_WIDE_SCSI)
3506 width = SM16BIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003507 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003508 width = SM8BIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003509
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003510 FPT_siwidr(port, width);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003511
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003512 currTar_Info->TarStatus |= (WIDE_NEGOCIATED | WIDE_ENABLED);
3513 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003514}
3515
Linus Torvalds1da177e2005-04-16 15:20:36 -07003516/*---------------------------------------------------------------------
3517 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003518 * Function: FPT_siwidr
Linus Torvalds1da177e2005-04-16 15:20:36 -07003519 *
3520 * Description: Answer the targets Wide nego message.
3521 *
3522 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08003523static void FPT_siwidr(unsigned long port, unsigned char width)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003525 ARAM_ACCESS(port);
3526 WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT));
3527 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
3528 WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMWDTR));
3529 WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
3530 WRW_HARPOON((port + SYNC_MSGS + 8), (MPM_OP + AMSG_OUT + width));
3531 WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
3532 SGRAM_ACCESS(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003533
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003534 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3535 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003536
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003537 WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003538
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003539 while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
3540 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003541}
3542
Linus Torvalds1da177e2005-04-16 15:20:36 -07003543/*---------------------------------------------------------------------
3544 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003545 * Function: FPT_sssyncv
Linus Torvalds1da177e2005-04-16 15:20:36 -07003546 *
3547 * Description: Write the desired value to the Sync Register for the
3548 * ID specified.
3549 *
3550 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003551static void FPT_sssyncv(unsigned long p_port, unsigned char p_id,
3552 unsigned char p_sync_value,
3553 struct sccb_mgr_tar_info *currTar_Info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003554{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003555 unsigned char index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003556
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003557 index = p_id;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003558
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003559 switch (index) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003560
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003561 case 0:
3562 index = 12; /* hp_synctarg_0 */
3563 break;
3564 case 1:
3565 index = 13; /* hp_synctarg_1 */
3566 break;
3567 case 2:
3568 index = 14; /* hp_synctarg_2 */
3569 break;
3570 case 3:
3571 index = 15; /* hp_synctarg_3 */
3572 break;
3573 case 4:
3574 index = 8; /* hp_synctarg_4 */
3575 break;
3576 case 5:
3577 index = 9; /* hp_synctarg_5 */
3578 break;
3579 case 6:
3580 index = 10; /* hp_synctarg_6 */
3581 break;
3582 case 7:
3583 index = 11; /* hp_synctarg_7 */
3584 break;
3585 case 8:
3586 index = 4; /* hp_synctarg_8 */
3587 break;
3588 case 9:
3589 index = 5; /* hp_synctarg_9 */
3590 break;
3591 case 10:
3592 index = 6; /* hp_synctarg_10 */
3593 break;
3594 case 11:
3595 index = 7; /* hp_synctarg_11 */
3596 break;
3597 case 12:
3598 index = 0; /* hp_synctarg_12 */
3599 break;
3600 case 13:
3601 index = 1; /* hp_synctarg_13 */
3602 break;
3603 case 14:
3604 index = 2; /* hp_synctarg_14 */
3605 break;
3606 case 15:
3607 index = 3; /* hp_synctarg_15 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003608
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003609 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003610
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003611 WR_HARPOON(p_port + hp_synctarg_base + index, p_sync_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003612
3613 currTar_Info->TarSyncCtrl = p_sync_value;
3614}
3615
Linus Torvalds1da177e2005-04-16 15:20:36 -07003616/*---------------------------------------------------------------------
3617 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003618 * Function: FPT_sresb
Linus Torvalds1da177e2005-04-16 15:20:36 -07003619 *
3620 * Description: Reset the desired card's SCSI bus.
3621 *
3622 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08003623static void FPT_sresb(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003625 unsigned char scsiID, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003627 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003628
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003629 WR_HARPOON(port + hp_page_ctrl,
3630 (RD_HARPOON(port + hp_page_ctrl) | G_INT_DISABLE));
3631 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003632
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003633 WR_HARPOON(port + hp_scsictrl_0, SCSI_RST);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003634
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003635 scsiID = RD_HARPOON(port + hp_seltimeout);
3636 WR_HARPOON(port + hp_seltimeout, TO_5ms);
3637 WRW_HARPOON((port + hp_intstat), TIMEOUT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003638
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003639 WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT | START_TO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003640
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003641 while (!(RDW_HARPOON((port + hp_intstat)) & TIMEOUT)) {
3642 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003643
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003644 WR_HARPOON(port + hp_seltimeout, scsiID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003645
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003646 WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003647
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003648 FPT_Wait(port, TO_5ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003649
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003650 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003652 WR_HARPOON(port + hp_int_mask, (RD_HARPOON(port + hp_int_mask) | 0x00));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003654 for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
3655 currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003656
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003657 if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
3658 currTar_Info->TarSyncCtrl = 0;
3659 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
3660 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003661
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003662 if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
3663 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
3664 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003665
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003666 FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003667
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003668 FPT_SccbMgrTableInitTarget(p_card, scsiID);
3669 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003670
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003671 FPT_BL_Card[p_card].scanIndex = 0x00;
3672 FPT_BL_Card[p_card].currentSCCB = NULL;
3673 FPT_BL_Card[p_card].globalFlags &= ~(F_TAG_STARTED | F_HOST_XFER_ACT
3674 | F_NEW_SCCB_CMD);
3675 FPT_BL_Card[p_card].cmdCounter = 0x00;
James Bottomley 47b5d692005-04-24 02:38:05 -05003676 FPT_BL_Card[p_card].discQCount = 0x00;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003677 FPT_BL_Card[p_card].tagQ_Lst = 0x01;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003678
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003679 for (i = 0; i < QUEUE_DEPTH; i++)
James Bottomley 47b5d692005-04-24 02:38:05 -05003680 FPT_BL_Card[p_card].discQ_Tbl[i] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003681
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003682 WR_HARPOON(port + hp_page_ctrl,
3683 (RD_HARPOON(port + hp_page_ctrl) & ~G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003684
3685}
3686
3687/*---------------------------------------------------------------------
3688 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003689 * Function: FPT_ssenss
Linus Torvalds1da177e2005-04-16 15:20:36 -07003690 *
3691 * Description: Setup for the Auto Sense command.
3692 *
3693 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003694static void FPT_ssenss(struct sccb_card *pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003695{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003696 unsigned char i;
3697 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003698
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003699 currSCCB = pCurrCard->currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003700
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003701 currSCCB->Save_CdbLen = currSCCB->CdbLength;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003703 for (i = 0; i < 6; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003704
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003705 currSCCB->Save_Cdb[i] = currSCCB->Cdb[i];
3706 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003707
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003708 currSCCB->CdbLength = SIX_BYTE_CMD;
3709 currSCCB->Cdb[0] = SCSI_REQUEST_SENSE;
3710 currSCCB->Cdb[1] = currSCCB->Cdb[1] & (unsigned char)0xE0; /*Keep LUN. */
3711 currSCCB->Cdb[2] = 0x00;
3712 currSCCB->Cdb[3] = 0x00;
3713 currSCCB->Cdb[4] = currSCCB->RequestSenseLength;
3714 currSCCB->Cdb[5] = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003715
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003716 currSCCB->Sccb_XferCnt = (unsigned long)currSCCB->RequestSenseLength;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003717
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003718 currSCCB->Sccb_ATC = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003719
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003720 currSCCB->Sccb_XferState |= F_AUTO_SENSE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003721
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003722 currSCCB->Sccb_XferState &= ~F_SG_XFER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003723
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003724 currSCCB->Sccb_idmsg = currSCCB->Sccb_idmsg & ~(unsigned char)DISC_PRIV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003726 currSCCB->ControlByte = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003727
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003728 currSCCB->Sccb_MGRFlags &= F_STATUSLOADED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003729}
3730
Linus Torvalds1da177e2005-04-16 15:20:36 -07003731/*---------------------------------------------------------------------
3732 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003733 * Function: FPT_sxfrp
Linus Torvalds1da177e2005-04-16 15:20:36 -07003734 *
3735 * Description: Transfer data into the bit bucket until the device
3736 * decides to switch phase.
3737 *
3738 *---------------------------------------------------------------------*/
3739
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08003740static void FPT_sxfrp(unsigned long p_port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003741{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003742 unsigned char curr_phz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003743
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003744 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003745
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003746 if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003747
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003748 FPT_hostDataXferAbort(p_port, p_card,
3749 FPT_BL_Card[p_card].currentSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003750
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003751 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003752
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003753 /* If the Automation handled the end of the transfer then do not
3754 match the phase or we will get out of sync with the ISR. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003755
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003756 if (RDW_HARPOON((p_port + hp_intstat)) &
3757 (BUS_FREE | XFER_CNT_0 | AUTO_INT))
3758 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003759
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003760 WR_HARPOON(p_port + hp_xfercnt_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003761
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003762 curr_phz = RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003763
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003764 WRW_HARPOON((p_port + hp_intstat), XFER_CNT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003766 WR_HARPOON(p_port + hp_scsisig, curr_phz);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003767
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003768 while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET)) &&
3769 (curr_phz ==
3770 (RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ)))
3771 {
3772 if (curr_phz & (unsigned char)SCSI_IOBIT) {
3773 WR_HARPOON(p_port + hp_portctrl_0,
3774 (SCSI_PORT | HOST_PORT | SCSI_INBIT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003776 if (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
3777 RD_HARPOON(p_port + hp_fifodata_0);
3778 }
3779 } else {
3780 WR_HARPOON(p_port + hp_portctrl_0,
3781 (SCSI_PORT | HOST_PORT | HOST_WRT));
3782 if (RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY) {
3783 WR_HARPOON(p_port + hp_fifodata_0, 0xFA);
3784 }
3785 }
3786 } /* End of While loop for padding data I/O phase */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003787
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003788 while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
3789 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ)
3790 break;
3791 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003792
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003793 WR_HARPOON(p_port + hp_portctrl_0,
3794 (SCSI_PORT | HOST_PORT | SCSI_INBIT));
3795 while (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
3796 RD_HARPOON(p_port + hp_fifodata_0);
3797 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003798
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003799 if (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
3800 WR_HARPOON(p_port + hp_autostart_0,
3801 (AUTO_IMMED + DISCONNECT_START));
3802 while (!(RDW_HARPOON((p_port + hp_intstat)) & AUTO_INT)) {
3803 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003804
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003805 if (RDW_HARPOON((p_port + hp_intstat)) &
3806 (ICMD_COMP | ITAR_DISC))
3807 while (!
3808 (RDW_HARPOON((p_port + hp_intstat)) &
3809 (BUS_FREE | RSEL))) ;
3810 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003811}
3812
Linus Torvalds1da177e2005-04-16 15:20:36 -07003813/*---------------------------------------------------------------------
3814 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003815 * Function: FPT_schkdd
Linus Torvalds1da177e2005-04-16 15:20:36 -07003816 *
3817 * Description: Make sure data has been flushed from both FIFOs and abort
3818 * the operations if necessary.
3819 *
3820 *---------------------------------------------------------------------*/
3821
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08003822static void FPT_schkdd(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003823{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003824 unsigned short TimeOutLoop;
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08003825 unsigned char sPhase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003826
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003827 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003829 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003831 if ((currSCCB->Sccb_scsistat != DATA_OUT_ST) &&
3832 (currSCCB->Sccb_scsistat != DATA_IN_ST)) {
3833 return;
3834 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003835
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003836 if (currSCCB->Sccb_XferState & F_ODD_BALL_CNT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003837
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003838 currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003839
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003840 currSCCB->Sccb_XferCnt = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003842 currSCCB->Sccb_XferState &= ~F_ODD_BALL_CNT;
3843 WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
3844 WR_HARPOON(port + hp_xferstat, 0x00);
3845 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003846
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003847 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003848
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003849 currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003850
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003851 currSCCB->Sccb_XferCnt = 0;
3852 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003853
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003854 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
3855 (currSCCB->HostStatus == SCCB_COMPLETE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003856
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003857 currSCCB->HostStatus = SCCB_PARITY_ERR;
3858 WRW_HARPOON((port + hp_intstat), PARITY);
3859 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003860
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003861 FPT_hostDataXferAbort(port, p_card, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003863 while (RD_HARPOON(port + hp_scsisig) & SCSI_ACK) {
3864 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003865
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003866 TimeOutLoop = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003867
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003868 while (RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY) {
3869 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
3870 return;
3871 }
3872 if (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) {
3873 break;
3874 }
3875 if (RDW_HARPOON((port + hp_intstat)) & RESET) {
3876 return;
3877 }
3878 if ((RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
3879 || (TimeOutLoop++ > 0x3000))
3880 break;
3881 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003882
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003883 sPhase = RD_HARPOON(port + hp_scsisig) & (SCSI_BSY | S_SCSI_PHZ);
3884 if ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) ||
3885 (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) ||
3886 (sPhase == (SCSI_BSY | S_DATAO_PH)) ||
3887 (sPhase == (SCSI_BSY | S_DATAI_PH))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003888
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003889 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003890
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003891 if (!(currSCCB->Sccb_XferState & F_ALL_XFERRED)) {
3892 if (currSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
3893 FPT_phaseDataIn(port, p_card);
3894 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003896 else {
3897 FPT_phaseDataOut(port, p_card);
3898 }
3899 } else {
3900 FPT_sxfrp(port, p_card);
3901 if (!(RDW_HARPOON((port + hp_intstat)) &
3902 (BUS_FREE | ICMD_COMP | ITAR_DISC | RESET))) {
3903 WRW_HARPOON((port + hp_intstat), AUTO_INT);
3904 FPT_phaseDecode(port, p_card);
3905 }
3906 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003908 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003909
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003910 else {
3911 WR_HARPOON(port + hp_portctrl_0, 0x00);
3912 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003913}
3914
Linus Torvalds1da177e2005-04-16 15:20:36 -07003915/*---------------------------------------------------------------------
3916 *
James Bottomley 47b5d692005-04-24 02:38:05 -05003917 * Function: FPT_sinits
Linus Torvalds1da177e2005-04-16 15:20:36 -07003918 *
3919 * Description: Setup SCCB manager fields in this SCCB.
3920 *
3921 *---------------------------------------------------------------------*/
3922
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003923static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003924{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003925 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003926
Dan Carpenter5d7ebb92009-12-28 20:08:39 +02003927 if ((p_sccb->TargID >= MAX_SCSI_TAR) || (p_sccb->Lun >= MAX_LUN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928 return;
3929 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003930 currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07003931
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003932 p_sccb->Sccb_XferState = 0x00;
3933 p_sccb->Sccb_XferCnt = p_sccb->DataLength;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003935 if ((p_sccb->OperationCode == SCATTER_GATHER_COMMAND) ||
3936 (p_sccb->OperationCode == RESIDUAL_SG_COMMAND)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003937
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003938 p_sccb->Sccb_SGoffset = 0;
3939 p_sccb->Sccb_XferState = F_SG_XFER;
3940 p_sccb->Sccb_XferCnt = 0x00;
3941 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003942
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003943 if (p_sccb->DataLength == 0x00)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003945 p_sccb->Sccb_XferState |= F_ALL_XFERRED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003947 if (p_sccb->ControlByte & F_USE_CMD_Q) {
3948 if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
3949 p_sccb->ControlByte &= ~F_USE_CMD_Q;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003950
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003951 else
3952 currTar_Info->TarStatus |= TAG_Q_TRYING;
3953 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003954
3955/* For !single SCSI device in system & device allow Disconnect
3956 or command is tag_q type then send Cmd with Disconnect Enable
3957 else send Cmd with Disconnect Disable */
3958
3959/*
James Bottomley 47b5d692005-04-24 02:38:05 -05003960 if (((!(FPT_BL_Card[p_card].globalFlags & F_SINGLE_DEVICE)) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07003961 (currTar_Info->TarStatus & TAR_ALLOW_DISC)) ||
3962 (currTar_Info->TarStatus & TAG_Q_TRYING)) {
3963*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003964 if ((currTar_Info->TarStatus & TAR_ALLOW_DISC) ||
3965 (currTar_Info->TarStatus & TAG_Q_TRYING)) {
3966 p_sccb->Sccb_idmsg =
3967 (unsigned char)(SMIDENT | DISC_PRIV) | p_sccb->Lun;
3968 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003970 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003971
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003972 p_sccb->Sccb_idmsg = (unsigned char)SMIDENT | p_sccb->Lun;
3973 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003975 p_sccb->HostStatus = 0x00;
3976 p_sccb->TargetStatus = 0x00;
3977 p_sccb->Sccb_tag = 0x00;
3978 p_sccb->Sccb_MGRFlags = 0x00;
3979 p_sccb->Sccb_sgseg = 0x00;
3980 p_sccb->Sccb_ATC = 0x00;
3981 p_sccb->Sccb_savedATC = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003982/*
3983 p_sccb->SccbVirtDataPtr = 0x00;
3984 p_sccb->Sccb_forwardlink = NULL;
3985 p_sccb->Sccb_backlink = NULL;
3986 */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08003987 p_sccb->Sccb_scsistat = BUS_FREE_ST;
3988 p_sccb->SccbStatus = SCCB_IN_PROCESS;
3989 p_sccb->Sccb_scsimsg = SMNO_OP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003990
3991}
3992
Linus Torvalds1da177e2005-04-16 15:20:36 -07003993/*---------------------------------------------------------------------
3994 *
3995 * Function: Phase Decode
3996 *
3997 * Description: Determine the phase and call the appropriate function.
3998 *
3999 *---------------------------------------------------------------------*/
4000
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004001static void FPT_phaseDecode(unsigned long p_port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004003 unsigned char phase_ref;
4004 void (*phase) (unsigned long, unsigned char);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004005
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004006 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004008 phase_ref =
4009 (unsigned char)(RD_HARPOON(p_port + hp_scsisig) & S_SCSI_PHZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004010
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004011 phase = FPT_s_PhaseTbl[phase_ref];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004012
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004013 (*phase) (p_port, p_card); /* Call the correct phase func */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004014}
4015
Linus Torvalds1da177e2005-04-16 15:20:36 -07004016/*---------------------------------------------------------------------
4017 *
4018 * Function: Data Out Phase
4019 *
4020 * Description: Start up both the BusMaster and Xbow.
4021 *
4022 *---------------------------------------------------------------------*/
4023
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004024static void FPT_phaseDataOut(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004025{
4026
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004027 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004029 currSCCB = FPT_BL_Card[p_card].currentSCCB;
4030 if (currSCCB == NULL) {
4031 return; /* Exit if No SCCB record */
4032 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004033
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004034 currSCCB->Sccb_scsistat = DATA_OUT_ST;
4035 currSCCB->Sccb_XferState &= ~(F_HOST_XFER_DIR | F_NO_DATA_YET);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004036
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004037 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004038
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004039 WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004040
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004041 WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004043 FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004044
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004045 if (currSCCB->Sccb_XferCnt == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004047 if ((currSCCB->ControlByte & SCCB_DATA_XFER_OUT) &&
4048 (currSCCB->HostStatus == SCCB_COMPLETE))
4049 currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004050
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004051 FPT_sxfrp(port, p_card);
4052 if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
4053 FPT_phaseDecode(port, p_card);
4054 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004055}
4056
Linus Torvalds1da177e2005-04-16 15:20:36 -07004057/*---------------------------------------------------------------------
4058 *
4059 * Function: Data In Phase
4060 *
4061 * Description: Startup the BusMaster and the XBOW.
4062 *
4063 *---------------------------------------------------------------------*/
4064
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004065static void FPT_phaseDataIn(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004066{
4067
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004068 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004069
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004070 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004072 if (currSCCB == NULL) {
4073 return; /* Exit if No SCCB record */
4074 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004075
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004076 currSCCB->Sccb_scsistat = DATA_IN_ST;
4077 currSCCB->Sccb_XferState |= F_HOST_XFER_DIR;
4078 currSCCB->Sccb_XferState &= ~F_NO_DATA_YET;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004079
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004080 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004081
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004082 WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004084 WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004085
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004086 FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004088 if (currSCCB->Sccb_XferCnt == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004089
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004090 if ((currSCCB->ControlByte & SCCB_DATA_XFER_IN) &&
4091 (currSCCB->HostStatus == SCCB_COMPLETE))
4092 currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004093
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004094 FPT_sxfrp(port, p_card);
4095 if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
4096 FPT_phaseDecode(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004097
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004098 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004099}
4100
4101/*---------------------------------------------------------------------
4102 *
4103 * Function: Command Phase
4104 *
4105 * Description: Load the CDB into the automation and start it up.
4106 *
4107 *---------------------------------------------------------------------*/
4108
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004109static void FPT_phaseCommand(unsigned long p_port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004111 struct sccb *currSCCB;
4112 unsigned long cdb_reg;
4113 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004114
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004115 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004116
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004117 if (currSCCB->OperationCode == RESET_COMMAND) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004118
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004119 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4120 currSCCB->CdbLength = SIX_BYTE_CMD;
4121 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004122
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004123 WR_HARPOON(p_port + hp_scsisig, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004124
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004125 ARAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004126
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004127 cdb_reg = p_port + CMD_STRT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004129 for (i = 0; i < currSCCB->CdbLength; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004130
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004131 if (currSCCB->OperationCode == RESET_COMMAND)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004132
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004133 WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + 0x00));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004134
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004135 else
4136 WRW_HARPOON(cdb_reg,
4137 (MPM_OP + ACOMMAND + currSCCB->Cdb[i]));
4138 cdb_reg += 2;
4139 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004140
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004141 if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
4142 WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004144 WR_HARPOON(p_port + hp_portctrl_0, (SCSI_PORT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004145
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004146 currSCCB->Sccb_scsistat = COMMAND_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004147
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004148 WR_HARPOON(p_port + hp_autostart_3, (AUTO_IMMED | CMD_ONLY_STRT));
4149 SGRAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004150}
4151
Linus Torvalds1da177e2005-04-16 15:20:36 -07004152/*---------------------------------------------------------------------
4153 *
4154 * Function: Status phase
4155 *
4156 * Description: Bring in the status and command complete message bytes
4157 *
4158 *---------------------------------------------------------------------*/
4159
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004160static void FPT_phaseStatus(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004161{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004162 /* Start-up the automation to finish off this command and let the
4163 isr handle the interrupt for command complete when it comes in.
4164 We could wait here for the interrupt to be generated?
4165 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004166
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004167 WR_HARPOON(port + hp_scsisig, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004168
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004169 WR_HARPOON(port + hp_autostart_0, (AUTO_IMMED + END_DATA_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004170}
4171
Linus Torvalds1da177e2005-04-16 15:20:36 -07004172/*---------------------------------------------------------------------
4173 *
4174 * Function: Phase Message Out
4175 *
4176 * Description: Send out our message (if we have one) and handle whatever
4177 * else is involed.
4178 *
4179 *---------------------------------------------------------------------*/
4180
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004181static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004182{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004183 unsigned char message, scsiID;
4184 struct sccb *currSCCB;
4185 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004186
James Bottomley 47b5d692005-04-24 02:38:05 -05004187 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004188
4189 if (currSCCB != NULL) {
4190
4191 message = currSCCB->Sccb_scsimsg;
4192 scsiID = currSCCB->TargID;
4193
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004194 if (message == SMDEV_RESET) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004195
James Bottomley 47b5d692005-04-24 02:38:05 -05004196 currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004197 currTar_Info->TarSyncCtrl = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004198 FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004199
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004200 if (FPT_sccbMgrTbl[p_card][scsiID].
4201 TarEEValue & EE_SYNC_MASK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004202
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004203 FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
4204 ~TAR_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004205
4206 }
4207
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004208 if (FPT_sccbMgrTbl[p_card][scsiID].
4209 TarEEValue & EE_WIDE_SCSI) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004210
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004211 FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
4212 ~TAR_WIDE_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004213 }
4214
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004215 FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
4216 FPT_SccbMgrTableInitTarget(p_card, scsiID);
4217 } else if (currSCCB->Sccb_scsistat == ABORT_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004218 currSCCB->HostStatus = SCCB_COMPLETE;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004219 if (FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] !=
4220 NULL) {
4221 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4222 Sccb_tag] = NULL;
James Bottomley 47b5d692005-04-24 02:38:05 -05004223 FPT_sccbMgrTbl[p_card][scsiID].TarTagQ_Cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004224 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004225
Linus Torvalds1da177e2005-04-16 15:20:36 -07004226 }
4227
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004228 else if (currSCCB->Sccb_scsistat < COMMAND_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004229
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004230 if (message == SMNO_OP) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004231 currSCCB->Sccb_MGRFlags |= F_DEV_SELECTED;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004232
4233 FPT_ssel(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004234 return;
4235 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004236 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004237
4238 if (message == SMABORT)
4239
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004240 FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004241 }
4242
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004243 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004244 message = SMABORT;
4245 }
4246
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004247 WRW_HARPOON((port + hp_intstat), (BUS_FREE | PHASE | XFER_CNT_0));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004248
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004249 WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004250
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004251 WR_HARPOON(port + hp_scsidata_0, message);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004252
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004253 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004254
4255 ACCEPT_MSG(port);
4256
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004257 WR_HARPOON(port + hp_portctrl_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004258
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004259 if ((message == SMABORT) || (message == SMDEV_RESET) ||
4260 (message == SMABORT_TAG)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004261
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004262 while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | PHASE))) {
4263 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004264
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004265 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
4266 WRW_HARPOON((port + hp_intstat), BUS_FREE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004267
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004268 if (currSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004270 if ((FPT_BL_Card[p_card].
4271 globalFlags & F_CONLUN_IO)
4272 &&
4273 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4274 TarStatus & TAR_TAG_Q_MASK) !=
4275 TAG_Q_TRYING))
4276 FPT_sccbMgrTbl[p_card][currSCCB->
4277 TargID].
4278 TarLUNBusy[currSCCB->Lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004279 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004280 FPT_sccbMgrTbl[p_card][currSCCB->
4281 TargID].
4282 TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004283
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004284 FPT_queueCmdComplete(&FPT_BL_Card[p_card],
4285 currSCCB, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004286 }
4287
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004288 else {
4289 FPT_BL_Card[p_card].globalFlags |=
4290 F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004291 }
4292 }
4293
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004294 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004295
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004296 FPT_sxfrp(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004297 }
4298 }
4299
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004300 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004301
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004302 if (message == SMPARITY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004303 currSCCB->Sccb_scsimsg = SMNO_OP;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004304 WR_HARPOON(port + hp_autostart_1,
4305 (AUTO_IMMED + DISCONNECT_START));
4306 } else {
4307 FPT_sxfrp(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004308 }
4309 }
4310}
4311
Linus Torvalds1da177e2005-04-16 15:20:36 -07004312/*---------------------------------------------------------------------
4313 *
4314 * Function: Message In phase
4315 *
4316 * Description: Bring in the message and determine what to do with it.
4317 *
4318 *---------------------------------------------------------------------*/
4319
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004320static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004321{
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08004322 unsigned char message;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004323 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004324
James Bottomley 47b5d692005-04-24 02:38:05 -05004325 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004326
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004327 if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004328
James Bottomley 47b5d692005-04-24 02:38:05 -05004329 FPT_phaseChkFifo(port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004330 }
4331
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004332 message = RD_HARPOON(port + hp_scsidata_0);
4333 if ((message == SMDISC) || (message == SMSAVE_DATA_PTR)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004334
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004335 WR_HARPOON(port + hp_autostart_1,
4336 (AUTO_IMMED + END_DATA_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004337
4338 }
4339
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004340 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004341
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004342 message = FPT_sfm(port, currSCCB);
4343 if (message) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004344
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004345 FPT_sdecm(message, port, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004346
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004347 } else {
4348 if (currSCCB->Sccb_scsimsg != SMPARITY)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004349 ACCEPT_MSG(port);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004350 WR_HARPOON(port + hp_autostart_1,
4351 (AUTO_IMMED + DISCONNECT_START));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004352 }
4353 }
4354
4355}
4356
Linus Torvalds1da177e2005-04-16 15:20:36 -07004357/*---------------------------------------------------------------------
4358 *
4359 * Function: Illegal phase
4360 *
4361 * Description: Target switched to some illegal phase, so all we can do
4362 * is report an error back to the host (if that is possible)
4363 * and send an ABORT message to the misbehaving target.
4364 *
4365 *---------------------------------------------------------------------*/
4366
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004367static void FPT_phaseIllegal(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004368{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004369 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004370
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004371 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004372
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004373 WR_HARPOON(port + hp_scsisig, RD_HARPOON(port + hp_scsisig));
4374 if (currSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004375
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004376 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4377 currSCCB->Sccb_scsistat = ABORT_ST;
4378 currSCCB->Sccb_scsimsg = SMABORT;
4379 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004380
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004381 ACCEPT_MSG_ATN(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004382}
4383
Linus Torvalds1da177e2005-04-16 15:20:36 -07004384/*---------------------------------------------------------------------
4385 *
4386 * Function: Phase Check FIFO
4387 *
4388 * Description: Make sure data has been flushed from both FIFOs and abort
4389 * the operations if necessary.
4390 *
4391 *---------------------------------------------------------------------*/
4392
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004393static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004394{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004395 unsigned long xfercnt;
4396 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004397
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004398 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004399
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004400 if (currSCCB->Sccb_scsistat == DATA_IN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004401
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004402 while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) &&
4403 (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)) {
4404 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004405
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004406 if (!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) {
4407 currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004408
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004409 currSCCB->Sccb_XferCnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004410
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004411 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
4412 (currSCCB->HostStatus == SCCB_COMPLETE)) {
4413 currSCCB->HostStatus = SCCB_PARITY_ERR;
4414 WRW_HARPOON((port + hp_intstat), PARITY);
4415 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004416
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004417 FPT_hostDataXferAbort(port, p_card, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004419 FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004420
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004421 while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY))
4422 && (RD_HARPOON(port + hp_ext_status) &
4423 BM_CMD_BUSY)) {
4424 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004425
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004426 }
4427 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004428
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004429 /*End Data In specific code. */
4430 GET_XFER_CNT(port, xfercnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004431
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004432 WR_HARPOON(port + hp_xfercnt_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004433
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004434 WR_HARPOON(port + hp_portctrl_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004435
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004436 currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - xfercnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004437
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004438 currSCCB->Sccb_XferCnt = xfercnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004439
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004440 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
4441 (currSCCB->HostStatus == SCCB_COMPLETE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004443 currSCCB->HostStatus = SCCB_PARITY_ERR;
4444 WRW_HARPOON((port + hp_intstat), PARITY);
4445 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004446
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004447 FPT_hostDataXferAbort(port, p_card, currSCCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004448
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004449 WR_HARPOON(port + hp_fifowrite, 0x00);
4450 WR_HARPOON(port + hp_fiforead, 0x00);
4451 WR_HARPOON(port + hp_xferstat, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004452
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004453 WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004454}
4455
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456/*---------------------------------------------------------------------
4457 *
4458 * Function: Phase Bus Free
4459 *
4460 * Description: We just went bus free so figure out if it was
4461 * because of command complete or from a disconnect.
4462 *
4463 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004464static void FPT_phaseBusFree(unsigned long port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004465{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004466 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004467
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004468 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004469
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004470 if (currSCCB != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004471
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004472 DISABLE_AUTO(port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004473
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004474 if (currSCCB->OperationCode == RESET_COMMAND) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004475
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004476 if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4477 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4478 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4479 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4480 TarLUNBusy[currSCCB->Lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004481 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004482 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4483 TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004484
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004485 FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
4486 p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004487
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004488 FPT_queueSearchSelect(&FPT_BL_Card[p_card], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004489
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004490 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004491
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004492 else if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
4493 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4494 (unsigned char)SYNC_SUPPORTED;
4495 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4496 ~EE_SYNC_MASK;
4497 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004498
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004499 else if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
4500 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
4501 (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4502 TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004503
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004504 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4505 ~EE_WIDE_SCSI;
4506 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004507
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004508 else if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
4509 /* Make sure this is not a phony BUS_FREE. If we were
4510 reselected or if BUSY is NOT on then this is a
4511 valid BUS FREE. SRR Wednesday, 5/10/1995. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004512
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004513 if ((!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ||
4514 (RDW_HARPOON((port + hp_intstat)) & RSEL)) {
4515 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4516 TarStatus &= ~TAR_TAG_Q_MASK;
4517 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4518 TarStatus |= TAG_Q_REJECT;
4519 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004520
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004521 else {
4522 return;
4523 }
4524 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004525
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004526 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004527
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004528 currSCCB->Sccb_scsistat = BUS_FREE_ST;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004529
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004530 if (!currSCCB->HostStatus) {
4531 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4532 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004533
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004534 if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4535 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4536 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4537 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4538 TarLUNBusy[currSCCB->Lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004539 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004540 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4541 TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004542
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004543 FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
4544 p_card);
4545 return;
4546 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004547
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004548 FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004549
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004550 } /*end if !=null */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004551}
4552
Linus Torvalds1da177e2005-04-16 15:20:36 -07004553/*---------------------------------------------------------------------
4554 *
4555 * Function: Auto Load Default Map
4556 *
4557 * Description: Load the Automation RAM with the defualt map values.
4558 *
4559 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004560static void FPT_autoLoadDefaultMap(unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004561{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004562 unsigned long map_addr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004563
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004564 ARAM_ACCESS(p_port);
4565 map_addr = p_port + hp_aramBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004566
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004567 WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0xC0)); /*ID MESSAGE */
4568 map_addr += 2;
4569 WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x20)); /*SIMPLE TAG QUEUEING MSG */
4570 map_addr += 2;
4571 WRW_HARPOON(map_addr, RAT_OP); /*RESET ATTENTION */
4572 map_addr += 2;
4573 WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x00)); /*TAG ID MSG */
4574 map_addr += 2;
4575 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 0 */
4576 map_addr += 2;
4577 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 1 */
4578 map_addr += 2;
4579 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 2 */
4580 map_addr += 2;
4581 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 3 */
4582 map_addr += 2;
4583 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 4 */
4584 map_addr += 2;
4585 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 5 */
4586 map_addr += 2;
4587 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 6 */
4588 map_addr += 2;
4589 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 7 */
4590 map_addr += 2;
4591 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 8 */
4592 map_addr += 2;
4593 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 9 */
4594 map_addr += 2;
4595 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 10 */
4596 map_addr += 2;
4597 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 11 */
4598 map_addr += 2;
4599 WRW_HARPOON(map_addr, (CPE_OP + ADATA_OUT + DINT)); /*JUMP IF DATA OUT */
4600 map_addr += 2;
4601 WRW_HARPOON(map_addr, (TCB_OP + FIFO_0 + DI)); /*JUMP IF NO DATA IN FIFO */
4602 map_addr += 2; /*This means AYNC DATA IN */
4603 WRW_HARPOON(map_addr, (SSI_OP + SSI_IDO_STRT)); /*STOP AND INTERRUPT */
4604 map_addr += 2;
4605 WRW_HARPOON(map_addr, (CPE_OP + ADATA_IN + DINT)); /*JUMP IF NOT DATA IN PHZ */
4606 map_addr += 2;
4607 WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST)); /*IF NOT MSG IN CHECK 4 DATA IN */
4608 map_addr += 2;
4609 WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x02)); /*SAVE DATA PTR MSG? */
4610 map_addr += 2;
4611 WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + DC)); /*GO CHECK FOR DISCONNECT MSG */
4612 map_addr += 2;
4613 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR1)); /*SAVE DATA PTRS MSG */
4614 map_addr += 2;
4615 WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST)); /*IF NOT MSG IN CHECK DATA IN */
4616 map_addr += 2;
4617 WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x04)); /*DISCONNECT MSG? */
4618 map_addr += 2;
4619 WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + UNKNWN)); /*UKNKNOWN MSG */
4620 map_addr += 2;
4621 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET)); /*XFER DISCONNECT MSG */
4622 map_addr += 2;
4623 WRW_HARPOON(map_addr, (SSI_OP + SSI_ITAR_DISC)); /*STOP AND INTERRUPT */
4624 map_addr += 2;
4625 WRW_HARPOON(map_addr, (CPN_OP + ASTATUS + UNKNWN)); /*JUMP IF NOT STATUS PHZ. */
4626 map_addr += 2;
4627 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR0)); /*GET STATUS BYTE */
4628 map_addr += 2;
4629 WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + CC)); /*ERROR IF NOT MSG IN PHZ */
4630 map_addr += 2;
4631 WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x00)); /*CHECK FOR CMD COMPLETE MSG. */
4632 map_addr += 2;
4633 WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + CC)); /*ERROR IF NOT CMD COMPLETE MSG. */
4634 map_addr += 2;
4635 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET)); /*GET CMD COMPLETE MSG */
4636 map_addr += 2;
4637 WRW_HARPOON(map_addr, (SSI_OP + SSI_ICMD_COMP)); /*END OF COMMAND */
4638 map_addr += 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004639
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004640 WRW_HARPOON(map_addr, (SSI_OP + SSI_IUNKWN)); /*RECEIVED UNKNOWN MSG BYTE */
4641 map_addr += 2;
4642 WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */
4643 map_addr += 2;
4644 WRW_HARPOON(map_addr, (SSI_OP + SSI_ITICKLE)); /*BIOS Tickled the Mgr */
4645 map_addr += 2;
4646 WRW_HARPOON(map_addr, (SSI_OP + SSI_IRFAIL)); /*EXPECTED ID/TAG MESSAGES AND */
4647 map_addr += 2; /* DIDN'T GET ONE */
4648 WRW_HARPOON(map_addr, (CRR_OP + AR3 + S_IDREG)); /* comp SCSI SEL ID & AR3 */
4649 map_addr += 2;
4650 WRW_HARPOON(map_addr, (BRH_OP + EQUAL + 0x00)); /*SEL ID OK then Conti. */
4651 map_addr += 2;
4652 WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */
Linus Torvalds1da177e2005-04-16 15:20:36 -07004653
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004654 SGRAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004655}
4656
4657/*---------------------------------------------------------------------
4658 *
4659 * Function: Auto Command Complete
4660 *
4661 * Description: Post command back to host and find another command
4662 * to execute.
4663 *
4664 *---------------------------------------------------------------------*/
4665
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08004666static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004667{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004668 struct sccb *currSCCB;
4669 unsigned char status_byte;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004670
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004671 currSCCB = FPT_BL_Card[p_card].currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004672
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004673 status_byte = RD_HARPOON(p_port + hp_gp_reg_0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004674
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004675 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004676
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004677 if (status_byte != SSGOOD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004678
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004679 if (status_byte == SSQ_FULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004680
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004681 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4682 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4683 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4684 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4685 TarLUNBusy[currSCCB->Lun] = 1;
4686 if (FPT_BL_Card[p_card].discQCount != 0)
James Bottomley 47b5d692005-04-24 02:38:05 -05004687 FPT_BL_Card[p_card].discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004688 FPT_BL_Card[p_card].
4689 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4690 [currSCCB->TargID].
4691 LunDiscQ_Idx[currSCCB->Lun]] =
4692 NULL;
4693 } else {
4694 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4695 TarLUNBusy[0] = 1;
4696 if (currSCCB->Sccb_tag) {
4697 if (FPT_BL_Card[p_card].discQCount != 0)
4698 FPT_BL_Card[p_card].
4699 discQCount--;
4700 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4701 Sccb_tag]
4702 = NULL;
4703 } else {
4704 if (FPT_BL_Card[p_card].discQCount != 0)
4705 FPT_BL_Card[p_card].
4706 discQCount--;
4707 FPT_BL_Card[p_card].
4708 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4709 [currSCCB->TargID].
4710 LunDiscQ_Idx[0]] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004711 }
4712 }
4713
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004714 currSCCB->Sccb_MGRFlags |= F_STATUSLOADED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004715
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004716 FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004717
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004718 return;
4719 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004720
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004721 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
4722 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4723 (unsigned char)SYNC_SUPPORTED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004724
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004725 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4726 ~EE_SYNC_MASK;
4727 FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004728
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004729 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4730 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4731 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4732 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4733 TarLUNBusy[currSCCB->Lun] = 1;
4734 if (FPT_BL_Card[p_card].discQCount != 0)
James Bottomley 47b5d692005-04-24 02:38:05 -05004735 FPT_BL_Card[p_card].discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004736 FPT_BL_Card[p_card].
4737 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4738 [currSCCB->TargID].
4739 LunDiscQ_Idx[currSCCB->Lun]] =
4740 NULL;
4741 } else {
4742 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4743 TarLUNBusy[0] = 1;
4744 if (currSCCB->Sccb_tag) {
4745 if (FPT_BL_Card[p_card].discQCount != 0)
4746 FPT_BL_Card[p_card].
4747 discQCount--;
4748 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4749 Sccb_tag]
4750 = NULL;
4751 } else {
4752 if (FPT_BL_Card[p_card].discQCount != 0)
4753 FPT_BL_Card[p_card].
4754 discQCount--;
4755 FPT_BL_Card[p_card].
4756 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4757 [currSCCB->TargID].
4758 LunDiscQ_Idx[0]] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004759 }
4760 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004761 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004762
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004763 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004764
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004765 if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004766
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004767 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
4768 (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4769 TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004770
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004771 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4772 ~EE_WIDE_SCSI;
4773 FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004774
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004775 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4776 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4777 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4778 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4779 TarLUNBusy[currSCCB->Lun] = 1;
4780 if (FPT_BL_Card[p_card].discQCount != 0)
James Bottomley 47b5d692005-04-24 02:38:05 -05004781 FPT_BL_Card[p_card].discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004782 FPT_BL_Card[p_card].
4783 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4784 [currSCCB->TargID].
4785 LunDiscQ_Idx[currSCCB->Lun]] =
4786 NULL;
4787 } else {
4788 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4789 TarLUNBusy[0] = 1;
4790 if (currSCCB->Sccb_tag) {
4791 if (FPT_BL_Card[p_card].discQCount != 0)
4792 FPT_BL_Card[p_card].
4793 discQCount--;
4794 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4795 Sccb_tag]
4796 = NULL;
4797 } else {
4798 if (FPT_BL_Card[p_card].discQCount != 0)
4799 FPT_BL_Card[p_card].
4800 discQCount--;
4801 FPT_BL_Card[p_card].
4802 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4803 [currSCCB->TargID].
4804 LunDiscQ_Idx[0]] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004805 }
4806 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004807 return;
4808
4809 }
4810
4811 if (status_byte == SSCHECK) {
4812 if (FPT_BL_Card[p_card].globalFlags & F_DO_RENEGO) {
4813 if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4814 TarEEValue & EE_SYNC_MASK) {
4815 FPT_sccbMgrTbl[p_card][currSCCB->
4816 TargID].
4817 TarStatus &= ~TAR_SYNC_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004818 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004819 if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4820 TarEEValue & EE_WIDE_SCSI) {
4821 FPT_sccbMgrTbl[p_card][currSCCB->
4822 TargID].
4823 TarStatus &= ~TAR_WIDE_MASK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004824 }
4825 }
4826 }
4827
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004828 if (!(currSCCB->Sccb_XferState & F_AUTO_SENSE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004829
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004830 currSCCB->SccbStatus = SCCB_ERROR;
4831 currSCCB->TargetStatus = status_byte;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004832
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004833 if (status_byte == SSCHECK) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004834
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004835 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4836 TarLUN_CA = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004837
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004838 if (currSCCB->RequestSenseLength !=
4839 NO_AUTO_REQUEST_SENSE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004840
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004841 if (currSCCB->RequestSenseLength == 0)
4842 currSCCB->RequestSenseLength =
4843 14;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004844
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004845 FPT_ssenss(&FPT_BL_Card[p_card]);
4846 FPT_BL_Card[p_card].globalFlags |=
4847 F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004848
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004849 if (((FPT_BL_Card[p_card].
4850 globalFlags & F_CONLUN_IO)
4851 &&
4852 ((FPT_sccbMgrTbl[p_card]
4853 [currSCCB->TargID].
4854 TarStatus & TAR_TAG_Q_MASK) !=
4855 TAG_Q_TRYING))) {
4856 FPT_sccbMgrTbl[p_card]
4857 [currSCCB->TargID].
4858 TarLUNBusy[currSCCB->Lun] =
4859 1;
4860 if (FPT_BL_Card[p_card].
4861 discQCount != 0)
4862 FPT_BL_Card[p_card].
4863 discQCount--;
4864 FPT_BL_Card[p_card].
4865 discQ_Tbl[FPT_sccbMgrTbl
4866 [p_card]
4867 [currSCCB->
4868 TargID].
4869 LunDiscQ_Idx
4870 [currSCCB->Lun]] =
4871 NULL;
4872 } else {
4873 FPT_sccbMgrTbl[p_card]
4874 [currSCCB->TargID].
4875 TarLUNBusy[0] = 1;
4876 if (currSCCB->Sccb_tag) {
4877 if (FPT_BL_Card[p_card].
4878 discQCount != 0)
4879 FPT_BL_Card
4880 [p_card].
4881 discQCount--;
4882 FPT_BL_Card[p_card].
4883 discQ_Tbl[currSCCB->
4884 Sccb_tag]
4885 = NULL;
4886 } else {
4887 if (FPT_BL_Card[p_card].
4888 discQCount != 0)
4889 FPT_BL_Card
4890 [p_card].
4891 discQCount--;
4892 FPT_BL_Card[p_card].
4893 discQ_Tbl
4894 [FPT_sccbMgrTbl
4895 [p_card][currSCCB->
4896 TargID].
4897 LunDiscQ_Idx[0]] =
4898 NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004899 }
4900 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004901 return;
4902 }
4903 }
4904 }
4905 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004906
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004907 if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4908 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4909 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4910 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->
4911 Lun] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004912 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004913 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004914
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004915 FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004916}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004917
4918#define SHORT_WAIT 0x0000000F
4919#define LONG_WAIT 0x0000FFFFL
4920
Linus Torvalds1da177e2005-04-16 15:20:36 -07004921/*---------------------------------------------------------------------
4922 *
4923 * Function: Data Transfer Processor
4924 *
4925 * Description: This routine performs two tasks.
4926 * (1) Start data transfer by calling HOST_DATA_XFER_START
4927 * function. Once data transfer is started, (2) Depends
4928 * on the type of data transfer mode Scatter/Gather mode
4929 * or NON Scatter/Gather mode. In NON Scatter/Gather mode,
4930 * this routine checks Sccb_MGRFlag (F_HOST_XFER_ACT bit) for
4931 * data transfer done. In Scatter/Gather mode, this routine
4932 * checks bus master command complete and dual rank busy
4933 * bit to keep chaining SC transfer command. Similarly,
4934 * in Scatter/Gather mode, it checks Sccb_MGRFlag
4935 * (F_HOST_XFER_ACT bit) for data transfer done.
4936 *
4937 *---------------------------------------------------------------------*/
4938
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004939static void FPT_dataXferProcessor(unsigned long port,
4940 struct sccb_card *pCurrCard)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004941{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004942 struct sccb *currSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004943
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004944 currSCCB = pCurrCard->currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004945
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004946 if (currSCCB->Sccb_XferState & F_SG_XFER) {
4947 if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
4948 {
4949 currSCCB->Sccb_sgseg += (unsigned char)SG_BUF_CNT;
4950 currSCCB->Sccb_SGoffset = 0x00;
4951 }
4952 pCurrCard->globalFlags |= F_HOST_XFER_ACT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004953
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004954 FPT_busMstrSGDataXferStart(port, currSCCB);
4955 }
4956
4957 else {
4958 if (!(pCurrCard->globalFlags & F_HOST_XFER_ACT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004959 pCurrCard->globalFlags |= F_HOST_XFER_ACT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004960
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004961 FPT_busMstrDataXferStart(port, currSCCB);
4962 }
4963 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004964}
4965
Linus Torvalds1da177e2005-04-16 15:20:36 -07004966/*---------------------------------------------------------------------
4967 *
4968 * Function: BusMaster Scatter Gather Data Transfer Start
4969 *
4970 * Description:
4971 *
4972 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004973static void FPT_busMstrSGDataXferStart(unsigned long p_port,
4974 struct sccb *pcurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004975{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004976 unsigned long count, addr, tmpSGCnt;
4977 unsigned int sg_index;
4978 unsigned char sg_count, i;
4979 unsigned long reg_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004980
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004981 if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07004982
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004983 count = ((unsigned long)HOST_RD_CMD) << 24;
4984 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004985
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004986 else {
4987 count = ((unsigned long)HOST_WRT_CMD) << 24;
4988 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004989
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004990 sg_count = 0;
4991 tmpSGCnt = 0;
4992 sg_index = pcurrSCCB->Sccb_sgseg;
4993 reg_offset = hp_aramBase;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004994
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004995 i = (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
4996 ~(SGRAM_ARAM | SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07004997
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08004998 WR_HARPOON(p_port + hp_page_ctrl, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004999
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005000 while ((sg_count < (unsigned char)SG_BUF_CNT) &&
5001 ((unsigned long)(sg_index * (unsigned int)SG_ELEMENT_SIZE) <
5002 pcurrSCCB->DataLength)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005003
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005004 tmpSGCnt += *(((unsigned long *)pcurrSCCB->DataPointer) +
5005 (sg_index * 2));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005006
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005007 count |= *(((unsigned long *)pcurrSCCB->DataPointer) +
5008 (sg_index * 2));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005009
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005010 addr = *(((unsigned long *)pcurrSCCB->DataPointer) +
5011 ((sg_index * 2) + 1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005012
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005013 if ((!sg_count) && (pcurrSCCB->Sccb_SGoffset)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005014
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005015 addr +=
5016 ((count & 0x00FFFFFFL) - pcurrSCCB->Sccb_SGoffset);
5017 count =
5018 (count & 0xFF000000L) | pcurrSCCB->Sccb_SGoffset;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005019
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005020 tmpSGCnt = count & 0x00FFFFFFL;
5021 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005022
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005023 WR_HARP32(p_port, reg_offset, addr);
5024 reg_offset += 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005025
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005026 WR_HARP32(p_port, reg_offset, count);
5027 reg_offset += 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005028
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005029 count &= 0xFF000000L;
5030 sg_index++;
5031 sg_count++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005032
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005033 } /*End While */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005034
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005035 pcurrSCCB->Sccb_XferCnt = tmpSGCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005036
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005037 WR_HARPOON(p_port + hp_sg_addr, (sg_count << 4));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005038
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005039 if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005040
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005041 WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005042
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005043 WR_HARPOON(p_port + hp_portctrl_0,
5044 (DMA_PORT | SCSI_PORT | SCSI_INBIT));
5045 WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
5046 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005047
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005048 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005049
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005050 if ((!(RD_HARPOON(p_port + hp_synctarg_0) & NARROW_SCSI)) &&
5051 (tmpSGCnt & 0x000000001)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005052
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005053 pcurrSCCB->Sccb_XferState |= F_ODD_BALL_CNT;
5054 tmpSGCnt--;
5055 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005056
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005057 WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005058
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005059 WR_HARPOON(p_port + hp_portctrl_0,
5060 (SCSI_PORT | DMA_PORT | DMA_RD));
5061 WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
5062 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005063
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005064 WR_HARPOON(p_port + hp_page_ctrl, (unsigned char)(i | SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005065
5066}
5067
Linus Torvalds1da177e2005-04-16 15:20:36 -07005068/*---------------------------------------------------------------------
5069 *
5070 * Function: BusMaster Data Transfer Start
5071 *
5072 * Description:
5073 *
5074 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005075static void FPT_busMstrDataXferStart(unsigned long p_port,
5076 struct sccb *pcurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005077{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005078 unsigned long addr, count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005079
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005080 if (!(pcurrSCCB->Sccb_XferState & F_AUTO_SENSE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005081
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005082 count = pcurrSCCB->Sccb_XferCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005083
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005084 addr =
5085 (unsigned long)pcurrSCCB->DataPointer + pcurrSCCB->Sccb_ATC;
5086 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005087
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005088 else {
5089 addr = pcurrSCCB->SensePointer;
5090 count = pcurrSCCB->RequestSenseLength;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005091
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005092 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005093
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005094 HP_SETUP_ADDR_CNT(p_port, addr, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005095
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005096 if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005097
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005098 WR_HARPOON(p_port + hp_portctrl_0,
5099 (DMA_PORT | SCSI_PORT | SCSI_INBIT));
5100 WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005101
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005102 WR_HARPOON(p_port + hp_xfer_cmd,
5103 (XFER_DMA_HOST | XFER_HOST_AUTO | XFER_DMA_8BIT));
5104 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005105
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005106 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005107
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005108 WR_HARPOON(p_port + hp_portctrl_0,
5109 (SCSI_PORT | DMA_PORT | DMA_RD));
5110 WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005111
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005112 WR_HARPOON(p_port + hp_xfer_cmd,
5113 (XFER_HOST_DMA | XFER_HOST_AUTO | XFER_DMA_8BIT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005114
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005115 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005116}
5117
Linus Torvalds1da177e2005-04-16 15:20:36 -07005118/*---------------------------------------------------------------------
5119 *
5120 * Function: BusMaster Timeout Handler
5121 *
5122 * Description: This function is called after a bus master command busy time
5123 * out is detected. This routines issue halt state machine
5124 * with a software time out for command busy. If command busy
5125 * is still asserted at the end of the time out, it issues
5126 * hard abort with another software time out. It hard abort
5127 * command busy is also time out, it'll just give up.
5128 *
5129 *---------------------------------------------------------------------*/
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08005130static unsigned char FPT_busMstrTimeOut(unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005131{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005132 unsigned long timeout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005133
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005134 timeout = LONG_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005135
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005136 WR_HARPOON(p_port + hp_sys_ctrl, HALT_MACH);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005137
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005138 while ((!(RD_HARPOON(p_port + hp_ext_status) & CMD_ABORTED))
5139 && timeout--) {
5140 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005141
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005142 if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
5143 WR_HARPOON(p_port + hp_sys_ctrl, HARD_ABORT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005144
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005145 timeout = LONG_WAIT;
5146 while ((RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY)
5147 && timeout--) {
5148 }
5149 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005150
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005151 RD_HARPOON(p_port + hp_int_status); /*Clear command complete */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005152
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005153 if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005154 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005155 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005156
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005157 else {
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005158 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005159 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005160}
5161
Linus Torvalds1da177e2005-04-16 15:20:36 -07005162/*---------------------------------------------------------------------
5163 *
5164 * Function: Host Data Transfer Abort
5165 *
5166 * Description: Abort any in progress transfer.
5167 *
5168 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005169static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card,
5170 struct sccb *pCurrSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005171{
5172
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005173 unsigned long timeout;
5174 unsigned long remain_cnt;
5175 unsigned int sg_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005176
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005177 FPT_BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005178
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005179 if (pCurrSCCB->Sccb_XferState & F_AUTO_SENSE) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005180
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005181 if (!(RD_HARPOON(port + hp_int_status) & INT_CMD_COMPL)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005182
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005183 WR_HARPOON(port + hp_bm_ctrl,
5184 (RD_HARPOON(port + hp_bm_ctrl) |
5185 FLUSH_XFER_CNTR));
5186 timeout = LONG_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005187
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005188 while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
5189 && timeout--) {
5190 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005191
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005192 WR_HARPOON(port + hp_bm_ctrl,
5193 (RD_HARPOON(port + hp_bm_ctrl) &
5194 ~FLUSH_XFER_CNTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005195
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005196 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005197
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005198 if (FPT_busMstrTimeOut(port)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005199
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005200 if (pCurrSCCB->HostStatus == 0x00)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005201
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005202 pCurrSCCB->HostStatus =
5203 SCCB_BM_ERR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005204
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005205 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005206
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005207 if (RD_HARPOON(port + hp_int_status) &
5208 INT_EXT_STATUS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005209
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005210 if (RD_HARPOON(port + hp_ext_status) &
5211 BAD_EXT_STATUS)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005212
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005213 if (pCurrSCCB->HostStatus ==
5214 0x00)
5215 {
5216 pCurrSCCB->HostStatus =
5217 SCCB_BM_ERR;
5218 }
5219 }
5220 }
5221 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005222
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005223 else if (pCurrSCCB->Sccb_XferCnt) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005224
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005225 if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005226
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005227 WR_HARPOON(port + hp_page_ctrl,
5228 (RD_HARPOON(port + hp_page_ctrl) &
5229 ~SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005230
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005231 WR_HARPOON(port + hp_sg_addr, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005232
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005233 sg_ptr = pCurrSCCB->Sccb_sgseg + SG_BUF_CNT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005234
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005235 if (sg_ptr >
5236 (unsigned int)(pCurrSCCB->DataLength /
5237 SG_ELEMENT_SIZE)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005238
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005239 sg_ptr =
5240 (unsigned int)(pCurrSCCB->DataLength /
5241 SG_ELEMENT_SIZE);
5242 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005243
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005244 remain_cnt = pCurrSCCB->Sccb_XferCnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005245
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005246 while (remain_cnt < 0x01000000L) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005247
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005248 sg_ptr--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005249
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005250 if (remain_cnt >
5251 (unsigned
5252 long)(*(((unsigned long *)pCurrSCCB->
5253 DataPointer) + (sg_ptr * 2)))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005254
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005255 remain_cnt -=
5256 (unsigned
5257 long)(*(((unsigned long *)
5258 pCurrSCCB->DataPointer) +
5259 (sg_ptr * 2)));
5260 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005261
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005262 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005263
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005264 break;
5265 }
5266 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005267
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005268 if (remain_cnt < 0x01000000L) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005269
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005270 pCurrSCCB->Sccb_SGoffset = remain_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005271
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005272 pCurrSCCB->Sccb_sgseg = (unsigned short)sg_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005273
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005274 if ((unsigned long)(sg_ptr * SG_ELEMENT_SIZE) ==
5275 pCurrSCCB->DataLength && (remain_cnt == 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005276
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005277 pCurrSCCB->Sccb_XferState |=
5278 F_ALL_XFERRED;
5279 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005280
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005281 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005282
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005283 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005284
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005285 pCurrSCCB->HostStatus =
5286 SCCB_GROSS_FW_ERR;
5287 }
5288 }
5289 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005290
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005291 if (!(pCurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005292
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005293 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005294
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005295 FPT_busMstrTimeOut(port);
5296 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005297
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005298 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005299
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005300 if (RD_HARPOON(port + hp_int_status) &
5301 INT_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005302
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005303 if (RD_HARPOON(port + hp_ext_status) &
5304 BAD_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005305
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005306 if (pCurrSCCB->HostStatus ==
5307 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005308
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005309 pCurrSCCB->HostStatus =
5310 SCCB_BM_ERR;
5311 }
5312 }
5313 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005314
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005315 }
5316 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005317
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005318 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005319
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005320 if ((RD_HARPOON(port + hp_fifo_cnt)) >= BM_THRESHOLD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005321
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005322 timeout = SHORT_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005323
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005324 while ((RD_HARPOON(port + hp_ext_status) &
5325 BM_CMD_BUSY)
5326 && ((RD_HARPOON(port + hp_fifo_cnt)) >=
5327 BM_THRESHOLD) && timeout--) {
5328 }
5329 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005330
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005331 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005332
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005333 WR_HARPOON(port + hp_bm_ctrl,
5334 (RD_HARPOON(port + hp_bm_ctrl) |
5335 FLUSH_XFER_CNTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005336
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005337 timeout = LONG_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005338
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005339 while ((RD_HARPOON(port + hp_ext_status) &
5340 BM_CMD_BUSY) && timeout--) {
5341 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005342
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005343 WR_HARPOON(port + hp_bm_ctrl,
5344 (RD_HARPOON(port + hp_bm_ctrl) &
5345 ~FLUSH_XFER_CNTR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005346
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005347 if (RD_HARPOON(port + hp_ext_status) &
5348 BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005349
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005350 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005351
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005352 pCurrSCCB->HostStatus =
5353 SCCB_BM_ERR;
5354 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005355
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005356 FPT_busMstrTimeOut(port);
5357 }
5358 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005359
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005360 if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005361
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005362 if (RD_HARPOON(port + hp_ext_status) &
5363 BAD_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005364
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005365 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005366
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005367 pCurrSCCB->HostStatus =
5368 SCCB_BM_ERR;
5369 }
5370 }
5371 }
5372 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005373
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005374 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005375
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005376 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005377
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005378 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005379
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005380 timeout = LONG_WAIT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005381
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005382 while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
5383 && timeout--) {
5384 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005385
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005386 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005387
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005388 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005389
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005390 pCurrSCCB->HostStatus = SCCB_BM_ERR;
5391 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005392
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005393 FPT_busMstrTimeOut(port);
5394 }
5395 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005396
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005397 if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005398
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005399 if (RD_HARPOON(port + hp_ext_status) & BAD_EXT_STATUS) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005400
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005401 if (pCurrSCCB->HostStatus == 0x00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005402
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005403 pCurrSCCB->HostStatus = SCCB_BM_ERR;
5404 }
5405 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005406
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005407 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005408
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005409 if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005410
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005411 WR_HARPOON(port + hp_page_ctrl,
5412 (RD_HARPOON(port + hp_page_ctrl) &
5413 ~SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005414
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005415 WR_HARPOON(port + hp_sg_addr, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005416
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005417 pCurrSCCB->Sccb_sgseg += SG_BUF_CNT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005418
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005419 pCurrSCCB->Sccb_SGoffset = 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005420
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005421 if ((unsigned long)(pCurrSCCB->Sccb_sgseg *
5422 SG_ELEMENT_SIZE) >=
5423 pCurrSCCB->DataLength) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005424
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005425 pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005426
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005427 pCurrSCCB->Sccb_sgseg =
5428 (unsigned short)(pCurrSCCB->DataLength /
5429 SG_ELEMENT_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005430
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005431 }
5432 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005433
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005434 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005435
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005436 if (!(pCurrSCCB->Sccb_XferState & F_AUTO_SENSE))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005437
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005438 pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
5439 }
5440 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005441
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005442 WR_HARPOON(port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005443}
5444
Linus Torvalds1da177e2005-04-16 15:20:36 -07005445/*---------------------------------------------------------------------
5446 *
5447 * Function: Host Data Transfer Restart
5448 *
5449 * Description: Reset the available count due to a restore data
5450 * pointers message.
5451 *
5452 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005453static void FPT_hostDataXferRestart(struct sccb *currSCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005454{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005455 unsigned long data_count;
5456 unsigned int sg_index;
5457 unsigned long *sg_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005458
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005459 if (currSCCB->Sccb_XferState & F_SG_XFER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005460
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005461 currSCCB->Sccb_XferCnt = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005462
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005463 sg_index = 0xffff; /*Index by long words into sg list. */
5464 data_count = 0; /*Running count of SG xfer counts. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005465
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005466 sg_ptr = (unsigned long *)currSCCB->DataPointer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005467
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005468 while (data_count < currSCCB->Sccb_ATC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005469
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005470 sg_index++;
5471 data_count += *(sg_ptr + (sg_index * 2));
5472 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005473
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005474 if (data_count == currSCCB->Sccb_ATC) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005475
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005476 currSCCB->Sccb_SGoffset = 0;
5477 sg_index++;
5478 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005479
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005480 else {
5481 currSCCB->Sccb_SGoffset =
5482 data_count - currSCCB->Sccb_ATC;
5483 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005484
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005485 currSCCB->Sccb_sgseg = (unsigned short)sg_index;
5486 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005487
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005488 else {
5489 currSCCB->Sccb_XferCnt =
5490 currSCCB->DataLength - currSCCB->Sccb_ATC;
5491 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005492}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005493
Linus Torvalds1da177e2005-04-16 15:20:36 -07005494/*---------------------------------------------------------------------
5495 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005496 * Function: FPT_scini
Linus Torvalds1da177e2005-04-16 15:20:36 -07005497 *
5498 * Description: Setup all data structures necessary for SCAM selection.
5499 *
5500 *---------------------------------------------------------------------*/
5501
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005502static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
5503 unsigned char p_power_up)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005504{
5505
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005506 unsigned char loser, assigned_id;
5507 unsigned long p_port;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005508
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005509 unsigned char i, k, ScamFlg;
5510 struct sccb_card *currCard;
5511 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005512
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005513 currCard = &FPT_BL_Card[p_card];
5514 p_port = currCard->ioPort;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005515 pCurrNvRam = currCard->pNvRamInfo;
5516
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005517 if (pCurrNvRam) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005518 ScamFlg = pCurrNvRam->niScamConf;
5519 i = pCurrNvRam->niSysConf;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005520 } else {
5521 ScamFlg =
5522 (unsigned char)FPT_utilEERead(p_port, SCAM_CONFIG / 2);
5523 i = (unsigned
5524 char)(FPT_utilEERead(p_port, (SYSTEM_CONFIG / 2)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005525 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005526 if (!(i & 0x02)) /* check if reset bus in AutoSCSI parameter set */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005527 return;
5528
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005529 FPT_inisci(p_card, p_port, p_our_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005530
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005531 /* Force to wait 1 sec after SCSI bus reset. Some SCAM device FW
5532 too slow to return to SCAM selection */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005533
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005534 /* if (p_power_up)
5535 FPT_Wait1Second(p_port);
5536 else
5537 FPT_Wait(p_port, TO_250ms); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005538
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005539 FPT_Wait1Second(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005540
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005541 if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2)) {
5542 while (!(FPT_scarb(p_port, INIT_SELTD))) {
5543 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005544
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005545 FPT_scsel(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005546
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005547 do {
5548 FPT_scxferc(p_port, SYNC_PTRN);
5549 FPT_scxferc(p_port, DOM_MSTR);
5550 loser =
5551 FPT_scsendi(p_port,
5552 &FPT_scamInfo[p_our_id].id_string[0]);
5553 } while (loser == 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005554
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005555 FPT_scbusf(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005556
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005557 if ((p_power_up) && (!loser)) {
5558 FPT_sresb(p_port, p_card);
5559 FPT_Wait(p_port, TO_250ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005560
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005561 while (!(FPT_scarb(p_port, INIT_SELTD))) {
5562 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005563
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005564 FPT_scsel(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005565
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005566 do {
5567 FPT_scxferc(p_port, SYNC_PTRN);
5568 FPT_scxferc(p_port, DOM_MSTR);
5569 loser =
5570 FPT_scsendi(p_port,
5571 &FPT_scamInfo[p_our_id].
5572 id_string[0]);
5573 } while (loser == 0xFF);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005574
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005575 FPT_scbusf(p_port);
5576 }
5577 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005578
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005579 else {
5580 loser = 0;
5581 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005582
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005583 if (!loser) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005584
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005585 FPT_scamInfo[p_our_id].state = ID_ASSIGNED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005586
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005587 if (ScamFlg & SCAM_ENABLED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005588
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005589 for (i = 0; i < MAX_SCSI_TAR; i++) {
5590 if ((FPT_scamInfo[i].state == ID_UNASSIGNED) ||
5591 (FPT_scamInfo[i].state == ID_UNUSED)) {
5592 if (FPT_scsell(p_port, i)) {
5593 FPT_scamInfo[i].state = LEGACY;
5594 if ((FPT_scamInfo[i].
5595 id_string[0] != 0xFF)
5596 || (FPT_scamInfo[i].
5597 id_string[1] != 0xFA)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005598
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005599 FPT_scamInfo[i].
5600 id_string[0] = 0xFF;
5601 FPT_scamInfo[i].
5602 id_string[1] = 0xFA;
5603 if (pCurrNvRam == NULL)
5604 currCard->
5605 globalFlags
5606 |=
5607 F_UPDATE_EEPROM;
5608 }
5609 }
5610 }
5611 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005612
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005613 FPT_sresb(p_port, p_card);
5614 FPT_Wait1Second(p_port);
5615 while (!(FPT_scarb(p_port, INIT_SELTD))) {
5616 }
5617 FPT_scsel(p_port);
5618 FPT_scasid(p_card, p_port);
5619 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005620
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005621 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005622
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005623 else if ((loser) && (ScamFlg & SCAM_ENABLED)) {
5624 FPT_scamInfo[p_our_id].id_string[0] = SLV_TYPE_CODE0;
5625 assigned_id = 0;
5626 FPT_scwtsel(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005627
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005628 do {
5629 while (FPT_scxferc(p_port, 0x00) != SYNC_PTRN) {
5630 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005631
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005632 i = FPT_scxferc(p_port, 0x00);
5633 if (i == ASSIGN_ID) {
5634 if (!
5635 (FPT_scsendi
5636 (p_port,
5637 &FPT_scamInfo[p_our_id].id_string[0]))) {
5638 i = FPT_scxferc(p_port, 0x00);
5639 if (FPT_scvalq(i)) {
5640 k = FPT_scxferc(p_port, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005641
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005642 if (FPT_scvalq(k)) {
5643 currCard->ourId =
5644 ((unsigned char)(i
5645 <<
5646 3)
5647 +
5648 (k &
5649 (unsigned char)7))
5650 & (unsigned char)
5651 0x3F;
5652 FPT_inisci(p_card,
5653 p_port,
5654 p_our_id);
5655 FPT_scamInfo[currCard->
5656 ourId].
5657 state = ID_ASSIGNED;
5658 FPT_scamInfo[currCard->
5659 ourId].
5660 id_string[0]
5661 = SLV_TYPE_CODE0;
5662 assigned_id = 1;
5663 }
5664 }
5665 }
5666 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005667
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005668 else if (i == SET_P_FLAG) {
5669 if (!(FPT_scsendi(p_port,
5670 &FPT_scamInfo[p_our_id].
5671 id_string[0])))
5672 FPT_scamInfo[p_our_id].id_string[0] |=
5673 0x80;
5674 }
5675 } while (!assigned_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005676
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005677 while (FPT_scxferc(p_port, 0x00) != CFG_CMPLT) {
5678 }
5679 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005680
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005681 if (ScamFlg & SCAM_ENABLED) {
5682 FPT_scbusf(p_port);
5683 if (currCard->globalFlags & F_UPDATE_EEPROM) {
5684 FPT_scsavdi(p_card, p_port);
5685 currCard->globalFlags &= ~F_UPDATE_EEPROM;
5686 }
5687 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005688
Linus Torvalds1da177e2005-04-16 15:20:36 -07005689/*
5690 for (i=0,k=0; i < MAX_SCSI_TAR; i++)
5691 {
James Bottomley 47b5d692005-04-24 02:38:05 -05005692 if ((FPT_scamInfo[i].state == ID_ASSIGNED) ||
5693 (FPT_scamInfo[i].state == LEGACY))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005694 k++;
5695 }
5696
5697 if (k==2)
5698 currCard->globalFlags |= F_SINGLE_DEVICE;
5699 else
5700 currCard->globalFlags &= ~F_SINGLE_DEVICE;
5701*/
5702}
5703
Linus Torvalds1da177e2005-04-16 15:20:36 -07005704/*---------------------------------------------------------------------
5705 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005706 * Function: FPT_scarb
Linus Torvalds1da177e2005-04-16 15:20:36 -07005707 *
5708 * Description: Gain control of the bus and wait SCAM select time (250ms)
5709 *
5710 *---------------------------------------------------------------------*/
5711
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08005712static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005713{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005714 if (p_sel_type == INIT_SELTD) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005715
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005716 while (RD_HARPOON(p_port + hp_scsisig) & (SCSI_SEL | SCSI_BSY)) {
5717 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005718
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005719 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005720 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005721
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005722 if (RD_HARPOON(p_port + hp_scsidata_0) != 00)
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 WR_HARPOON(p_port + hp_scsisig,
5726 (RD_HARPOON(p_port + hp_scsisig) | SCSI_BSY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005727
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005728 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005729
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005730 WR_HARPOON(p_port + hp_scsisig,
5731 (RD_HARPOON(p_port + hp_scsisig) &
5732 ~SCSI_BSY));
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005733 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005734 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005735
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005736 WR_HARPOON(p_port + hp_scsisig,
5737 (RD_HARPOON(p_port + hp_scsisig) | SCSI_SEL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005738
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005739 if (RD_HARPOON(p_port + hp_scsidata_0) != 00) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005740
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005741 WR_HARPOON(p_port + hp_scsisig,
5742 (RD_HARPOON(p_port + hp_scsisig) &
5743 ~(SCSI_BSY | SCSI_SEL)));
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005744 return 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005745 }
5746 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005747
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005748 WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
5749 & ~ACTdeassert));
5750 WR_HARPOON(p_port + hp_scsireset, SCAM_EN);
5751 WR_HARPOON(p_port + hp_scsidata_0, 0x00);
5752 WR_HARPOON(p_port + hp_scsidata_1, 0x00);
5753 WR_HARPOON(p_port + hp_portctrl_0, SCSI_BUS_EN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005754
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005755 WR_HARPOON(p_port + hp_scsisig,
5756 (RD_HARPOON(p_port + hp_scsisig) | SCSI_MSG));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005757
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005758 WR_HARPOON(p_port + hp_scsisig, (RD_HARPOON(p_port + hp_scsisig)
5759 & ~SCSI_BSY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005760
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005761 FPT_Wait(p_port, TO_250ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005762
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005763 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005764}
5765
Linus Torvalds1da177e2005-04-16 15:20:36 -07005766/*---------------------------------------------------------------------
5767 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005768 * Function: FPT_scbusf
Linus Torvalds1da177e2005-04-16 15:20:36 -07005769 *
5770 * Description: Release the SCSI bus and disable SCAM selection.
5771 *
5772 *---------------------------------------------------------------------*/
5773
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08005774static void FPT_scbusf(unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005775{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005776 WR_HARPOON(p_port + hp_page_ctrl,
5777 (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005778
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005779 WR_HARPOON(p_port + hp_scsidata_0, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005780
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005781 WR_HARPOON(p_port + hp_portctrl_0, (RD_HARPOON(p_port + hp_portctrl_0)
5782 & ~SCSI_BUS_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005783
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005784 WR_HARPOON(p_port + hp_scsisig, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005785
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005786 WR_HARPOON(p_port + hp_scsireset, (RD_HARPOON(p_port + hp_scsireset)
5787 & ~SCAM_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005788
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005789 WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
5790 | ACTdeassert));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005791
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005792 WRW_HARPOON((p_port + hp_intstat), (BUS_FREE | AUTO_INT | SCAM_SEL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005793
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005794 WR_HARPOON(p_port + hp_page_ctrl,
5795 (RD_HARPOON(p_port + hp_page_ctrl) & ~G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005796}
5797
Linus Torvalds1da177e2005-04-16 15:20:36 -07005798/*---------------------------------------------------------------------
5799 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005800 * Function: FPT_scasid
Linus Torvalds1da177e2005-04-16 15:20:36 -07005801 *
5802 * Description: Assign an ID to all the SCAM devices.
5803 *
5804 *---------------------------------------------------------------------*/
5805
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08005806static void FPT_scasid(unsigned char p_card, unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005807{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005808 unsigned char temp_id_string[ID_STRING_LENGTH];
Linus Torvalds1da177e2005-04-16 15:20:36 -07005809
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005810 unsigned char i, k, scam_id;
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08005811 unsigned char crcBytes[3];
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005812 struct nvram_info *pCurrNvRam;
5813 unsigned short *pCrcBytes;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005814
James Bottomley 47b5d692005-04-24 02:38:05 -05005815 pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005816
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005817 i = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005818
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005819 while (!i) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005820
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005821 for (k = 0; k < ID_STRING_LENGTH; k++) {
5822 temp_id_string[k] = (unsigned char)0x00;
5823 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005824
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005825 FPT_scxferc(p_port, SYNC_PTRN);
5826 FPT_scxferc(p_port, ASSIGN_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005827
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005828 if (!(FPT_sciso(p_port, &temp_id_string[0]))) {
5829 if (pCurrNvRam) {
Alexey Dobriyanfd1e29e2006-03-08 00:14:27 -08005830 pCrcBytes = (unsigned short *)&crcBytes[0];
James Bottomley 47b5d692005-04-24 02:38:05 -05005831 *pCrcBytes = FPT_CalcCrc16(&temp_id_string[0]);
5832 crcBytes[2] = FPT_CalcLrc(&temp_id_string[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005833 temp_id_string[1] = crcBytes[2];
5834 temp_id_string[2] = crcBytes[0];
5835 temp_id_string[3] = crcBytes[1];
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005836 for (k = 4; k < ID_STRING_LENGTH; k++)
5837 temp_id_string[k] = (unsigned char)0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005838 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005839 i = FPT_scmachid(p_card, temp_id_string);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005840
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005841 if (i == CLR_PRIORITY) {
5842 FPT_scxferc(p_port, MISC_CODE);
5843 FPT_scxferc(p_port, CLR_P_FLAG);
5844 i = 0; /*Not the last ID yet. */
5845 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005846
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005847 else if (i != NO_ID_AVAIL) {
5848 if (i < 8)
5849 FPT_scxferc(p_port, ID_0_7);
5850 else
5851 FPT_scxferc(p_port, ID_8_F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005852
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005853 scam_id = (i & (unsigned char)0x07);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005854
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005855 for (k = 1; k < 0x08; k <<= 1)
5856 if (!(k & i))
5857 scam_id += 0x08; /*Count number of zeros in DB0-3. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005858
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005859 FPT_scxferc(p_port, scam_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005860
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005861 i = 0; /*Not the last ID yet. */
5862 }
5863 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005864
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005865 else {
5866 i = 1;
5867 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005868
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005869 } /*End while */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005870
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005871 FPT_scxferc(p_port, SYNC_PTRN);
5872 FPT_scxferc(p_port, CFG_CMPLT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005873}
5874
Linus Torvalds1da177e2005-04-16 15:20:36 -07005875/*---------------------------------------------------------------------
5876 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005877 * Function: FPT_scsel
Linus Torvalds1da177e2005-04-16 15:20:36 -07005878 *
5879 * Description: Select all the SCAM devices.
5880 *
5881 *---------------------------------------------------------------------*/
5882
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08005883static void FPT_scsel(unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005884{
5885
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005886 WR_HARPOON(p_port + hp_scsisig, SCSI_SEL);
5887 FPT_scwiros(p_port, SCSI_MSG);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005888
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005889 WR_HARPOON(p_port + hp_scsisig, (SCSI_SEL | SCSI_BSY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005890
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005891 WR_HARPOON(p_port + hp_scsisig,
5892 (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5893 WR_HARPOON(p_port + hp_scsidata_0,
5894 (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) |
5895 (unsigned char)(BIT(7) + BIT(6))));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005896
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005897 WR_HARPOON(p_port + hp_scsisig, (SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5898 FPT_scwiros(p_port, SCSI_SEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005899
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005900 WR_HARPOON(p_port + hp_scsidata_0,
5901 (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) &
5902 ~(unsigned char)BIT(6)));
5903 FPT_scwirod(p_port, BIT(6));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005904
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005905 WR_HARPOON(p_port + hp_scsisig,
5906 (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
Linus Torvalds1da177e2005-04-16 15:20:36 -07005907}
5908
Linus Torvalds1da177e2005-04-16 15:20:36 -07005909/*---------------------------------------------------------------------
5910 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005911 * Function: FPT_scxferc
Linus Torvalds1da177e2005-04-16 15:20:36 -07005912 *
5913 * Description: Handshake the p_data (DB4-0) across the bus.
5914 *
5915 *---------------------------------------------------------------------*/
5916
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08005917static unsigned char FPT_scxferc(unsigned long p_port, unsigned char p_data)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005918{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005919 unsigned char curr_data, ret_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005920
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005921 curr_data = p_data | BIT(7) | BIT(5); /*Start with DB7 & DB5 asserted. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005922
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005923 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005924
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005925 curr_data &= ~BIT(7);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005926
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005927 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005928
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005929 FPT_scwirod(p_port, BIT(7)); /*Wait for DB7 to be released. */
5930 while (!(RD_HARPOON(p_port + hp_scsidata_0) & BIT(5))) ;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005931
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005932 ret_data = (RD_HARPOON(p_port + hp_scsidata_0) & (unsigned char)0x1F);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005933
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005934 curr_data |= BIT(6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005935
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005936 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005937
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005938 curr_data &= ~BIT(5);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005939
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005940 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005941
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005942 FPT_scwirod(p_port, BIT(5)); /*Wait for DB5 to be released. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005943
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005944 curr_data &= ~(BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0)); /*Release data bits */
5945 curr_data |= BIT(7);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005946
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005947 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005948
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005949 curr_data &= ~BIT(6);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005950
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005951 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005952
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005953 FPT_scwirod(p_port, BIT(6)); /*Wait for DB6 to be released. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005954
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005955 return ret_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005956}
5957
Linus Torvalds1da177e2005-04-16 15:20:36 -07005958/*---------------------------------------------------------------------
5959 *
James Bottomley 47b5d692005-04-24 02:38:05 -05005960 * Function: FPT_scsendi
Linus Torvalds1da177e2005-04-16 15:20:36 -07005961 *
5962 * Description: Transfer our Identification string to determine if we
5963 * will be the dominant master.
5964 *
5965 *---------------------------------------------------------------------*/
5966
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005967static unsigned char FPT_scsendi(unsigned long p_port,
5968 unsigned char p_id_string[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07005969{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005970 unsigned char ret_data, byte_cnt, bit_cnt, defer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005971
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005972 defer = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005973
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005974 for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005975
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005976 for (bit_cnt = 0x80; bit_cnt != 0; bit_cnt >>= 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005977
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005978 if (defer)
5979 ret_data = FPT_scxferc(p_port, 00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005980
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005981 else if (p_id_string[byte_cnt] & bit_cnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005982
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005983 ret_data = FPT_scxferc(p_port, 02);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005984
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005985 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07005986
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005987 ret_data = FPT_scxferc(p_port, 01);
5988 if (ret_data & 02)
5989 defer = 1;
5990 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005991
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005992 if ((ret_data & 0x1C) == 0x10)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005993 return 0x00; /*End of isolation stage, we won! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005994
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005995 if (ret_data & 0x1C)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005996 return 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005997
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08005998 if ((defer) && (!(ret_data & 0x1F)))
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08005999 return 0x01; /*End of isolation stage, we lost. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006000
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006001 } /*bit loop */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006002
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006003 } /*byte loop */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006004
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006005 if (defer)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006006 return 0x01; /*We lost */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006007 else
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006008 return 0; /*We WON! Yeeessss! */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006009}
6010
Linus Torvalds1da177e2005-04-16 15:20:36 -07006011/*---------------------------------------------------------------------
6012 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006013 * Function: FPT_sciso
Linus Torvalds1da177e2005-04-16 15:20:36 -07006014 *
6015 * Description: Transfer the Identification string.
6016 *
6017 *---------------------------------------------------------------------*/
6018
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006019static unsigned char FPT_sciso(unsigned long p_port,
6020 unsigned char p_id_string[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07006021{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006022 unsigned char ret_data, the_data, byte_cnt, bit_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006023
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006024 the_data = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006025
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006026 for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006027
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006028 for (bit_cnt = 0; bit_cnt < 8; bit_cnt++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006029
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006030 ret_data = FPT_scxferc(p_port, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006031
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006032 if (ret_data & 0xFC)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006033 return 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006034
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006035 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006036
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006037 the_data <<= 1;
6038 if (ret_data & BIT(1)) {
6039 the_data |= 1;
6040 }
6041 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006042
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006043 if ((ret_data & 0x1F) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006044/*
6045 if(bit_cnt != 0 || bit_cnt != 8)
6046 {
6047 byte_cnt = 0;
6048 bit_cnt = 0;
James Bottomley 47b5d692005-04-24 02:38:05 -05006049 FPT_scxferc(p_port, SYNC_PTRN);
6050 FPT_scxferc(p_port, ASSIGN_ID);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006051 continue;
6052 }
6053*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006054 if (byte_cnt)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006055 return 0x00;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006056 else
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006057 return 0xFF;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006058 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006059
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006060 } /*bit loop */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006061
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006062 p_id_string[byte_cnt] = the_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006063
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006064 } /*byte loop */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006065
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006066 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006067}
6068
Linus Torvalds1da177e2005-04-16 15:20:36 -07006069/*---------------------------------------------------------------------
6070 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006071 * Function: FPT_scwirod
Linus Torvalds1da177e2005-04-16 15:20:36 -07006072 *
6073 * Description: Sample the SCSI data bus making sure the signal has been
6074 * deasserted for the correct number of consecutive samples.
6075 *
6076 *---------------------------------------------------------------------*/
6077
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08006078static void FPT_scwirod(unsigned long p_port, unsigned char p_data_bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006079{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006080 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006081
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006082 i = 0;
6083 while (i < MAX_SCSI_TAR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006084
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006085 if (RD_HARPOON(p_port + hp_scsidata_0) & p_data_bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006086
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006087 i = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006088
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006089 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07006090
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006091 i++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006092
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006093 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006094}
6095
Linus Torvalds1da177e2005-04-16 15:20:36 -07006096/*---------------------------------------------------------------------
6097 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006098 * Function: FPT_scwiros
Linus Torvalds1da177e2005-04-16 15:20:36 -07006099 *
6100 * Description: Sample the SCSI Signal lines making sure the signal has been
6101 * deasserted for the correct number of consecutive samples.
6102 *
6103 *---------------------------------------------------------------------*/
6104
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08006105static void FPT_scwiros(unsigned long p_port, unsigned char p_data_bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006106{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006107 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006108
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006109 i = 0;
6110 while (i < MAX_SCSI_TAR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006111
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006112 if (RD_HARPOON(p_port + hp_scsisig) & p_data_bit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006113
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006114 i = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006115
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006116 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07006117
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006118 i++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006119
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006120 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006121}
6122
Linus Torvalds1da177e2005-04-16 15:20:36 -07006123/*---------------------------------------------------------------------
6124 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006125 * Function: FPT_scvalq
Linus Torvalds1da177e2005-04-16 15:20:36 -07006126 *
6127 * Description: Make sure we received a valid data byte.
6128 *
6129 *---------------------------------------------------------------------*/
6130
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08006131static unsigned char FPT_scvalq(unsigned char p_quintet)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006132{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006133 unsigned char count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006134
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006135 for (count = 1; count < 0x08; count <<= 1) {
6136 if (!(p_quintet & count))
6137 p_quintet -= 0x80;
6138 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006139
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006140 if (p_quintet & 0x18)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006141 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006142
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006143 else
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006144 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006145}
6146
Linus Torvalds1da177e2005-04-16 15:20:36 -07006147/*---------------------------------------------------------------------
6148 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006149 * Function: FPT_scsell
Linus Torvalds1da177e2005-04-16 15:20:36 -07006150 *
6151 * Description: Select the specified device ID using a selection timeout
6152 * less than 4ms. If somebody responds then it is a legacy
6153 * drive and this ID must be marked as such.
6154 *
6155 *---------------------------------------------------------------------*/
6156
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08006157static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006158{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006159 unsigned long i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006160
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006161 WR_HARPOON(p_port + hp_page_ctrl,
6162 (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006163
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006164 ARAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006165
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006166 WR_HARPOON(p_port + hp_addstat,
6167 (RD_HARPOON(p_port + hp_addstat) | SCAM_TIMER));
6168 WR_HARPOON(p_port + hp_seltimeout, TO_4ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006169
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006170 for (i = p_port + CMD_STRT; i < p_port + CMD_STRT + 12; i += 2) {
6171 WRW_HARPOON(i, (MPM_OP + ACOMMAND));
6172 }
6173 WRW_HARPOON(i, (BRH_OP + ALWAYS + NP));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006174
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006175 WRW_HARPOON((p_port + hp_intstat),
6176 (RESET | TIMEOUT | SEL | BUS_FREE | AUTO_INT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006177
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006178 WR_HARPOON(p_port + hp_select_id, targ_id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006179
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006180 WR_HARPOON(p_port + hp_portctrl_0, SCSI_PORT);
6181 WR_HARPOON(p_port + hp_autostart_3, (SELECT | CMD_ONLY_STRT));
6182 WR_HARPOON(p_port + hp_scsictrl_0, (SEL_TAR | ENA_RESEL));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006183
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006184 while (!(RDW_HARPOON((p_port + hp_intstat)) &
6185 (RESET | PROG_HLT | TIMEOUT | AUTO_INT))) {
6186 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006187
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006188 if (RDW_HARPOON((p_port + hp_intstat)) & RESET)
6189 FPT_Wait(p_port, TO_250ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006190
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006191 DISABLE_AUTO(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006192
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006193 WR_HARPOON(p_port + hp_addstat,
6194 (RD_HARPOON(p_port + hp_addstat) & ~SCAM_TIMER));
6195 WR_HARPOON(p_port + hp_seltimeout, TO_290ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006196
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006197 SGRAM_ACCESS(p_port);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006198
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006199 if (RDW_HARPOON((p_port + hp_intstat)) & (RESET | TIMEOUT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006200
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006201 WRW_HARPOON((p_port + hp_intstat),
6202 (RESET | TIMEOUT | SEL | BUS_FREE | PHASE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006203
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006204 WR_HARPOON(p_port + hp_page_ctrl,
6205 (RD_HARPOON(p_port + hp_page_ctrl) &
6206 ~G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006207
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006208 return 0; /*No legacy device */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006209 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006210
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006211 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006212
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006213 while (!(RDW_HARPOON((p_port + hp_intstat)) & BUS_FREE)) {
6214 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ) {
6215 WR_HARPOON(p_port + hp_scsisig,
6216 (SCSI_ACK + S_ILL_PH));
6217 ACCEPT_MSG(p_port);
6218 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006219 }
6220
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006221 WRW_HARPOON((p_port + hp_intstat), CLR_ALL_INT_1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006222
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006223 WR_HARPOON(p_port + hp_page_ctrl,
6224 (RD_HARPOON(p_port + hp_page_ctrl) &
6225 ~G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006226
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006227 return 1; /*Found one of them oldies! */
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006228 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006229}
6230
Linus Torvalds1da177e2005-04-16 15:20:36 -07006231/*---------------------------------------------------------------------
6232 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006233 * Function: FPT_scwtsel
Linus Torvalds1da177e2005-04-16 15:20:36 -07006234 *
6235 * Description: Wait to be selected by another SCAM initiator.
6236 *
6237 *---------------------------------------------------------------------*/
6238
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08006239static void FPT_scwtsel(unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006240{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006241 while (!(RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL)) {
6242 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006243}
6244
Linus Torvalds1da177e2005-04-16 15:20:36 -07006245/*---------------------------------------------------------------------
6246 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006247 * Function: FPT_inisci
Linus Torvalds1da177e2005-04-16 15:20:36 -07006248 *
6249 * Description: Setup the data Structure with the info from the EEPROM.
6250 *
6251 *---------------------------------------------------------------------*/
6252
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006253static void FPT_inisci(unsigned char p_card, unsigned long p_port,
6254 unsigned char p_our_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006255{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006256 unsigned char i, k, max_id;
6257 unsigned short ee_data;
6258 struct nvram_info *pCurrNvRam;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006259
James Bottomley 47b5d692005-04-24 02:38:05 -05006260 pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006261
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006262 if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6263 max_id = 0x08;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006264
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006265 else
6266 max_id = 0x10;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006267
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006268 if (pCurrNvRam) {
6269 for (i = 0; i < max_id; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006270
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006271 for (k = 0; k < 4; k++)
6272 FPT_scamInfo[i].id_string[k] =
6273 pCurrNvRam->niScamTbl[i][k];
6274 for (k = 4; k < ID_STRING_LENGTH; k++)
6275 FPT_scamInfo[i].id_string[k] =
6276 (unsigned char)0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006277
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006278 if (FPT_scamInfo[i].id_string[0] == 0x00)
6279 FPT_scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */
6280 else
6281 FPT_scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006282
6283 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006284 } else {
6285 for (i = 0; i < max_id; i++) {
6286 for (k = 0; k < ID_STRING_LENGTH; k += 2) {
6287 ee_data =
6288 FPT_utilEERead(p_port,
6289 (unsigned
6290 short)((EE_SCAMBASE / 2) +
6291 (unsigned short)(i *
6292 ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
6293 FPT_scamInfo[i].id_string[k] =
6294 (unsigned char)ee_data;
6295 ee_data >>= 8;
6296 FPT_scamInfo[i].id_string[k + 1] =
6297 (unsigned char)ee_data;
6298 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006299
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006300 if ((FPT_scamInfo[i].id_string[0] == 0x00) ||
6301 (FPT_scamInfo[i].id_string[0] == 0xFF))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006302
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006303 FPT_scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006304
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006305 else
6306 FPT_scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006307
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006308 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006309 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006310 for (k = 0; k < ID_STRING_LENGTH; k++)
James Bottomley 47b5d692005-04-24 02:38:05 -05006311 FPT_scamInfo[p_our_id].id_string[k] = FPT_scamHAString[k];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006312
6313}
6314
6315/*---------------------------------------------------------------------
6316 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006317 * Function: FPT_scmachid
Linus Torvalds1da177e2005-04-16 15:20:36 -07006318 *
6319 * Description: Match the Device ID string with our values stored in
6320 * the EEPROM.
6321 *
6322 *---------------------------------------------------------------------*/
6323
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006324static unsigned char FPT_scmachid(unsigned char p_card,
6325 unsigned char p_id_string[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07006326{
6327
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006328 unsigned char i, k, match;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006329
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006330 for (i = 0; i < MAX_SCSI_TAR; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006331
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006332 match = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006333
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006334 for (k = 0; k < ID_STRING_LENGTH; k++) {
6335 if (p_id_string[k] != FPT_scamInfo[i].id_string[k])
6336 match = 0;
6337 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006338
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006339 if (match) {
6340 FPT_scamInfo[i].state = ID_ASSIGNED;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006341 return i;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006342 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006343
Linus Torvalds1da177e2005-04-16 15:20:36 -07006344 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006345
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006346 if (p_id_string[0] & BIT(5))
6347 i = 8;
6348 else
6349 i = MAX_SCSI_TAR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006350
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006351 if (((p_id_string[0] & 0x06) == 0x02)
6352 || ((p_id_string[0] & 0x06) == 0x04))
6353 match = p_id_string[1] & (unsigned char)0x1F;
6354 else
6355 match = 7;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006356
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006357 while (i > 0) {
6358 i--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006359
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006360 if (FPT_scamInfo[match].state == ID_UNUSED) {
6361 for (k = 0; k < ID_STRING_LENGTH; k++) {
6362 FPT_scamInfo[match].id_string[k] =
6363 p_id_string[k];
6364 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006365
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006366 FPT_scamInfo[match].state = ID_ASSIGNED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006367
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006368 if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
6369 FPT_BL_Card[p_card].globalFlags |=
6370 F_UPDATE_EEPROM;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006371 return match;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006372
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006373 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006374
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006375 match--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006376
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006377 if (match == 0xFF) {
6378 if (p_id_string[0] & BIT(5))
6379 match = 7;
6380 else
6381 match = MAX_SCSI_TAR - 1;
6382 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006383 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006384
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006385 if (p_id_string[0] & BIT(7)) {
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006386 return CLR_PRIORITY;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006387 }
6388
6389 if (p_id_string[0] & BIT(5))
6390 i = 8;
6391 else
6392 i = MAX_SCSI_TAR;
6393
6394 if (((p_id_string[0] & 0x06) == 0x02)
6395 || ((p_id_string[0] & 0x06) == 0x04))
6396 match = p_id_string[1] & (unsigned char)0x1F;
6397 else
6398 match = 7;
6399
6400 while (i > 0) {
6401
6402 i--;
6403
6404 if (FPT_scamInfo[match].state == ID_UNASSIGNED) {
6405 for (k = 0; k < ID_STRING_LENGTH; k++) {
6406 FPT_scamInfo[match].id_string[k] =
6407 p_id_string[k];
6408 }
6409
6410 FPT_scamInfo[match].id_string[0] |= BIT(7);
6411 FPT_scamInfo[match].state = ID_ASSIGNED;
6412 if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
6413 FPT_BL_Card[p_card].globalFlags |=
6414 F_UPDATE_EEPROM;
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006415 return match;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006416
6417 }
6418
6419 match--;
6420
6421 if (match == 0xFF) {
6422 if (p_id_string[0] & BIT(5))
6423 match = 7;
6424 else
6425 match = MAX_SCSI_TAR - 1;
6426 }
6427 }
6428
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08006429 return NO_ID_AVAIL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006430}
6431
Linus Torvalds1da177e2005-04-16 15:20:36 -07006432/*---------------------------------------------------------------------
6433 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006434 * Function: FPT_scsavdi
Linus Torvalds1da177e2005-04-16 15:20:36 -07006435 *
6436 * Description: Save off the device SCAM ID strings.
6437 *
6438 *---------------------------------------------------------------------*/
6439
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08006440static void FPT_scsavdi(unsigned char p_card, unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006441{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006442 unsigned char i, k, max_id;
6443 unsigned short ee_data, sum_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006444
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006445 sum_data = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006446
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006447 for (i = 1; i < EE_SCAMBASE / 2; i++) {
6448 sum_data += FPT_utilEERead(p_port, i);
6449 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006450
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006451 FPT_utilEEWriteOnOff(p_port, 1); /* Enable write access to the EEPROM */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006452
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006453 if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6454 max_id = 0x08;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006455
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006456 else
6457 max_id = 0x10;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006458
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006459 for (i = 0; i < max_id; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006460
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006461 for (k = 0; k < ID_STRING_LENGTH; k += 2) {
6462 ee_data = FPT_scamInfo[i].id_string[k + 1];
6463 ee_data <<= 8;
6464 ee_data |= FPT_scamInfo[i].id_string[k];
6465 sum_data += ee_data;
6466 FPT_utilEEWrite(p_port, ee_data,
6467 (unsigned short)((EE_SCAMBASE / 2) +
6468 (unsigned short)(i *
6469 ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
6470 }
6471 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006472
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006473 FPT_utilEEWrite(p_port, sum_data, EEPROM_CHECK_SUM / 2);
6474 FPT_utilEEWriteOnOff(p_port, 0); /* Turn off write access */
Linus Torvalds1da177e2005-04-16 15:20:36 -07006475}
Linus Torvalds1da177e2005-04-16 15:20:36 -07006476
6477/*---------------------------------------------------------------------
6478 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006479 * Function: FPT_XbowInit
Linus Torvalds1da177e2005-04-16 15:20:36 -07006480 *
6481 * Description: Setup the Xbow for normal operation.
6482 *
6483 *---------------------------------------------------------------------*/
6484
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08006485static void FPT_XbowInit(unsigned long port, unsigned char ScamFlg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006486{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006487 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006488
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006489 i = RD_HARPOON(port + hp_page_ctrl);
6490 WR_HARPOON(port + hp_page_ctrl, (unsigned char)(i | G_INT_DISABLE));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006491
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006492 WR_HARPOON(port + hp_scsireset, 0x00);
6493 WR_HARPOON(port + hp_portctrl_1, HOST_MODE8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006494
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006495 WR_HARPOON(port + hp_scsireset, (DMA_RESET | HPSCSI_RESET | PROG_RESET |
6496 FIFO_CLR));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006497
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006498 WR_HARPOON(port + hp_scsireset, SCSI_INI);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006499
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006500 WR_HARPOON(port + hp_clkctrl_0, CLKCTRL_DEFAULT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006501
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006502 WR_HARPOON(port + hp_scsisig, 0x00); /* Clear any signals we might */
6503 WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006504
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006505 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006506
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006507 FPT_default_intena = RESET | RSEL | PROG_HLT | TIMEOUT |
6508 BUS_FREE | XFER_CNT_0 | AUTO_INT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006509
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006510 if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2))
James Bottomley 47b5d692005-04-24 02:38:05 -05006511 FPT_default_intena |= SCAM_SEL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006512
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006513 WRW_HARPOON((port + hp_intena), FPT_default_intena);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006514
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006515 WR_HARPOON(port + hp_seltimeout, TO_290ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006516
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006517 /* Turn on SCSI_MODE8 for narrow cards to fix the
6518 strapping issue with the DUAL CHANNEL card */
6519 if (RD_HARPOON(port + hp_page_ctrl) & NARROW_SCSI_CARD)
6520 WR_HARPOON(port + hp_addstat, SCSI_MODE8);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006521
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006522 WR_HARPOON(port + hp_page_ctrl, i);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006523
6524}
6525
Linus Torvalds1da177e2005-04-16 15:20:36 -07006526/*---------------------------------------------------------------------
6527 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006528 * Function: FPT_BusMasterInit
Linus Torvalds1da177e2005-04-16 15:20:36 -07006529 *
6530 * Description: Initialize the BusMaster for normal operations.
6531 *
6532 *---------------------------------------------------------------------*/
6533
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08006534static void FPT_BusMasterInit(unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006535{
6536
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006537 WR_HARPOON(p_port + hp_sys_ctrl, DRVR_RST);
6538 WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006539
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006540 WR_HARPOON(p_port + hp_host_blk_cnt, XFER_BLK64);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006541
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006542 WR_HARPOON(p_port + hp_bm_ctrl, (BMCTRL_DEFAULT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006543
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006544 WR_HARPOON(p_port + hp_ee_ctrl, (SCSI_TERM_ENA_H));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006545
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006546 RD_HARPOON(p_port + hp_int_status); /*Clear interrupts. */
6547 WR_HARPOON(p_port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
6548 WR_HARPOON(p_port + hp_page_ctrl, (RD_HARPOON(p_port + hp_page_ctrl) &
6549 ~SCATTER_EN));
Linus Torvalds1da177e2005-04-16 15:20:36 -07006550}
6551
Linus Torvalds1da177e2005-04-16 15:20:36 -07006552/*---------------------------------------------------------------------
6553 *
James Bottomley 47b5d692005-04-24 02:38:05 -05006554 * Function: FPT_DiagEEPROM
Linus Torvalds1da177e2005-04-16 15:20:36 -07006555 *
6556 * Description: Verfiy checksum and 'Key' and initialize the EEPROM if
6557 * necessary.
6558 *
6559 *---------------------------------------------------------------------*/
6560
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08006561static void FPT_DiagEEPROM(unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006562{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006563 unsigned short index, temp, max_wd_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006564
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006565 if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6566 max_wd_cnt = EEPROM_WD_CNT;
6567 else
6568 max_wd_cnt = EEPROM_WD_CNT * 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006569
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006570 temp = FPT_utilEERead(p_port, FW_SIGNATURE / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006571
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006572 if (temp == 0x4641) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006573
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006574 for (index = 2; index < max_wd_cnt; index++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006575
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006576 temp += FPT_utilEERead(p_port, index);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006577
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006578 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006579
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006580 if (temp == FPT_utilEERead(p_port, EEPROM_CHECK_SUM / 2)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006581
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006582 return; /*EEPROM is Okay so return now! */
6583 }
6584 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006585
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006586 FPT_utilEEWriteOnOff(p_port, (unsigned char)1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006587
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006588 for (index = 0; index < max_wd_cnt; index++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006589
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006590 FPT_utilEEWrite(p_port, 0x0000, index);
6591 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006592
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006593 temp = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006594
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006595 FPT_utilEEWrite(p_port, 0x4641, FW_SIGNATURE / 2);
6596 temp += 0x4641;
6597 FPT_utilEEWrite(p_port, 0x3920, MODEL_NUMB_0 / 2);
6598 temp += 0x3920;
6599 FPT_utilEEWrite(p_port, 0x3033, MODEL_NUMB_2 / 2);
6600 temp += 0x3033;
6601 FPT_utilEEWrite(p_port, 0x2020, MODEL_NUMB_4 / 2);
6602 temp += 0x2020;
6603 FPT_utilEEWrite(p_port, 0x70D3, SYSTEM_CONFIG / 2);
6604 temp += 0x70D3;
6605 FPT_utilEEWrite(p_port, 0x0010, BIOS_CONFIG / 2);
6606 temp += 0x0010;
6607 FPT_utilEEWrite(p_port, 0x0003, SCAM_CONFIG / 2);
6608 temp += 0x0003;
6609 FPT_utilEEWrite(p_port, 0x0007, ADAPTER_SCSI_ID / 2);
6610 temp += 0x0007;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006611
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006612 FPT_utilEEWrite(p_port, 0x0000, IGNORE_B_SCAN / 2);
6613 temp += 0x0000;
6614 FPT_utilEEWrite(p_port, 0x0000, SEND_START_ENA / 2);
6615 temp += 0x0000;
6616 FPT_utilEEWrite(p_port, 0x0000, DEVICE_ENABLE / 2);
6617 temp += 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006618
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006619 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL01 / 2);
6620 temp += 0x4242;
6621 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL23 / 2);
6622 temp += 0x4242;
6623 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL45 / 2);
6624 temp += 0x4242;
6625 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL67 / 2);
6626 temp += 0x4242;
6627 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL89 / 2);
6628 temp += 0x4242;
6629 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLab / 2);
6630 temp += 0x4242;
6631 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLcd / 2);
6632 temp += 0x4242;
6633 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLef / 2);
6634 temp += 0x4242;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006635
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006636 FPT_utilEEWrite(p_port, 0x6C46, 64 / 2); /*PRODUCT ID */
6637 temp += 0x6C46;
6638 FPT_utilEEWrite(p_port, 0x7361, 66 / 2); /* FlashPoint LT */
6639 temp += 0x7361;
6640 FPT_utilEEWrite(p_port, 0x5068, 68 / 2);
6641 temp += 0x5068;
6642 FPT_utilEEWrite(p_port, 0x696F, 70 / 2);
6643 temp += 0x696F;
6644 FPT_utilEEWrite(p_port, 0x746E, 72 / 2);
6645 temp += 0x746E;
6646 FPT_utilEEWrite(p_port, 0x4C20, 74 / 2);
6647 temp += 0x4C20;
6648 FPT_utilEEWrite(p_port, 0x2054, 76 / 2);
6649 temp += 0x2054;
6650 FPT_utilEEWrite(p_port, 0x2020, 78 / 2);
6651 temp += 0x2020;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006652
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006653 index = ((EE_SCAMBASE / 2) + (7 * 16));
6654 FPT_utilEEWrite(p_port, (0x0700 + TYPE_CODE0), index);
6655 temp += (0x0700 + TYPE_CODE0);
6656 index++;
6657 FPT_utilEEWrite(p_port, 0x5542, index); /*Vendor ID code */
6658 temp += 0x5542; /* BUSLOGIC */
6659 index++;
6660 FPT_utilEEWrite(p_port, 0x4C53, index);
6661 temp += 0x4C53;
6662 index++;
6663 FPT_utilEEWrite(p_port, 0x474F, index);
6664 temp += 0x474F;
6665 index++;
6666 FPT_utilEEWrite(p_port, 0x4349, index);
6667 temp += 0x4349;
6668 index++;
6669 FPT_utilEEWrite(p_port, 0x5442, index); /*Vendor unique code */
6670 temp += 0x5442; /* BT- 930 */
6671 index++;
6672 FPT_utilEEWrite(p_port, 0x202D, index);
6673 temp += 0x202D;
6674 index++;
6675 FPT_utilEEWrite(p_port, 0x3339, index);
6676 temp += 0x3339;
6677 index++; /*Serial # */
6678 FPT_utilEEWrite(p_port, 0x2030, index); /* 01234567 */
6679 temp += 0x2030;
6680 index++;
6681 FPT_utilEEWrite(p_port, 0x5453, index);
6682 temp += 0x5453;
6683 index++;
6684 FPT_utilEEWrite(p_port, 0x5645, index);
6685 temp += 0x5645;
6686 index++;
6687 FPT_utilEEWrite(p_port, 0x2045, index);
6688 temp += 0x2045;
6689 index++;
6690 FPT_utilEEWrite(p_port, 0x202F, index);
6691 temp += 0x202F;
6692 index++;
6693 FPT_utilEEWrite(p_port, 0x4F4A, index);
6694 temp += 0x4F4A;
6695 index++;
6696 FPT_utilEEWrite(p_port, 0x204E, index);
6697 temp += 0x204E;
6698 index++;
6699 FPT_utilEEWrite(p_port, 0x3539, index);
6700 temp += 0x3539;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006701
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006702 FPT_utilEEWrite(p_port, temp, EEPROM_CHECK_SUM / 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006703
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006704 FPT_utilEEWriteOnOff(p_port, (unsigned char)0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006705
6706}
6707
Linus Torvalds1da177e2005-04-16 15:20:36 -07006708/*---------------------------------------------------------------------
6709 *
6710 * Function: Queue Search Select
6711 *
6712 * Description: Try to find a new command to execute.
6713 *
6714 *---------------------------------------------------------------------*/
6715
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006716static void FPT_queueSearchSelect(struct sccb_card *pCurrCard,
6717 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006718{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006719 unsigned char scan_ptr, lun;
6720 struct sccb_mgr_tar_info *currTar_Info;
6721 struct sccb *pOldSccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006722
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006723 scan_ptr = pCurrCard->scanIndex;
6724 do {
James Bottomley 47b5d692005-04-24 02:38:05 -05006725 currTar_Info = &FPT_sccbMgrTbl[p_card][scan_ptr];
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006726 if ((pCurrCard->globalFlags & F_CONLUN_IO) &&
6727 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
6728 TAG_Q_TRYING)) {
6729 if (currTar_Info->TarSelQ_Cnt != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006730
6731 scan_ptr++;
6732 if (scan_ptr == MAX_SCSI_TAR)
6733 scan_ptr = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006734
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006735 for (lun = 0; lun < MAX_LUN; lun++) {
6736 if (currTar_Info->TarLUNBusy[lun] == 0) {
6737
6738 pCurrCard->currentSCCB =
6739 currTar_Info->TarSelQ_Head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006740 pOldSccb = NULL;
6741
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006742 while ((pCurrCard->
6743 currentSCCB != NULL)
6744 && (lun !=
6745 pCurrCard->
6746 currentSCCB->Lun)) {
6747 pOldSccb =
6748 pCurrCard->
6749 currentSCCB;
6750 pCurrCard->currentSCCB =
6751 (struct sccb
6752 *)(pCurrCard->
6753 currentSCCB)->
6754 Sccb_forwardlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006755 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006756 if (pCurrCard->currentSCCB ==
6757 NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006758 continue;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006759 if (pOldSccb != NULL) {
6760 pOldSccb->
6761 Sccb_forwardlink =
6762 (struct sccb
6763 *)(pCurrCard->
6764 currentSCCB)->
6765 Sccb_forwardlink;
6766 pOldSccb->
6767 Sccb_backlink =
6768 (struct sccb
6769 *)(pCurrCard->
6770 currentSCCB)->
6771 Sccb_backlink;
6772 currTar_Info->
6773 TarSelQ_Cnt--;
6774 } else {
6775 currTar_Info->
6776 TarSelQ_Head =
6777 (struct sccb
6778 *)(pCurrCard->
6779 currentSCCB)->
6780 Sccb_forwardlink;
6781
6782 if (currTar_Info->
6783 TarSelQ_Head ==
6784 NULL) {
6785 currTar_Info->
6786 TarSelQ_Tail
6787 = NULL;
6788 currTar_Info->
6789 TarSelQ_Cnt
6790 = 0;
6791 } else {
6792 currTar_Info->
6793 TarSelQ_Cnt--;
6794 currTar_Info->
6795 TarSelQ_Head->
6796 Sccb_backlink
6797 =
6798 (struct sccb
6799 *)NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006800 }
6801 }
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006802 pCurrCard->scanIndex = scan_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006803
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006804 pCurrCard->globalFlags |=
6805 F_NEW_SCCB_CMD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006806
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006807 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006808 }
6809 }
6810 }
6811
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006812 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006813 scan_ptr++;
6814 if (scan_ptr == MAX_SCSI_TAR) {
6815 scan_ptr = 0;
6816 }
6817 }
6818
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006819 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006820 if ((currTar_Info->TarSelQ_Cnt != 0) &&
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006821 (currTar_Info->TarLUNBusy[0] == 0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006822
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006823 pCurrCard->currentSCCB =
6824 currTar_Info->TarSelQ_Head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006825
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006826 currTar_Info->TarSelQ_Head =
6827 (struct sccb *)(pCurrCard->currentSCCB)->
6828 Sccb_forwardlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006829
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006830 if (currTar_Info->TarSelQ_Head == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006831 currTar_Info->TarSelQ_Tail = NULL;
6832 currTar_Info->TarSelQ_Cnt = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006833 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006834 currTar_Info->TarSelQ_Cnt--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006835 currTar_Info->TarSelQ_Head->
6836 Sccb_backlink = (struct sccb *)NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006837 }
6838
6839 scan_ptr++;
6840 if (scan_ptr == MAX_SCSI_TAR)
6841 scan_ptr = 0;
6842
6843 pCurrCard->scanIndex = scan_ptr;
6844
6845 pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
6846
6847 break;
6848 }
6849
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006850 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006851 scan_ptr++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006852 if (scan_ptr == MAX_SCSI_TAR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006853 scan_ptr = 0;
6854 }
6855 }
6856 }
6857 } while (scan_ptr != pCurrCard->scanIndex);
6858}
6859
Linus Torvalds1da177e2005-04-16 15:20:36 -07006860/*---------------------------------------------------------------------
6861 *
6862 * Function: Queue Select Fail
6863 *
6864 * Description: Add the current SCCB to the head of the Queue.
6865 *
6866 *---------------------------------------------------------------------*/
6867
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006868static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
6869 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006870{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006871 unsigned char thisTarg;
6872 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006873
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006874 if (pCurrCard->currentSCCB != NULL) {
6875 thisTarg =
6876 (unsigned char)(((struct sccb *)(pCurrCard->currentSCCB))->
6877 TargID);
6878 currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006879
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006880 pCurrCard->currentSCCB->Sccb_backlink = (struct sccb *)NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006881
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006882 pCurrCard->currentSCCB->Sccb_forwardlink =
6883 currTar_Info->TarSelQ_Head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006884
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006885 if (currTar_Info->TarSelQ_Cnt == 0) {
6886 currTar_Info->TarSelQ_Tail = pCurrCard->currentSCCB;
6887 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006888
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006889 else {
6890 currTar_Info->TarSelQ_Head->Sccb_backlink =
6891 pCurrCard->currentSCCB;
6892 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006893
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006894 currTar_Info->TarSelQ_Head = pCurrCard->currentSCCB;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006895
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006896 pCurrCard->currentSCCB = NULL;
6897 currTar_Info->TarSelQ_Cnt++;
6898 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07006899}
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006900
Linus Torvalds1da177e2005-04-16 15:20:36 -07006901/*---------------------------------------------------------------------
6902 *
6903 * Function: Queue Command Complete
6904 *
6905 * Description: Call the callback function with the current SCCB.
6906 *
6907 *---------------------------------------------------------------------*/
6908
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006909static void FPT_queueCmdComplete(struct sccb_card *pCurrCard,
6910 struct sccb *p_sccb, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006911{
6912
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006913 unsigned char i, SCSIcmd;
6914 CALL_BK_FN callback;
6915 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006916
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006917 SCSIcmd = p_sccb->Cdb[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07006918
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006919 if (!(p_sccb->Sccb_XferState & F_ALL_XFERRED)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006920
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006921 if ((p_sccb->
6922 ControlByte & (SCCB_DATA_XFER_OUT | SCCB_DATA_XFER_IN))
6923 && (p_sccb->HostStatus == SCCB_COMPLETE)
6924 && (p_sccb->TargetStatus != SSCHECK))
Linus Torvalds1da177e2005-04-16 15:20:36 -07006925
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006926 if ((SCSIcmd == SCSI_READ) ||
6927 (SCSIcmd == SCSI_WRITE) ||
6928 (SCSIcmd == SCSI_READ_EXTENDED) ||
6929 (SCSIcmd == SCSI_WRITE_EXTENDED) ||
6930 (SCSIcmd == SCSI_WRITE_AND_VERIFY) ||
6931 (SCSIcmd == SCSI_START_STOP_UNIT) ||
6932 (pCurrCard->globalFlags & F_NO_FILTER)
6933 )
6934 p_sccb->HostStatus = SCCB_DATA_UNDER_RUN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006935 }
6936
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006937 if (p_sccb->SccbStatus == SCCB_IN_PROCESS) {
6938 if (p_sccb->HostStatus || p_sccb->TargetStatus)
6939 p_sccb->SccbStatus = SCCB_ERROR;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006940 else
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006941 p_sccb->SccbStatus = SCCB_SUCCESS;
6942 }
6943
6944 if (p_sccb->Sccb_XferState & F_AUTO_SENSE) {
6945
6946 p_sccb->CdbLength = p_sccb->Save_CdbLen;
6947 for (i = 0; i < 6; i++) {
6948 p_sccb->Cdb[i] = p_sccb->Save_Cdb[i];
6949 }
6950 }
6951
6952 if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) ||
6953 (p_sccb->OperationCode == RESIDUAL_COMMAND)) {
6954
6955 FPT_utilUpdateResidual(p_sccb);
6956 }
6957
6958 pCurrCard->cmdCounter--;
6959 if (!pCurrCard->cmdCounter) {
6960
6961 if (pCurrCard->globalFlags & F_GREEN_PC) {
6962 WR_HARPOON(pCurrCard->ioPort + hp_clkctrl_0,
6963 (PWR_DWN | CLKCTRL_DEFAULT));
6964 WR_HARPOON(pCurrCard->ioPort + hp_sys_ctrl, STOP_CLK);
6965 }
6966
6967 WR_HARPOON(pCurrCard->ioPort + hp_semaphore,
6968 (RD_HARPOON(pCurrCard->ioPort + hp_semaphore) &
6969 ~SCCB_MGR_ACTIVE));
6970
6971 }
6972
6973 if (pCurrCard->discQCount != 0) {
6974 currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
6975 if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
6976 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
6977 TAG_Q_TRYING))) {
6978 pCurrCard->discQCount--;
6979 pCurrCard->discQ_Tbl[currTar_Info->
6980 LunDiscQ_Idx[p_sccb->Lun]] = NULL;
6981 } else {
6982 if (p_sccb->Sccb_tag) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006983 pCurrCard->discQCount--;
6984 pCurrCard->discQ_Tbl[p_sccb->Sccb_tag] = NULL;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006985 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07006986 pCurrCard->discQCount--;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006987 pCurrCard->discQ_Tbl[currTar_Info->
6988 LunDiscQ_Idx[0]] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006989 }
6990 }
6991
6992 }
6993
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08006994 callback = (CALL_BK_FN) p_sccb->SccbCallback;
6995 callback(p_sccb);
6996 pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
6997 pCurrCard->currentSCCB = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006998}
Linus Torvalds1da177e2005-04-16 15:20:36 -07006999
Linus Torvalds1da177e2005-04-16 15:20:36 -07007000/*---------------------------------------------------------------------
7001 *
7002 * Function: Queue Disconnect
7003 *
7004 * Description: Add SCCB to our disconnect array.
7005 *
7006 *---------------------------------------------------------------------*/
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007007static void FPT_queueDisconnect(struct sccb *p_sccb, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007008{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007009 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007010
James Bottomley 47b5d692005-04-24 02:38:05 -05007011 currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007012
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007013 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
7014 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
7015 FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
7016 LunDiscQ_Idx[p_sccb->Lun]] =
7017 p_sccb;
7018 } else {
7019 if (p_sccb->Sccb_tag) {
7020 FPT_BL_Card[p_card].discQ_Tbl[p_sccb->Sccb_tag] =
7021 p_sccb;
7022 FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarLUNBusy[0] =
7023 0;
James Bottomley 47b5d692005-04-24 02:38:05 -05007024 FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarTagQ_Cnt++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007025 } else {
7026 FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
7027 LunDiscQ_Idx[0]] = p_sccb;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007028 }
7029 }
James Bottomley 47b5d692005-04-24 02:38:05 -05007030 FPT_BL_Card[p_card].currentSCCB = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007031}
7032
Linus Torvalds1da177e2005-04-16 15:20:36 -07007033/*---------------------------------------------------------------------
7034 *
7035 * Function: Queue Flush SCCB
7036 *
7037 * Description: Flush all SCCB's back to the host driver for this target.
7038 *
7039 *---------------------------------------------------------------------*/
7040
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007041static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007042{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007043 unsigned char qtag, thisTarg;
7044 struct sccb *currSCCB;
7045 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007046
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007047 currSCCB = FPT_BL_Card[p_card].currentSCCB;
7048 if (currSCCB != NULL) {
7049 thisTarg = (unsigned char)currSCCB->TargID;
7050 currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007051
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007052 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007053
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007054 if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
7055 (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
7056 thisTarg)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007057
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007058 FPT_BL_Card[p_card].discQ_Tbl[qtag]->
7059 HostStatus = (unsigned char)error_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007060
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007061 FPT_queueCmdComplete(&FPT_BL_Card[p_card],
7062 FPT_BL_Card[p_card].
7063 discQ_Tbl[qtag], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007064
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007065 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
7066 currTar_Info->TarTagQ_Cnt--;
7067
7068 }
7069 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007070 }
7071
7072}
7073
7074/*---------------------------------------------------------------------
7075 *
7076 * Function: Queue Flush Target SCCB
7077 *
7078 * Description: Flush all SCCB's back to the host driver for this target.
7079 *
7080 *---------------------------------------------------------------------*/
7081
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007082static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
7083 unsigned char error_code)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007084{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007085 unsigned char qtag;
7086 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007087
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007088 currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007089
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007090 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007091
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007092 if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
7093 (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007094
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007095 FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus =
7096 (unsigned char)error_code;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007097
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007098 FPT_queueCmdComplete(&FPT_BL_Card[p_card],
7099 FPT_BL_Card[p_card].
7100 discQ_Tbl[qtag], p_card);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007101
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007102 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
7103 currTar_Info->TarTagQ_Cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007104
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007105 }
7106 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007107
7108}
7109
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007110static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007111{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007112 struct sccb_mgr_tar_info *currTar_Info;
7113 currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007114
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007115 p_SCCB->Sccb_forwardlink = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007116
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007117 p_SCCB->Sccb_backlink = currTar_Info->TarSelQ_Tail;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007118
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007119 if (currTar_Info->TarSelQ_Cnt == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007120
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007121 currTar_Info->TarSelQ_Head = p_SCCB;
7122 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007123
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007124 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007125
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007126 currTar_Info->TarSelQ_Tail->Sccb_forwardlink = p_SCCB;
7127 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007128
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007129 currTar_Info->TarSelQ_Tail = p_SCCB;
7130 currTar_Info->TarSelQ_Cnt++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007131}
7132
Linus Torvalds1da177e2005-04-16 15:20:36 -07007133/*---------------------------------------------------------------------
7134 *
7135 * Function: Queue Find SCCB
7136 *
7137 * Description: Search the target select Queue for this SCCB, and
7138 * remove it if found.
7139 *
7140 *---------------------------------------------------------------------*/
7141
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007142static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB,
7143 unsigned char p_card)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007144{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007145 struct sccb *q_ptr;
7146 struct sccb_mgr_tar_info *currTar_Info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007147
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007148 currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
Linus Torvalds1da177e2005-04-16 15:20:36 -07007149
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007150 q_ptr = currTar_Info->TarSelQ_Head;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007151
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007152 while (q_ptr != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007153
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007154 if (q_ptr == p_SCCB) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007155
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007156 if (currTar_Info->TarSelQ_Head == q_ptr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007157
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007158 currTar_Info->TarSelQ_Head =
7159 q_ptr->Sccb_forwardlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007160 }
7161
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007162 if (currTar_Info->TarSelQ_Tail == q_ptr) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007163
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007164 currTar_Info->TarSelQ_Tail =
7165 q_ptr->Sccb_backlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007166 }
7167
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007168 if (q_ptr->Sccb_forwardlink != NULL) {
7169 q_ptr->Sccb_forwardlink->Sccb_backlink =
7170 q_ptr->Sccb_backlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007171 }
7172
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007173 if (q_ptr->Sccb_backlink != NULL) {
7174 q_ptr->Sccb_backlink->Sccb_forwardlink =
7175 q_ptr->Sccb_forwardlink;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007176 }
7177
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007178 currTar_Info->TarSelQ_Cnt--;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007179
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007180 return 1;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007181 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007182
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007183 else {
7184 q_ptr = q_ptr->Sccb_forwardlink;
7185 }
7186 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007187
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007188 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007189
7190}
7191
Linus Torvalds1da177e2005-04-16 15:20:36 -07007192/*---------------------------------------------------------------------
7193 *
7194 * Function: Utility Update Residual Count
7195 *
7196 * Description: Update the XferCnt to the remaining byte count.
7197 * If we transferred all the data then just write zero.
7198 * If Non-SG transfer then report Total Cnt - Actual Transfer
7199 * Cnt. For SG transfers add the count fields of all
7200 * remaining SG elements, as well as any partial remaining
7201 * element.
7202 *
7203 *---------------------------------------------------------------------*/
7204
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007205static void FPT_utilUpdateResidual(struct sccb *p_SCCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007206{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007207 unsigned long partial_cnt;
7208 unsigned int sg_index;
7209 unsigned long *sg_ptr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007210
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007211 if (p_SCCB->Sccb_XferState & F_ALL_XFERRED) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007212
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007213 p_SCCB->DataLength = 0x0000;
7214 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007215
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007216 else if (p_SCCB->Sccb_XferState & F_SG_XFER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007217
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007218 partial_cnt = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007219
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007220 sg_index = p_SCCB->Sccb_sgseg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007221
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007222 sg_ptr = (unsigned long *)p_SCCB->DataPointer;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007223
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007224 if (p_SCCB->Sccb_SGoffset) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007225
7226 partial_cnt = p_SCCB->Sccb_SGoffset;
7227 sg_index++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007228 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007229
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007230 while (((unsigned long)sg_index *
7231 (unsigned long)SG_ELEMENT_SIZE) < p_SCCB->DataLength) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007232
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007233 partial_cnt += *(sg_ptr + (sg_index * 2));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007234 sg_index++;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007235 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007236
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007237 p_SCCB->DataLength = partial_cnt;
7238 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007239
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007240 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007241
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007242 p_SCCB->DataLength -= p_SCCB->Sccb_ATC;
7243 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007244}
7245
Linus Torvalds1da177e2005-04-16 15:20:36 -07007246/*---------------------------------------------------------------------
7247 *
7248 * Function: Wait 1 Second
7249 *
7250 * Description: Wait for 1 second.
7251 *
7252 *---------------------------------------------------------------------*/
7253
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08007254static void FPT_Wait1Second(unsigned long p_port)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007255{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007256 unsigned char i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007257
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007258 for (i = 0; i < 4; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007259
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007260 FPT_Wait(p_port, TO_250ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007261
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007262 if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
7263 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007264
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007265 if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
7266 break;
7267 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007268}
7269
Linus Torvalds1da177e2005-04-16 15:20:36 -07007270/*---------------------------------------------------------------------
7271 *
James Bottomley 47b5d692005-04-24 02:38:05 -05007272 * Function: FPT_Wait
Linus Torvalds1da177e2005-04-16 15:20:36 -07007273 *
7274 * Description: Wait the desired delay.
7275 *
7276 *---------------------------------------------------------------------*/
7277
Alexey Dobriyand63a4cc2006-03-08 00:14:26 -08007278static void FPT_Wait(unsigned long p_port, unsigned char p_delay)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007279{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007280 unsigned char old_timer;
7281 unsigned char green_flag;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007282
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007283 old_timer = RD_HARPOON(p_port + hp_seltimeout);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007284
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007285 green_flag = RD_HARPOON(p_port + hp_clkctrl_0);
7286 WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007287
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007288 WR_HARPOON(p_port + hp_seltimeout, p_delay);
7289 WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
7290 WRW_HARPOON((p_port + hp_intena), (FPT_default_intena & ~TIMEOUT));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007291
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007292 WR_HARPOON(p_port + hp_portctrl_0,
7293 (RD_HARPOON(p_port + hp_portctrl_0) | START_TO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007294
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007295 while (!(RDW_HARPOON((p_port + hp_intstat)) & TIMEOUT)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007296
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007297 if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
7298 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007299
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007300 if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
7301 break;
7302 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007303
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007304 WR_HARPOON(p_port + hp_portctrl_0,
7305 (RD_HARPOON(p_port + hp_portctrl_0) & ~START_TO));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007306
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007307 WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
7308 WRW_HARPOON((p_port + hp_intena), FPT_default_intena);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007309
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007310 WR_HARPOON(p_port + hp_clkctrl_0, green_flag);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007311
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007312 WR_HARPOON(p_port + hp_seltimeout, old_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007313}
7314
Linus Torvalds1da177e2005-04-16 15:20:36 -07007315/*---------------------------------------------------------------------
7316 *
7317 * Function: Enable/Disable Write to EEPROM
7318 *
7319 * Description: The EEPROM must first be enabled for writes
7320 * A total of 9 clocks are needed.
7321 *
7322 *---------------------------------------------------------------------*/
7323
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007324static void FPT_utilEEWriteOnOff(unsigned long p_port, unsigned char p_mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007325{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007326 unsigned char ee_value;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007327
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007328 ee_value =
7329 (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
7330 (EXT_ARB_ACK | SCSI_TERM_ENA_H));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007331
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007332 if (p_mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007333
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007334 FPT_utilEESendCmdAddr(p_port, EWEN, EWEN_ADDR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007335
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007336 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07007337
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007338 FPT_utilEESendCmdAddr(p_port, EWDS, EWDS_ADDR);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007339
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007340 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */
7341 WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /*Turn off Master Select */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007342}
7343
Linus Torvalds1da177e2005-04-16 15:20:36 -07007344/*---------------------------------------------------------------------
7345 *
7346 * Function: Write EEPROM
7347 *
7348 * Description: Write a word to the EEPROM at the specified
7349 * address.
7350 *
7351 *---------------------------------------------------------------------*/
7352
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007353static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data,
7354 unsigned short ee_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007355{
7356
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007357 unsigned char ee_value;
7358 unsigned short i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007359
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007360 ee_value =
7361 (unsigned
7362 char)((RD_HARPOON(p_port + hp_ee_ctrl) &
7363 (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007364
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007365 FPT_utilEESendCmdAddr(p_port, EE_WRITE, ee_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007366
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007367 ee_value |= (SEE_MS + SEE_CS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007368
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007369 for (i = 0x8000; i != 0; i >>= 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007370
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007371 if (i & ee_data)
7372 ee_value |= SEE_DO;
7373 else
7374 ee_value &= ~SEE_DO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007375
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007376 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7377 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7378 ee_value |= SEE_CLK; /* Clock data! */
7379 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7380 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7381 ee_value &= ~SEE_CLK;
7382 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7383 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7384 }
7385 ee_value &= (EXT_ARB_ACK | SCSI_TERM_ENA_H);
7386 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007387
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007388 FPT_Wait(p_port, TO_10ms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007389
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007390 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS | SEE_CS)); /* Set CS to EEPROM */
7391 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /* Turn off CS */
7392 WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /* Turn off Master Select */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007393}
7394
7395/*---------------------------------------------------------------------
7396 *
7397 * Function: Read EEPROM
7398 *
7399 * Description: Read a word from the EEPROM at the desired
7400 * address.
7401 *
7402 *---------------------------------------------------------------------*/
7403
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007404static unsigned short FPT_utilEERead(unsigned long p_port,
7405 unsigned short ee_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007406{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007407 unsigned short i, ee_data1, ee_data2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007408
7409 i = 0;
James Bottomley 47b5d692005-04-24 02:38:05 -05007410 ee_data1 = FPT_utilEEReadOrg(p_port, ee_addr);
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007411 do {
James Bottomley 47b5d692005-04-24 02:38:05 -05007412 ee_data2 = FPT_utilEEReadOrg(p_port, ee_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007413
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007414 if (ee_data1 == ee_data2)
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007415 return ee_data1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007416
7417 ee_data1 = ee_data2;
7418 i++;
7419
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007420 } while (i < 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007421
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007422 return ee_data1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007423}
7424
7425/*---------------------------------------------------------------------
7426 *
7427 * Function: Read EEPROM Original
7428 *
7429 * Description: Read a word from the EEPROM at the desired
7430 * address.
7431 *
7432 *---------------------------------------------------------------------*/
7433
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007434static unsigned short FPT_utilEEReadOrg(unsigned long p_port,
7435 unsigned short ee_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007436{
7437
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007438 unsigned char ee_value;
7439 unsigned short i, ee_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007440
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007441 ee_value =
7442 (unsigned
7443 char)((RD_HARPOON(p_port + hp_ee_ctrl) &
7444 (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
Linus Torvalds1da177e2005-04-16 15:20:36 -07007445
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007446 FPT_utilEESendCmdAddr(p_port, EE_READ, ee_addr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007447
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007448 ee_value |= (SEE_MS + SEE_CS);
7449 ee_data = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007450
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007451 for (i = 1; i <= 16; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007452
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007453 ee_value |= SEE_CLK; /* Clock data! */
7454 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7455 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7456 ee_value &= ~SEE_CLK;
7457 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7458 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007459
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007460 ee_data <<= 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007461
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007462 if (RD_HARPOON(p_port + hp_ee_ctrl) & SEE_DI)
7463 ee_data |= 1;
7464 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007465
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007466 ee_value &= ~(SEE_MS + SEE_CS);
7467 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */
7468 WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /*Turn off Master Select */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007469
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007470 return ee_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007471}
7472
Linus Torvalds1da177e2005-04-16 15:20:36 -07007473/*---------------------------------------------------------------------
7474 *
7475 * Function: Send EE command and Address to the EEPROM
7476 *
7477 * Description: Transfers the correct command and sends the address
7478 * to the eeprom.
7479 *
7480 *---------------------------------------------------------------------*/
7481
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007482static void FPT_utilEESendCmdAddr(unsigned long p_port, unsigned char ee_cmd,
7483 unsigned short ee_addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007484{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007485 unsigned char ee_value;
7486 unsigned char narrow_flg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007487
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007488 unsigned short i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007489
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007490 narrow_flg =
7491 (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
7492 NARROW_SCSI_CARD);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007493
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007494 ee_value = SEE_MS;
7495 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007496
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007497 ee_value |= SEE_CS; /* Set CS to EEPROM */
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 for (i = 0x04; i != 0; i >>= 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007501
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007502 if (i & ee_cmd)
7503 ee_value |= SEE_DO;
7504 else
7505 ee_value &= ~SEE_DO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007506
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007507 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7508 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7509 ee_value |= SEE_CLK; /* Clock data! */
7510 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7511 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7512 ee_value &= ~SEE_CLK;
7513 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7514 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7515 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007516
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007517 if (narrow_flg)
7518 i = 0x0080;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007519
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007520 else
7521 i = 0x0200;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007522
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007523 while (i != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007524
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007525 if (i & ee_addr)
7526 ee_value |= SEE_DO;
7527 else
7528 ee_value &= ~SEE_DO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007529
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007530 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7531 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7532 ee_value |= SEE_CLK; /* Clock data! */
7533 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7534 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7535 ee_value &= ~SEE_CLK;
7536 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7537 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007538
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007539 i >>= 1;
7540 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007541}
7542
Alexey Dobriyanc823fee2006-03-08 00:14:25 -08007543static unsigned short FPT_CalcCrc16(unsigned char buffer[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07007544{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007545 unsigned short crc = 0;
7546 int i, j;
7547 unsigned short ch;
7548 for (i = 0; i < ID_STRING_LENGTH; i++) {
7549 ch = (unsigned short)buffer[i];
7550 for (j = 0; j < 8; j++) {
7551 if ((crc ^ ch) & 1)
7552 crc = (crc >> 1) ^ CRCMASK;
7553 else
7554 crc >>= 1;
7555 ch >>= 1;
7556 }
7557 }
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007558 return crc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007559}
7560
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08007561static unsigned char FPT_CalcLrc(unsigned char buffer[])
Linus Torvalds1da177e2005-04-16 15:20:36 -07007562{
7563 int i;
Alexey Dobriyandb038cf2006-03-08 00:14:24 -08007564 unsigned char lrc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007565 lrc = 0;
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007566 for (i = 0; i < ID_STRING_LENGTH; i++)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007567 lrc ^= buffer[i];
Alexey Dobriyan5c1b85e2006-03-08 00:14:37 -08007568 return lrc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007569}
7570
Linus Torvalds1da177e2005-04-16 15:20:36 -07007571/*
7572 The following inline definitions avoid type conflicts.
7573*/
7574
7575static inline unsigned char
Khalid Aziz839cb992013-05-16 19:44:13 -06007576FlashPoint__ProbeHostAdapter(struct fpoint_info *FlashPointInfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007577{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007578 return FlashPoint_ProbeHostAdapter((struct sccb_mgr_info *)
7579 FlashPointInfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007580}
7581
Khalid Aziz839cb992013-05-16 19:44:13 -06007582static inline unsigned int
7583FlashPoint__HardwareResetHostAdapter(struct fpoint_info *FlashPointInfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007584{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007585 return FlashPoint_HardwareResetHostAdapter((struct sccb_mgr_info *)
7586 FlashPointInfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007587}
7588
7589static inline void
Khalid Aziz839cb992013-05-16 19:44:13 -06007590FlashPoint__ReleaseHostAdapter(unsigned int CardHandle)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007591{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007592 FlashPoint_ReleaseHostAdapter(CardHandle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007593}
7594
Linus Torvalds1da177e2005-04-16 15:20:36 -07007595static inline void
Khalid Aziz839cb992013-05-16 19:44:13 -06007596FlashPoint__StartCCB(unsigned int CardHandle,
7597 struct blogic_ccb *CCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007598{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007599 FlashPoint_StartCCB(CardHandle, (struct sccb *)CCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007600}
7601
Linus Torvalds1da177e2005-04-16 15:20:36 -07007602static inline void
Khalid Aziz839cb992013-05-16 19:44:13 -06007603FlashPoint__AbortCCB(unsigned int CardHandle,
7604 struct blogic_ccb *CCB)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007605{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007606 FlashPoint_AbortCCB(CardHandle, (struct sccb *)CCB);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007607}
7608
Richard Knutsson2065e312007-02-05 16:39:01 -08007609static inline bool
Khalid Aziz839cb992013-05-16 19:44:13 -06007610FlashPoint__InterruptPending(unsigned int CardHandle)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007611{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007612 return FlashPoint_InterruptPending(CardHandle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007613}
7614
Linus Torvalds1da177e2005-04-16 15:20:36 -07007615static inline int
Khalid Aziz839cb992013-05-16 19:44:13 -06007616FlashPoint__HandleInterrupt(unsigned int CardHandle)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007617{
Alexey Dobriyan5c04a7b2006-03-08 00:14:35 -08007618 return FlashPoint_HandleInterrupt(CardHandle);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007619}
7620
Linus Torvalds1da177e2005-04-16 15:20:36 -07007621#define FlashPoint_ProbeHostAdapter FlashPoint__ProbeHostAdapter
7622#define FlashPoint_HardwareResetHostAdapter FlashPoint__HardwareResetHostAdapter
7623#define FlashPoint_ReleaseHostAdapter FlashPoint__ReleaseHostAdapter
7624#define FlashPoint_StartCCB FlashPoint__StartCCB
7625#define FlashPoint_AbortCCB FlashPoint__AbortCCB
7626#define FlashPoint_InterruptPending FlashPoint__InterruptPending
7627#define FlashPoint_HandleInterrupt FlashPoint__HandleInterrupt
7628
Matthew Wilcox78b4b052008-03-13 06:55:08 -06007629#else /* !CONFIG_SCSI_FLASHPOINT */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007630
7631/*
7632 Define prototypes for the FlashPoint SCCB Manager Functions.
7633*/
7634
Khalid Aziz839cb992013-05-16 19:44:13 -06007635extern unsigned char FlashPoint_ProbeHostAdapter(struct fpoint_info *);
7636extern unsigned int FlashPoint_HardwareResetHostAdapter(struct fpoint_info *);
7637extern void FlashPoint_StartCCB(unsigned int, struct blogic_ccb *);
7638extern int FlashPoint_AbortCCB(unsigned int, struct blogic_ccb *);
7639extern bool FlashPoint_InterruptPending(unsigned int);
7640extern int FlashPoint_HandleInterrupt(unsigned int);
7641extern void FlashPoint_ReleaseHostAdapter(unsigned int);
Linus Torvalds1da177e2005-04-16 15:20:36 -07007642
Matthew Wilcox78b4b052008-03-13 06:55:08 -06007643#endif /* CONFIG_SCSI_FLASHPOINT */