xref: /openbmc/linux/drivers/scsi/FlashPoint.c (revision 5e0266f0)
1 /*
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 
18 
19 #ifdef CONFIG_SCSI_FLASHPOINT
20 
21 #define MAX_CARDS	8
22 #undef BUSTYPE_PCI
23 
24 #define CRCMASK	0xA001
25 
26 #define FAILURE         0xFFFFFFFFL
27 
28 struct sccb;
29 typedef void (*CALL_BK_FN) (struct sccb *);
30 
31 struct sccb_mgr_info {
32 	u32 si_baseaddr;
33 	unsigned char si_present;
34 	unsigned char si_intvect;
35 	unsigned char si_id;
36 	unsigned char si_lun;
37 	u16 si_fw_revision;
38 	u16 si_per_targ_init_sync;
39 	u16 si_per_targ_fast_nego;
40 	u16 si_per_targ_ultra_nego;
41 	u16 si_per_targ_no_disc;
42 	u16 si_per_targ_wide_nego;
43 	u16 si_mflags;
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 	u32 si_OS_reserved;
50 	unsigned char si_XlatInfo[4];
51 	u32 si_reserved2[5];
52 	u32 si_secondary_range;
53 };
54 
55 #define SCSI_PARITY_ENA		  0x0001
56 #define LOW_BYTE_TERM		  0x0010
57 #define HIGH_BYTE_TERM		  0x0020
58 #define BUSTYPE_PCI	  0x3
59 
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 
67 #define HARPOON_FAMILY        0x02
68 
69 /* SCCB struct used for both SCCB and UCB manager compiles!
70  * The UCB Manager treats the SCCB as it's 'native hardware structure'
71  */
72 
73 /*#pragma pack(1)*/
74 struct sccb {
75 	unsigned char OperationCode;
76 	unsigned char ControlByte;
77 	unsigned char CdbLength;
78 	unsigned char RequestSenseLength;
79 	u32 DataLength;
80 	void *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 	u32 Reserved2;
90 	u32 SensePointer;
91 
92 	CALL_BK_FN SccbCallback;	/* VOID (*SccbCallback)(); */
93 	u32 SccbIOPort;			/* Identifies board base port */
94 	unsigned char SccbStatus;
95 	unsigned char SCCBRes2;
96 	u16 SccbOSFlags;
97 
98 	u32 Sccb_XferCnt;	/* actual transfer count */
99 	u32 Sccb_ATC;
100 	u32 SccbVirtDataPtr;	/* virtual addr for OS/2 */
101 	u32 Sccb_res1;
102 	u16 Sccb_MGRFlags;
103 	u16 Sccb_sgseg;
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 	u32 Sccb_savedATC;
111 	unsigned char Save_Cdb[6];
112 	unsigned char Save_CdbLen;
113 	unsigned char Sccb_XferState;
114 	u32 Sccb_SGoffset;
115 };
116 
117 #pragma pack()
118 
119 #define SCATTER_GATHER_COMMAND    0x02
120 #define RESIDUAL_COMMAND          0x03
121 #define RESIDUAL_SG_COMMAND       0x04
122 #define RESET_COMMAND             0x81
123 
124 #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 */
128 
129 #define NO_AUTO_REQUEST_SENSE    0x01	/* No Request Sense Buffer */
130 
131 #define BUS_FREE_ST     0
132 #define SELECT_ST       1
133 #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 */
137 #define COMMAND_ST      6
138 #define DATA_OUT_ST     7
139 #define DATA_IN_ST      8
140 #define DISCONNECT_ST   9
141 #define ABORT_ST        11
142 
143 #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 
150 #define F_STATUSLOADED                 0x01
151 #define F_DEV_SELECTED                 0x04
152 
153 #define SCCB_COMPLETE               0x00	/* SCCB completed without error */
154 #define SCCB_DATA_UNDER_RUN         0x0C
155 #define SCCB_SELECTION_TIMEOUT      0x11	/* Set SCSI selection timed out */
156 #define SCCB_DATA_OVER_RUN          0x12
157 #define SCCB_PHASE_SEQUENCE_FAIL    0x14	/* Target bus phase sequence failure */
158 
159 #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 */
162 
163 #define SCCB_IN_PROCESS            0x00
164 #define SCCB_SUCCESS               0x01
165 #define SCCB_ABORT                 0x02
166 #define SCCB_ERROR                 0x04
167 
168 #define  ORION_FW_REV      3110
169 
170 #define QUEUE_DEPTH     254+1	/*1 for Normal disconnect 32 for Q'ing. */
171 
172 #define	MAX_MB_CARDS	4	/* Max. no of cards suppoerted on Mother Board */
173 
174 #define MAX_SCSI_TAR    16
175 #define MAX_LUN         32
176 #define LUN_MASK			0x1f
177 
178 #define SG_BUF_CNT      16	/*Number of prefetched elements. */
179 
180 #define SG_ELEMENT_SIZE 8	/*Eight byte per element. */
181 
182 #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))
188 
189 #define  TAR_SYNC_MASK     (BIT(7)+BIT(6))
190 #define  SYNC_TRYING               BIT(6)
191 #define  SYNC_SUPPORTED    (BIT(7)+BIT(6))
192 
193 #define  TAR_WIDE_MASK     (BIT(5)+BIT(4))
194 #define  WIDE_ENABLED              BIT(4)
195 #define  WIDE_NEGOCIATED   BIT(5)
196 
197 #define  TAR_TAG_Q_MASK    (BIT(3)+BIT(2))
198 #define  TAG_Q_TRYING              BIT(2)
199 #define  TAG_Q_REJECT      BIT(3)
200 
201 #define  TAR_ALLOW_DISC    BIT(0)
202 
203 #define  EE_SYNC_MASK      (BIT(0)+BIT(1))
204 #define  EE_SYNC_5MB       BIT(0)
205 #define  EE_SYNC_10MB      BIT(1)
206 #define  EE_SYNC_20MB      (BIT(0)+BIT(1))
207 
208 #define  EE_WIDE_SCSI      BIT(7)
209 
210 struct sccb_mgr_tar_info {
211 
212 	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];
223 };
224 
225 struct nvram_info {
226 	unsigned char niModel;		/* Model No. of card */
227 	unsigned char niCardNo;		/* Card no. */
228 	u32 niBaseAddr;			/* Port Address of card */
229 	unsigned char niSysConf;	/* Adapter Configuration byte -
230 					   Byte 16 of eeprom map */
231 	unsigned char niScsiConf;	/* SCSI Configuration byte -
232 					   Byte 17 of eeprom map */
233 	unsigned char niScamConf;	/* SCAM Configuration byte -
234 					   Byte 20 of eeprom map */
235 	unsigned char niAdapId;		/* Host Adapter ID -
236 					   Byte 24 of eerpom map */
237 	unsigned char niSyncTbl[MAX_SCSI_TAR / 2];	/* Sync/Wide byte
238 							   of targets */
239 	unsigned char niScamTbl[MAX_SCSI_TAR][4];	/* Compressed Scam name
240 							   string of Targets */
241 };
242 
243 #define	MODEL_LT		1
244 #define	MODEL_DL		2
245 #define	MODEL_LW		3
246 #define	MODEL_DW		4
247 
248 struct sccb_card {
249 	struct sccb *currentSCCB;
250 	struct sccb_mgr_info *cardInfo;
251 
252 	u32 ioPort;
253 
254 	unsigned short cmdCounter;
255 	unsigned char discQCount;
256 	unsigned char tagQ_Lst;
257 	unsigned char cardIndex;
258 	unsigned char scanIndex;
259 	unsigned char globalFlags;
260 	unsigned char ourId;
261 	struct nvram_info *pNvRamInfo;
262 	struct sccb *discQ_Tbl[QUEUE_DEPTH];
263 
264 };
265 
266 #define F_TAG_STARTED		0x01
267 #define F_CONLUN_IO			0x02
268 #define F_DO_RENEGO			0x04
269 #define F_NO_FILTER			0x08
270 #define F_GREEN_PC			0x10
271 #define F_HOST_XFER_ACT		0x20
272 #define F_NEW_SCCB_CMD		0x40
273 #define F_UPDATE_EEPROM		0x80
274 
275 #define  ID_STRING_LENGTH  32
276 #define  TYPE_CODE0        0x63	/*Level2 Mstr (bits 7-6),  */
277 
278 #define  SLV_TYPE_CODE0    0xA3	/*Priority Bit set (bits 7-6),  */
279 
280 #define  ASSIGN_ID   0x00
281 #define  SET_P_FLAG  0x01
282 #define  CFG_CMPLT   0x03
283 #define  DOM_MSTR    0x0F
284 #define  SYNC_PTRN   0x1F
285 
286 #define  ID_0_7      0x18
287 #define  ID_8_F      0x11
288 #define  MISC_CODE   0x14
289 #define  CLR_P_FLAG  0x18
290 
291 #define  INIT_SELTD  0x01
292 #define  LEVEL2_TAR  0x02
293 
294 enum scam_id_st { ID0, ID1, ID2, ID3, ID4, ID5, ID6, ID7, ID8, ID9, ID10, ID11,
295 	    ID12,
296 	ID13, ID14, ID15, ID_UNUSED, ID_UNASSIGNED, ID_ASSIGNED, LEGACY,
297 	CLR_PRIORITY, NO_ID_AVAIL
298 };
299 
300 typedef struct SCCBscam_info {
301 
302 	unsigned char id_string[ID_STRING_LENGTH];
303 	enum scam_id_st state;
304 
305 } SCCBSCAM_INFO;
306 
307 
308 #define  SMIDENT                 0x80
309 #define  DISC_PRIV               0x40
310 
311 #define  SM8BIT                  0x00
312 #define  SM16BIT                 0x01
313 
314 #define  SIX_BYTE_CMD            0x06
315 #define  TWELVE_BYTE_CMD         0x0C
316 
317 #define  ASYNC                   0x00
318 #define  MAX_OFFSET              0x0F	/* Maxbyteoffset for Sync Xfers */
319 
320 #define  EEPROM_WD_CNT     256
321 
322 #define  EEPROM_CHECK_SUM  0
323 #define  FW_SIGNATURE      2
324 #define  MODEL_NUMB_0      4
325 #define  MODEL_NUMB_2      6
326 #define  MODEL_NUMB_4      8
327 #define  SYSTEM_CONFIG     16
328 #define  SCSI_CONFIG       17
329 #define  BIOS_CONFIG       18
330 #define  SCAM_CONFIG       20
331 #define  ADAPTER_SCSI_ID   24
332 
333 #define  IGNORE_B_SCAN     32
334 #define  SEND_START_ENA    34
335 #define  DEVICE_ENABLE     36
336 
337 #define  SYNC_RATE_TBL     38
338 #define  SYNC_RATE_TBL01   38
339 #define  SYNC_RATE_TBL23   40
340 #define  SYNC_RATE_TBL45   42
341 #define  SYNC_RATE_TBL67   44
342 #define  SYNC_RATE_TBL89   46
343 #define  SYNC_RATE_TBLab   48
344 #define  SYNC_RATE_TBLcd   50
345 #define  SYNC_RATE_TBLef   52
346 
347 #define  EE_SCAMBASE      256
348 
349 #define  SCAM_ENABLED   BIT(2)
350 #define  SCAM_LEVEL2    BIT(3)
351 
352 #define	RENEGO_ENA		BIT(10)
353 #define	CONNIO_ENA		BIT(11)
354 #define  GREEN_PC_ENA   BIT(12)
355 
356 #define  AUTO_RATE_00   00
357 #define  AUTO_RATE_05   01
358 #define  AUTO_RATE_10   02
359 #define  AUTO_RATE_20   03
360 
361 #define  WIDE_NEGO_BIT     BIT(7)
362 #define  DISC_ENABLE_BIT   BIT(6)
363 
364 #define  hp_vendor_id_0       0x00	/* LSB */
365 #define  ORION_VEND_0   0x4B
366 
367 #define  hp_vendor_id_1       0x01	/* MSB */
368 #define  ORION_VEND_1   0x10
369 
370 #define  hp_device_id_0       0x02	/* LSB */
371 #define  ORION_DEV_0    0x30
372 
373 #define  hp_device_id_1       0x03	/* MSB */
374 #define  ORION_DEV_1    0x81
375 
376 	/* Sub Vendor ID and Sub Device ID only available in
377 	   Harpoon Version 2 and higher */
378 
379 #define  hp_sub_device_id_0   0x06	/* LSB */
380 
381 #define  hp_semaphore         0x0C
382 #define SCCB_MGR_ACTIVE    BIT(0)
383 #define TICKLE_ME          BIT(1)
384 #define SCCB_MGR_PRESENT   BIT(3)
385 #define BIOS_IN_USE        BIT(4)
386 
387 #define  hp_sys_ctrl          0x0F
388 
389 #define  STOP_CLK          BIT(0)	/*Turn off BusMaster Clock */
390 #define  DRVR_RST          BIT(1)	/*Firmware Reset to 80C15 chip */
391 #define  HALT_MACH         BIT(3)	/*Halt State Machine      */
392 #define  HARD_ABORT        BIT(4)	/*Hard Abort              */
393 
394 #define  hp_host_blk_cnt      0x13
395 
396 #define  XFER_BLK64        0x06	/*     1 1 0 64 byte per block */
397 
398 #define  BM_THRESHOLD      0x40	/* PCI mode can only xfer 16 bytes */
399 
400 #define  hp_int_mask          0x17
401 
402 #define  INT_CMD_COMPL     BIT(0)	/* DMA command complete   */
403 #define  INT_EXT_STATUS    BIT(1)	/* Extended Status Set    */
404 
405 #define  hp_xfer_cnt_lo       0x18
406 #define  hp_xfer_cnt_hi       0x1A
407 #define  hp_xfer_cmd          0x1B
408 
409 #define  XFER_HOST_DMA     0x00	/*     0 0 0 Transfer Host -> DMA */
410 #define  XFER_DMA_HOST     0x01	/*     0 0 1 Transfer DMA  -> Host */
411 
412 #define  XFER_HOST_AUTO    0x00	/*     0 0 Auto Transfer Size   */
413 
414 #define  XFER_DMA_8BIT     0x20	/*     0 1 8 BIT  Transfer Size */
415 
416 #define  DISABLE_INT       BIT(7)	/*Do not interrupt at end of cmd. */
417 
418 #define  HOST_WRT_CMD      ((DISABLE_INT + XFER_HOST_DMA + XFER_HOST_AUTO + XFER_DMA_8BIT))
419 #define  HOST_RD_CMD       ((DISABLE_INT + XFER_DMA_HOST + XFER_HOST_AUTO + XFER_DMA_8BIT))
420 
421 #define  hp_host_addr_lo      0x1C
422 #define  hp_host_addr_hmi     0x1E
423 
424 #define  hp_ee_ctrl           0x22
425 
426 #define  EXT_ARB_ACK       BIT(7)
427 #define  SCSI_TERM_ENA_H   BIT(6)	/* SCSI high byte terminator */
428 #define  SEE_MS            BIT(5)
429 #define  SEE_CS            BIT(3)
430 #define  SEE_CLK           BIT(2)
431 #define  SEE_DO            BIT(1)
432 #define  SEE_DI            BIT(0)
433 
434 #define  EE_READ           0x06
435 #define  EE_WRITE          0x05
436 #define  EWEN              0x04
437 #define  EWEN_ADDR         0x03C0
438 #define  EWDS              0x04
439 #define  EWDS_ADDR         0x0000
440 
441 #define  hp_bm_ctrl           0x26
442 
443 #define  SCSI_TERM_ENA_L   BIT(0)	/*Enable/Disable external terminators */
444 #define  FLUSH_XFER_CNTR   BIT(1)	/*Flush transfer counter */
445 #define  FORCE1_XFER       BIT(5)	/*Always xfer one byte in byte mode */
446 #define  FAST_SINGLE       BIT(6)	/*?? */
447 
448 #define  BMCTRL_DEFAULT    (FORCE1_XFER|FAST_SINGLE|SCSI_TERM_ENA_L)
449 
450 #define  hp_sg_addr           0x28
451 #define  hp_page_ctrl         0x29
452 
453 #define  SCATTER_EN        BIT(0)
454 #define  SGRAM_ARAM        BIT(1)
455 #define  G_INT_DISABLE     BIT(3)	/* Enable/Disable all Interrupts */
456 #define  NARROW_SCSI_CARD  BIT(4)	/* NARROW/WIDE SCSI config pin */
457 
458 #define  hp_pci_stat_cfg      0x2D
459 
460 #define  REC_MASTER_ABORT  BIT(5)	/*received Master abort */
461 
462 #define  hp_rev_num           0x33
463 
464 #define  hp_stack_data        0x34
465 #define  hp_stack_addr        0x35
466 
467 #define  hp_ext_status        0x36
468 
469 #define  BM_FORCE_OFF      BIT(0)	/*Bus Master is forced to get off */
470 #define  PCI_TGT_ABORT     BIT(0)	/*PCI bus master transaction aborted */
471 #define  PCI_DEV_TMOUT     BIT(1)	/*PCI Device Time out */
472 #define  CMD_ABORTED       BIT(4)	/*Command aborted */
473 #define  BM_PARITY_ERR     BIT(5)	/*parity error on data received   */
474 #define  PIO_OVERRUN       BIT(6)	/*Slave data overrun */
475 #define  BM_CMD_BUSY       BIT(7)	/*Bus master transfer command busy */
476 #define  BAD_EXT_STATUS    (BM_FORCE_OFF | PCI_DEV_TMOUT | CMD_ABORTED | \
477                                   BM_PARITY_ERR | PIO_OVERRUN)
478 
479 #define  hp_int_status        0x37
480 
481 #define  EXT_STATUS_ON     BIT(1)	/*Extended status is valid */
482 #define  SCSI_INTERRUPT    BIT(2)	/*Global indication of a SCSI int. */
483 #define  INT_ASSERTED      BIT(5)	/* */
484 
485 #define  hp_fifo_cnt          0x38
486 
487 #define  hp_intena		 0x40
488 
489 #define  RESET		 BIT(7)
490 #define  PROG_HLT		 BIT(6)
491 #define  PARITY		 BIT(5)
492 #define  FIFO		 BIT(4)
493 #define  SEL		 BIT(3)
494 #define  SCAM_SEL		 BIT(2)
495 #define  RSEL		 BIT(1)
496 #define  TIMEOUT		 BIT(0)
497 #define  BUS_FREE		 BIT(15)
498 #define  XFER_CNT_0	 BIT(14)
499 #define  PHASE		 BIT(13)
500 #define  IUNKWN		 BIT(12)
501 #define  ICMD_COMP	 BIT(11)
502 #define  ITICKLE		 BIT(10)
503 #define  IDO_STRT		 BIT(9)
504 #define  ITAR_DISC	 BIT(8)
505 #define  AUTO_INT		 (BIT(12)+BIT(11)+BIT(10)+BIT(9)+BIT(8))
506 #define  CLR_ALL_INT	 0xFFFF
507 #define  CLR_ALL_INT_1	 0xFF00
508 
509 #define  hp_intstat		 0x42
510 
511 #define  hp_scsisig           0x44
512 
513 #define  SCSI_SEL          BIT(7)
514 #define  SCSI_BSY          BIT(6)
515 #define  SCSI_REQ          BIT(5)
516 #define  SCSI_ACK          BIT(4)
517 #define  SCSI_ATN          BIT(3)
518 #define  SCSI_CD           BIT(2)
519 #define  SCSI_MSG          BIT(1)
520 #define  SCSI_IOBIT        BIT(0)
521 
522 #define  S_SCSI_PHZ        (BIT(2)+BIT(1)+BIT(0))
523 #define  S_MSGO_PH         (BIT(2)+BIT(1)       )
524 #define  S_MSGI_PH         (BIT(2)+BIT(1)+BIT(0))
525 #define  S_DATAI_PH        (              BIT(0))
526 #define  S_DATAO_PH        0x00
527 #define  S_ILL_PH          (       BIT(1)       )
528 
529 #define  hp_scsictrl_0        0x45
530 
531 #define  SEL_TAR           BIT(6)
532 #define  ENA_ATN           BIT(4)
533 #define  ENA_RESEL         BIT(2)
534 #define  SCSI_RST          BIT(1)
535 #define  ENA_SCAM_SEL      BIT(0)
536 
537 #define  hp_portctrl_0        0x46
538 
539 #define  SCSI_PORT         BIT(7)
540 #define  SCSI_INBIT        BIT(6)
541 #define  DMA_PORT          BIT(5)
542 #define  DMA_RD            BIT(4)
543 #define  HOST_PORT         BIT(3)
544 #define  HOST_WRT          BIT(2)
545 #define  SCSI_BUS_EN       BIT(1)
546 #define  START_TO          BIT(0)
547 
548 #define  hp_scsireset         0x47
549 
550 #define  SCSI_INI          BIT(6)
551 #define  SCAM_EN           BIT(5)
552 #define  DMA_RESET         BIT(3)
553 #define  HPSCSI_RESET      BIT(2)
554 #define  PROG_RESET        BIT(1)
555 #define  FIFO_CLR          BIT(0)
556 
557 #define  hp_xfercnt_0         0x48
558 #define  hp_xfercnt_2         0x4A
559 
560 #define  hp_fifodata_0        0x4C
561 #define  hp_addstat           0x4E
562 
563 #define  SCAM_TIMER        BIT(7)
564 #define  SCSI_MODE8        BIT(3)
565 #define  SCSI_PAR_ERR      BIT(0)
566 
567 #define  hp_prgmcnt_0         0x4F
568 
569 #define  hp_selfid_0          0x50
570 #define  hp_selfid_1          0x51
571 #define  hp_arb_id            0x52
572 
573 #define  hp_select_id         0x53
574 
575 #define  hp_synctarg_base     0x54
576 #define  hp_synctarg_12       0x54
577 #define  hp_synctarg_13       0x55
578 #define  hp_synctarg_14       0x56
579 #define  hp_synctarg_15       0x57
580 
581 #define  hp_synctarg_8        0x58
582 #define  hp_synctarg_9        0x59
583 #define  hp_synctarg_10       0x5A
584 #define  hp_synctarg_11       0x5B
585 
586 #define  hp_synctarg_4        0x5C
587 #define  hp_synctarg_5        0x5D
588 #define  hp_synctarg_6        0x5E
589 #define  hp_synctarg_7        0x5F
590 
591 #define  hp_synctarg_0        0x60
592 #define  hp_synctarg_1        0x61
593 #define  hp_synctarg_2        0x62
594 #define  hp_synctarg_3        0x63
595 
596 #define  NARROW_SCSI       BIT(4)
597 #define  DEFAULT_OFFSET    0x0F
598 
599 #define  hp_autostart_0       0x64
600 #define  hp_autostart_1       0x65
601 #define  hp_autostart_3       0x67
602 
603 #define  AUTO_IMMED    BIT(5)
604 #define  SELECT   BIT(6)
605 #define  END_DATA (BIT(7)+BIT(6))
606 
607 #define  hp_gp_reg_0          0x68
608 #define  hp_gp_reg_1          0x69
609 #define  hp_gp_reg_3          0x6B
610 
611 #define  hp_seltimeout        0x6C
612 
613 #define  TO_4ms            0x67	/* 3.9959ms */
614 
615 #define  TO_5ms            0x03	/* 4.9152ms */
616 #define  TO_10ms           0x07	/* 11.xxxms */
617 #define  TO_250ms          0x99	/* 250.68ms */
618 #define  TO_290ms          0xB1	/* 289.99ms */
619 
620 #define  hp_clkctrl_0         0x6D
621 
622 #define  PWR_DWN           BIT(6)
623 #define  ACTdeassert       BIT(4)
624 #define  CLK_40MHZ         (BIT(1) + BIT(0))
625 
626 #define  CLKCTRL_DEFAULT   (ACTdeassert | CLK_40MHZ)
627 
628 #define  hp_fiforead          0x6E
629 #define  hp_fifowrite         0x6F
630 
631 #define  hp_offsetctr         0x70
632 #define  hp_xferstat          0x71
633 
634 #define  FIFO_EMPTY        BIT(6)
635 
636 #define  hp_portctrl_1        0x72
637 
638 #define  CHK_SCSI_P        BIT(3)
639 #define  HOST_MODE8        BIT(0)
640 
641 #define  hp_xfer_pad          0x73
642 
643 #define  ID_UNLOCK         BIT(3)
644 
645 #define  hp_scsidata_0        0x74
646 #define  hp_scsidata_1        0x75
647 
648 #define  hp_aramBase          0x80
649 #define  BIOS_DATA_OFFSET     0x60
650 #define  BIOS_RELATIVE_CARD   0x64
651 
652 #define  AR3      (BIT(9) + BIT(8))
653 #define  SDATA    BIT(10)
654 
655 #define  CRD_OP   BIT(11)	/* Cmp Reg. w/ Data */
656 
657 #define  CRR_OP   BIT(12)	/* Cmp Reg. w. Reg. */
658 
659 #define  CPE_OP   (BIT(14)+BIT(11))	/* Cmp SCSI phs & Branch EQ */
660 
661 #define  CPN_OP   (BIT(14)+BIT(12))	/* Cmp SCSI phs & Branch NOT EQ */
662 
663 #define  ADATA_OUT   0x00
664 #define  ADATA_IN    BIT(8)
665 #define  ACOMMAND    BIT(10)
666 #define  ASTATUS     (BIT(10)+BIT(8))
667 #define  AMSG_OUT    (BIT(10)+BIT(9))
668 #define  AMSG_IN     (BIT(10)+BIT(9)+BIT(8))
669 
670 #define  BRH_OP   BIT(13)	/* Branch */
671 
672 #define  ALWAYS   0x00
673 #define  EQUAL    BIT(8)
674 #define  NOT_EQ   BIT(9)
675 
676 #define  TCB_OP   (BIT(13)+BIT(11))	/* Test condition & branch */
677 
678 #define  FIFO_0      BIT(10)
679 
680 #define  MPM_OP   BIT(15)	/* Match phase and move data */
681 
682 #define  MRR_OP   BIT(14)	/* Move DReg. to Reg. */
683 
684 #define  S_IDREG  (BIT(2)+BIT(1)+BIT(0))
685 
686 #define  D_AR0    0x00
687 #define  D_AR1    BIT(0)
688 #define  D_BUCKET (BIT(2) + BIT(1) + BIT(0))
689 
690 #define  RAT_OP      (BIT(14)+BIT(13)+BIT(11))
691 
692 #define  SSI_OP      (BIT(15)+BIT(11))
693 
694 #define  SSI_ITAR_DISC	(ITAR_DISC >> 8)
695 #define  SSI_IDO_STRT	(IDO_STRT >> 8)
696 
697 #define  SSI_ICMD_COMP	(ICMD_COMP >> 8)
698 #define  SSI_ITICKLE	(ITICKLE >> 8)
699 
700 #define  SSI_IUNKWN	(IUNKWN >> 8)
701 #define  SSI_INO_CC	(IUNKWN >> 8)
702 #define  SSI_IRFAIL	(IUNKWN >> 8)
703 
704 #define  NP    0x10		/*Next Phase */
705 #define  NTCMD 0x02		/*Non- Tagged Command start */
706 #define  CMDPZ 0x04		/*Command phase */
707 #define  DINT  0x12		/*Data Out/In interrupt */
708 #define  DI    0x13		/*Data Out */
709 #define  DC    0x19		/*Disconnect Message */
710 #define  ST    0x1D		/*Status Phase */
711 #define  UNKNWN 0x24		/*Unknown bus action */
712 #define  CC    0x25		/*Command Completion failure */
713 #define  TICK  0x26		/*New target reselected us. */
714 #define  SELCHK 0x28		/*Select & Check SCSI ID latch reg */
715 
716 #define  ID_MSG_STRT    hp_aramBase + 0x00
717 #define  NON_TAG_ID_MSG hp_aramBase + 0x06
718 #define  CMD_STRT       hp_aramBase + 0x08
719 #define  SYNC_MSGS      hp_aramBase + 0x08
720 
721 #define  TAG_STRT          0x00
722 #define  DISCONNECT_START  0x10/2
723 #define  END_DATA_START    0x14/2
724 #define  CMD_ONLY_STRT     CMDPZ/2
725 #define  SELCHK_STRT     SELCHK/2
726 
727 #define GET_XFER_CNT(port, xfercnt) {RD_HARP32(port,hp_xfercnt_0,xfercnt); xfercnt &= 0xFFFFFF;}
728 /* #define GET_XFER_CNT(port, xfercnt) (xfercnt = RD_HARPOON(port+hp_xfercnt_2), \
729                                  xfercnt <<= 16,\
730                                  xfercnt |= RDW_HARPOON((unsigned short)(port+hp_xfercnt_0)))
731  */
732 #define HP_SETUP_ADDR_CNT(port,addr,count) (WRW_HARPOON((port+hp_host_addr_lo), (unsigned short)(addr & 0x0000FFFFL)),\
733          addr >>= 16,\
734          WRW_HARPOON((port+hp_host_addr_hmi), (unsigned short)(addr & 0x0000FFFFL)),\
735          WR_HARP32(port,hp_xfercnt_0,count),\
736          WRW_HARPOON((port+hp_xfer_cnt_lo), (unsigned short)(count & 0x0000FFFFL)),\
737          count >>= 16,\
738          WR_HARPOON(port+hp_xfer_cnt_hi, (count & 0xFF)))
739 
740 #define ACCEPT_MSG(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
741                           WR_HARPOON(port+hp_scsisig, S_ILL_PH);}
742 
743 #define ACCEPT_MSG_ATN(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
744                           WR_HARPOON(port+hp_scsisig, (S_ILL_PH|SCSI_ATN));}
745 
746 #define DISABLE_AUTO(port) (WR_HARPOON(port+hp_scsireset, PROG_RESET),\
747                         WR_HARPOON(port+hp_scsireset, 0x00))
748 
749 #define ARAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
750                              (RD_HARPOON(p_port+hp_page_ctrl) | SGRAM_ARAM)))
751 
752 #define SGRAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
753                              (RD_HARPOON(p_port+hp_page_ctrl) & ~SGRAM_ARAM)))
754 
755 #define MDISABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
756                              (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE)))
757 
758 #define MENABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
759                              (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE)))
760 
761 static unsigned char FPT_sisyncn(u32 port, unsigned char p_card,
762 				 unsigned char syncFlag);
763 static void FPT_ssel(u32 port, unsigned char p_card);
764 static void FPT_sres(u32 port, unsigned char p_card,
765 		     struct sccb_card *pCurrCard);
766 static void FPT_shandem(u32 port, unsigned char p_card,
767 			struct sccb *pCurrSCCB);
768 static void FPT_stsyncn(u32 port, unsigned char p_card);
769 static void FPT_sisyncr(u32 port, unsigned char sync_pulse,
770 			unsigned char offset);
771 static void FPT_sssyncv(u32 p_port, unsigned char p_id,
772 			unsigned char p_sync_value,
773 			struct sccb_mgr_tar_info *currTar_Info);
774 static void FPT_sresb(u32 port, unsigned char p_card);
775 static void FPT_sxfrp(u32 p_port, unsigned char p_card);
776 static void FPT_schkdd(u32 port, unsigned char p_card);
777 static unsigned char FPT_RdStack(u32 port, unsigned char index);
778 static void FPT_WrStack(u32 portBase, unsigned char index,
779 			unsigned char data);
780 static unsigned char FPT_ChkIfChipInitialized(u32 ioPort);
781 
782 static void FPT_SendMsg(u32 port, unsigned char message);
783 static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
784 				   unsigned char error_code);
785 
786 static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card);
787 static void FPT_RNVRamData(struct nvram_info *pNvRamInfo);
788 
789 static unsigned char FPT_siwidn(u32 port, unsigned char p_card);
790 static void FPT_stwidn(u32 port, unsigned char p_card);
791 static void FPT_siwidr(u32 port, unsigned char width);
792 
793 static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
794 				unsigned char p_card);
795 static void FPT_queueDisconnect(struct sccb *p_SCCB, unsigned char p_card);
796 static void FPT_queueCmdComplete(struct sccb_card *pCurrCard,
797 				 struct sccb *p_SCCB, unsigned char p_card);
798 static void FPT_queueSearchSelect(struct sccb_card *pCurrCard,
799 				  unsigned char p_card);
800 static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code);
801 static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char card);
802 static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB,
803 				       unsigned char p_card);
804 static void FPT_utilUpdateResidual(struct sccb *p_SCCB);
805 static unsigned short FPT_CalcCrc16(unsigned char buffer[]);
806 static unsigned char FPT_CalcLrc(unsigned char buffer[]);
807 
808 static void FPT_Wait1Second(u32 p_port);
809 static void FPT_Wait(u32 p_port, unsigned char p_delay);
810 static void FPT_utilEEWriteOnOff(u32 p_port, unsigned char p_mode);
811 static void FPT_utilEEWrite(u32 p_port, unsigned short ee_data,
812 			    unsigned short ee_addr);
813 static unsigned short FPT_utilEERead(u32 p_port,
814 				     unsigned short ee_addr);
815 static unsigned short FPT_utilEEReadOrg(u32 p_port,
816 					unsigned short ee_addr);
817 static void FPT_utilEESendCmdAddr(u32 p_port, unsigned char ee_cmd,
818 				  unsigned short ee_addr);
819 
820 static void FPT_phaseDataOut(u32 port, unsigned char p_card);
821 static void FPT_phaseDataIn(u32 port, unsigned char p_card);
822 static void FPT_phaseCommand(u32 port, unsigned char p_card);
823 static void FPT_phaseStatus(u32 port, unsigned char p_card);
824 static void FPT_phaseMsgOut(u32 port, unsigned char p_card);
825 static void FPT_phaseMsgIn(u32 port, unsigned char p_card);
826 static void FPT_phaseIllegal(u32 port, unsigned char p_card);
827 
828 static void FPT_phaseDecode(u32 port, unsigned char p_card);
829 static void FPT_phaseChkFifo(u32 port, unsigned char p_card);
830 static void FPT_phaseBusFree(u32 p_port, unsigned char p_card);
831 
832 static void FPT_XbowInit(u32 port, unsigned char scamFlg);
833 static void FPT_BusMasterInit(u32 p_port);
834 static void FPT_DiagEEPROM(u32 p_port);
835 
836 static void FPT_dataXferProcessor(u32 port,
837 				  struct sccb_card *pCurrCard);
838 static void FPT_busMstrSGDataXferStart(u32 port,
839 				       struct sccb *pCurrSCCB);
840 static void FPT_busMstrDataXferStart(u32 port,
841 				     struct sccb *pCurrSCCB);
842 static void FPT_hostDataXferAbort(u32 port, unsigned char p_card,
843 				  struct sccb *pCurrSCCB);
844 static void FPT_hostDataXferRestart(struct sccb *currSCCB);
845 
846 static unsigned char FPT_SccbMgr_bad_isr(u32 p_port,
847 					 unsigned char p_card,
848 					 struct sccb_card *pCurrCard,
849 					 unsigned short p_int);
850 
851 static void FPT_SccbMgrTableInitAll(void);
852 static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard,
853 				     unsigned char p_card);
854 static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
855 				       unsigned char target);
856 
857 static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
858 		      unsigned char p_power_up);
859 
860 static int FPT_scarb(u32 p_port, unsigned char p_sel_type);
861 static void FPT_scbusf(u32 p_port);
862 static void FPT_scsel(u32 p_port);
863 static void FPT_scasid(unsigned char p_card, u32 p_port);
864 static unsigned char FPT_scxferc(u32 p_port, unsigned char p_data);
865 static unsigned char FPT_scsendi(u32 p_port,
866 				 unsigned char p_id_string[]);
867 static unsigned char FPT_sciso(u32 p_port,
868 			       unsigned char p_id_string[]);
869 static void FPT_scwirod(u32 p_port, unsigned char p_data_bit);
870 static void FPT_scwiros(u32 p_port, unsigned char p_data_bit);
871 static unsigned char FPT_scvalq(unsigned char p_quintet);
872 static unsigned char FPT_scsell(u32 p_port, unsigned char targ_id);
873 static void FPT_scwtsel(u32 p_port);
874 static void FPT_inisci(unsigned char p_card, u32 p_port,
875 		       unsigned char p_our_id);
876 static void FPT_scsavdi(unsigned char p_card, u32 p_port);
877 static unsigned char FPT_scmachid(unsigned char p_card,
878 				  unsigned char p_id_string[]);
879 
880 static void FPT_autoCmdCmplt(u32 p_port, unsigned char p_card);
881 static void FPT_autoLoadDefaultMap(u32 p_port);
882 
883 static struct sccb_mgr_tar_info FPT_sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] =
884     { {{0}} };
885 static struct sccb_card FPT_BL_Card[MAX_CARDS] = { {0} };
886 static SCCBSCAM_INFO FPT_scamInfo[MAX_SCSI_TAR] = { {{0}} };
887 static struct nvram_info FPT_nvRamInfo[MAX_MB_CARDS] = { {0} };
888 
889 static unsigned char FPT_mbCards = 0;
890 static unsigned char FPT_scamHAString[] =
891     { 0x63, 0x07, 'B', 'U', 'S', 'L', 'O', 'G', 'I', 'C',
892 	' ', 'B', 'T', '-', '9', '3', '0',
893 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
894 	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
895 };
896 
897 static unsigned short FPT_default_intena = 0;
898 
899 static void (*FPT_s_PhaseTbl[8]) (u32, unsigned char) = {
900 0};
901 
902 /*---------------------------------------------------------------------
903  *
904  * Function: FlashPoint_ProbeHostAdapter
905  *
906  * Description: Setup and/or Search for cards and return info to caller.
907  *
908  *---------------------------------------------------------------------*/
909 
910 static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo)
911 {
912 	static unsigned char first_time = 1;
913 
914 	unsigned char i, j, id, ScamFlg;
915 	unsigned short temp, temp2, temp3, temp4, temp5, temp6;
916 	u32 ioport;
917 	struct nvram_info *pCurrNvRam;
918 
919 	ioport = pCardInfo->si_baseaddr;
920 
921 	if (RD_HARPOON(ioport + hp_vendor_id_0) != ORION_VEND_0)
922 		return (int)FAILURE;
923 
924 	if ((RD_HARPOON(ioport + hp_vendor_id_1) != ORION_VEND_1))
925 		return (int)FAILURE;
926 
927 	if ((RD_HARPOON(ioport + hp_device_id_0) != ORION_DEV_0))
928 		return (int)FAILURE;
929 
930 	if ((RD_HARPOON(ioport + hp_device_id_1) != ORION_DEV_1))
931 		return (int)FAILURE;
932 
933 	if (RD_HARPOON(ioport + hp_rev_num) != 0x0f) {
934 
935 /* For new Harpoon then check for sub_device ID LSB
936    the bits(0-3) must be all ZERO for compatible with
937    current version of SCCBMgr, else skip this Harpoon
938 	device. */
939 
940 		if (RD_HARPOON(ioport + hp_sub_device_id_0) & 0x0f)
941 			return (int)FAILURE;
942 	}
943 
944 	if (first_time) {
945 		FPT_SccbMgrTableInitAll();
946 		first_time = 0;
947 		FPT_mbCards = 0;
948 	}
949 
950 	if (FPT_RdStack(ioport, 0) != 0x00) {
951 		if (FPT_ChkIfChipInitialized(ioport) == 0) {
952 			pCurrNvRam = NULL;
953 			WR_HARPOON(ioport + hp_semaphore, 0x00);
954 			FPT_XbowInit(ioport, 0);	/*Must Init the SCSI before attempting */
955 			FPT_DiagEEPROM(ioport);
956 		} else {
957 			if (FPT_mbCards < MAX_MB_CARDS) {
958 				pCurrNvRam = &FPT_nvRamInfo[FPT_mbCards];
959 				FPT_mbCards++;
960 				pCurrNvRam->niBaseAddr = ioport;
961 				FPT_RNVRamData(pCurrNvRam);
962 			} else
963 				return (int)FAILURE;
964 		}
965 	} else
966 		pCurrNvRam = NULL;
967 
968 	WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT);
969 	WR_HARPOON(ioport + hp_sys_ctrl, 0x00);
970 
971 	if (pCurrNvRam)
972 		pCardInfo->si_id = pCurrNvRam->niAdapId;
973 	else
974 		pCardInfo->si_id =
975 		    (unsigned
976 		     char)(FPT_utilEERead(ioport,
977 					  (ADAPTER_SCSI_ID /
978 					   2)) & (unsigned char)0x0FF);
979 
980 	pCardInfo->si_lun = 0x00;
981 	pCardInfo->si_fw_revision = ORION_FW_REV;
982 	temp2 = 0x0000;
983 	temp3 = 0x0000;
984 	temp4 = 0x0000;
985 	temp5 = 0x0000;
986 	temp6 = 0x0000;
987 
988 	for (id = 0; id < (16 / 2); id++) {
989 
990 		if (pCurrNvRam) {
991 			temp = (unsigned short)pCurrNvRam->niSyncTbl[id];
992 			temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
993 			    (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
994 		} else
995 			temp =
996 			    FPT_utilEERead(ioport,
997 					   (unsigned short)((SYNC_RATE_TBL / 2)
998 							    + id));
999 
1000 		for (i = 0; i < 2; temp >>= 8, i++) {
1001 
1002 			temp2 >>= 1;
1003 			temp3 >>= 1;
1004 			temp4 >>= 1;
1005 			temp5 >>= 1;
1006 			temp6 >>= 1;
1007 			switch (temp & 0x3) {
1008 			case AUTO_RATE_20:	/* Synchronous, 20 mega-transfers/second */
1009 				temp6 |= 0x8000;
1010 				fallthrough;
1011 			case AUTO_RATE_10:	/* Synchronous, 10 mega-transfers/second */
1012 				temp5 |= 0x8000;
1013 				fallthrough;
1014 			case AUTO_RATE_05:	/* Synchronous, 5 mega-transfers/second */
1015 				temp2 |= 0x8000;
1016 				fallthrough;
1017 			case AUTO_RATE_00:	/* Asynchronous */
1018 				break;
1019 			}
1020 
1021 			if (temp & DISC_ENABLE_BIT)
1022 				temp3 |= 0x8000;
1023 
1024 			if (temp & WIDE_NEGO_BIT)
1025 				temp4 |= 0x8000;
1026 
1027 		}
1028 	}
1029 
1030 	pCardInfo->si_per_targ_init_sync = temp2;
1031 	pCardInfo->si_per_targ_no_disc = temp3;
1032 	pCardInfo->si_per_targ_wide_nego = temp4;
1033 	pCardInfo->si_per_targ_fast_nego = temp5;
1034 	pCardInfo->si_per_targ_ultra_nego = temp6;
1035 
1036 	if (pCurrNvRam)
1037 		i = pCurrNvRam->niSysConf;
1038 	else
1039 		i = (unsigned
1040 		     char)(FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)));
1041 
1042 	if (pCurrNvRam)
1043 		ScamFlg = pCurrNvRam->niScamConf;
1044 	else
1045 		ScamFlg =
1046 		    (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
1047 
1048 	pCardInfo->si_mflags = 0x0000;
1049 
1050 	if (i & 0x01)
1051 		pCardInfo->si_mflags |= SCSI_PARITY_ENA;
1052 
1053 	if (!(i & 0x02))
1054 		pCardInfo->si_mflags |= SOFT_RESET;
1055 
1056 	if (i & 0x10)
1057 		pCardInfo->si_mflags |= EXTENDED_TRANSLATION;
1058 
1059 	if (ScamFlg & SCAM_ENABLED)
1060 		pCardInfo->si_mflags |= FLAG_SCAM_ENABLED;
1061 
1062 	if (ScamFlg & SCAM_LEVEL2)
1063 		pCardInfo->si_mflags |= FLAG_SCAM_LEVEL2;
1064 
1065 	j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
1066 	if (i & 0x04) {
1067 		j |= SCSI_TERM_ENA_L;
1068 	}
1069 	WR_HARPOON(ioport + hp_bm_ctrl, j);
1070 
1071 	j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
1072 	if (i & 0x08) {
1073 		j |= SCSI_TERM_ENA_H;
1074 	}
1075 	WR_HARPOON(ioport + hp_ee_ctrl, j);
1076 
1077 	if (!(RD_HARPOON(ioport + hp_page_ctrl) & NARROW_SCSI_CARD))
1078 
1079 		pCardInfo->si_mflags |= SUPPORT_16TAR_32LUN;
1080 
1081 	pCardInfo->si_card_family = HARPOON_FAMILY;
1082 	pCardInfo->si_bustype = BUSTYPE_PCI;
1083 
1084 	if (pCurrNvRam) {
1085 		pCardInfo->si_card_model[0] = '9';
1086 		switch (pCurrNvRam->niModel & 0x0f) {
1087 		case MODEL_LT:
1088 			pCardInfo->si_card_model[1] = '3';
1089 			pCardInfo->si_card_model[2] = '0';
1090 			break;
1091 		case MODEL_LW:
1092 			pCardInfo->si_card_model[1] = '5';
1093 			pCardInfo->si_card_model[2] = '0';
1094 			break;
1095 		case MODEL_DL:
1096 			pCardInfo->si_card_model[1] = '3';
1097 			pCardInfo->si_card_model[2] = '2';
1098 			break;
1099 		case MODEL_DW:
1100 			pCardInfo->si_card_model[1] = '5';
1101 			pCardInfo->si_card_model[2] = '2';
1102 			break;
1103 		}
1104 	} else {
1105 		temp = FPT_utilEERead(ioport, (MODEL_NUMB_0 / 2));
1106 		pCardInfo->si_card_model[0] = (unsigned char)(temp >> 8);
1107 		temp = FPT_utilEERead(ioport, (MODEL_NUMB_2 / 2));
1108 
1109 		pCardInfo->si_card_model[1] = (unsigned char)(temp & 0x00FF);
1110 		pCardInfo->si_card_model[2] = (unsigned char)(temp >> 8);
1111 	}
1112 
1113 	if (pCardInfo->si_card_model[1] == '3') {
1114 		if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
1115 			pCardInfo->si_mflags |= LOW_BYTE_TERM;
1116 	} else if (pCardInfo->si_card_model[2] == '0') {
1117 		temp = RD_HARPOON(ioport + hp_xfer_pad);
1118 		WR_HARPOON(ioport + hp_xfer_pad, (temp & ~BIT(4)));
1119 		if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
1120 			pCardInfo->si_mflags |= LOW_BYTE_TERM;
1121 		WR_HARPOON(ioport + hp_xfer_pad, (temp | BIT(4)));
1122 		if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
1123 			pCardInfo->si_mflags |= HIGH_BYTE_TERM;
1124 		WR_HARPOON(ioport + hp_xfer_pad, temp);
1125 	} else {
1126 		temp = RD_HARPOON(ioport + hp_ee_ctrl);
1127 		temp2 = RD_HARPOON(ioport + hp_xfer_pad);
1128 		WR_HARPOON(ioport + hp_ee_ctrl, (temp | SEE_CS));
1129 		WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4)));
1130 		temp3 = 0;
1131 		for (i = 0; i < 8; i++) {
1132 			temp3 <<= 1;
1133 			if (!(RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7)))
1134 				temp3 |= 1;
1135 			WR_HARPOON(ioport + hp_xfer_pad, (temp2 & ~BIT(4)));
1136 			WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4)));
1137 		}
1138 		WR_HARPOON(ioport + hp_ee_ctrl, temp);
1139 		WR_HARPOON(ioport + hp_xfer_pad, temp2);
1140 		if (!(temp3 & BIT(7)))
1141 			pCardInfo->si_mflags |= LOW_BYTE_TERM;
1142 		if (!(temp3 & BIT(6)))
1143 			pCardInfo->si_mflags |= HIGH_BYTE_TERM;
1144 	}
1145 
1146 	ARAM_ACCESS(ioport);
1147 
1148 	for (i = 0; i < 4; i++) {
1149 
1150 		pCardInfo->si_XlatInfo[i] =
1151 		    RD_HARPOON(ioport + hp_aramBase + BIOS_DATA_OFFSET + i);
1152 	}
1153 
1154 	/* return with -1 if no sort, else return with
1155 	   logical card number sorted by BIOS (zero-based) */
1156 
1157 	pCardInfo->si_relative_cardnum =
1158 	    (unsigned
1159 	     char)(RD_HARPOON(ioport + hp_aramBase + BIOS_RELATIVE_CARD) - 1);
1160 
1161 	SGRAM_ACCESS(ioport);
1162 
1163 	FPT_s_PhaseTbl[0] = FPT_phaseDataOut;
1164 	FPT_s_PhaseTbl[1] = FPT_phaseDataIn;
1165 	FPT_s_PhaseTbl[2] = FPT_phaseIllegal;
1166 	FPT_s_PhaseTbl[3] = FPT_phaseIllegal;
1167 	FPT_s_PhaseTbl[4] = FPT_phaseCommand;
1168 	FPT_s_PhaseTbl[5] = FPT_phaseStatus;
1169 	FPT_s_PhaseTbl[6] = FPT_phaseMsgOut;
1170 	FPT_s_PhaseTbl[7] = FPT_phaseMsgIn;
1171 
1172 	pCardInfo->si_present = 0x01;
1173 
1174 	return 0;
1175 }
1176 
1177 /*---------------------------------------------------------------------
1178  *
1179  * Function: FlashPoint_HardwareResetHostAdapter
1180  *
1181  * Description: Setup adapter for normal operation (hard reset).
1182  *
1183  *---------------------------------------------------------------------*/
1184 
1185 static void *FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info
1186 							 *pCardInfo)
1187 {
1188 	struct sccb_card *CurrCard = NULL;
1189 	struct nvram_info *pCurrNvRam;
1190 	unsigned char i, j, thisCard, ScamFlg;
1191 	unsigned short temp, sync_bit_map, id;
1192 	u32 ioport;
1193 
1194 	ioport = pCardInfo->si_baseaddr;
1195 
1196 	for (thisCard = 0; thisCard <= MAX_CARDS; thisCard++) {
1197 
1198 		if (thisCard == MAX_CARDS)
1199 			return (void *)FAILURE;
1200 
1201 		if (FPT_BL_Card[thisCard].ioPort == ioport) {
1202 
1203 			CurrCard = &FPT_BL_Card[thisCard];
1204 			FPT_SccbMgrTableInitCard(CurrCard, thisCard);
1205 			break;
1206 		}
1207 
1208 		else if (FPT_BL_Card[thisCard].ioPort == 0x00) {
1209 
1210 			FPT_BL_Card[thisCard].ioPort = ioport;
1211 			CurrCard = &FPT_BL_Card[thisCard];
1212 
1213 			if (FPT_mbCards)
1214 				for (i = 0; i < FPT_mbCards; i++) {
1215 					if (CurrCard->ioPort ==
1216 					    FPT_nvRamInfo[i].niBaseAddr)
1217 						CurrCard->pNvRamInfo =
1218 						    &FPT_nvRamInfo[i];
1219 				}
1220 			FPT_SccbMgrTableInitCard(CurrCard, thisCard);
1221 			CurrCard->cardIndex = thisCard;
1222 			CurrCard->cardInfo = pCardInfo;
1223 
1224 			break;
1225 		}
1226 	}
1227 
1228 	pCurrNvRam = CurrCard->pNvRamInfo;
1229 
1230 	if (pCurrNvRam) {
1231 		ScamFlg = pCurrNvRam->niScamConf;
1232 	} else {
1233 		ScamFlg =
1234 		    (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
1235 	}
1236 
1237 	FPT_BusMasterInit(ioport);
1238 	FPT_XbowInit(ioport, ScamFlg);
1239 
1240 	FPT_autoLoadDefaultMap(ioport);
1241 
1242 	for (i = 0, id = 0x01; i != pCardInfo->si_id; i++, id <<= 1) {
1243 	}
1244 
1245 	WR_HARPOON(ioport + hp_selfid_0, id);
1246 	WR_HARPOON(ioport + hp_selfid_1, 0x00);
1247 	WR_HARPOON(ioport + hp_arb_id, pCardInfo->si_id);
1248 	CurrCard->ourId = pCardInfo->si_id;
1249 
1250 	i = (unsigned char)pCardInfo->si_mflags;
1251 	if (i & SCSI_PARITY_ENA)
1252 		WR_HARPOON(ioport + hp_portctrl_1, (HOST_MODE8 | CHK_SCSI_P));
1253 
1254 	j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
1255 	if (i & LOW_BYTE_TERM)
1256 		j |= SCSI_TERM_ENA_L;
1257 	WR_HARPOON(ioport + hp_bm_ctrl, j);
1258 
1259 	j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
1260 	if (i & HIGH_BYTE_TERM)
1261 		j |= SCSI_TERM_ENA_H;
1262 	WR_HARPOON(ioport + hp_ee_ctrl, j);
1263 
1264 	if (!(pCardInfo->si_mflags & SOFT_RESET)) {
1265 
1266 		FPT_sresb(ioport, thisCard);
1267 
1268 		FPT_scini(thisCard, pCardInfo->si_id, 0);
1269 	}
1270 
1271 	if (pCardInfo->si_mflags & POST_ALL_UNDERRRUNS)
1272 		CurrCard->globalFlags |= F_NO_FILTER;
1273 
1274 	if (pCurrNvRam) {
1275 		if (pCurrNvRam->niSysConf & 0x10)
1276 			CurrCard->globalFlags |= F_GREEN_PC;
1277 	} else {
1278 		if (FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)) & GREEN_PC_ENA)
1279 			CurrCard->globalFlags |= F_GREEN_PC;
1280 	}
1281 
1282 	/* Set global flag to indicate Re-Negotiation to be done on all
1283 	   ckeck condition */
1284 	if (pCurrNvRam) {
1285 		if (pCurrNvRam->niScsiConf & 0x04)
1286 			CurrCard->globalFlags |= F_DO_RENEGO;
1287 	} else {
1288 		if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & RENEGO_ENA)
1289 			CurrCard->globalFlags |= F_DO_RENEGO;
1290 	}
1291 
1292 	if (pCurrNvRam) {
1293 		if (pCurrNvRam->niScsiConf & 0x08)
1294 			CurrCard->globalFlags |= F_CONLUN_IO;
1295 	} else {
1296 		if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & CONNIO_ENA)
1297 			CurrCard->globalFlags |= F_CONLUN_IO;
1298 	}
1299 
1300 	temp = pCardInfo->si_per_targ_no_disc;
1301 
1302 	for (i = 0, id = 1; i < MAX_SCSI_TAR; i++, id <<= 1) {
1303 
1304 		if (temp & id)
1305 			FPT_sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC;
1306 	}
1307 
1308 	sync_bit_map = 0x0001;
1309 
1310 	for (id = 0; id < (MAX_SCSI_TAR / 2); id++) {
1311 
1312 		if (pCurrNvRam) {
1313 			temp = (unsigned short)pCurrNvRam->niSyncTbl[id];
1314 			temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
1315 			    (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
1316 		} else
1317 			temp =
1318 			    FPT_utilEERead(ioport,
1319 					   (unsigned short)((SYNC_RATE_TBL / 2)
1320 							    + id));
1321 
1322 		for (i = 0; i < 2; temp >>= 8, i++) {
1323 
1324 			if (pCardInfo->si_per_targ_init_sync & sync_bit_map) {
1325 
1326 				FPT_sccbMgrTbl[thisCard][id * 2 +
1327 							 i].TarEEValue =
1328 				    (unsigned char)temp;
1329 			}
1330 
1331 			else {
1332 				FPT_sccbMgrTbl[thisCard][id * 2 +
1333 							 i].TarStatus |=
1334 				    SYNC_SUPPORTED;
1335 				FPT_sccbMgrTbl[thisCard][id * 2 +
1336 							 i].TarEEValue =
1337 				    (unsigned char)(temp & ~EE_SYNC_MASK);
1338 			}
1339 
1340 /*         if ((pCardInfo->si_per_targ_wide_nego & sync_bit_map) ||
1341             (id*2+i >= 8)){
1342 */
1343 			if (pCardInfo->si_per_targ_wide_nego & sync_bit_map) {
1344 
1345 				FPT_sccbMgrTbl[thisCard][id * 2 +
1346 							 i].TarEEValue |=
1347 				    EE_WIDE_SCSI;
1348 
1349 			}
1350 
1351 			else {	/* NARROW SCSI */
1352 				FPT_sccbMgrTbl[thisCard][id * 2 +
1353 							 i].TarStatus |=
1354 				    WIDE_NEGOCIATED;
1355 			}
1356 
1357 			sync_bit_map <<= 1;
1358 
1359 		}
1360 	}
1361 
1362 	WR_HARPOON((ioport + hp_semaphore),
1363 		   (unsigned char)(RD_HARPOON((ioport + hp_semaphore)) |
1364 				   SCCB_MGR_PRESENT));
1365 
1366 	return (void *)CurrCard;
1367 }
1368 
1369 static void FlashPoint_ReleaseHostAdapter(void *pCurrCard)
1370 {
1371 	unsigned char i;
1372 	u32 portBase;
1373 	u32 regOffset;
1374 	u32 scamData;
1375 	u32 *pScamTbl;
1376 	struct nvram_info *pCurrNvRam;
1377 
1378 	pCurrNvRam = ((struct sccb_card *)pCurrCard)->pNvRamInfo;
1379 
1380 	if (pCurrNvRam) {
1381 		FPT_WrStack(pCurrNvRam->niBaseAddr, 0, pCurrNvRam->niModel);
1382 		FPT_WrStack(pCurrNvRam->niBaseAddr, 1, pCurrNvRam->niSysConf);
1383 		FPT_WrStack(pCurrNvRam->niBaseAddr, 2, pCurrNvRam->niScsiConf);
1384 		FPT_WrStack(pCurrNvRam->niBaseAddr, 3, pCurrNvRam->niScamConf);
1385 		FPT_WrStack(pCurrNvRam->niBaseAddr, 4, pCurrNvRam->niAdapId);
1386 
1387 		for (i = 0; i < MAX_SCSI_TAR / 2; i++)
1388 			FPT_WrStack(pCurrNvRam->niBaseAddr,
1389 				    (unsigned char)(i + 5),
1390 				    pCurrNvRam->niSyncTbl[i]);
1391 
1392 		portBase = pCurrNvRam->niBaseAddr;
1393 
1394 		for (i = 0; i < MAX_SCSI_TAR; i++) {
1395 			regOffset = hp_aramBase + 64 + i * 4;
1396 			pScamTbl = (u32 *)&pCurrNvRam->niScamTbl[i];
1397 			scamData = *pScamTbl;
1398 			WR_HARP32(portBase, regOffset, scamData);
1399 		}
1400 
1401 	} else {
1402 		FPT_WrStack(((struct sccb_card *)pCurrCard)->ioPort, 0, 0);
1403 	}
1404 }
1405 
1406 static void FPT_RNVRamData(struct nvram_info *pNvRamInfo)
1407 {
1408 	unsigned char i;
1409 	u32 portBase;
1410 	u32 regOffset;
1411 	u32 scamData;
1412 	u32 *pScamTbl;
1413 
1414 	pNvRamInfo->niModel = FPT_RdStack(pNvRamInfo->niBaseAddr, 0);
1415 	pNvRamInfo->niSysConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 1);
1416 	pNvRamInfo->niScsiConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 2);
1417 	pNvRamInfo->niScamConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 3);
1418 	pNvRamInfo->niAdapId = FPT_RdStack(pNvRamInfo->niBaseAddr, 4);
1419 
1420 	for (i = 0; i < MAX_SCSI_TAR / 2; i++)
1421 		pNvRamInfo->niSyncTbl[i] =
1422 		    FPT_RdStack(pNvRamInfo->niBaseAddr, (unsigned char)(i + 5));
1423 
1424 	portBase = pNvRamInfo->niBaseAddr;
1425 
1426 	for (i = 0; i < MAX_SCSI_TAR; i++) {
1427 		regOffset = hp_aramBase + 64 + i * 4;
1428 		RD_HARP32(portBase, regOffset, scamData);
1429 		pScamTbl = (u32 *)&pNvRamInfo->niScamTbl[i];
1430 		*pScamTbl = scamData;
1431 	}
1432 
1433 }
1434 
1435 static unsigned char FPT_RdStack(u32 portBase, unsigned char index)
1436 {
1437 	WR_HARPOON(portBase + hp_stack_addr, index);
1438 	return RD_HARPOON(portBase + hp_stack_data);
1439 }
1440 
1441 static void FPT_WrStack(u32 portBase, unsigned char index, unsigned char data)
1442 {
1443 	WR_HARPOON(portBase + hp_stack_addr, index);
1444 	WR_HARPOON(portBase + hp_stack_data, data);
1445 }
1446 
1447 static unsigned char FPT_ChkIfChipInitialized(u32 ioPort)
1448 {
1449 	if ((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != FPT_RdStack(ioPort, 4))
1450 		return 0;
1451 	if ((RD_HARPOON(ioPort + hp_clkctrl_0) & CLKCTRL_DEFAULT)
1452 	    != CLKCTRL_DEFAULT)
1453 		return 0;
1454 	if ((RD_HARPOON(ioPort + hp_seltimeout) == TO_250ms) ||
1455 	    (RD_HARPOON(ioPort + hp_seltimeout) == TO_290ms))
1456 		return 1;
1457 	return 0;
1458 
1459 }
1460 
1461 /*---------------------------------------------------------------------
1462  *
1463  * Function: FlashPoint_StartCCB
1464  *
1465  * Description: Start a command pointed to by p_Sccb. When the
1466  *              command is completed it will be returned via the
1467  *              callback function.
1468  *
1469  *---------------------------------------------------------------------*/
1470 static void FlashPoint_StartCCB(void *curr_card, struct sccb *p_Sccb)
1471 {
1472 	u32 ioport;
1473 	unsigned char thisCard, lun;
1474 	struct sccb *pSaveSccb;
1475 	CALL_BK_FN callback;
1476 	struct sccb_card *pCurrCard = curr_card;
1477 
1478 	thisCard = pCurrCard->cardIndex;
1479 	ioport = pCurrCard->ioPort;
1480 
1481 	if ((p_Sccb->TargID >= MAX_SCSI_TAR) || (p_Sccb->Lun >= MAX_LUN)) {
1482 
1483 		p_Sccb->HostStatus = SCCB_COMPLETE;
1484 		p_Sccb->SccbStatus = SCCB_ERROR;
1485 		callback = (CALL_BK_FN) p_Sccb->SccbCallback;
1486 		if (callback)
1487 			callback(p_Sccb);
1488 
1489 		return;
1490 	}
1491 
1492 	FPT_sinits(p_Sccb, thisCard);
1493 
1494 	if (!pCurrCard->cmdCounter) {
1495 		WR_HARPOON(ioport + hp_semaphore,
1496 			   (RD_HARPOON(ioport + hp_semaphore)
1497 			    | SCCB_MGR_ACTIVE));
1498 
1499 		if (pCurrCard->globalFlags & F_GREEN_PC) {
1500 			WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT);
1501 			WR_HARPOON(ioport + hp_sys_ctrl, 0x00);
1502 		}
1503 	}
1504 
1505 	pCurrCard->cmdCounter++;
1506 
1507 	if (RD_HARPOON(ioport + hp_semaphore) & BIOS_IN_USE) {
1508 
1509 		WR_HARPOON(ioport + hp_semaphore,
1510 			   (RD_HARPOON(ioport + hp_semaphore)
1511 			    | TICKLE_ME));
1512 		if (p_Sccb->OperationCode == RESET_COMMAND) {
1513 			pSaveSccb =
1514 			    pCurrCard->currentSCCB;
1515 			pCurrCard->currentSCCB = p_Sccb;
1516 			FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
1517 			pCurrCard->currentSCCB =
1518 			    pSaveSccb;
1519 		} else {
1520 			FPT_queueAddSccb(p_Sccb, thisCard);
1521 		}
1522 	}
1523 
1524 	else if ((RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) {
1525 
1526 		if (p_Sccb->OperationCode == RESET_COMMAND) {
1527 			pSaveSccb =
1528 			    pCurrCard->currentSCCB;
1529 			pCurrCard->currentSCCB = p_Sccb;
1530 			FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
1531 			pCurrCard->currentSCCB =
1532 			    pSaveSccb;
1533 		} else {
1534 			FPT_queueAddSccb(p_Sccb, thisCard);
1535 		}
1536 	}
1537 
1538 	else {
1539 
1540 		MDISABLE_INT(ioport);
1541 
1542 		if ((pCurrCard->globalFlags & F_CONLUN_IO) &&
1543 		    ((FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].
1544 		      TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
1545 			lun = p_Sccb->Lun;
1546 		else
1547 			lun = 0;
1548 		if ((pCurrCard->currentSCCB == NULL) &&
1549 		    (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarSelQ_Cnt == 0)
1550 		    && (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarLUNBusy[lun]
1551 			== 0)) {
1552 
1553 			pCurrCard->currentSCCB = p_Sccb;
1554 			FPT_ssel(p_Sccb->SccbIOPort, thisCard);
1555 		}
1556 
1557 		else {
1558 
1559 			if (p_Sccb->OperationCode == RESET_COMMAND) {
1560 				pSaveSccb = pCurrCard->currentSCCB;
1561 				pCurrCard->currentSCCB = p_Sccb;
1562 				FPT_queueSelectFail(&FPT_BL_Card[thisCard],
1563 						    thisCard);
1564 				pCurrCard->currentSCCB = pSaveSccb;
1565 			} else {
1566 				FPT_queueAddSccb(p_Sccb, thisCard);
1567 			}
1568 		}
1569 
1570 		MENABLE_INT(ioport);
1571 	}
1572 
1573 }
1574 
1575 /*---------------------------------------------------------------------
1576  *
1577  * Function: FlashPoint_AbortCCB
1578  *
1579  * Description: Abort the command pointed to by p_Sccb.  When the
1580  *              command is completed it will be returned via the
1581  *              callback function.
1582  *
1583  *---------------------------------------------------------------------*/
1584 static int FlashPoint_AbortCCB(void *pCurrCard, struct sccb *p_Sccb)
1585 {
1586 	u32 ioport;
1587 
1588 	unsigned char thisCard;
1589 	CALL_BK_FN callback;
1590 	struct sccb *pSaveSCCB;
1591 	struct sccb_mgr_tar_info *currTar_Info;
1592 
1593 	ioport = ((struct sccb_card *)pCurrCard)->ioPort;
1594 
1595 	thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
1596 
1597 	if (!(RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) {
1598 
1599 		if (FPT_queueFindSccb(p_Sccb, thisCard)) {
1600 
1601 			((struct sccb_card *)pCurrCard)->cmdCounter--;
1602 
1603 			if (!((struct sccb_card *)pCurrCard)->cmdCounter)
1604 				WR_HARPOON(ioport + hp_semaphore,
1605 					   (RD_HARPOON(ioport + hp_semaphore)
1606 					    & (unsigned
1607 					       char)(~(SCCB_MGR_ACTIVE |
1608 						       TICKLE_ME))));
1609 
1610 			p_Sccb->SccbStatus = SCCB_ABORT;
1611 			callback = p_Sccb->SccbCallback;
1612 			callback(p_Sccb);
1613 
1614 			return 0;
1615 		}
1616 
1617 		else {
1618 			if (((struct sccb_card *)pCurrCard)->currentSCCB ==
1619 			    p_Sccb) {
1620 				p_Sccb->SccbStatus = SCCB_ABORT;
1621 				return 0;
1622 
1623 			}
1624 
1625 			else {
1626 				if (p_Sccb->Sccb_tag) {
1627 					MDISABLE_INT(ioport);
1628 					if (((struct sccb_card *)pCurrCard)->
1629 					    discQ_Tbl[p_Sccb->Sccb_tag] ==
1630 					    p_Sccb) {
1631 						p_Sccb->SccbStatus = SCCB_ABORT;
1632 						p_Sccb->Sccb_scsistat =
1633 						    ABORT_ST;
1634 						p_Sccb->Sccb_scsimsg =
1635 						    ABORT_TASK;
1636 
1637 						if (((struct sccb_card *)
1638 						     pCurrCard)->currentSCCB ==
1639 						    NULL) {
1640 							((struct sccb_card *)
1641 							 pCurrCard)->
1642 					currentSCCB = p_Sccb;
1643 							FPT_ssel(ioport,
1644 								 thisCard);
1645 						} else {
1646 							pSaveSCCB =
1647 							    ((struct sccb_card
1648 							      *)pCurrCard)->
1649 							    currentSCCB;
1650 							((struct sccb_card *)
1651 							 pCurrCard)->
1652 					currentSCCB = p_Sccb;
1653 							FPT_queueSelectFail((struct sccb_card *)pCurrCard, thisCard);
1654 							((struct sccb_card *)
1655 							 pCurrCard)->
1656 					currentSCCB = pSaveSCCB;
1657 						}
1658 					}
1659 					MENABLE_INT(ioport);
1660 					return 0;
1661 				} else {
1662 					currTar_Info =
1663 					    &FPT_sccbMgrTbl[thisCard][p_Sccb->
1664 								      TargID];
1665 
1666 					if (FPT_BL_Card[thisCard].
1667 					    discQ_Tbl[currTar_Info->
1668 						      LunDiscQ_Idx[p_Sccb->Lun]]
1669 					    == p_Sccb) {
1670 						p_Sccb->SccbStatus = SCCB_ABORT;
1671 						return 0;
1672 					}
1673 				}
1674 			}
1675 		}
1676 	}
1677 	return -1;
1678 }
1679 
1680 /*---------------------------------------------------------------------
1681  *
1682  * Function: FlashPoint_InterruptPending
1683  *
1684  * Description: Do a quick check to determine if there is a pending
1685  *              interrupt for this card and disable the IRQ Pin if so.
1686  *
1687  *---------------------------------------------------------------------*/
1688 static unsigned char FlashPoint_InterruptPending(void *pCurrCard)
1689 {
1690 	u32 ioport;
1691 
1692 	ioport = ((struct sccb_card *)pCurrCard)->ioPort;
1693 
1694 	if (RD_HARPOON(ioport + hp_int_status) & INT_ASSERTED) {
1695 		return 1;
1696 	}
1697 
1698 	else
1699 
1700 		return 0;
1701 }
1702 
1703 /*---------------------------------------------------------------------
1704  *
1705  * Function: FlashPoint_HandleInterrupt
1706  *
1707  * Description: This is our entry point when an interrupt is generated
1708  *              by the card and the upper level driver passes it on to
1709  *              us.
1710  *
1711  *---------------------------------------------------------------------*/
1712 static int FlashPoint_HandleInterrupt(void *pcard)
1713 {
1714 	struct sccb *currSCCB;
1715 	unsigned char thisCard, result, bm_status;
1716 	unsigned short hp_int;
1717 	unsigned char i, target;
1718 	struct sccb_card *pCurrCard = pcard;
1719 	u32 ioport;
1720 
1721 	thisCard = pCurrCard->cardIndex;
1722 	ioport = pCurrCard->ioPort;
1723 
1724 	MDISABLE_INT(ioport);
1725 
1726 	if (RD_HARPOON(ioport + hp_int_status) & EXT_STATUS_ON)
1727 		bm_status = RD_HARPOON(ioport + hp_ext_status) &
1728 					(unsigned char)BAD_EXT_STATUS;
1729 	else
1730 		bm_status = 0;
1731 
1732 	WR_HARPOON(ioport + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
1733 
1734 	while ((hp_int = RDW_HARPOON((ioport + hp_intstat)) &
1735 				FPT_default_intena) | bm_status) {
1736 
1737 		currSCCB = pCurrCard->currentSCCB;
1738 
1739 		if (hp_int & (FIFO | TIMEOUT | RESET | SCAM_SEL) || bm_status) {
1740 			result =
1741 			    FPT_SccbMgr_bad_isr(ioport, thisCard, pCurrCard,
1742 						hp_int);
1743 			WRW_HARPOON((ioport + hp_intstat),
1744 				    (FIFO | TIMEOUT | RESET | SCAM_SEL));
1745 			bm_status = 0;
1746 
1747 			if (result) {
1748 
1749 				MENABLE_INT(ioport);
1750 				return result;
1751 			}
1752 		}
1753 
1754 		else if (hp_int & ICMD_COMP) {
1755 
1756 			if (!(hp_int & BUS_FREE)) {
1757 				/* Wait for the BusFree before starting a new command.  We
1758 				   must also check for being reselected since the BusFree
1759 				   may not show up if another device reselects us in 1.5us or
1760 				   less.  SRR Wednesday, 3/8/1995.
1761 				 */
1762 				while (!
1763 				       (RDW_HARPOON((ioport + hp_intstat)) &
1764 					(BUS_FREE | RSEL))) ;
1765 			}
1766 
1767 			if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
1768 
1769 				FPT_phaseChkFifo(ioport, thisCard);
1770 
1771 /*         WRW_HARPOON((ioport+hp_intstat),
1772             (BUS_FREE | ICMD_COMP | ITAR_DISC | XFER_CNT_0));
1773          */
1774 
1775 			WRW_HARPOON((ioport + hp_intstat), CLR_ALL_INT_1);
1776 
1777 			FPT_autoCmdCmplt(ioport, thisCard);
1778 
1779 		}
1780 
1781 		else if (hp_int & ITAR_DISC) {
1782 
1783 			if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
1784 				FPT_phaseChkFifo(ioport, thisCard);
1785 
1786 			if (RD_HARPOON(ioport + hp_gp_reg_1) ==
1787 					SAVE_POINTERS) {
1788 
1789 				WR_HARPOON(ioport + hp_gp_reg_1, 0x00);
1790 				currSCCB->Sccb_XferState |= F_NO_DATA_YET;
1791 
1792 				currSCCB->Sccb_savedATC = currSCCB->Sccb_ATC;
1793 			}
1794 
1795 			currSCCB->Sccb_scsistat = DISCONNECT_ST;
1796 			FPT_queueDisconnect(currSCCB, thisCard);
1797 
1798 			/* Wait for the BusFree before starting a new command.  We
1799 			   must also check for being reselected since the BusFree
1800 			   may not show up if another device reselects us in 1.5us or
1801 			   less.  SRR Wednesday, 3/8/1995.
1802 			 */
1803 			while (!
1804 			       (RDW_HARPOON((ioport + hp_intstat)) &
1805 				(BUS_FREE | RSEL))
1806 			       && !((RDW_HARPOON((ioport + hp_intstat)) & PHASE)
1807 				    && RD_HARPOON((ioport + hp_scsisig)) ==
1808 				    (SCSI_BSY | SCSI_REQ | SCSI_CD | SCSI_MSG |
1809 				     SCSI_IOBIT))) ;
1810 
1811 			/*
1812 			   The additional loop exit condition above detects a timing problem
1813 			   with the revision D/E harpoon chips.  The caller should reset the
1814 			   host adapter to recover when 0xFE is returned.
1815 			 */
1816 			if (!
1817 			    (RDW_HARPOON((ioport + hp_intstat)) &
1818 			     (BUS_FREE | RSEL))) {
1819 				MENABLE_INT(ioport);
1820 				return 0xFE;
1821 			}
1822 
1823 			WRW_HARPOON((ioport + hp_intstat),
1824 				    (BUS_FREE | ITAR_DISC));
1825 
1826 			pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
1827 
1828 		}
1829 
1830 		else if (hp_int & RSEL) {
1831 
1832 			WRW_HARPOON((ioport + hp_intstat),
1833 				    (PROG_HLT | RSEL | PHASE | BUS_FREE));
1834 
1835 			if (RDW_HARPOON((ioport + hp_intstat)) & ITAR_DISC) {
1836 				if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
1837 					FPT_phaseChkFifo(ioport, thisCard);
1838 
1839 				if (RD_HARPOON(ioport + hp_gp_reg_1) ==
1840 				    SAVE_POINTERS) {
1841 					WR_HARPOON(ioport + hp_gp_reg_1, 0x00);
1842 					currSCCB->Sccb_XferState |=
1843 					    F_NO_DATA_YET;
1844 					currSCCB->Sccb_savedATC =
1845 					    currSCCB->Sccb_ATC;
1846 				}
1847 
1848 				WRW_HARPOON((ioport + hp_intstat),
1849 					    (BUS_FREE | ITAR_DISC));
1850 				currSCCB->Sccb_scsistat = DISCONNECT_ST;
1851 				FPT_queueDisconnect(currSCCB, thisCard);
1852 			}
1853 
1854 			FPT_sres(ioport, thisCard, pCurrCard);
1855 			FPT_phaseDecode(ioport, thisCard);
1856 
1857 		}
1858 
1859 		else if ((hp_int & IDO_STRT) && (!(hp_int & BUS_FREE))) {
1860 
1861 			WRW_HARPOON((ioport + hp_intstat),
1862 				    (IDO_STRT | XFER_CNT_0));
1863 			FPT_phaseDecode(ioport, thisCard);
1864 
1865 		}
1866 
1867 		else if ((hp_int & IUNKWN) || (hp_int & PROG_HLT)) {
1868 			WRW_HARPOON((ioport + hp_intstat),
1869 				    (PHASE | IUNKWN | PROG_HLT));
1870 			if ((RD_HARPOON(ioport + hp_prgmcnt_0) & (unsigned char)
1871 			     0x3f) < (unsigned char)SELCHK) {
1872 				FPT_phaseDecode(ioport, thisCard);
1873 			} else {
1874 				/* Harpoon problem some SCSI target device respond to selection
1875 				   with short BUSY pulse (<400ns) this will make the Harpoon is not able
1876 				   to latch the correct Target ID into reg. x53.
1877 				   The work around require to correct this reg. But when write to this
1878 				   reg. (0x53) also increment the FIFO write addr reg (0x6f), thus we
1879 				   need to read this reg first then restore it later. After update to 0x53 */
1880 
1881 				i = (unsigned
1882 				     char)(RD_HARPOON(ioport + hp_fifowrite));
1883 				target =
1884 				    (unsigned
1885 				     char)(RD_HARPOON(ioport + hp_gp_reg_3));
1886 				WR_HARPOON(ioport + hp_xfer_pad,
1887 					   (unsigned char)ID_UNLOCK);
1888 				WR_HARPOON(ioport + hp_select_id,
1889 					   (unsigned char)(target | target <<
1890 							   4));
1891 				WR_HARPOON(ioport + hp_xfer_pad,
1892 					   (unsigned char)0x00);
1893 				WR_HARPOON(ioport + hp_fifowrite, i);
1894 				WR_HARPOON(ioport + hp_autostart_3,
1895 					   (AUTO_IMMED + TAG_STRT));
1896 			}
1897 		}
1898 
1899 		else if (hp_int & XFER_CNT_0) {
1900 
1901 			WRW_HARPOON((ioport + hp_intstat), XFER_CNT_0);
1902 
1903 			FPT_schkdd(ioport, thisCard);
1904 
1905 		}
1906 
1907 		else if (hp_int & BUS_FREE) {
1908 
1909 			WRW_HARPOON((ioport + hp_intstat), BUS_FREE);
1910 
1911 			if (pCurrCard->globalFlags & F_HOST_XFER_ACT) {
1912 
1913 				FPT_hostDataXferAbort(ioport, thisCard,
1914 						      currSCCB);
1915 			}
1916 
1917 			FPT_phaseBusFree(ioport, thisCard);
1918 		}
1919 
1920 		else if (hp_int & ITICKLE) {
1921 
1922 			WRW_HARPOON((ioport + hp_intstat), ITICKLE);
1923 			pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
1924 		}
1925 
1926 		if (((struct sccb_card *)pCurrCard)->
1927 		    globalFlags & F_NEW_SCCB_CMD) {
1928 
1929 			pCurrCard->globalFlags &= ~F_NEW_SCCB_CMD;
1930 
1931 			if (pCurrCard->currentSCCB == NULL)
1932 				FPT_queueSearchSelect(pCurrCard, thisCard);
1933 
1934 			if (pCurrCard->currentSCCB != NULL) {
1935 				pCurrCard->globalFlags &= ~F_NEW_SCCB_CMD;
1936 				FPT_ssel(ioport, thisCard);
1937 			}
1938 
1939 			break;
1940 
1941 		}
1942 
1943 	}			/*end while */
1944 
1945 	MENABLE_INT(ioport);
1946 
1947 	return 0;
1948 }
1949 
1950 /*---------------------------------------------------------------------
1951  *
1952  * Function: Sccb_bad_isr
1953  *
1954  * Description: Some type of interrupt has occurred which is slightly
1955  *              out of the ordinary.  We will now decode it fully, in
1956  *              this routine.  This is broken up in an attempt to save
1957  *              processing time.
1958  *
1959  *---------------------------------------------------------------------*/
1960 static unsigned char FPT_SccbMgr_bad_isr(u32 p_port, unsigned char p_card,
1961 					 struct sccb_card *pCurrCard,
1962 					 unsigned short p_int)
1963 {
1964 	unsigned char temp, ScamFlg;
1965 	struct sccb_mgr_tar_info *currTar_Info;
1966 	struct nvram_info *pCurrNvRam;
1967 
1968 	if (RD_HARPOON(p_port + hp_ext_status) &
1969 	    (BM_FORCE_OFF | PCI_DEV_TMOUT | BM_PARITY_ERR | PIO_OVERRUN)) {
1970 
1971 		if (pCurrCard->globalFlags & F_HOST_XFER_ACT) {
1972 
1973 			FPT_hostDataXferAbort(p_port, p_card,
1974 					      pCurrCard->currentSCCB);
1975 		}
1976 
1977 		if (RD_HARPOON(p_port + hp_pci_stat_cfg) & REC_MASTER_ABORT)
1978 		{
1979 			WR_HARPOON(p_port + hp_pci_stat_cfg,
1980 				   (RD_HARPOON(p_port + hp_pci_stat_cfg) &
1981 				    ~REC_MASTER_ABORT));
1982 
1983 			WR_HARPOON(p_port + hp_host_blk_cnt, 0x00);
1984 
1985 		}
1986 
1987 		if (pCurrCard->currentSCCB != NULL) {
1988 
1989 			if (!pCurrCard->currentSCCB->HostStatus)
1990 				pCurrCard->currentSCCB->HostStatus =
1991 				    SCCB_BM_ERR;
1992 
1993 			FPT_sxfrp(p_port, p_card);
1994 
1995 			temp = (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
1996 					       (EXT_ARB_ACK | SCSI_TERM_ENA_H));
1997 			WR_HARPOON(p_port + hp_ee_ctrl,
1998 				   ((unsigned char)temp | SEE_MS | SEE_CS));
1999 			WR_HARPOON(p_port + hp_ee_ctrl, temp);
2000 
2001 			if (!
2002 			    (RDW_HARPOON((p_port + hp_intstat)) &
2003 			     (BUS_FREE | RESET))) {
2004 				FPT_phaseDecode(p_port, p_card);
2005 			}
2006 		}
2007 	}
2008 
2009 	else if (p_int & RESET) {
2010 
2011 		WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
2012 		WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
2013 		if (pCurrCard->currentSCCB != NULL) {
2014 
2015 			if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
2016 
2017 				FPT_hostDataXferAbort(p_port, p_card,
2018 						      pCurrCard->currentSCCB);
2019 		}
2020 
2021 		DISABLE_AUTO(p_port);
2022 
2023 		FPT_sresb(p_port, p_card);
2024 
2025 		while (RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST) {
2026 		}
2027 
2028 		pCurrNvRam = pCurrCard->pNvRamInfo;
2029 		if (pCurrNvRam) {
2030 			ScamFlg = pCurrNvRam->niScamConf;
2031 		} else {
2032 			ScamFlg =
2033 			    (unsigned char)FPT_utilEERead(p_port,
2034 							  SCAM_CONFIG / 2);
2035 		}
2036 
2037 		FPT_XbowInit(p_port, ScamFlg);
2038 
2039 		FPT_scini(p_card, pCurrCard->ourId, 0);
2040 
2041 		return 0xFF;
2042 	}
2043 
2044 	else if (p_int & FIFO) {
2045 
2046 		WRW_HARPOON((p_port + hp_intstat), FIFO);
2047 
2048 		if (pCurrCard->currentSCCB != NULL)
2049 			FPT_sxfrp(p_port, p_card);
2050 	}
2051 
2052 	else if (p_int & TIMEOUT) {
2053 
2054 		DISABLE_AUTO(p_port);
2055 
2056 		WRW_HARPOON((p_port + hp_intstat),
2057 			    (PROG_HLT | TIMEOUT | SEL | BUS_FREE | PHASE |
2058 			     IUNKWN));
2059 
2060 		pCurrCard->currentSCCB->HostStatus = SCCB_SELECTION_TIMEOUT;
2061 
2062 		currTar_Info =
2063 		    &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
2064 		if ((pCurrCard->globalFlags & F_CONLUN_IO)
2065 		    && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
2066 			TAG_Q_TRYING))
2067 			currTar_Info->TarLUNBusy[pCurrCard->currentSCCB->Lun] =
2068 			    0;
2069 		else
2070 			currTar_Info->TarLUNBusy[0] = 0;
2071 
2072 		if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
2073 			currTar_Info->TarSyncCtrl = 0;
2074 			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2075 		}
2076 
2077 		if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
2078 			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2079 		}
2080 
2081 		FPT_sssyncv(p_port, pCurrCard->currentSCCB->TargID, NARROW_SCSI,
2082 			    currTar_Info);
2083 
2084 		FPT_queueCmdComplete(pCurrCard, pCurrCard->currentSCCB, p_card);
2085 
2086 	}
2087 
2088 	else if (p_int & SCAM_SEL) {
2089 
2090 		FPT_scarb(p_port, LEVEL2_TAR);
2091 		FPT_scsel(p_port);
2092 		FPT_scasid(p_card, p_port);
2093 
2094 		FPT_scbusf(p_port);
2095 
2096 		WRW_HARPOON((p_port + hp_intstat), SCAM_SEL);
2097 	}
2098 
2099 	return 0x00;
2100 }
2101 
2102 /*---------------------------------------------------------------------
2103  *
2104  * Function: SccbMgrTableInit
2105  *
2106  * Description: Initialize all Sccb manager data structures.
2107  *
2108  *---------------------------------------------------------------------*/
2109 
2110 static void FPT_SccbMgrTableInitAll(void)
2111 {
2112 	unsigned char thisCard;
2113 
2114 	for (thisCard = 0; thisCard < MAX_CARDS; thisCard++) {
2115 		FPT_SccbMgrTableInitCard(&FPT_BL_Card[thisCard], thisCard);
2116 
2117 		FPT_BL_Card[thisCard].ioPort = 0x00;
2118 		FPT_BL_Card[thisCard].cardInfo = NULL;
2119 		FPT_BL_Card[thisCard].cardIndex = 0xFF;
2120 		FPT_BL_Card[thisCard].ourId = 0x00;
2121 		FPT_BL_Card[thisCard].pNvRamInfo = NULL;
2122 	}
2123 }
2124 
2125 /*---------------------------------------------------------------------
2126  *
2127  * Function: SccbMgrTableInit
2128  *
2129  * Description: Initialize all Sccb manager data structures.
2130  *
2131  *---------------------------------------------------------------------*/
2132 
2133 static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard,
2134 				     unsigned char p_card)
2135 {
2136 	unsigned char scsiID, qtag;
2137 
2138 	for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
2139 		FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
2140 	}
2141 
2142 	for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
2143 		FPT_sccbMgrTbl[p_card][scsiID].TarStatus = 0;
2144 		FPT_sccbMgrTbl[p_card][scsiID].TarEEValue = 0;
2145 		FPT_SccbMgrTableInitTarget(p_card, scsiID);
2146 	}
2147 
2148 	pCurrCard->scanIndex = 0x00;
2149 	pCurrCard->currentSCCB = NULL;
2150 	pCurrCard->globalFlags = 0x00;
2151 	pCurrCard->cmdCounter = 0x00;
2152 	pCurrCard->tagQ_Lst = 0x01;
2153 	pCurrCard->discQCount = 0;
2154 
2155 }
2156 
2157 /*---------------------------------------------------------------------
2158  *
2159  * Function: SccbMgrTableInit
2160  *
2161  * Description: Initialize all Sccb manager data structures.
2162  *
2163  *---------------------------------------------------------------------*/
2164 
2165 static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
2166 				       unsigned char target)
2167 {
2168 
2169 	unsigned char lun, qtag;
2170 	struct sccb_mgr_tar_info *currTar_Info;
2171 
2172 	currTar_Info = &FPT_sccbMgrTbl[p_card][target];
2173 
2174 	currTar_Info->TarSelQ_Cnt = 0;
2175 	currTar_Info->TarSyncCtrl = 0;
2176 
2177 	currTar_Info->TarSelQ_Head = NULL;
2178 	currTar_Info->TarSelQ_Tail = NULL;
2179 	currTar_Info->TarTagQ_Cnt = 0;
2180 	currTar_Info->TarLUN_CA = 0;
2181 
2182 	for (lun = 0; lun < MAX_LUN; lun++) {
2183 		currTar_Info->TarLUNBusy[lun] = 0;
2184 		currTar_Info->LunDiscQ_Idx[lun] = 0;
2185 	}
2186 
2187 	for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
2188 		if (FPT_BL_Card[p_card].discQ_Tbl[qtag] != NULL) {
2189 			if (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
2190 			    target) {
2191 				FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
2192 				FPT_BL_Card[p_card].discQCount--;
2193 			}
2194 		}
2195 	}
2196 }
2197 
2198 /*---------------------------------------------------------------------
2199  *
2200  * Function: sfetm
2201  *
2202  * Description: Read in a message byte from the SCSI bus, and check
2203  *              for a parity error.
2204  *
2205  *---------------------------------------------------------------------*/
2206 
2207 static unsigned char FPT_sfm(u32 port, struct sccb *pCurrSCCB)
2208 {
2209 	unsigned char message;
2210 	unsigned short TimeOutLoop;
2211 
2212 	TimeOutLoop = 0;
2213 	while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2214 	       (TimeOutLoop++ < 20000)) {
2215 	}
2216 
2217 	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
2218 
2219 	message = RD_HARPOON(port + hp_scsidata_0);
2220 
2221 	WR_HARPOON(port + hp_scsisig, SCSI_ACK + S_MSGI_PH);
2222 
2223 	if (TimeOutLoop > 20000)
2224 		message = 0x00;	/* force message byte = 0 if Time Out on Req */
2225 
2226 	if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
2227 	    (RD_HARPOON(port + hp_addstat) & SCSI_PAR_ERR)) {
2228 		WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2229 		WR_HARPOON(port + hp_xferstat, 0);
2230 		WR_HARPOON(port + hp_fiforead, 0);
2231 		WR_HARPOON(port + hp_fifowrite, 0);
2232 		if (pCurrSCCB != NULL) {
2233 			pCurrSCCB->Sccb_scsimsg = MSG_PARITY_ERROR;
2234 		}
2235 		message = 0x00;
2236 		do {
2237 			ACCEPT_MSG_ATN(port);
2238 			TimeOutLoop = 0;
2239 			while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2240 			       (TimeOutLoop++ < 20000)) {
2241 			}
2242 			if (TimeOutLoop > 20000) {
2243 				WRW_HARPOON((port + hp_intstat), PARITY);
2244 				return message;
2245 			}
2246 			if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) !=
2247 			    S_MSGI_PH) {
2248 				WRW_HARPOON((port + hp_intstat), PARITY);
2249 				return message;
2250 			}
2251 			WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
2252 
2253 			RD_HARPOON(port + hp_scsidata_0);
2254 
2255 			WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2256 
2257 		} while (1);
2258 
2259 	}
2260 	WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2261 	WR_HARPOON(port + hp_xferstat, 0);
2262 	WR_HARPOON(port + hp_fiforead, 0);
2263 	WR_HARPOON(port + hp_fifowrite, 0);
2264 	return message;
2265 }
2266 
2267 /*---------------------------------------------------------------------
2268  *
2269  * Function: FPT_ssel
2270  *
2271  * Description: Load up automation and select target device.
2272  *
2273  *---------------------------------------------------------------------*/
2274 
2275 static void FPT_ssel(u32 port, unsigned char p_card)
2276 {
2277 
2278 	unsigned char auto_loaded, i, target, *theCCB;
2279 
2280 	u32 cdb_reg;
2281 	struct sccb_card *CurrCard;
2282 	struct sccb *currSCCB;
2283 	struct sccb_mgr_tar_info *currTar_Info;
2284 	unsigned char lastTag, lun;
2285 
2286 	CurrCard = &FPT_BL_Card[p_card];
2287 	currSCCB = CurrCard->currentSCCB;
2288 	target = currSCCB->TargID;
2289 	currTar_Info = &FPT_sccbMgrTbl[p_card][target];
2290 	lastTag = CurrCard->tagQ_Lst;
2291 
2292 	ARAM_ACCESS(port);
2293 
2294 	if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
2295 		currSCCB->ControlByte &= ~F_USE_CMD_Q;
2296 
2297 	if (((CurrCard->globalFlags & F_CONLUN_IO) &&
2298 	     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
2299 
2300 		lun = currSCCB->Lun;
2301 	else
2302 		lun = 0;
2303 
2304 	if (CurrCard->globalFlags & F_TAG_STARTED) {
2305 		if (!(currSCCB->ControlByte & F_USE_CMD_Q)) {
2306 			if ((currTar_Info->TarLUN_CA == 0)
2307 			    && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
2308 				== TAG_Q_TRYING)) {
2309 
2310 				if (currTar_Info->TarTagQ_Cnt != 0) {
2311 					currTar_Info->TarLUNBusy[lun] = 1;
2312 					FPT_queueSelectFail(CurrCard, p_card);
2313 					SGRAM_ACCESS(port);
2314 					return;
2315 				}
2316 
2317 				else {
2318 					currTar_Info->TarLUNBusy[lun] = 1;
2319 				}
2320 
2321 			}
2322 			/*End non-tagged */
2323 			else {
2324 				currTar_Info->TarLUNBusy[lun] = 1;
2325 			}
2326 
2327 		}
2328 		/*!Use cmd Q Tagged */
2329 		else {
2330 			if (currTar_Info->TarLUN_CA == 1) {
2331 				FPT_queueSelectFail(CurrCard, p_card);
2332 				SGRAM_ACCESS(port);
2333 				return;
2334 			}
2335 
2336 			currTar_Info->TarLUNBusy[lun] = 1;
2337 
2338 		}		/*else use cmd Q tagged */
2339 
2340 	}
2341 	/*if glob tagged started */
2342 	else {
2343 		currTar_Info->TarLUNBusy[lun] = 1;
2344 	}
2345 
2346 	if ((((CurrCard->globalFlags & F_CONLUN_IO) &&
2347 	      ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
2348 	     || (!(currSCCB->ControlByte & F_USE_CMD_Q)))) {
2349 		if (CurrCard->discQCount >= QUEUE_DEPTH) {
2350 			currTar_Info->TarLUNBusy[lun] = 1;
2351 			FPT_queueSelectFail(CurrCard, p_card);
2352 			SGRAM_ACCESS(port);
2353 			return;
2354 		}
2355 		for (i = 1; i < QUEUE_DEPTH; i++) {
2356 			if (++lastTag >= QUEUE_DEPTH)
2357 				lastTag = 1;
2358 			if (CurrCard->discQ_Tbl[lastTag] == NULL) {
2359 				CurrCard->tagQ_Lst = lastTag;
2360 				currTar_Info->LunDiscQ_Idx[lun] = lastTag;
2361 				CurrCard->discQ_Tbl[lastTag] = currSCCB;
2362 				CurrCard->discQCount++;
2363 				break;
2364 			}
2365 		}
2366 		if (i == QUEUE_DEPTH) {
2367 			currTar_Info->TarLUNBusy[lun] = 1;
2368 			FPT_queueSelectFail(CurrCard, p_card);
2369 			SGRAM_ACCESS(port);
2370 			return;
2371 		}
2372 	}
2373 
2374 	auto_loaded = 0;
2375 
2376 	WR_HARPOON(port + hp_select_id, target);
2377 	WR_HARPOON(port + hp_gp_reg_3, target);	/* Use by new automation logic */
2378 
2379 	if (currSCCB->OperationCode == RESET_COMMAND) {
2380 		WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
2381 						   (currSCCB->
2382 						    Sccb_idmsg & ~DISC_PRIV)));
2383 
2384 		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + NP);
2385 
2386 		currSCCB->Sccb_scsimsg = TARGET_RESET;
2387 
2388 		WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
2389 		auto_loaded = 1;
2390 		currSCCB->Sccb_scsistat = SELECT_BDR_ST;
2391 
2392 		if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
2393 			currTar_Info->TarSyncCtrl = 0;
2394 			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2395 		}
2396 
2397 		if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
2398 			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2399 		}
2400 
2401 		FPT_sssyncv(port, target, NARROW_SCSI, currTar_Info);
2402 		FPT_SccbMgrTableInitTarget(p_card, target);
2403 
2404 	}
2405 
2406 	else if (currSCCB->Sccb_scsistat == ABORT_ST) {
2407 		WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
2408 						   (currSCCB->
2409 						    Sccb_idmsg & ~DISC_PRIV)));
2410 
2411 		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
2412 
2413 		WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT +
2414 						     (((unsigned
2415 							char)(currSCCB->
2416 							      ControlByte &
2417 							      TAG_TYPE_MASK)
2418 						       >> 6) | (unsigned char)
2419 						      0x20)));
2420 		WRW_HARPOON((port + SYNC_MSGS + 2),
2421 			    (MPM_OP + AMSG_OUT + currSCCB->Sccb_tag));
2422 		WRW_HARPOON((port + SYNC_MSGS + 4), (BRH_OP + ALWAYS + NP));
2423 
2424 		WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
2425 		auto_loaded = 1;
2426 
2427 	}
2428 
2429 	else if (!(currTar_Info->TarStatus & WIDE_NEGOCIATED)) {
2430 		auto_loaded = FPT_siwidn(port, p_card);
2431 		currSCCB->Sccb_scsistat = SELECT_WN_ST;
2432 	}
2433 
2434 	else if (!((currTar_Info->TarStatus & TAR_SYNC_MASK)
2435 		   == SYNC_SUPPORTED)) {
2436 		auto_loaded = FPT_sisyncn(port, p_card, 0);
2437 		currSCCB->Sccb_scsistat = SELECT_SN_ST;
2438 	}
2439 
2440 	if (!auto_loaded) {
2441 
2442 		if (currSCCB->ControlByte & F_USE_CMD_Q) {
2443 
2444 			CurrCard->globalFlags |= F_TAG_STARTED;
2445 
2446 			if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
2447 			    == TAG_Q_REJECT) {
2448 				currSCCB->ControlByte &= ~F_USE_CMD_Q;
2449 
2450 				/* Fix up the start instruction with a jump to
2451 				   Non-Tag-CMD handling */
2452 				WRW_HARPOON((port + ID_MSG_STRT),
2453 					    BRH_OP + ALWAYS + NTCMD);
2454 
2455 				WRW_HARPOON((port + NON_TAG_ID_MSG),
2456 					    (MPM_OP + AMSG_OUT +
2457 					     currSCCB->Sccb_idmsg));
2458 
2459 				WR_HARPOON(port + hp_autostart_3,
2460 					   (SELECT + SELCHK_STRT));
2461 
2462 				/* Setup our STATE so we know what happened when
2463 				   the wheels fall off. */
2464 				currSCCB->Sccb_scsistat = SELECT_ST;
2465 
2466 				currTar_Info->TarLUNBusy[lun] = 1;
2467 			}
2468 
2469 			else {
2470 				WRW_HARPOON((port + ID_MSG_STRT),
2471 					    (MPM_OP + AMSG_OUT +
2472 					     currSCCB->Sccb_idmsg));
2473 
2474 				WRW_HARPOON((port + ID_MSG_STRT + 2),
2475 					    (MPM_OP + AMSG_OUT +
2476 					     (((unsigned char)(currSCCB->
2477 							       ControlByte &
2478 							       TAG_TYPE_MASK)
2479 					       >> 6) | (unsigned char)0x20)));
2480 
2481 				for (i = 1; i < QUEUE_DEPTH; i++) {
2482 					if (++lastTag >= QUEUE_DEPTH)
2483 						lastTag = 1;
2484 					if (CurrCard->discQ_Tbl[lastTag] ==
2485 					    NULL) {
2486 						WRW_HARPOON((port +
2487 							     ID_MSG_STRT + 6),
2488 							    (MPM_OP + AMSG_OUT +
2489 							     lastTag));
2490 						CurrCard->tagQ_Lst = lastTag;
2491 						currSCCB->Sccb_tag = lastTag;
2492 						CurrCard->discQ_Tbl[lastTag] =
2493 						    currSCCB;
2494 						CurrCard->discQCount++;
2495 						break;
2496 					}
2497 				}
2498 
2499 				if (i == QUEUE_DEPTH) {
2500 					currTar_Info->TarLUNBusy[lun] = 1;
2501 					FPT_queueSelectFail(CurrCard, p_card);
2502 					SGRAM_ACCESS(port);
2503 					return;
2504 				}
2505 
2506 				currSCCB->Sccb_scsistat = SELECT_Q_ST;
2507 
2508 				WR_HARPOON(port + hp_autostart_3,
2509 					   (SELECT + SELCHK_STRT));
2510 			}
2511 		}
2512 
2513 		else {
2514 
2515 			WRW_HARPOON((port + ID_MSG_STRT),
2516 				    BRH_OP + ALWAYS + NTCMD);
2517 
2518 			WRW_HARPOON((port + NON_TAG_ID_MSG),
2519 				    (MPM_OP + AMSG_OUT + currSCCB->Sccb_idmsg));
2520 
2521 			currSCCB->Sccb_scsistat = SELECT_ST;
2522 
2523 			WR_HARPOON(port + hp_autostart_3,
2524 				   (SELECT + SELCHK_STRT));
2525 		}
2526 
2527 		theCCB = (unsigned char *)&currSCCB->Cdb[0];
2528 
2529 		cdb_reg = port + CMD_STRT;
2530 
2531 		for (i = 0; i < currSCCB->CdbLength; i++) {
2532 			WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + *theCCB));
2533 			cdb_reg += 2;
2534 			theCCB++;
2535 		}
2536 
2537 		if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
2538 			WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
2539 
2540 	}
2541 	/* auto_loaded */
2542 	WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
2543 	WR_HARPOON(port + hp_xferstat, 0x00);
2544 
2545 	WRW_HARPOON((port + hp_intstat), (PROG_HLT | TIMEOUT | SEL | BUS_FREE));
2546 
2547 	WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT));
2548 
2549 	if (!(currSCCB->Sccb_MGRFlags & F_DEV_SELECTED)) {
2550 		WR_HARPOON(port + hp_scsictrl_0,
2551 			   (SEL_TAR | ENA_ATN | ENA_RESEL | ENA_SCAM_SEL));
2552 	} else {
2553 
2554 /*      auto_loaded =  (RD_HARPOON(port+hp_autostart_3) & (unsigned char)0x1F);
2555       auto_loaded |= AUTO_IMMED; */
2556 		auto_loaded = AUTO_IMMED;
2557 
2558 		DISABLE_AUTO(port);
2559 
2560 		WR_HARPOON(port + hp_autostart_3, auto_loaded);
2561 	}
2562 
2563 	SGRAM_ACCESS(port);
2564 }
2565 
2566 /*---------------------------------------------------------------------
2567  *
2568  * Function: FPT_sres
2569  *
2570  * Description: Hookup the correct CCB and handle the incoming messages.
2571  *
2572  *---------------------------------------------------------------------*/
2573 
2574 static void FPT_sres(u32 port, unsigned char p_card,
2575 		     struct sccb_card *pCurrCard)
2576 {
2577 
2578 	unsigned char our_target, message, lun = 0, tag, msgRetryCount;
2579 
2580 	struct sccb_mgr_tar_info *currTar_Info;
2581 	struct sccb *currSCCB;
2582 
2583 	if (pCurrCard->currentSCCB != NULL) {
2584 		currTar_Info =
2585 		    &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
2586 		DISABLE_AUTO(port);
2587 
2588 		WR_HARPOON((port + hp_scsictrl_0), (ENA_RESEL | ENA_SCAM_SEL));
2589 
2590 		currSCCB = pCurrCard->currentSCCB;
2591 		if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
2592 			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2593 			currSCCB->Sccb_scsistat = BUS_FREE_ST;
2594 		}
2595 		if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
2596 			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2597 			currSCCB->Sccb_scsistat = BUS_FREE_ST;
2598 		}
2599 		if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
2600 		     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
2601 		      TAG_Q_TRYING))) {
2602 			currTar_Info->TarLUNBusy[currSCCB->Lun] = 0;
2603 			if (currSCCB->Sccb_scsistat != ABORT_ST) {
2604 				pCurrCard->discQCount--;
2605 				pCurrCard->discQ_Tbl[currTar_Info->
2606 						     LunDiscQ_Idx[currSCCB->
2607 								  Lun]]
2608 				    = NULL;
2609 			}
2610 		} else {
2611 			currTar_Info->TarLUNBusy[0] = 0;
2612 			if (currSCCB->Sccb_tag) {
2613 				if (currSCCB->Sccb_scsistat != ABORT_ST) {
2614 					pCurrCard->discQCount--;
2615 					pCurrCard->discQ_Tbl[currSCCB->
2616 							     Sccb_tag] = NULL;
2617 				}
2618 			} else {
2619 				if (currSCCB->Sccb_scsistat != ABORT_ST) {
2620 					pCurrCard->discQCount--;
2621 					pCurrCard->discQ_Tbl[currTar_Info->
2622 							     LunDiscQ_Idx[0]] =
2623 					    NULL;
2624 				}
2625 			}
2626 		}
2627 
2628 		FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
2629 	}
2630 
2631 	WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
2632 
2633 	our_target = (unsigned char)(RD_HARPOON(port + hp_select_id) >> 4);
2634 	currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
2635 
2636 	msgRetryCount = 0;
2637 	do {
2638 
2639 		currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
2640 		tag = 0;
2641 
2642 		while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
2643 			if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
2644 
2645 				WRW_HARPOON((port + hp_intstat), PHASE);
2646 				return;
2647 			}
2648 		}
2649 
2650 		WRW_HARPOON((port + hp_intstat), PHASE);
2651 		if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH) {
2652 
2653 			message = FPT_sfm(port, pCurrCard->currentSCCB);
2654 			if (message) {
2655 
2656 				if (message <= (0x80 | LUN_MASK)) {
2657 					lun = message & (unsigned char)LUN_MASK;
2658 
2659 					if ((currTar_Info->
2660 					     TarStatus & TAR_TAG_Q_MASK) ==
2661 					    TAG_Q_TRYING) {
2662 						if (currTar_Info->TarTagQ_Cnt !=
2663 						    0) {
2664 
2665 							if (!
2666 							    (currTar_Info->
2667 							     TarLUN_CA)) {
2668 								ACCEPT_MSG(port);	/*Release the ACK for ID msg. */
2669 
2670 								message =
2671 								    FPT_sfm
2672 								    (port,
2673 								     pCurrCard->
2674 								     currentSCCB);
2675 								if (message) {
2676 									ACCEPT_MSG
2677 									    (port);
2678 								}
2679 
2680 								else
2681 									message
2682 									    = 0;
2683 
2684 								if (message !=
2685 								    0) {
2686 									tag =
2687 									    FPT_sfm
2688 									    (port,
2689 									     pCurrCard->
2690 									     currentSCCB);
2691 
2692 									if (!
2693 									    (tag))
2694 										message
2695 										    =
2696 										    0;
2697 								}
2698 
2699 							}
2700 							/*C.A. exists! */
2701 						}
2702 						/*End Q cnt != 0 */
2703 					}
2704 					/*End Tag cmds supported! */
2705 				}
2706 				/*End valid ID message.  */
2707 				else {
2708 
2709 					ACCEPT_MSG_ATN(port);
2710 				}
2711 
2712 			}
2713 			/* End good id message. */
2714 			else {
2715 
2716 				message = 0;
2717 			}
2718 		} else {
2719 			ACCEPT_MSG_ATN(port);
2720 
2721 			while (!
2722 			       (RDW_HARPOON((port + hp_intstat)) &
2723 				(PHASE | RESET))
2724 			       && !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
2725 			       && (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
2726 
2727 			return;
2728 		}
2729 
2730 		if (message == 0) {
2731 			msgRetryCount++;
2732 			if (msgRetryCount == 1) {
2733 				FPT_SendMsg(port, MSG_PARITY_ERROR);
2734 			} else {
2735 				FPT_SendMsg(port, TARGET_RESET);
2736 
2737 				FPT_sssyncv(port, our_target, NARROW_SCSI,
2738 					    currTar_Info);
2739 
2740 				if (FPT_sccbMgrTbl[p_card][our_target].
2741 				    TarEEValue & EE_SYNC_MASK) {
2742 
2743 					FPT_sccbMgrTbl[p_card][our_target].
2744 					    TarStatus &= ~TAR_SYNC_MASK;
2745 
2746 				}
2747 
2748 				if (FPT_sccbMgrTbl[p_card][our_target].
2749 				    TarEEValue & EE_WIDE_SCSI) {
2750 
2751 					FPT_sccbMgrTbl[p_card][our_target].
2752 					    TarStatus &= ~TAR_WIDE_MASK;
2753 				}
2754 
2755 				FPT_queueFlushTargSccb(p_card, our_target,
2756 						       SCCB_COMPLETE);
2757 				FPT_SccbMgrTableInitTarget(p_card, our_target);
2758 				return;
2759 			}
2760 		}
2761 	} while (message == 0);
2762 
2763 	if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
2764 	     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
2765 		currTar_Info->TarLUNBusy[lun] = 1;
2766 		pCurrCard->currentSCCB =
2767 		    pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[lun]];
2768 		if (pCurrCard->currentSCCB != NULL) {
2769 			ACCEPT_MSG(port);
2770 		} else {
2771 			ACCEPT_MSG_ATN(port);
2772 		}
2773 	} else {
2774 		currTar_Info->TarLUNBusy[0] = 1;
2775 
2776 		if (tag) {
2777 			if (pCurrCard->discQ_Tbl[tag] != NULL) {
2778 				pCurrCard->currentSCCB =
2779 				    pCurrCard->discQ_Tbl[tag];
2780 				currTar_Info->TarTagQ_Cnt--;
2781 				ACCEPT_MSG(port);
2782 			} else {
2783 				ACCEPT_MSG_ATN(port);
2784 			}
2785 		} else {
2786 			pCurrCard->currentSCCB =
2787 			    pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]];
2788 			if (pCurrCard->currentSCCB != NULL) {
2789 				ACCEPT_MSG(port);
2790 			} else {
2791 				ACCEPT_MSG_ATN(port);
2792 			}
2793 		}
2794 	}
2795 
2796 	if (pCurrCard->currentSCCB != NULL) {
2797 		if (pCurrCard->currentSCCB->Sccb_scsistat == ABORT_ST) {
2798 			/* During Abort Tag command, the target could have got re-selected
2799 			   and completed the command. Check the select Q and remove the CCB
2800 			   if it is in the Select Q */
2801 			FPT_queueFindSccb(pCurrCard->currentSCCB, p_card);
2802 		}
2803 	}
2804 
2805 	while (!(RDW_HARPOON((port + hp_intstat)) & (PHASE | RESET)) &&
2806 	       !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ) &&
2807 	       (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
2808 }
2809 
2810 static void FPT_SendMsg(u32 port, unsigned char message)
2811 {
2812 	while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
2813 		if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
2814 
2815 			WRW_HARPOON((port + hp_intstat), PHASE);
2816 			return;
2817 		}
2818 	}
2819 
2820 	WRW_HARPOON((port + hp_intstat), PHASE);
2821 	if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGO_PH) {
2822 		WRW_HARPOON((port + hp_intstat),
2823 			    (BUS_FREE | PHASE | XFER_CNT_0));
2824 
2825 		WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
2826 
2827 		WR_HARPOON(port + hp_scsidata_0, message);
2828 
2829 		WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2830 
2831 		ACCEPT_MSG(port);
2832 
2833 		WR_HARPOON(port + hp_portctrl_0, 0x00);
2834 
2835 		if ((message == ABORT_TASK_SET) || (message == TARGET_RESET) ||
2836 		    (message == ABORT_TASK)) {
2837 			while (!
2838 			       (RDW_HARPOON((port + hp_intstat)) &
2839 				(BUS_FREE | PHASE))) {
2840 			}
2841 
2842 			if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
2843 				WRW_HARPOON((port + hp_intstat), BUS_FREE);
2844 			}
2845 		}
2846 	}
2847 }
2848 
2849 /*---------------------------------------------------------------------
2850  *
2851  * Function: FPT_sdecm
2852  *
2853  * Description: Determine the proper response to the message from the
2854  *              target device.
2855  *
2856  *---------------------------------------------------------------------*/
2857 static void FPT_sdecm(unsigned char message, u32 port, unsigned char p_card)
2858 {
2859 	struct sccb *currSCCB;
2860 	struct sccb_card *CurrCard;
2861 	struct sccb_mgr_tar_info *currTar_Info;
2862 
2863 	CurrCard = &FPT_BL_Card[p_card];
2864 	currSCCB = CurrCard->currentSCCB;
2865 
2866 	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
2867 
2868 	if (message == RESTORE_POINTERS) {
2869 		if (!(currSCCB->Sccb_XferState & F_NO_DATA_YET)) {
2870 			currSCCB->Sccb_ATC = currSCCB->Sccb_savedATC;
2871 
2872 			FPT_hostDataXferRestart(currSCCB);
2873 		}
2874 
2875 		ACCEPT_MSG(port);
2876 		WR_HARPOON(port + hp_autostart_1,
2877 			   (AUTO_IMMED + DISCONNECT_START));
2878 	}
2879 
2880 	else if (message == COMMAND_COMPLETE) {
2881 
2882 		if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
2883 			currTar_Info->TarStatus &=
2884 			    ~(unsigned char)TAR_TAG_Q_MASK;
2885 			currTar_Info->TarStatus |= (unsigned char)TAG_Q_REJECT;
2886 		}
2887 
2888 		ACCEPT_MSG(port);
2889 
2890 	}
2891 
2892 	else if ((message == NOP) || (message >= IDENTIFY_BASE) ||
2893 		 (message == INITIATE_RECOVERY) ||
2894 		 (message == RELEASE_RECOVERY)) {
2895 
2896 		ACCEPT_MSG(port);
2897 		WR_HARPOON(port + hp_autostart_1,
2898 			   (AUTO_IMMED + DISCONNECT_START));
2899 	}
2900 
2901 	else if (message == MESSAGE_REJECT) {
2902 
2903 		if ((currSCCB->Sccb_scsistat == SELECT_SN_ST) ||
2904 		    (currSCCB->Sccb_scsistat == SELECT_WN_ST) ||
2905 		    ((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)
2906 		    || ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) ==
2907 			TAG_Q_TRYING))
2908 		{
2909 			WRW_HARPOON((port + hp_intstat), BUS_FREE);
2910 
2911 			ACCEPT_MSG(port);
2912 
2913 			while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2914 			       (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
2915 			{
2916 			}
2917 
2918 			if (currSCCB->Lun == 0x00) {
2919 				if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
2920 
2921 					currTar_Info->TarStatus |=
2922 					    (unsigned char)SYNC_SUPPORTED;
2923 
2924 					currTar_Info->TarEEValue &=
2925 					    ~EE_SYNC_MASK;
2926 				}
2927 
2928 				else if (currSCCB->Sccb_scsistat ==
2929 					  SELECT_WN_ST) {
2930 
2931 					currTar_Info->TarStatus =
2932 					    (currTar_Info->
2933 					     TarStatus & ~WIDE_ENABLED) |
2934 					    WIDE_NEGOCIATED;
2935 
2936 					currTar_Info->TarEEValue &=
2937 					    ~EE_WIDE_SCSI;
2938 
2939 				}
2940 
2941 				else if ((currTar_Info->
2942 					  TarStatus & TAR_TAG_Q_MASK) ==
2943 					 TAG_Q_TRYING) {
2944 					currTar_Info->TarStatus =
2945 					    (currTar_Info->
2946 					     TarStatus & ~(unsigned char)
2947 					     TAR_TAG_Q_MASK) | TAG_Q_REJECT;
2948 
2949 					currSCCB->ControlByte &= ~F_USE_CMD_Q;
2950 					CurrCard->discQCount--;
2951 					CurrCard->discQ_Tbl[currSCCB->
2952 							    Sccb_tag] = NULL;
2953 					currSCCB->Sccb_tag = 0x00;
2954 
2955 				}
2956 			}
2957 
2958 			if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
2959 
2960 				if (currSCCB->Lun == 0x00) {
2961 					WRW_HARPOON((port + hp_intstat),
2962 						    BUS_FREE);
2963 					CurrCard->globalFlags |= F_NEW_SCCB_CMD;
2964 				}
2965 			}
2966 
2967 			else {
2968 
2969 				if ((CurrCard->globalFlags & F_CONLUN_IO) &&
2970 				    ((currTar_Info->
2971 				      TarStatus & TAR_TAG_Q_MASK) !=
2972 				     TAG_Q_TRYING))
2973 					currTar_Info->TarLUNBusy[currSCCB->
2974 								 Lun] = 1;
2975 				else
2976 					currTar_Info->TarLUNBusy[0] = 1;
2977 
2978 				currSCCB->ControlByte &=
2979 				    ~(unsigned char)F_USE_CMD_Q;
2980 
2981 				WR_HARPOON(port + hp_autostart_1,
2982 					   (AUTO_IMMED + DISCONNECT_START));
2983 
2984 			}
2985 		}
2986 
2987 		else {
2988 			ACCEPT_MSG(port);
2989 
2990 			while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2991 			       (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
2992 			{
2993 			}
2994 
2995 			if (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)) {
2996 				WR_HARPOON(port + hp_autostart_1,
2997 					   (AUTO_IMMED + DISCONNECT_START));
2998 			}
2999 		}
3000 	}
3001 
3002 	else if (message == EXTENDED_MESSAGE) {
3003 
3004 		ACCEPT_MSG(port);
3005 		FPT_shandem(port, p_card, currSCCB);
3006 	}
3007 
3008 	else if (message == IGNORE_WIDE_RESIDUE) {
3009 
3010 		ACCEPT_MSG(port);	/* ACK the RESIDUE MSG */
3011 
3012 		message = FPT_sfm(port, currSCCB);
3013 
3014 		if (currSCCB->Sccb_scsimsg != MSG_PARITY_ERROR)
3015 			ACCEPT_MSG(port);
3016 		WR_HARPOON(port + hp_autostart_1,
3017 			   (AUTO_IMMED + DISCONNECT_START));
3018 	}
3019 
3020 	else {
3021 
3022 		currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
3023 		currSCCB->Sccb_scsimsg = MESSAGE_REJECT;
3024 
3025 		ACCEPT_MSG_ATN(port);
3026 		WR_HARPOON(port + hp_autostart_1,
3027 			   (AUTO_IMMED + DISCONNECT_START));
3028 	}
3029 }
3030 
3031 /*---------------------------------------------------------------------
3032  *
3033  * Function: FPT_shandem
3034  *
3035  * Description: Decide what to do with the extended message.
3036  *
3037  *---------------------------------------------------------------------*/
3038 static void FPT_shandem(u32 port, unsigned char p_card, struct sccb *pCurrSCCB)
3039 {
3040 	unsigned char length, message;
3041 
3042 	length = FPT_sfm(port, pCurrSCCB);
3043 	if (length) {
3044 
3045 		ACCEPT_MSG(port);
3046 		message = FPT_sfm(port, pCurrSCCB);
3047 		if (message) {
3048 
3049 			if (message == EXTENDED_SDTR) {
3050 
3051 				if (length == 0x03) {
3052 
3053 					ACCEPT_MSG(port);
3054 					FPT_stsyncn(port, p_card);
3055 				} else {
3056 
3057 					pCurrSCCB->Sccb_scsimsg = MESSAGE_REJECT;
3058 					ACCEPT_MSG_ATN(port);
3059 				}
3060 			} else if (message == EXTENDED_WDTR) {
3061 
3062 				if (length == 0x02) {
3063 
3064 					ACCEPT_MSG(port);
3065 					FPT_stwidn(port, p_card);
3066 				} else {
3067 
3068 					pCurrSCCB->Sccb_scsimsg = MESSAGE_REJECT;
3069 					ACCEPT_MSG_ATN(port);
3070 
3071 					WR_HARPOON(port + hp_autostart_1,
3072 						   (AUTO_IMMED +
3073 						    DISCONNECT_START));
3074 				}
3075 			} else {
3076 
3077 				pCurrSCCB->Sccb_scsimsg = MESSAGE_REJECT;
3078 				ACCEPT_MSG_ATN(port);
3079 
3080 				WR_HARPOON(port + hp_autostart_1,
3081 					   (AUTO_IMMED + DISCONNECT_START));
3082 			}
3083 		} else {
3084 			if (pCurrSCCB->Sccb_scsimsg != MSG_PARITY_ERROR)
3085 				ACCEPT_MSG(port);
3086 			WR_HARPOON(port + hp_autostart_1,
3087 				   (AUTO_IMMED + DISCONNECT_START));
3088 		}
3089 	} else {
3090 		if (pCurrSCCB->Sccb_scsimsg == MSG_PARITY_ERROR)
3091 			WR_HARPOON(port + hp_autostart_1,
3092 				   (AUTO_IMMED + DISCONNECT_START));
3093 	}
3094 }
3095 
3096 /*---------------------------------------------------------------------
3097  *
3098  * Function: FPT_sisyncn
3099  *
3100  * Description: Read in a message byte from the SCSI bus, and check
3101  *              for a parity error.
3102  *
3103  *---------------------------------------------------------------------*/
3104 
3105 static unsigned char FPT_sisyncn(u32 port, unsigned char p_card,
3106 				 unsigned char syncFlag)
3107 {
3108 	struct sccb *currSCCB;
3109 	struct sccb_mgr_tar_info *currTar_Info;
3110 
3111 	currSCCB = FPT_BL_Card[p_card].currentSCCB;
3112 	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
3113 
3114 	if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)) {
3115 
3116 		WRW_HARPOON((port + ID_MSG_STRT),
3117 			    (MPM_OP + AMSG_OUT +
3118 			     (currSCCB->
3119 			      Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
3120 
3121 		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
3122 
3123 		WRW_HARPOON((port + SYNC_MSGS + 0),
3124 			    (MPM_OP + AMSG_OUT + EXTENDED_MESSAGE));
3125 		WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
3126 		WRW_HARPOON((port + SYNC_MSGS + 4),
3127 			    (MPM_OP + AMSG_OUT + EXTENDED_SDTR));
3128 
3129 		if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
3130 
3131 			WRW_HARPOON((port + SYNC_MSGS + 6),
3132 				    (MPM_OP + AMSG_OUT + 12));
3133 
3134 		else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
3135 			 EE_SYNC_10MB)
3136 
3137 			WRW_HARPOON((port + SYNC_MSGS + 6),
3138 				    (MPM_OP + AMSG_OUT + 25));
3139 
3140 		else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
3141 			 EE_SYNC_5MB)
3142 
3143 			WRW_HARPOON((port + SYNC_MSGS + 6),
3144 				    (MPM_OP + AMSG_OUT + 50));
3145 
3146 		else
3147 			WRW_HARPOON((port + SYNC_MSGS + 6),
3148 				    (MPM_OP + AMSG_OUT + 00));
3149 
3150 		WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
3151 		WRW_HARPOON((port + SYNC_MSGS + 10),
3152 			    (MPM_OP + AMSG_OUT + DEFAULT_OFFSET));
3153 		WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
3154 
3155 		if (syncFlag == 0) {
3156 			WR_HARPOON(port + hp_autostart_3,
3157 				   (SELECT + SELCHK_STRT));
3158 			currTar_Info->TarStatus =
3159 			    ((currTar_Info->
3160 			      TarStatus & ~(unsigned char)TAR_SYNC_MASK) |
3161 			     (unsigned char)SYNC_TRYING);
3162 		} else {
3163 			WR_HARPOON(port + hp_autostart_3,
3164 				   (AUTO_IMMED + CMD_ONLY_STRT));
3165 		}
3166 
3167 		return 1;
3168 	}
3169 
3170 	else {
3171 
3172 		currTar_Info->TarStatus |= (unsigned char)SYNC_SUPPORTED;
3173 		currTar_Info->TarEEValue &= ~EE_SYNC_MASK;
3174 		return 0;
3175 	}
3176 }
3177 
3178 /*---------------------------------------------------------------------
3179  *
3180  * Function: FPT_stsyncn
3181  *
3182  * Description: The has sent us a Sync Nego message so handle it as
3183  *              necessary.
3184  *
3185  *---------------------------------------------------------------------*/
3186 static void FPT_stsyncn(u32 port, unsigned char p_card)
3187 {
3188 	unsigned char sync_msg, offset, sync_reg, our_sync_msg;
3189 	struct sccb *currSCCB;
3190 	struct sccb_mgr_tar_info *currTar_Info;
3191 
3192 	currSCCB = FPT_BL_Card[p_card].currentSCCB;
3193 	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
3194 
3195 	sync_msg = FPT_sfm(port, currSCCB);
3196 
3197 	if ((sync_msg == 0x00) && (currSCCB->Sccb_scsimsg == MSG_PARITY_ERROR)) {
3198 		WR_HARPOON(port + hp_autostart_1,
3199 			   (AUTO_IMMED + DISCONNECT_START));
3200 		return;
3201 	}
3202 
3203 	ACCEPT_MSG(port);
3204 
3205 	offset = FPT_sfm(port, currSCCB);
3206 
3207 	if ((offset == 0x00) && (currSCCB->Sccb_scsimsg == MSG_PARITY_ERROR)) {
3208 		WR_HARPOON(port + hp_autostart_1,
3209 			   (AUTO_IMMED + DISCONNECT_START));
3210 		return;
3211 	}
3212 
3213 	if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
3214 
3215 		our_sync_msg = 12;	/* Setup our Message to 20mb/s */
3216 
3217 	else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_10MB)
3218 
3219 		our_sync_msg = 25;	/* Setup our Message to 10mb/s */
3220 
3221 	else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_5MB)
3222 
3223 		our_sync_msg = 50;	/* Setup our Message to 5mb/s */
3224 	else
3225 
3226 		our_sync_msg = 0;	/* Message = Async */
3227 
3228 	if (sync_msg < our_sync_msg) {
3229 		sync_msg = our_sync_msg;	/*if faster, then set to max. */
3230 	}
3231 
3232 	if (offset == ASYNC)
3233 		sync_msg = ASYNC;
3234 
3235 	if (offset > MAX_OFFSET)
3236 		offset = MAX_OFFSET;
3237 
3238 	sync_reg = 0x00;
3239 
3240 	if (sync_msg > 12)
3241 
3242 		sync_reg = 0x20;	/* Use 10MB/s */
3243 
3244 	if (sync_msg > 25)
3245 
3246 		sync_reg = 0x40;	/* Use 6.6MB/s */
3247 
3248 	if (sync_msg > 38)
3249 
3250 		sync_reg = 0x60;	/* Use 5MB/s */
3251 
3252 	if (sync_msg > 50)
3253 
3254 		sync_reg = 0x80;	/* Use 4MB/s */
3255 
3256 	if (sync_msg > 62)
3257 
3258 		sync_reg = 0xA0;	/* Use 3.33MB/s */
3259 
3260 	if (sync_msg > 75)
3261 
3262 		sync_reg = 0xC0;	/* Use 2.85MB/s */
3263 
3264 	if (sync_msg > 87)
3265 
3266 		sync_reg = 0xE0;	/* Use 2.5MB/s */
3267 
3268 	if (sync_msg > 100) {
3269 
3270 		sync_reg = 0x00;	/* Use ASYNC */
3271 		offset = 0x00;
3272 	}
3273 
3274 	if (currTar_Info->TarStatus & WIDE_ENABLED)
3275 
3276 		sync_reg |= offset;
3277 
3278 	else
3279 
3280 		sync_reg |= (offset | NARROW_SCSI);
3281 
3282 	FPT_sssyncv(port, currSCCB->TargID, sync_reg, currTar_Info);
3283 
3284 	if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
3285 
3286 		ACCEPT_MSG(port);
3287 
3288 		currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3289 					    ~(unsigned char)TAR_SYNC_MASK) |
3290 					   (unsigned char)SYNC_SUPPORTED);
3291 
3292 		WR_HARPOON(port + hp_autostart_1,
3293 			   (AUTO_IMMED + DISCONNECT_START));
3294 	}
3295 
3296 	else {
3297 
3298 		ACCEPT_MSG_ATN(port);
3299 
3300 		FPT_sisyncr(port, sync_msg, offset);
3301 
3302 		currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3303 					    ~(unsigned char)TAR_SYNC_MASK) |
3304 					   (unsigned char)SYNC_SUPPORTED);
3305 	}
3306 }
3307 
3308 /*---------------------------------------------------------------------
3309  *
3310  * Function: FPT_sisyncr
3311  *
3312  * Description: Answer the targets sync message.
3313  *
3314  *---------------------------------------------------------------------*/
3315 static void FPT_sisyncr(u32 port, unsigned char sync_pulse,
3316 			unsigned char offset)
3317 {
3318 	ARAM_ACCESS(port);
3319 	WRW_HARPOON((port + SYNC_MSGS + 0),
3320 		    (MPM_OP + AMSG_OUT + EXTENDED_MESSAGE));
3321 	WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
3322 	WRW_HARPOON((port + SYNC_MSGS + 4),
3323 		    (MPM_OP + AMSG_OUT + EXTENDED_SDTR));
3324 	WRW_HARPOON((port + SYNC_MSGS + 6), (MPM_OP + AMSG_OUT + sync_pulse));
3325 	WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
3326 	WRW_HARPOON((port + SYNC_MSGS + 10), (MPM_OP + AMSG_OUT + offset));
3327 	WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
3328 	SGRAM_ACCESS(port);
3329 
3330 	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3331 	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
3332 
3333 	WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
3334 
3335 	while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
3336 	}
3337 }
3338 
3339 /*---------------------------------------------------------------------
3340  *
3341  * Function: FPT_siwidn
3342  *
3343  * Description: Read in a message byte from the SCSI bus, and check
3344  *              for a parity error.
3345  *
3346  *---------------------------------------------------------------------*/
3347 
3348 static unsigned char FPT_siwidn(u32 port, unsigned char p_card)
3349 {
3350 	struct sccb *currSCCB;
3351 	struct sccb_mgr_tar_info *currTar_Info;
3352 
3353 	currSCCB = FPT_BL_Card[p_card].currentSCCB;
3354 	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
3355 
3356 	if (!((currTar_Info->TarStatus & TAR_WIDE_MASK) == WIDE_NEGOCIATED)) {
3357 
3358 		WRW_HARPOON((port + ID_MSG_STRT),
3359 			    (MPM_OP + AMSG_OUT +
3360 			     (currSCCB->
3361 			      Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
3362 
3363 		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
3364 
3365 		WRW_HARPOON((port + SYNC_MSGS + 0),
3366 			    (MPM_OP + AMSG_OUT + EXTENDED_MESSAGE));
3367 		WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
3368 		WRW_HARPOON((port + SYNC_MSGS + 4),
3369 			    (MPM_OP + AMSG_OUT + EXTENDED_WDTR));
3370 		WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
3371 		WRW_HARPOON((port + SYNC_MSGS + 8),
3372 			    (MPM_OP + AMSG_OUT + SM16BIT));
3373 		WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
3374 
3375 		WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
3376 
3377 		currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3378 					    ~(unsigned char)TAR_WIDE_MASK) |
3379 					   (unsigned char)WIDE_ENABLED);
3380 
3381 		return 1;
3382 	}
3383 
3384 	else {
3385 
3386 		currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3387 					    ~(unsigned char)TAR_WIDE_MASK) |
3388 					   WIDE_NEGOCIATED);
3389 
3390 		currTar_Info->TarEEValue &= ~EE_WIDE_SCSI;
3391 		return 0;
3392 	}
3393 }
3394 
3395 /*---------------------------------------------------------------------
3396  *
3397  * Function: FPT_stwidn
3398  *
3399  * Description: The has sent us a Wide Nego message so handle it as
3400  *              necessary.
3401  *
3402  *---------------------------------------------------------------------*/
3403 static void FPT_stwidn(u32 port, unsigned char p_card)
3404 {
3405 	unsigned char width;
3406 	struct sccb *currSCCB;
3407 	struct sccb_mgr_tar_info *currTar_Info;
3408 
3409 	currSCCB = FPT_BL_Card[p_card].currentSCCB;
3410 	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
3411 
3412 	width = FPT_sfm(port, currSCCB);
3413 
3414 	if ((width == 0x00) && (currSCCB->Sccb_scsimsg == MSG_PARITY_ERROR)) {
3415 		WR_HARPOON(port + hp_autostart_1,
3416 			   (AUTO_IMMED + DISCONNECT_START));
3417 		return;
3418 	}
3419 
3420 	if (!(currTar_Info->TarEEValue & EE_WIDE_SCSI))
3421 		width = 0;
3422 
3423 	if (width) {
3424 		currTar_Info->TarStatus |= WIDE_ENABLED;
3425 		width = 0;
3426 	} else {
3427 		width = NARROW_SCSI;
3428 		currTar_Info->TarStatus &= ~WIDE_ENABLED;
3429 	}
3430 
3431 	FPT_sssyncv(port, currSCCB->TargID, width, currTar_Info);
3432 
3433 	if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
3434 
3435 		currTar_Info->TarStatus |= WIDE_NEGOCIATED;
3436 
3437 		if (!
3438 		    ((currTar_Info->TarStatus & TAR_SYNC_MASK) ==
3439 		     SYNC_SUPPORTED)) {
3440 			ACCEPT_MSG_ATN(port);
3441 			ARAM_ACCESS(port);
3442 			FPT_sisyncn(port, p_card, 1);
3443 			currSCCB->Sccb_scsistat = SELECT_SN_ST;
3444 			SGRAM_ACCESS(port);
3445 		} else {
3446 			ACCEPT_MSG(port);
3447 			WR_HARPOON(port + hp_autostart_1,
3448 				   (AUTO_IMMED + DISCONNECT_START));
3449 		}
3450 	}
3451 
3452 	else {
3453 
3454 		ACCEPT_MSG_ATN(port);
3455 
3456 		if (currTar_Info->TarEEValue & EE_WIDE_SCSI)
3457 			width = SM16BIT;
3458 		else
3459 			width = SM8BIT;
3460 
3461 		FPT_siwidr(port, width);
3462 
3463 		currTar_Info->TarStatus |= (WIDE_NEGOCIATED | WIDE_ENABLED);
3464 	}
3465 }
3466 
3467 /*---------------------------------------------------------------------
3468  *
3469  * Function: FPT_siwidr
3470  *
3471  * Description: Answer the targets Wide nego message.
3472  *
3473  *---------------------------------------------------------------------*/
3474 static void FPT_siwidr(u32 port, unsigned char width)
3475 {
3476 	ARAM_ACCESS(port);
3477 	WRW_HARPOON((port + SYNC_MSGS + 0),
3478 		    (MPM_OP + AMSG_OUT + EXTENDED_MESSAGE));
3479 	WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
3480 	WRW_HARPOON((port + SYNC_MSGS + 4),
3481 		    (MPM_OP + AMSG_OUT + EXTENDED_WDTR));
3482 	WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
3483 	WRW_HARPOON((port + SYNC_MSGS + 8), (MPM_OP + AMSG_OUT + width));
3484 	WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
3485 	SGRAM_ACCESS(port);
3486 
3487 	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3488 	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
3489 
3490 	WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
3491 
3492 	while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
3493 	}
3494 }
3495 
3496 /*---------------------------------------------------------------------
3497  *
3498  * Function: FPT_sssyncv
3499  *
3500  * Description: Write the desired value to the Sync Register for the
3501  *              ID specified.
3502  *
3503  *---------------------------------------------------------------------*/
3504 static void FPT_sssyncv(u32 p_port, unsigned char p_id,
3505 			unsigned char p_sync_value,
3506 			struct sccb_mgr_tar_info *currTar_Info)
3507 {
3508 	unsigned char index;
3509 
3510 	index = p_id;
3511 
3512 	switch (index) {
3513 
3514 	case 0:
3515 		index = 12;	/* hp_synctarg_0 */
3516 		break;
3517 	case 1:
3518 		index = 13;	/* hp_synctarg_1 */
3519 		break;
3520 	case 2:
3521 		index = 14;	/* hp_synctarg_2 */
3522 		break;
3523 	case 3:
3524 		index = 15;	/* hp_synctarg_3 */
3525 		break;
3526 	case 4:
3527 		index = 8;	/* hp_synctarg_4 */
3528 		break;
3529 	case 5:
3530 		index = 9;	/* hp_synctarg_5 */
3531 		break;
3532 	case 6:
3533 		index = 10;	/* hp_synctarg_6 */
3534 		break;
3535 	case 7:
3536 		index = 11;	/* hp_synctarg_7 */
3537 		break;
3538 	case 8:
3539 		index = 4;	/* hp_synctarg_8 */
3540 		break;
3541 	case 9:
3542 		index = 5;	/* hp_synctarg_9 */
3543 		break;
3544 	case 10:
3545 		index = 6;	/* hp_synctarg_10 */
3546 		break;
3547 	case 11:
3548 		index = 7;	/* hp_synctarg_11 */
3549 		break;
3550 	case 12:
3551 		index = 0;	/* hp_synctarg_12 */
3552 		break;
3553 	case 13:
3554 		index = 1;	/* hp_synctarg_13 */
3555 		break;
3556 	case 14:
3557 		index = 2;	/* hp_synctarg_14 */
3558 		break;
3559 	case 15:
3560 		index = 3;	/* hp_synctarg_15 */
3561 
3562 	}
3563 
3564 	WR_HARPOON(p_port + hp_synctarg_base + index, p_sync_value);
3565 
3566 	currTar_Info->TarSyncCtrl = p_sync_value;
3567 }
3568 
3569 /*---------------------------------------------------------------------
3570  *
3571  * Function: FPT_sresb
3572  *
3573  * Description: Reset the desired card's SCSI bus.
3574  *
3575  *---------------------------------------------------------------------*/
3576 static void FPT_sresb(u32 port, unsigned char p_card)
3577 {
3578 	unsigned char scsiID, i;
3579 
3580 	struct sccb_mgr_tar_info *currTar_Info;
3581 
3582 	WR_HARPOON(port + hp_page_ctrl,
3583 		   (RD_HARPOON(port + hp_page_ctrl) | G_INT_DISABLE));
3584 	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
3585 
3586 	WR_HARPOON(port + hp_scsictrl_0, SCSI_RST);
3587 
3588 	scsiID = RD_HARPOON(port + hp_seltimeout);
3589 	WR_HARPOON(port + hp_seltimeout, TO_5ms);
3590 	WRW_HARPOON((port + hp_intstat), TIMEOUT);
3591 
3592 	WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT | START_TO));
3593 
3594 	while (!(RDW_HARPOON((port + hp_intstat)) & TIMEOUT)) {
3595 	}
3596 
3597 	WR_HARPOON(port + hp_seltimeout, scsiID);
3598 
3599 	WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
3600 
3601 	FPT_Wait(port, TO_5ms);
3602 
3603 	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
3604 
3605 	WR_HARPOON(port + hp_int_mask, (RD_HARPOON(port + hp_int_mask) | 0x00));
3606 
3607 	for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
3608 		currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
3609 
3610 		if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
3611 			currTar_Info->TarSyncCtrl = 0;
3612 			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
3613 		}
3614 
3615 		if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
3616 			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
3617 		}
3618 
3619 		FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
3620 
3621 		FPT_SccbMgrTableInitTarget(p_card, scsiID);
3622 	}
3623 
3624 	FPT_BL_Card[p_card].scanIndex = 0x00;
3625 	FPT_BL_Card[p_card].currentSCCB = NULL;
3626 	FPT_BL_Card[p_card].globalFlags &= ~(F_TAG_STARTED | F_HOST_XFER_ACT
3627 					     | F_NEW_SCCB_CMD);
3628 	FPT_BL_Card[p_card].cmdCounter = 0x00;
3629 	FPT_BL_Card[p_card].discQCount = 0x00;
3630 	FPT_BL_Card[p_card].tagQ_Lst = 0x01;
3631 
3632 	for (i = 0; i < QUEUE_DEPTH; i++)
3633 		FPT_BL_Card[p_card].discQ_Tbl[i] = NULL;
3634 
3635 	WR_HARPOON(port + hp_page_ctrl,
3636 		   (RD_HARPOON(port + hp_page_ctrl) & ~G_INT_DISABLE));
3637 
3638 }
3639 
3640 /*---------------------------------------------------------------------
3641  *
3642  * Function: FPT_ssenss
3643  *
3644  * Description: Setup for the Auto Sense command.
3645  *
3646  *---------------------------------------------------------------------*/
3647 static void FPT_ssenss(struct sccb_card *pCurrCard)
3648 {
3649 	unsigned char i;
3650 	struct sccb *currSCCB;
3651 
3652 	currSCCB = pCurrCard->currentSCCB;
3653 
3654 	currSCCB->Save_CdbLen = currSCCB->CdbLength;
3655 
3656 	for (i = 0; i < 6; i++) {
3657 
3658 		currSCCB->Save_Cdb[i] = currSCCB->Cdb[i];
3659 	}
3660 
3661 	currSCCB->CdbLength = SIX_BYTE_CMD;
3662 	currSCCB->Cdb[0] = REQUEST_SENSE;
3663 	currSCCB->Cdb[1] = currSCCB->Cdb[1] & (unsigned char)0xE0;	/*Keep LUN. */
3664 	currSCCB->Cdb[2] = 0x00;
3665 	currSCCB->Cdb[3] = 0x00;
3666 	currSCCB->Cdb[4] = currSCCB->RequestSenseLength;
3667 	currSCCB->Cdb[5] = 0x00;
3668 
3669 	currSCCB->Sccb_XferCnt = (u32)currSCCB->RequestSenseLength;
3670 
3671 	currSCCB->Sccb_ATC = 0x00;
3672 
3673 	currSCCB->Sccb_XferState |= F_AUTO_SENSE;
3674 
3675 	currSCCB->Sccb_XferState &= ~F_SG_XFER;
3676 
3677 	currSCCB->Sccb_idmsg = currSCCB->Sccb_idmsg & ~(unsigned char)DISC_PRIV;
3678 
3679 	currSCCB->ControlByte = 0x00;
3680 
3681 	currSCCB->Sccb_MGRFlags &= F_STATUSLOADED;
3682 }
3683 
3684 /*---------------------------------------------------------------------
3685  *
3686  * Function: FPT_sxfrp
3687  *
3688  * Description: Transfer data into the bit bucket until the device
3689  *              decides to switch phase.
3690  *
3691  *---------------------------------------------------------------------*/
3692 
3693 static void FPT_sxfrp(u32 p_port, unsigned char p_card)
3694 {
3695 	unsigned char curr_phz;
3696 
3697 	DISABLE_AUTO(p_port);
3698 
3699 	if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
3700 
3701 		FPT_hostDataXferAbort(p_port, p_card,
3702 				      FPT_BL_Card[p_card].currentSCCB);
3703 
3704 	}
3705 
3706 	/* If the Automation handled the end of the transfer then do not
3707 	   match the phase or we will get out of sync with the ISR.       */
3708 
3709 	if (RDW_HARPOON((p_port + hp_intstat)) &
3710 	    (BUS_FREE | XFER_CNT_0 | AUTO_INT))
3711 		return;
3712 
3713 	WR_HARPOON(p_port + hp_xfercnt_0, 0x00);
3714 
3715 	curr_phz = RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ;
3716 
3717 	WRW_HARPOON((p_port + hp_intstat), XFER_CNT_0);
3718 
3719 	WR_HARPOON(p_port + hp_scsisig, curr_phz);
3720 
3721 	while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET)) &&
3722 	       (curr_phz ==
3723 		(RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ)))
3724 	{
3725 		if (curr_phz & (unsigned char)SCSI_IOBIT) {
3726 			WR_HARPOON(p_port + hp_portctrl_0,
3727 				   (SCSI_PORT | HOST_PORT | SCSI_INBIT));
3728 
3729 			if (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
3730 				RD_HARPOON(p_port + hp_fifodata_0);
3731 			}
3732 		} else {
3733 			WR_HARPOON(p_port + hp_portctrl_0,
3734 				   (SCSI_PORT | HOST_PORT | HOST_WRT));
3735 			if (RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY) {
3736 				WR_HARPOON(p_port + hp_fifodata_0, 0xFA);
3737 			}
3738 		}
3739 	}			/* End of While loop for padding data I/O phase */
3740 
3741 	while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
3742 		if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ)
3743 			break;
3744 	}
3745 
3746 	WR_HARPOON(p_port + hp_portctrl_0,
3747 		   (SCSI_PORT | HOST_PORT | SCSI_INBIT));
3748 	while (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
3749 		RD_HARPOON(p_port + hp_fifodata_0);
3750 	}
3751 
3752 	if (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
3753 		WR_HARPOON(p_port + hp_autostart_0,
3754 			   (AUTO_IMMED + DISCONNECT_START));
3755 		while (!(RDW_HARPOON((p_port + hp_intstat)) & AUTO_INT)) {
3756 		}
3757 
3758 		if (RDW_HARPOON((p_port + hp_intstat)) &
3759 		    (ICMD_COMP | ITAR_DISC))
3760 			while (!
3761 			       (RDW_HARPOON((p_port + hp_intstat)) &
3762 				(BUS_FREE | RSEL))) ;
3763 	}
3764 }
3765 
3766 /*---------------------------------------------------------------------
3767  *
3768  * Function: FPT_schkdd
3769  *
3770  * Description: Make sure data has been flushed from both FIFOs and abort
3771  *              the operations if necessary.
3772  *
3773  *---------------------------------------------------------------------*/
3774 
3775 static void FPT_schkdd(u32 port, unsigned char p_card)
3776 {
3777 	unsigned short TimeOutLoop;
3778 	unsigned char sPhase;
3779 
3780 	struct sccb *currSCCB;
3781 
3782 	currSCCB = FPT_BL_Card[p_card].currentSCCB;
3783 
3784 	if ((currSCCB->Sccb_scsistat != DATA_OUT_ST) &&
3785 	    (currSCCB->Sccb_scsistat != DATA_IN_ST)) {
3786 		return;
3787 	}
3788 
3789 	if (currSCCB->Sccb_XferState & F_ODD_BALL_CNT) {
3790 
3791 		currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - 1);
3792 
3793 		currSCCB->Sccb_XferCnt = 1;
3794 
3795 		currSCCB->Sccb_XferState &= ~F_ODD_BALL_CNT;
3796 		WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
3797 		WR_HARPOON(port + hp_xferstat, 0x00);
3798 	}
3799 
3800 	else {
3801 
3802 		currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
3803 
3804 		currSCCB->Sccb_XferCnt = 0;
3805 	}
3806 
3807 	if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
3808 	    (currSCCB->HostStatus == SCCB_COMPLETE)) {
3809 
3810 		currSCCB->HostStatus = SCCB_PARITY_ERR;
3811 		WRW_HARPOON((port + hp_intstat), PARITY);
3812 	}
3813 
3814 	FPT_hostDataXferAbort(port, p_card, currSCCB);
3815 
3816 	while (RD_HARPOON(port + hp_scsisig) & SCSI_ACK) {
3817 	}
3818 
3819 	TimeOutLoop = 0;
3820 
3821 	while (RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY) {
3822 		if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
3823 			return;
3824 		}
3825 		if (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) {
3826 			break;
3827 		}
3828 		if (RDW_HARPOON((port + hp_intstat)) & RESET) {
3829 			return;
3830 		}
3831 		if ((RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
3832 		    || (TimeOutLoop++ > 0x3000))
3833 			break;
3834 	}
3835 
3836 	sPhase = RD_HARPOON(port + hp_scsisig) & (SCSI_BSY | S_SCSI_PHZ);
3837 	if ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) ||
3838 	    (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) ||
3839 	    (sPhase == (SCSI_BSY | S_DATAO_PH)) ||
3840 	    (sPhase == (SCSI_BSY | S_DATAI_PH))) {
3841 
3842 		WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3843 
3844 		if (!(currSCCB->Sccb_XferState & F_ALL_XFERRED)) {
3845 			if (currSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
3846 				FPT_phaseDataIn(port, p_card);
3847 			}
3848 
3849 			else {
3850 				FPT_phaseDataOut(port, p_card);
3851 			}
3852 		} else {
3853 			FPT_sxfrp(port, p_card);
3854 			if (!(RDW_HARPOON((port + hp_intstat)) &
3855 			      (BUS_FREE | ICMD_COMP | ITAR_DISC | RESET))) {
3856 				WRW_HARPOON((port + hp_intstat), AUTO_INT);
3857 				FPT_phaseDecode(port, p_card);
3858 			}
3859 		}
3860 
3861 	}
3862 
3863 	else {
3864 		WR_HARPOON(port + hp_portctrl_0, 0x00);
3865 	}
3866 }
3867 
3868 /*---------------------------------------------------------------------
3869  *
3870  * Function: FPT_sinits
3871  *
3872  * Description: Setup SCCB manager fields in this SCCB.
3873  *
3874  *---------------------------------------------------------------------*/
3875 
3876 static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card)
3877 {
3878 	struct sccb_mgr_tar_info *currTar_Info;
3879 
3880 	if ((p_sccb->TargID >= MAX_SCSI_TAR) || (p_sccb->Lun >= MAX_LUN)) {
3881 		return;
3882 	}
3883 	currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
3884 
3885 	p_sccb->Sccb_XferState = 0x00;
3886 	p_sccb->Sccb_XferCnt = p_sccb->DataLength;
3887 
3888 	if ((p_sccb->OperationCode == SCATTER_GATHER_COMMAND) ||
3889 	    (p_sccb->OperationCode == RESIDUAL_SG_COMMAND)) {
3890 
3891 		p_sccb->Sccb_SGoffset = 0;
3892 		p_sccb->Sccb_XferState = F_SG_XFER;
3893 		p_sccb->Sccb_XferCnt = 0x00;
3894 	}
3895 
3896 	if (p_sccb->DataLength == 0x00)
3897 
3898 		p_sccb->Sccb_XferState |= F_ALL_XFERRED;
3899 
3900 	if (p_sccb->ControlByte & F_USE_CMD_Q) {
3901 		if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
3902 			p_sccb->ControlByte &= ~F_USE_CMD_Q;
3903 
3904 		else
3905 			currTar_Info->TarStatus |= TAG_Q_TRYING;
3906 	}
3907 
3908 /*      For !single SCSI device in system  & device allow Disconnect
3909 	or command is tag_q type then send Cmd with Disconnect Enable
3910 	else send Cmd with Disconnect Disable */
3911 
3912 /*
3913    if (((!(FPT_BL_Card[p_card].globalFlags & F_SINGLE_DEVICE)) &&
3914       (currTar_Info->TarStatus & TAR_ALLOW_DISC)) ||
3915       (currTar_Info->TarStatus & TAG_Q_TRYING)) {
3916 */
3917 	if ((currTar_Info->TarStatus & TAR_ALLOW_DISC) ||
3918 	    (currTar_Info->TarStatus & TAG_Q_TRYING)) {
3919 		p_sccb->Sccb_idmsg = IDENTIFY(true, p_sccb->Lun);
3920 	} else {
3921 		p_sccb->Sccb_idmsg = IDENTIFY(false, p_sccb->Lun);
3922 	}
3923 
3924 	p_sccb->HostStatus = 0x00;
3925 	p_sccb->TargetStatus = 0x00;
3926 	p_sccb->Sccb_tag = 0x00;
3927 	p_sccb->Sccb_MGRFlags = 0x00;
3928 	p_sccb->Sccb_sgseg = 0x00;
3929 	p_sccb->Sccb_ATC = 0x00;
3930 	p_sccb->Sccb_savedATC = 0x00;
3931 /*
3932    p_sccb->SccbVirtDataPtr    = 0x00;
3933    p_sccb->Sccb_forwardlink   = NULL;
3934    p_sccb->Sccb_backlink      = NULL;
3935  */
3936 	p_sccb->Sccb_scsistat = BUS_FREE_ST;
3937 	p_sccb->SccbStatus = SCCB_IN_PROCESS;
3938 	p_sccb->Sccb_scsimsg = NOP;
3939 
3940 }
3941 
3942 /*---------------------------------------------------------------------
3943  *
3944  * Function: Phase Decode
3945  *
3946  * Description: Determine the phase and call the appropriate function.
3947  *
3948  *---------------------------------------------------------------------*/
3949 
3950 static void FPT_phaseDecode(u32 p_port, unsigned char p_card)
3951 {
3952 	unsigned char phase_ref;
3953 	void (*phase) (u32, unsigned char);
3954 
3955 	DISABLE_AUTO(p_port);
3956 
3957 	phase_ref =
3958 	    (unsigned char)(RD_HARPOON(p_port + hp_scsisig) & S_SCSI_PHZ);
3959 
3960 	phase = FPT_s_PhaseTbl[phase_ref];
3961 
3962 	(*phase) (p_port, p_card);	/* Call the correct phase func */
3963 }
3964 
3965 /*---------------------------------------------------------------------
3966  *
3967  * Function: Data Out Phase
3968  *
3969  * Description: Start up both the BusMaster and Xbow.
3970  *
3971  *---------------------------------------------------------------------*/
3972 
3973 static void FPT_phaseDataOut(u32 port, unsigned char p_card)
3974 {
3975 
3976 	struct sccb *currSCCB;
3977 
3978 	currSCCB = FPT_BL_Card[p_card].currentSCCB;
3979 	if (currSCCB == NULL) {
3980 		return;		/* Exit if No SCCB record */
3981 	}
3982 
3983 	currSCCB->Sccb_scsistat = DATA_OUT_ST;
3984 	currSCCB->Sccb_XferState &= ~(F_HOST_XFER_DIR | F_NO_DATA_YET);
3985 
3986 	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3987 
3988 	WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
3989 
3990 	WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
3991 
3992 	FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
3993 
3994 	if (currSCCB->Sccb_XferCnt == 0) {
3995 
3996 		if ((currSCCB->ControlByte & SCCB_DATA_XFER_OUT) &&
3997 		    (currSCCB->HostStatus == SCCB_COMPLETE))
3998 			currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
3999 
4000 		FPT_sxfrp(port, p_card);
4001 		if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
4002 			FPT_phaseDecode(port, p_card);
4003 	}
4004 }
4005 
4006 /*---------------------------------------------------------------------
4007  *
4008  * Function: Data In Phase
4009  *
4010  * Description: Startup the BusMaster and the XBOW.
4011  *
4012  *---------------------------------------------------------------------*/
4013 
4014 static void FPT_phaseDataIn(u32 port, unsigned char p_card)
4015 {
4016 
4017 	struct sccb *currSCCB;
4018 
4019 	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4020 
4021 	if (currSCCB == NULL) {
4022 		return;		/* Exit if No SCCB record */
4023 	}
4024 
4025 	currSCCB->Sccb_scsistat = DATA_IN_ST;
4026 	currSCCB->Sccb_XferState |= F_HOST_XFER_DIR;
4027 	currSCCB->Sccb_XferState &= ~F_NO_DATA_YET;
4028 
4029 	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
4030 
4031 	WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
4032 
4033 	WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
4034 
4035 	FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
4036 
4037 	if (currSCCB->Sccb_XferCnt == 0) {
4038 
4039 		if ((currSCCB->ControlByte & SCCB_DATA_XFER_IN) &&
4040 		    (currSCCB->HostStatus == SCCB_COMPLETE))
4041 			currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
4042 
4043 		FPT_sxfrp(port, p_card);
4044 		if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
4045 			FPT_phaseDecode(port, p_card);
4046 
4047 	}
4048 }
4049 
4050 /*---------------------------------------------------------------------
4051  *
4052  * Function: Command Phase
4053  *
4054  * Description: Load the CDB into the automation and start it up.
4055  *
4056  *---------------------------------------------------------------------*/
4057 
4058 static void FPT_phaseCommand(u32 p_port, unsigned char p_card)
4059 {
4060 	struct sccb *currSCCB;
4061 	u32 cdb_reg;
4062 	unsigned char i;
4063 
4064 	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4065 
4066 	if (currSCCB->OperationCode == RESET_COMMAND) {
4067 
4068 		currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4069 		currSCCB->CdbLength = SIX_BYTE_CMD;
4070 	}
4071 
4072 	WR_HARPOON(p_port + hp_scsisig, 0x00);
4073 
4074 	ARAM_ACCESS(p_port);
4075 
4076 	cdb_reg = p_port + CMD_STRT;
4077 
4078 	for (i = 0; i < currSCCB->CdbLength; i++) {
4079 
4080 		if (currSCCB->OperationCode == RESET_COMMAND)
4081 
4082 			WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + 0x00));
4083 
4084 		else
4085 			WRW_HARPOON(cdb_reg,
4086 				    (MPM_OP + ACOMMAND + currSCCB->Cdb[i]));
4087 		cdb_reg += 2;
4088 	}
4089 
4090 	if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
4091 		WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
4092 
4093 	WR_HARPOON(p_port + hp_portctrl_0, (SCSI_PORT));
4094 
4095 	currSCCB->Sccb_scsistat = COMMAND_ST;
4096 
4097 	WR_HARPOON(p_port + hp_autostart_3, (AUTO_IMMED | CMD_ONLY_STRT));
4098 	SGRAM_ACCESS(p_port);
4099 }
4100 
4101 /*---------------------------------------------------------------------
4102  *
4103  * Function: Status phase
4104  *
4105  * Description: Bring in the status and command complete message bytes
4106  *
4107  *---------------------------------------------------------------------*/
4108 
4109 static void FPT_phaseStatus(u32 port, unsigned char p_card)
4110 {
4111 	/* Start-up the automation to finish off this command and let the
4112 	   isr handle the interrupt for command complete when it comes in.
4113 	   We could wait here for the interrupt to be generated?
4114 	 */
4115 
4116 	WR_HARPOON(port + hp_scsisig, 0x00);
4117 
4118 	WR_HARPOON(port + hp_autostart_0, (AUTO_IMMED + END_DATA_START));
4119 }
4120 
4121 /*---------------------------------------------------------------------
4122  *
4123  * Function: Phase Message Out
4124  *
4125  * Description: Send out our message (if we have one) and handle whatever
4126  *              else is involed.
4127  *
4128  *---------------------------------------------------------------------*/
4129 
4130 static void FPT_phaseMsgOut(u32 port, unsigned char p_card)
4131 {
4132 	unsigned char message, scsiID;
4133 	struct sccb *currSCCB;
4134 	struct sccb_mgr_tar_info *currTar_Info;
4135 
4136 	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4137 
4138 	if (currSCCB != NULL) {
4139 
4140 		message = currSCCB->Sccb_scsimsg;
4141 		scsiID = currSCCB->TargID;
4142 
4143 		if (message == TARGET_RESET) {
4144 
4145 			currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
4146 			currTar_Info->TarSyncCtrl = 0;
4147 			FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
4148 
4149 			if (FPT_sccbMgrTbl[p_card][scsiID].
4150 			    TarEEValue & EE_SYNC_MASK) {
4151 
4152 				FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
4153 				    ~TAR_SYNC_MASK;
4154 
4155 			}
4156 
4157 			if (FPT_sccbMgrTbl[p_card][scsiID].
4158 			    TarEEValue & EE_WIDE_SCSI) {
4159 
4160 				FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
4161 				    ~TAR_WIDE_MASK;
4162 			}
4163 
4164 			FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
4165 			FPT_SccbMgrTableInitTarget(p_card, scsiID);
4166 		} else if (currSCCB->Sccb_scsistat == ABORT_ST) {
4167 			currSCCB->HostStatus = SCCB_COMPLETE;
4168 			if (FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] !=
4169 			    NULL) {
4170 				FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4171 							      Sccb_tag] = NULL;
4172 				FPT_sccbMgrTbl[p_card][scsiID].TarTagQ_Cnt--;
4173 			}
4174 
4175 		}
4176 
4177 		else if (currSCCB->Sccb_scsistat < COMMAND_ST) {
4178 
4179 			if (message == NOP) {
4180 				currSCCB->Sccb_MGRFlags |= F_DEV_SELECTED;
4181 
4182 				FPT_ssel(port, p_card);
4183 				return;
4184 			}
4185 		} else {
4186 
4187 			if (message == ABORT_TASK_SET)
4188 
4189 				FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
4190 		}
4191 
4192 	} else {
4193 		message = ABORT_TASK_SET;
4194 	}
4195 
4196 	WRW_HARPOON((port + hp_intstat), (BUS_FREE | PHASE | XFER_CNT_0));
4197 
4198 	WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
4199 
4200 	WR_HARPOON(port + hp_scsidata_0, message);
4201 
4202 	WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
4203 
4204 	ACCEPT_MSG(port);
4205 
4206 	WR_HARPOON(port + hp_portctrl_0, 0x00);
4207 
4208 	if ((message == ABORT_TASK_SET) || (message == TARGET_RESET) ||
4209 	    (message == ABORT_TASK)) {
4210 
4211 		while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | PHASE))) {
4212 		}
4213 
4214 		if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
4215 			WRW_HARPOON((port + hp_intstat), BUS_FREE);
4216 
4217 			if (currSCCB != NULL) {
4218 
4219 				if ((FPT_BL_Card[p_card].
4220 				     globalFlags & F_CONLUN_IO)
4221 				    &&
4222 				    ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4223 				      TarStatus & TAR_TAG_Q_MASK) !=
4224 				     TAG_Q_TRYING))
4225 					FPT_sccbMgrTbl[p_card][currSCCB->
4226 							       TargID].
4227 					    TarLUNBusy[currSCCB->Lun] = 0;
4228 				else
4229 					FPT_sccbMgrTbl[p_card][currSCCB->
4230 							       TargID].
4231 					    TarLUNBusy[0] = 0;
4232 
4233 				FPT_queueCmdComplete(&FPT_BL_Card[p_card],
4234 						     currSCCB, p_card);
4235 			}
4236 
4237 			else {
4238 				FPT_BL_Card[p_card].globalFlags |=
4239 				    F_NEW_SCCB_CMD;
4240 			}
4241 		}
4242 
4243 		else {
4244 
4245 			FPT_sxfrp(port, p_card);
4246 		}
4247 	}
4248 
4249 	else {
4250 
4251 		if (message == MSG_PARITY_ERROR) {
4252 			currSCCB->Sccb_scsimsg = NOP;
4253 			WR_HARPOON(port + hp_autostart_1,
4254 				   (AUTO_IMMED + DISCONNECT_START));
4255 		} else {
4256 			FPT_sxfrp(port, p_card);
4257 		}
4258 	}
4259 }
4260 
4261 /*---------------------------------------------------------------------
4262  *
4263  * Function: Message In phase
4264  *
4265  * Description: Bring in the message and determine what to do with it.
4266  *
4267  *---------------------------------------------------------------------*/
4268 
4269 static void FPT_phaseMsgIn(u32 port, unsigned char p_card)
4270 {
4271 	unsigned char message;
4272 	struct sccb *currSCCB;
4273 
4274 	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4275 
4276 	if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
4277 
4278 		FPT_phaseChkFifo(port, p_card);
4279 	}
4280 
4281 	message = RD_HARPOON(port + hp_scsidata_0);
4282 	if ((message == DISCONNECT) || (message == SAVE_POINTERS)) {
4283 
4284 		WR_HARPOON(port + hp_autostart_1,
4285 			   (AUTO_IMMED + END_DATA_START));
4286 
4287 	}
4288 
4289 	else {
4290 
4291 		message = FPT_sfm(port, currSCCB);
4292 		if (message) {
4293 
4294 			FPT_sdecm(message, port, p_card);
4295 
4296 		} else {
4297 			if (currSCCB->Sccb_scsimsg != MSG_PARITY_ERROR)
4298 				ACCEPT_MSG(port);
4299 			WR_HARPOON(port + hp_autostart_1,
4300 				   (AUTO_IMMED + DISCONNECT_START));
4301 		}
4302 	}
4303 
4304 }
4305 
4306 /*---------------------------------------------------------------------
4307  *
4308  * Function: Illegal phase
4309  *
4310  * Description: Target switched to some illegal phase, so all we can do
4311  *              is report an error back to the host (if that is possible)
4312  *              and send an ABORT message to the misbehaving target.
4313  *
4314  *---------------------------------------------------------------------*/
4315 
4316 static void FPT_phaseIllegal(u32 port, unsigned char p_card)
4317 {
4318 	struct sccb *currSCCB;
4319 
4320 	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4321 
4322 	WR_HARPOON(port + hp_scsisig, RD_HARPOON(port + hp_scsisig));
4323 	if (currSCCB != NULL) {
4324 
4325 		currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4326 		currSCCB->Sccb_scsistat = ABORT_ST;
4327 		currSCCB->Sccb_scsimsg = ABORT_TASK_SET;
4328 	}
4329 
4330 	ACCEPT_MSG_ATN(port);
4331 }
4332 
4333 /*---------------------------------------------------------------------
4334  *
4335  * Function: Phase Check FIFO
4336  *
4337  * Description: Make sure data has been flushed from both FIFOs and abort
4338  *              the operations if necessary.
4339  *
4340  *---------------------------------------------------------------------*/
4341 
4342 static void FPT_phaseChkFifo(u32 port, unsigned char p_card)
4343 {
4344 	u32 xfercnt;
4345 	struct sccb *currSCCB;
4346 
4347 	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4348 
4349 	if (currSCCB->Sccb_scsistat == DATA_IN_ST) {
4350 
4351 		while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) &&
4352 		       (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)) {
4353 		}
4354 
4355 		if (!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) {
4356 			currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
4357 
4358 			currSCCB->Sccb_XferCnt = 0;
4359 
4360 			if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
4361 			    (currSCCB->HostStatus == SCCB_COMPLETE)) {
4362 				currSCCB->HostStatus = SCCB_PARITY_ERR;
4363 				WRW_HARPOON((port + hp_intstat), PARITY);
4364 			}
4365 
4366 			FPT_hostDataXferAbort(port, p_card, currSCCB);
4367 
4368 			FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
4369 
4370 			while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY))
4371 			       && (RD_HARPOON(port + hp_ext_status) &
4372 				   BM_CMD_BUSY)) {
4373 			}
4374 
4375 		}
4376 	}
4377 
4378 	/*End Data In specific code. */
4379 	GET_XFER_CNT(port, xfercnt);
4380 
4381 	WR_HARPOON(port + hp_xfercnt_0, 0x00);
4382 
4383 	WR_HARPOON(port + hp_portctrl_0, 0x00);
4384 
4385 	currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - xfercnt);
4386 
4387 	currSCCB->Sccb_XferCnt = xfercnt;
4388 
4389 	if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
4390 	    (currSCCB->HostStatus == SCCB_COMPLETE)) {
4391 
4392 		currSCCB->HostStatus = SCCB_PARITY_ERR;
4393 		WRW_HARPOON((port + hp_intstat), PARITY);
4394 	}
4395 
4396 	FPT_hostDataXferAbort(port, p_card, currSCCB);
4397 
4398 	WR_HARPOON(port + hp_fifowrite, 0x00);
4399 	WR_HARPOON(port + hp_fiforead, 0x00);
4400 	WR_HARPOON(port + hp_xferstat, 0x00);
4401 
4402 	WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
4403 }
4404 
4405 /*---------------------------------------------------------------------
4406  *
4407  * Function: Phase Bus Free
4408  *
4409  * Description: We just went bus free so figure out if it was
4410  *              because of command complete or from a disconnect.
4411  *
4412  *---------------------------------------------------------------------*/
4413 static void FPT_phaseBusFree(u32 port, unsigned char p_card)
4414 {
4415 	struct sccb *currSCCB;
4416 
4417 	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4418 
4419 	if (currSCCB != NULL) {
4420 
4421 		DISABLE_AUTO(port);
4422 
4423 		if (currSCCB->OperationCode == RESET_COMMAND) {
4424 
4425 			if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4426 			    ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4427 			      TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4428 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4429 				    TarLUNBusy[currSCCB->Lun] = 0;
4430 			else
4431 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4432 				    TarLUNBusy[0] = 0;
4433 
4434 			FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
4435 					     p_card);
4436 
4437 			FPT_queueSearchSelect(&FPT_BL_Card[p_card], p_card);
4438 
4439 		}
4440 
4441 		else if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
4442 			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4443 			    (unsigned char)SYNC_SUPPORTED;
4444 			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4445 			    ~EE_SYNC_MASK;
4446 		}
4447 
4448 		else if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
4449 			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
4450 			    (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4451 			     TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
4452 
4453 			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4454 			    ~EE_WIDE_SCSI;
4455 		}
4456 
4457 		else if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
4458 			/* Make sure this is not a phony BUS_FREE.  If we were
4459 			   reselected or if BUSY is NOT on then this is a
4460 			   valid BUS FREE.  SRR Wednesday, 5/10/1995.     */
4461 
4462 			if ((!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ||
4463 			    (RDW_HARPOON((port + hp_intstat)) & RSEL)) {
4464 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4465 				    TarStatus &= ~TAR_TAG_Q_MASK;
4466 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4467 				    TarStatus |= TAG_Q_REJECT;
4468 			}
4469 
4470 			else {
4471 				return;
4472 			}
4473 		}
4474 
4475 		else {
4476 
4477 			currSCCB->Sccb_scsistat = BUS_FREE_ST;
4478 
4479 			if (!currSCCB->HostStatus) {
4480 				currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4481 			}
4482 
4483 			if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4484 			    ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4485 			      TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4486 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4487 				    TarLUNBusy[currSCCB->Lun] = 0;
4488 			else
4489 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4490 				    TarLUNBusy[0] = 0;
4491 
4492 			FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
4493 					     p_card);
4494 			return;
4495 		}
4496 
4497 		FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
4498 
4499 	}			/*end if !=null */
4500 }
4501 
4502 /*---------------------------------------------------------------------
4503  *
4504  * Function: Auto Load Default Map
4505  *
4506  * Description: Load the Automation RAM with the default map values.
4507  *
4508  *---------------------------------------------------------------------*/
4509 static void FPT_autoLoadDefaultMap(u32 p_port)
4510 {
4511 	u32 map_addr;
4512 
4513 	ARAM_ACCESS(p_port);
4514 	map_addr = p_port + hp_aramBase;
4515 
4516 	WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0xC0));	/*ID MESSAGE */
4517 	map_addr += 2;
4518 	WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x20));	/*SIMPLE TAG QUEUEING MSG */
4519 	map_addr += 2;
4520 	WRW_HARPOON(map_addr, RAT_OP);	/*RESET ATTENTION */
4521 	map_addr += 2;
4522 	WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x00));	/*TAG ID MSG */
4523 	map_addr += 2;
4524 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 0 */
4525 	map_addr += 2;
4526 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 1 */
4527 	map_addr += 2;
4528 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 2 */
4529 	map_addr += 2;
4530 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 3 */
4531 	map_addr += 2;
4532 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 4 */
4533 	map_addr += 2;
4534 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 5 */
4535 	map_addr += 2;
4536 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 6 */
4537 	map_addr += 2;
4538 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 7 */
4539 	map_addr += 2;
4540 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 8 */
4541 	map_addr += 2;
4542 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 9 */
4543 	map_addr += 2;
4544 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 10 */
4545 	map_addr += 2;
4546 	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 11 */
4547 	map_addr += 2;
4548 	WRW_HARPOON(map_addr, (CPE_OP + ADATA_OUT + DINT));	/*JUMP IF DATA OUT */
4549 	map_addr += 2;
4550 	WRW_HARPOON(map_addr, (TCB_OP + FIFO_0 + DI));	/*JUMP IF NO DATA IN FIFO */
4551 	map_addr += 2;		/*This means AYNC DATA IN */
4552 	WRW_HARPOON(map_addr, (SSI_OP + SSI_IDO_STRT));	/*STOP AND INTERRUPT */
4553 	map_addr += 2;
4554 	WRW_HARPOON(map_addr, (CPE_OP + ADATA_IN + DINT));	/*JUMP IF NOT DATA IN PHZ */
4555 	map_addr += 2;
4556 	WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST));	/*IF NOT MSG IN CHECK 4 DATA IN */
4557 	map_addr += 2;
4558 	WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x02));	/*SAVE DATA PTR MSG? */
4559 	map_addr += 2;
4560 	WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + DC));	/*GO CHECK FOR DISCONNECT MSG */
4561 	map_addr += 2;
4562 	WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR1));	/*SAVE DATA PTRS MSG */
4563 	map_addr += 2;
4564 	WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST));	/*IF NOT MSG IN CHECK DATA IN */
4565 	map_addr += 2;
4566 	WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x04));	/*DISCONNECT MSG? */
4567 	map_addr += 2;
4568 	WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + UNKNWN));	/*UKNKNOWN MSG */
4569 	map_addr += 2;
4570 	WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET));	/*XFER DISCONNECT MSG */
4571 	map_addr += 2;
4572 	WRW_HARPOON(map_addr, (SSI_OP + SSI_ITAR_DISC));	/*STOP AND INTERRUPT */
4573 	map_addr += 2;
4574 	WRW_HARPOON(map_addr, (CPN_OP + ASTATUS + UNKNWN));	/*JUMP IF NOT STATUS PHZ. */
4575 	map_addr += 2;
4576 	WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR0));	/*GET STATUS BYTE */
4577 	map_addr += 2;
4578 	WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + CC));	/*ERROR IF NOT MSG IN PHZ */
4579 	map_addr += 2;
4580 	WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x00));	/*CHECK FOR CMD COMPLETE MSG. */
4581 	map_addr += 2;
4582 	WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + CC));	/*ERROR IF NOT CMD COMPLETE MSG. */
4583 	map_addr += 2;
4584 	WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET));	/*GET CMD COMPLETE MSG */
4585 	map_addr += 2;
4586 	WRW_HARPOON(map_addr, (SSI_OP + SSI_ICMD_COMP));	/*END OF COMMAND */
4587 	map_addr += 2;
4588 
4589 	WRW_HARPOON(map_addr, (SSI_OP + SSI_IUNKWN));	/*RECEIVED UNKNOWN MSG BYTE */
4590 	map_addr += 2;
4591 	WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC));	/*NO COMMAND COMPLETE AFTER STATUS */
4592 	map_addr += 2;
4593 	WRW_HARPOON(map_addr, (SSI_OP + SSI_ITICKLE));	/*BIOS Tickled the Mgr */
4594 	map_addr += 2;
4595 	WRW_HARPOON(map_addr, (SSI_OP + SSI_IRFAIL));	/*EXPECTED ID/TAG MESSAGES AND */
4596 	map_addr += 2;		/* DIDN'T GET ONE */
4597 	WRW_HARPOON(map_addr, (CRR_OP + AR3 + S_IDREG));	/* comp SCSI SEL ID & AR3 */
4598 	map_addr += 2;
4599 	WRW_HARPOON(map_addr, (BRH_OP + EQUAL + 0x00));	/*SEL ID OK then Conti. */
4600 	map_addr += 2;
4601 	WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC));	/*NO COMMAND COMPLETE AFTER STATUS */
4602 
4603 	SGRAM_ACCESS(p_port);
4604 }
4605 
4606 /*---------------------------------------------------------------------
4607  *
4608  * Function: Auto Command Complete
4609  *
4610  * Description: Post command back to host and find another command
4611  *              to execute.
4612  *
4613  *---------------------------------------------------------------------*/
4614 
4615 static void FPT_autoCmdCmplt(u32 p_port, unsigned char p_card)
4616 {
4617 	struct sccb *currSCCB;
4618 	unsigned char status_byte;
4619 
4620 	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4621 
4622 	status_byte = RD_HARPOON(p_port + hp_gp_reg_0);
4623 
4624 	FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA = 0;
4625 
4626 	if (status_byte != SAM_STAT_GOOD) {
4627 
4628 		if (status_byte == SAM_STAT_TASK_SET_FULL) {
4629 
4630 			if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4631 			     ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4632 			       TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4633 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4634 				    TarLUNBusy[currSCCB->Lun] = 1;
4635 				if (FPT_BL_Card[p_card].discQCount != 0)
4636 					FPT_BL_Card[p_card].discQCount--;
4637 				FPT_BL_Card[p_card].
4638 				    discQ_Tbl[FPT_sccbMgrTbl[p_card]
4639 					      [currSCCB->TargID].
4640 					      LunDiscQ_Idx[currSCCB->Lun]] =
4641 				    NULL;
4642 			} else {
4643 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4644 				    TarLUNBusy[0] = 1;
4645 				if (currSCCB->Sccb_tag) {
4646 					if (FPT_BL_Card[p_card].discQCount != 0)
4647 						FPT_BL_Card[p_card].
4648 						    discQCount--;
4649 					FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4650 								      Sccb_tag]
4651 					    = NULL;
4652 				} else {
4653 					if (FPT_BL_Card[p_card].discQCount != 0)
4654 						FPT_BL_Card[p_card].
4655 						    discQCount--;
4656 					FPT_BL_Card[p_card].
4657 					    discQ_Tbl[FPT_sccbMgrTbl[p_card]
4658 						      [currSCCB->TargID].
4659 						      LunDiscQ_Idx[0]] = NULL;
4660 				}
4661 			}
4662 
4663 			currSCCB->Sccb_MGRFlags |= F_STATUSLOADED;
4664 
4665 			FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
4666 
4667 			return;
4668 		}
4669 
4670 		if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
4671 			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4672 			    (unsigned char)SYNC_SUPPORTED;
4673 
4674 			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4675 			    ~EE_SYNC_MASK;
4676 			FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
4677 
4678 			if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4679 			     ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4680 			       TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4681 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4682 				    TarLUNBusy[currSCCB->Lun] = 1;
4683 				if (FPT_BL_Card[p_card].discQCount != 0)
4684 					FPT_BL_Card[p_card].discQCount--;
4685 				FPT_BL_Card[p_card].
4686 				    discQ_Tbl[FPT_sccbMgrTbl[p_card]
4687 					      [currSCCB->TargID].
4688 					      LunDiscQ_Idx[currSCCB->Lun]] =
4689 				    NULL;
4690 			} else {
4691 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4692 				    TarLUNBusy[0] = 1;
4693 				if (currSCCB->Sccb_tag) {
4694 					if (FPT_BL_Card[p_card].discQCount != 0)
4695 						FPT_BL_Card[p_card].
4696 						    discQCount--;
4697 					FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4698 								      Sccb_tag]
4699 					    = NULL;
4700 				} else {
4701 					if (FPT_BL_Card[p_card].discQCount != 0)
4702 						FPT_BL_Card[p_card].
4703 						    discQCount--;
4704 					FPT_BL_Card[p_card].
4705 					    discQ_Tbl[FPT_sccbMgrTbl[p_card]
4706 						      [currSCCB->TargID].
4707 						      LunDiscQ_Idx[0]] = NULL;
4708 				}
4709 			}
4710 			return;
4711 
4712 		}
4713 
4714 		if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
4715 
4716 			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
4717 			    (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4718 			     TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
4719 
4720 			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4721 			    ~EE_WIDE_SCSI;
4722 			FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
4723 
4724 			if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4725 			     ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4726 			       TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4727 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4728 				    TarLUNBusy[currSCCB->Lun] = 1;
4729 				if (FPT_BL_Card[p_card].discQCount != 0)
4730 					FPT_BL_Card[p_card].discQCount--;
4731 				FPT_BL_Card[p_card].
4732 				    discQ_Tbl[FPT_sccbMgrTbl[p_card]
4733 					      [currSCCB->TargID].
4734 					      LunDiscQ_Idx[currSCCB->Lun]] =
4735 				    NULL;
4736 			} else {
4737 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4738 				    TarLUNBusy[0] = 1;
4739 				if (currSCCB->Sccb_tag) {
4740 					if (FPT_BL_Card[p_card].discQCount != 0)
4741 						FPT_BL_Card[p_card].
4742 						    discQCount--;
4743 					FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4744 								      Sccb_tag]
4745 					    = NULL;
4746 				} else {
4747 					if (FPT_BL_Card[p_card].discQCount != 0)
4748 						FPT_BL_Card[p_card].
4749 						    discQCount--;
4750 					FPT_BL_Card[p_card].
4751 					    discQ_Tbl[FPT_sccbMgrTbl[p_card]
4752 						      [currSCCB->TargID].
4753 						      LunDiscQ_Idx[0]] = NULL;
4754 				}
4755 			}
4756 			return;
4757 
4758 		}
4759 
4760 		if (status_byte == SAM_STAT_CHECK_CONDITION) {
4761 			if (FPT_BL_Card[p_card].globalFlags & F_DO_RENEGO) {
4762 				if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4763 				    TarEEValue & EE_SYNC_MASK) {
4764 					FPT_sccbMgrTbl[p_card][currSCCB->
4765 							       TargID].
4766 					    TarStatus &= ~TAR_SYNC_MASK;
4767 				}
4768 				if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4769 				    TarEEValue & EE_WIDE_SCSI) {
4770 					FPT_sccbMgrTbl[p_card][currSCCB->
4771 							       TargID].
4772 					    TarStatus &= ~TAR_WIDE_MASK;
4773 				}
4774 			}
4775 		}
4776 
4777 		if (!(currSCCB->Sccb_XferState & F_AUTO_SENSE)) {
4778 
4779 			currSCCB->SccbStatus = SCCB_ERROR;
4780 			currSCCB->TargetStatus = status_byte;
4781 
4782 			if (status_byte == SAM_STAT_CHECK_CONDITION) {
4783 
4784 				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4785 				    TarLUN_CA = 1;
4786 
4787 				if (currSCCB->RequestSenseLength !=
4788 				    NO_AUTO_REQUEST_SENSE) {
4789 
4790 					if (currSCCB->RequestSenseLength == 0)
4791 						currSCCB->RequestSenseLength =
4792 						    14;
4793 
4794 					FPT_ssenss(&FPT_BL_Card[p_card]);
4795 					FPT_BL_Card[p_card].globalFlags |=
4796 					    F_NEW_SCCB_CMD;
4797 
4798 					if (((FPT_BL_Card[p_card].
4799 					      globalFlags & F_CONLUN_IO)
4800 					     &&
4801 					     ((FPT_sccbMgrTbl[p_card]
4802 					       [currSCCB->TargID].
4803 					       TarStatus & TAR_TAG_Q_MASK) !=
4804 					      TAG_Q_TRYING))) {
4805 						FPT_sccbMgrTbl[p_card]
4806 						    [currSCCB->TargID].
4807 						    TarLUNBusy[currSCCB->Lun] =
4808 						    1;
4809 						if (FPT_BL_Card[p_card].
4810 						    discQCount != 0)
4811 							FPT_BL_Card[p_card].
4812 							    discQCount--;
4813 						FPT_BL_Card[p_card].
4814 						    discQ_Tbl[FPT_sccbMgrTbl
4815 							      [p_card]
4816 							      [currSCCB->
4817 							       TargID].
4818 							      LunDiscQ_Idx
4819 							      [currSCCB->Lun]] =
4820 						    NULL;
4821 					} else {
4822 						FPT_sccbMgrTbl[p_card]
4823 						    [currSCCB->TargID].
4824 						    TarLUNBusy[0] = 1;
4825 						if (currSCCB->Sccb_tag) {
4826 							if (FPT_BL_Card[p_card].
4827 							    discQCount != 0)
4828 								FPT_BL_Card
4829 								    [p_card].
4830 								    discQCount--;
4831 							FPT_BL_Card[p_card].
4832 							    discQ_Tbl[currSCCB->
4833 								      Sccb_tag]
4834 							    = NULL;
4835 						} else {
4836 							if (FPT_BL_Card[p_card].
4837 							    discQCount != 0)
4838 								FPT_BL_Card
4839 								    [p_card].
4840 								    discQCount--;
4841 							FPT_BL_Card[p_card].
4842 							    discQ_Tbl
4843 							    [FPT_sccbMgrTbl
4844 							     [p_card][currSCCB->
4845 								      TargID].
4846 							     LunDiscQ_Idx[0]] =
4847 							    NULL;
4848 						}
4849 					}
4850 					return;
4851 				}
4852 			}
4853 		}
4854 	}
4855 
4856 	if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4857 	    ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4858 	      TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4859 		FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->
4860 								    Lun] = 0;
4861 	else
4862 		FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0;
4863 
4864 	FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, p_card);
4865 }
4866 
4867 #define SHORT_WAIT   0x0000000F
4868 #define LONG_WAIT    0x0000FFFFL
4869 
4870 /*---------------------------------------------------------------------
4871  *
4872  * Function: Data Transfer Processor
4873  *
4874  * Description: This routine performs two tasks.
4875  *              (1) Start data transfer by calling HOST_DATA_XFER_START
4876  *              function.  Once data transfer is started, (2) Depends
4877  *              on the type of data transfer mode Scatter/Gather mode
4878  *              or NON Scatter/Gather mode.  In NON Scatter/Gather mode,
4879  *              this routine checks Sccb_MGRFlag (F_HOST_XFER_ACT bit) for
4880  *              data transfer done.  In Scatter/Gather mode, this routine
4881  *              checks bus master command complete and dual rank busy
4882  *              bit to keep chaining SC transfer command.  Similarly,
4883  *              in Scatter/Gather mode, it checks Sccb_MGRFlag
4884  *              (F_HOST_XFER_ACT bit) for data transfer done.
4885  *
4886  *---------------------------------------------------------------------*/
4887 
4888 static void FPT_dataXferProcessor(u32 port, struct sccb_card *pCurrCard)
4889 {
4890 	struct sccb *currSCCB;
4891 
4892 	currSCCB = pCurrCard->currentSCCB;
4893 
4894 	if (currSCCB->Sccb_XferState & F_SG_XFER) {
4895 		if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
4896 		{
4897 			currSCCB->Sccb_sgseg += (unsigned char)SG_BUF_CNT;
4898 			currSCCB->Sccb_SGoffset = 0x00;
4899 		}
4900 		pCurrCard->globalFlags |= F_HOST_XFER_ACT;
4901 
4902 		FPT_busMstrSGDataXferStart(port, currSCCB);
4903 	}
4904 
4905 	else {
4906 		if (!(pCurrCard->globalFlags & F_HOST_XFER_ACT)) {
4907 			pCurrCard->globalFlags |= F_HOST_XFER_ACT;
4908 
4909 			FPT_busMstrDataXferStart(port, currSCCB);
4910 		}
4911 	}
4912 }
4913 
4914 /*---------------------------------------------------------------------
4915  *
4916  * Function: BusMaster Scatter Gather Data Transfer Start
4917  *
4918  * Description:
4919  *
4920  *---------------------------------------------------------------------*/
4921 static void FPT_busMstrSGDataXferStart(u32 p_port, struct sccb *pcurrSCCB)
4922 {
4923 	u32 count, addr, tmpSGCnt;
4924 	unsigned int sg_index;
4925 	unsigned char sg_count, i;
4926 	u32 reg_offset;
4927 	struct blogic_sg_seg *segp;
4928 
4929 	if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)
4930 		count = ((u32)HOST_RD_CMD) << 24;
4931 	else
4932 		count = ((u32)HOST_WRT_CMD) << 24;
4933 
4934 	sg_count = 0;
4935 	tmpSGCnt = 0;
4936 	sg_index = pcurrSCCB->Sccb_sgseg;
4937 	reg_offset = hp_aramBase;
4938 
4939 	i = (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
4940 			    ~(SGRAM_ARAM | SCATTER_EN));
4941 
4942 	WR_HARPOON(p_port + hp_page_ctrl, i);
4943 
4944 	while ((sg_count < (unsigned char)SG_BUF_CNT) &&
4945 			((sg_index * (unsigned int)SG_ELEMENT_SIZE) <
4946 			pcurrSCCB->DataLength)) {
4947 
4948 		segp = (struct blogic_sg_seg *)(pcurrSCCB->DataPointer) +
4949 				sg_index;
4950 		tmpSGCnt += segp->segbytes;
4951 		count |= segp->segbytes;
4952 		addr = segp->segdata;
4953 
4954 		if ((!sg_count) && (pcurrSCCB->Sccb_SGoffset)) {
4955 			addr +=
4956 			    ((count & 0x00FFFFFFL) - pcurrSCCB->Sccb_SGoffset);
4957 			count =
4958 			    (count & 0xFF000000L) | pcurrSCCB->Sccb_SGoffset;
4959 			tmpSGCnt = count & 0x00FFFFFFL;
4960 		}
4961 
4962 		WR_HARP32(p_port, reg_offset, addr);
4963 		reg_offset += 4;
4964 
4965 		WR_HARP32(p_port, reg_offset, count);
4966 		reg_offset += 4;
4967 
4968 		count &= 0xFF000000L;
4969 		sg_index++;
4970 		sg_count++;
4971 
4972 	}			/*End While */
4973 
4974 	pcurrSCCB->Sccb_XferCnt = tmpSGCnt;
4975 
4976 	WR_HARPOON(p_port + hp_sg_addr, (sg_count << 4));
4977 
4978 	if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
4979 
4980 		WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
4981 
4982 		WR_HARPOON(p_port + hp_portctrl_0,
4983 			   (DMA_PORT | SCSI_PORT | SCSI_INBIT));
4984 		WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
4985 	}
4986 
4987 	else {
4988 
4989 		if ((!(RD_HARPOON(p_port + hp_synctarg_0) & NARROW_SCSI)) &&
4990 		    (tmpSGCnt & 0x000000001)) {
4991 
4992 			pcurrSCCB->Sccb_XferState |= F_ODD_BALL_CNT;
4993 			tmpSGCnt--;
4994 		}
4995 
4996 		WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
4997 
4998 		WR_HARPOON(p_port + hp_portctrl_0,
4999 			   (SCSI_PORT | DMA_PORT | DMA_RD));
5000 		WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
5001 	}
5002 
5003 	WR_HARPOON(p_port + hp_page_ctrl, (unsigned char)(i | SCATTER_EN));
5004 
5005 }
5006 
5007 /*---------------------------------------------------------------------
5008  *
5009  * Function: BusMaster Data Transfer Start
5010  *
5011  * Description:
5012  *
5013  *---------------------------------------------------------------------*/
5014 static void FPT_busMstrDataXferStart(u32 p_port, struct sccb *pcurrSCCB)
5015 {
5016 	u32 addr, count;
5017 
5018 	if (!(pcurrSCCB->Sccb_XferState & F_AUTO_SENSE)) {
5019 
5020 		count = pcurrSCCB->Sccb_XferCnt;
5021 
5022 		addr = (u32)(unsigned long)pcurrSCCB->DataPointer + pcurrSCCB->Sccb_ATC;
5023 	}
5024 
5025 	else {
5026 		addr = pcurrSCCB->SensePointer;
5027 		count = pcurrSCCB->RequestSenseLength;
5028 
5029 	}
5030 
5031 	HP_SETUP_ADDR_CNT(p_port, addr, count);
5032 
5033 	if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
5034 
5035 		WR_HARPOON(p_port + hp_portctrl_0,
5036 			   (DMA_PORT | SCSI_PORT | SCSI_INBIT));
5037 		WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
5038 
5039 		WR_HARPOON(p_port + hp_xfer_cmd,
5040 			   (XFER_DMA_HOST | XFER_HOST_AUTO | XFER_DMA_8BIT));
5041 	}
5042 
5043 	else {
5044 
5045 		WR_HARPOON(p_port + hp_portctrl_0,
5046 			   (SCSI_PORT | DMA_PORT | DMA_RD));
5047 		WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
5048 
5049 		WR_HARPOON(p_port + hp_xfer_cmd,
5050 			   (XFER_HOST_DMA | XFER_HOST_AUTO | XFER_DMA_8BIT));
5051 
5052 	}
5053 }
5054 
5055 /*---------------------------------------------------------------------
5056  *
5057  * Function: BusMaster Timeout Handler
5058  *
5059  * Description: This function is called after a bus master command busy time
5060  *               out is detected.  This routines issue halt state machine
5061  *               with a software time out for command busy.  If command busy
5062  *               is still asserted at the end of the time out, it issues
5063  *               hard abort with another software time out.  It hard abort
5064  *               command busy is also time out, it'll just give up.
5065  *
5066  *---------------------------------------------------------------------*/
5067 static unsigned char FPT_busMstrTimeOut(u32 p_port)
5068 {
5069 	unsigned long timeout;
5070 
5071 	timeout = LONG_WAIT;
5072 
5073 	WR_HARPOON(p_port + hp_sys_ctrl, HALT_MACH);
5074 
5075 	while ((!(RD_HARPOON(p_port + hp_ext_status) & CMD_ABORTED))
5076 	       && timeout--) {
5077 	}
5078 
5079 	if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
5080 		WR_HARPOON(p_port + hp_sys_ctrl, HARD_ABORT);
5081 
5082 		timeout = LONG_WAIT;
5083 		while ((RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY)
5084 		       && timeout--) {
5085 		}
5086 	}
5087 
5088 	RD_HARPOON(p_port + hp_int_status);	/*Clear command complete */
5089 
5090 	if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
5091 		return 1;
5092 	}
5093 
5094 	else {
5095 		return 0;
5096 	}
5097 }
5098 
5099 /*---------------------------------------------------------------------
5100  *
5101  * Function: Host Data Transfer Abort
5102  *
5103  * Description: Abort any in progress transfer.
5104  *
5105  *---------------------------------------------------------------------*/
5106 static void FPT_hostDataXferAbort(u32 port, unsigned char p_card,
5107 				  struct sccb *pCurrSCCB)
5108 {
5109 
5110 	unsigned long timeout;
5111 	unsigned long remain_cnt;
5112 	u32 sg_ptr;
5113 	struct blogic_sg_seg *segp;
5114 
5115 	FPT_BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT;
5116 
5117 	if (pCurrSCCB->Sccb_XferState & F_AUTO_SENSE) {
5118 
5119 		if (!(RD_HARPOON(port + hp_int_status) & INT_CMD_COMPL)) {
5120 
5121 			WR_HARPOON(port + hp_bm_ctrl,
5122 				   (RD_HARPOON(port + hp_bm_ctrl) |
5123 				    FLUSH_XFER_CNTR));
5124 			timeout = LONG_WAIT;
5125 
5126 			while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
5127 			       && timeout--) {
5128 			}
5129 
5130 			WR_HARPOON(port + hp_bm_ctrl,
5131 				   (RD_HARPOON(port + hp_bm_ctrl) &
5132 				    ~FLUSH_XFER_CNTR));
5133 
5134 			if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
5135 
5136 				if (FPT_busMstrTimeOut(port)) {
5137 
5138 					if (pCurrSCCB->HostStatus == 0x00)
5139 
5140 						pCurrSCCB->HostStatus =
5141 						    SCCB_BM_ERR;
5142 
5143 				}
5144 
5145 				if (RD_HARPOON(port + hp_int_status) &
5146 				    INT_EXT_STATUS)
5147 
5148 					if (RD_HARPOON(port + hp_ext_status) &
5149 					    BAD_EXT_STATUS)
5150 
5151 						if (pCurrSCCB->HostStatus ==
5152 						    0x00)
5153 						{
5154 							pCurrSCCB->HostStatus =
5155 							    SCCB_BM_ERR;
5156 						}
5157 			}
5158 		}
5159 	}
5160 
5161 	else if (pCurrSCCB->Sccb_XferCnt) {
5162 
5163 		if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
5164 
5165 			WR_HARPOON(port + hp_page_ctrl,
5166 				   (RD_HARPOON(port + hp_page_ctrl) &
5167 				    ~SCATTER_EN));
5168 
5169 			WR_HARPOON(port + hp_sg_addr, 0x00);
5170 
5171 			sg_ptr = pCurrSCCB->Sccb_sgseg + SG_BUF_CNT;
5172 
5173 			if (sg_ptr >
5174 			    (unsigned int)(pCurrSCCB->DataLength /
5175 					   SG_ELEMENT_SIZE)) {
5176 
5177 				sg_ptr = (u32)(pCurrSCCB->DataLength /
5178 							SG_ELEMENT_SIZE);
5179 			}
5180 
5181 			remain_cnt = pCurrSCCB->Sccb_XferCnt;
5182 
5183 			while (remain_cnt < 0x01000000L) {
5184 
5185 				sg_ptr--;
5186 				segp = (struct blogic_sg_seg *)(pCurrSCCB->
5187 						DataPointer) + (sg_ptr * 2);
5188 				if (remain_cnt > (unsigned long)segp->segbytes)
5189 					remain_cnt -=
5190 						(unsigned long)segp->segbytes;
5191 				else
5192 					break;
5193 			}
5194 
5195 			if (remain_cnt < 0x01000000L) {
5196 
5197 				pCurrSCCB->Sccb_SGoffset = remain_cnt;
5198 
5199 				pCurrSCCB->Sccb_sgseg = (unsigned short)sg_ptr;
5200 
5201 				if ((unsigned long)(sg_ptr * SG_ELEMENT_SIZE) ==
5202 				    pCurrSCCB->DataLength && (remain_cnt == 0))
5203 
5204 					pCurrSCCB->Sccb_XferState |=
5205 					    F_ALL_XFERRED;
5206 			}
5207 
5208 			else {
5209 
5210 				if (pCurrSCCB->HostStatus == 0x00) {
5211 
5212 					pCurrSCCB->HostStatus =
5213 					    SCCB_GROSS_FW_ERR;
5214 				}
5215 			}
5216 		}
5217 
5218 		if (!(pCurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)) {
5219 
5220 			if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
5221 
5222 				FPT_busMstrTimeOut(port);
5223 			}
5224 
5225 			else {
5226 
5227 				if (RD_HARPOON(port + hp_int_status) &
5228 				    INT_EXT_STATUS) {
5229 
5230 					if (RD_HARPOON(port + hp_ext_status) &
5231 					    BAD_EXT_STATUS) {
5232 
5233 						if (pCurrSCCB->HostStatus ==
5234 						    0x00) {
5235 
5236 							pCurrSCCB->HostStatus =
5237 							    SCCB_BM_ERR;
5238 						}
5239 					}
5240 				}
5241 
5242 			}
5243 		}
5244 
5245 		else {
5246 
5247 			if ((RD_HARPOON(port + hp_fifo_cnt)) >= BM_THRESHOLD) {
5248 
5249 				timeout = SHORT_WAIT;
5250 
5251 				while ((RD_HARPOON(port + hp_ext_status) &
5252 					BM_CMD_BUSY)
5253 				       && ((RD_HARPOON(port + hp_fifo_cnt)) >=
5254 					   BM_THRESHOLD) && timeout--) {
5255 				}
5256 			}
5257 
5258 			if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
5259 
5260 				WR_HARPOON(port + hp_bm_ctrl,
5261 					   (RD_HARPOON(port + hp_bm_ctrl) |
5262 					    FLUSH_XFER_CNTR));
5263 
5264 				timeout = LONG_WAIT;
5265 
5266 				while ((RD_HARPOON(port + hp_ext_status) &
5267 					BM_CMD_BUSY) && timeout--) {
5268 				}
5269 
5270 				WR_HARPOON(port + hp_bm_ctrl,
5271 					   (RD_HARPOON(port + hp_bm_ctrl) &
5272 					    ~FLUSH_XFER_CNTR));
5273 
5274 				if (RD_HARPOON(port + hp_ext_status) &
5275 				    BM_CMD_BUSY) {
5276 
5277 					if (pCurrSCCB->HostStatus == 0x00) {
5278 
5279 						pCurrSCCB->HostStatus =
5280 						    SCCB_BM_ERR;
5281 					}
5282 
5283 					FPT_busMstrTimeOut(port);
5284 				}
5285 			}
5286 
5287 			if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
5288 
5289 				if (RD_HARPOON(port + hp_ext_status) &
5290 				    BAD_EXT_STATUS) {
5291 
5292 					if (pCurrSCCB->HostStatus == 0x00) {
5293 
5294 						pCurrSCCB->HostStatus =
5295 						    SCCB_BM_ERR;
5296 					}
5297 				}
5298 			}
5299 		}
5300 
5301 	}
5302 
5303 	else {
5304 
5305 		if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
5306 
5307 			timeout = LONG_WAIT;
5308 
5309 			while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
5310 			       && timeout--) {
5311 			}
5312 
5313 			if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
5314 
5315 				if (pCurrSCCB->HostStatus == 0x00) {
5316 
5317 					pCurrSCCB->HostStatus = SCCB_BM_ERR;
5318 				}
5319 
5320 				FPT_busMstrTimeOut(port);
5321 			}
5322 		}
5323 
5324 		if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
5325 
5326 			if (RD_HARPOON(port + hp_ext_status) & BAD_EXT_STATUS) {
5327 
5328 				if (pCurrSCCB->HostStatus == 0x00) {
5329 
5330 					pCurrSCCB->HostStatus = SCCB_BM_ERR;
5331 				}
5332 			}
5333 
5334 		}
5335 
5336 		if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
5337 
5338 			WR_HARPOON(port + hp_page_ctrl,
5339 				   (RD_HARPOON(port + hp_page_ctrl) &
5340 				    ~SCATTER_EN));
5341 
5342 			WR_HARPOON(port + hp_sg_addr, 0x00);
5343 
5344 			pCurrSCCB->Sccb_sgseg += SG_BUF_CNT;
5345 
5346 			pCurrSCCB->Sccb_SGoffset = 0x00;
5347 
5348 			if ((u32)(pCurrSCCB->Sccb_sgseg * SG_ELEMENT_SIZE) >=
5349 					pCurrSCCB->DataLength) {
5350 
5351 				pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
5352 				pCurrSCCB->Sccb_sgseg =
5353 				    (unsigned short)(pCurrSCCB->DataLength /
5354 						     SG_ELEMENT_SIZE);
5355 			}
5356 		}
5357 
5358 		else {
5359 			if (!(pCurrSCCB->Sccb_XferState & F_AUTO_SENSE))
5360 				pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
5361 		}
5362 	}
5363 
5364 	WR_HARPOON(port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
5365 }
5366 
5367 /*---------------------------------------------------------------------
5368  *
5369  * Function: Host Data Transfer Restart
5370  *
5371  * Description: Reset the available count due to a restore data
5372  *              pointers message.
5373  *
5374  *---------------------------------------------------------------------*/
5375 static void FPT_hostDataXferRestart(struct sccb *currSCCB)
5376 {
5377 	unsigned long data_count;
5378 	unsigned int sg_index;
5379 	struct blogic_sg_seg *segp;
5380 
5381 	if (currSCCB->Sccb_XferState & F_SG_XFER) {
5382 
5383 		currSCCB->Sccb_XferCnt = 0;
5384 
5385 		sg_index = 0xffff;	/*Index by long words into sg list. */
5386 		data_count = 0;		/*Running count of SG xfer counts. */
5387 
5388 
5389 		while (data_count < currSCCB->Sccb_ATC) {
5390 
5391 			sg_index++;
5392 			segp = (struct blogic_sg_seg *)(currSCCB->DataPointer) +
5393 						(sg_index * 2);
5394 			data_count += segp->segbytes;
5395 		}
5396 
5397 		if (data_count == currSCCB->Sccb_ATC) {
5398 
5399 			currSCCB->Sccb_SGoffset = 0;
5400 			sg_index++;
5401 		}
5402 
5403 		else {
5404 			currSCCB->Sccb_SGoffset =
5405 			    data_count - currSCCB->Sccb_ATC;
5406 		}
5407 
5408 		currSCCB->Sccb_sgseg = (unsigned short)sg_index;
5409 	}
5410 
5411 	else {
5412 		currSCCB->Sccb_XferCnt =
5413 		    currSCCB->DataLength - currSCCB->Sccb_ATC;
5414 	}
5415 }
5416 
5417 /*---------------------------------------------------------------------
5418  *
5419  * Function: FPT_scini
5420  *
5421  * Description: Setup all data structures necessary for SCAM selection.
5422  *
5423  *---------------------------------------------------------------------*/
5424 
5425 static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
5426 		      unsigned char p_power_up)
5427 {
5428 
5429 	unsigned char loser, assigned_id;
5430 	u32 p_port;
5431 
5432 	unsigned char i, k, ScamFlg;
5433 	struct sccb_card *currCard;
5434 	struct nvram_info *pCurrNvRam;
5435 
5436 	currCard = &FPT_BL_Card[p_card];
5437 	p_port = currCard->ioPort;
5438 	pCurrNvRam = currCard->pNvRamInfo;
5439 
5440 	if (pCurrNvRam) {
5441 		ScamFlg = pCurrNvRam->niScamConf;
5442 		i = pCurrNvRam->niSysConf;
5443 	} else {
5444 		ScamFlg =
5445 		    (unsigned char)FPT_utilEERead(p_port, SCAM_CONFIG / 2);
5446 		i = (unsigned
5447 		     char)(FPT_utilEERead(p_port, (SYSTEM_CONFIG / 2)));
5448 	}
5449 	if (!(i & 0x02))	/* check if reset bus in AutoSCSI parameter set */
5450 		return;
5451 
5452 	FPT_inisci(p_card, p_port, p_our_id);
5453 
5454 	/* Force to wait 1 sec after SCSI bus reset. Some SCAM device FW
5455 	   too slow to return to SCAM selection */
5456 
5457 	/* if (p_power_up)
5458 	   FPT_Wait1Second(p_port);
5459 	   else
5460 	   FPT_Wait(p_port, TO_250ms); */
5461 
5462 	FPT_Wait1Second(p_port);
5463 
5464 	if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2)) {
5465 		while (!(FPT_scarb(p_port, INIT_SELTD))) {
5466 		}
5467 
5468 		FPT_scsel(p_port);
5469 
5470 		do {
5471 			FPT_scxferc(p_port, SYNC_PTRN);
5472 			FPT_scxferc(p_port, DOM_MSTR);
5473 			loser =
5474 			    FPT_scsendi(p_port,
5475 					&FPT_scamInfo[p_our_id].id_string[0]);
5476 		} while (loser == 0xFF);
5477 
5478 		FPT_scbusf(p_port);
5479 
5480 		if ((p_power_up) && (!loser)) {
5481 			FPT_sresb(p_port, p_card);
5482 			FPT_Wait(p_port, TO_250ms);
5483 
5484 			while (!(FPT_scarb(p_port, INIT_SELTD))) {
5485 			}
5486 
5487 			FPT_scsel(p_port);
5488 
5489 			do {
5490 				FPT_scxferc(p_port, SYNC_PTRN);
5491 				FPT_scxferc(p_port, DOM_MSTR);
5492 				loser =
5493 				    FPT_scsendi(p_port,
5494 						&FPT_scamInfo[p_our_id].
5495 						id_string[0]);
5496 			} while (loser == 0xFF);
5497 
5498 			FPT_scbusf(p_port);
5499 		}
5500 	}
5501 
5502 	else {
5503 		loser = 0;
5504 	}
5505 
5506 	if (!loser) {
5507 
5508 		FPT_scamInfo[p_our_id].state = ID_ASSIGNED;
5509 
5510 		if (ScamFlg & SCAM_ENABLED) {
5511 
5512 			for (i = 0; i < MAX_SCSI_TAR; i++) {
5513 				if ((FPT_scamInfo[i].state == ID_UNASSIGNED) ||
5514 				    (FPT_scamInfo[i].state == ID_UNUSED)) {
5515 					if (FPT_scsell(p_port, i)) {
5516 						FPT_scamInfo[i].state = LEGACY;
5517 						if ((FPT_scamInfo[i].
5518 						     id_string[0] != 0xFF)
5519 						    || (FPT_scamInfo[i].
5520 							id_string[1] != 0xFA)) {
5521 
5522 							FPT_scamInfo[i].
5523 							    id_string[0] = 0xFF;
5524 							FPT_scamInfo[i].
5525 							    id_string[1] = 0xFA;
5526 							if (pCurrNvRam == NULL)
5527 								currCard->
5528 								    globalFlags
5529 								    |=
5530 								    F_UPDATE_EEPROM;
5531 						}
5532 					}
5533 				}
5534 			}
5535 
5536 			FPT_sresb(p_port, p_card);
5537 			FPT_Wait1Second(p_port);
5538 			while (!(FPT_scarb(p_port, INIT_SELTD))) {
5539 			}
5540 			FPT_scsel(p_port);
5541 			FPT_scasid(p_card, p_port);
5542 		}
5543 
5544 	}
5545 
5546 	else if ((loser) && (ScamFlg & SCAM_ENABLED)) {
5547 		FPT_scamInfo[p_our_id].id_string[0] = SLV_TYPE_CODE0;
5548 		assigned_id = 0;
5549 		FPT_scwtsel(p_port);
5550 
5551 		do {
5552 			while (FPT_scxferc(p_port, 0x00) != SYNC_PTRN) {
5553 			}
5554 
5555 			i = FPT_scxferc(p_port, 0x00);
5556 			if (i == ASSIGN_ID) {
5557 				if (!
5558 				    (FPT_scsendi
5559 				     (p_port,
5560 				      &FPT_scamInfo[p_our_id].id_string[0]))) {
5561 					i = FPT_scxferc(p_port, 0x00);
5562 					if (FPT_scvalq(i)) {
5563 						k = FPT_scxferc(p_port, 0x00);
5564 
5565 						if (FPT_scvalq(k)) {
5566 							currCard->ourId =
5567 							    ((unsigned char)(i
5568 									     <<
5569 									     3)
5570 							     +
5571 							     (k &
5572 							      (unsigned char)7))
5573 							    & (unsigned char)
5574 							    0x3F;
5575 							FPT_inisci(p_card,
5576 								   p_port,
5577 								   p_our_id);
5578 							FPT_scamInfo[currCard->
5579 								     ourId].
5580 							    state = ID_ASSIGNED;
5581 							FPT_scamInfo[currCard->
5582 								     ourId].
5583 							    id_string[0]
5584 							    = SLV_TYPE_CODE0;
5585 							assigned_id = 1;
5586 						}
5587 					}
5588 				}
5589 			}
5590 
5591 			else if (i == SET_P_FLAG) {
5592 				if (!(FPT_scsendi(p_port,
5593 						  &FPT_scamInfo[p_our_id].
5594 						  id_string[0])))
5595 					FPT_scamInfo[p_our_id].id_string[0] |=
5596 					    0x80;
5597 			}
5598 		} while (!assigned_id);
5599 
5600 		while (FPT_scxferc(p_port, 0x00) != CFG_CMPLT) {
5601 		}
5602 	}
5603 
5604 	if (ScamFlg & SCAM_ENABLED) {
5605 		FPT_scbusf(p_port);
5606 		if (currCard->globalFlags & F_UPDATE_EEPROM) {
5607 			FPT_scsavdi(p_card, p_port);
5608 			currCard->globalFlags &= ~F_UPDATE_EEPROM;
5609 		}
5610 	}
5611 
5612 /*
5613    for (i=0,k=0; i < MAX_SCSI_TAR; i++)
5614       {
5615       if ((FPT_scamInfo[i].state == ID_ASSIGNED) ||
5616          (FPT_scamInfo[i].state == LEGACY))
5617          k++;
5618       }
5619 
5620    if (k==2)
5621       currCard->globalFlags |= F_SINGLE_DEVICE;
5622    else
5623       currCard->globalFlags &= ~F_SINGLE_DEVICE;
5624 */
5625 }
5626 
5627 /*---------------------------------------------------------------------
5628  *
5629  * Function: FPT_scarb
5630  *
5631  * Description: Gain control of the bus and wait SCAM select time (250ms)
5632  *
5633  *---------------------------------------------------------------------*/
5634 
5635 static int FPT_scarb(u32 p_port, unsigned char p_sel_type)
5636 {
5637 	if (p_sel_type == INIT_SELTD) {
5638 
5639 		while (RD_HARPOON(p_port + hp_scsisig) & (SCSI_SEL | SCSI_BSY)) {
5640 		}
5641 
5642 		if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL)
5643 			return 0;
5644 
5645 		if (RD_HARPOON(p_port + hp_scsidata_0) != 00)
5646 			return 0;
5647 
5648 		WR_HARPOON(p_port + hp_scsisig,
5649 			   (RD_HARPOON(p_port + hp_scsisig) | SCSI_BSY));
5650 
5651 		if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL) {
5652 
5653 			WR_HARPOON(p_port + hp_scsisig,
5654 				   (RD_HARPOON(p_port + hp_scsisig) &
5655 				    ~SCSI_BSY));
5656 			return 0;
5657 		}
5658 
5659 		WR_HARPOON(p_port + hp_scsisig,
5660 			   (RD_HARPOON(p_port + hp_scsisig) | SCSI_SEL));
5661 
5662 		if (RD_HARPOON(p_port + hp_scsidata_0) != 00) {
5663 
5664 			WR_HARPOON(p_port + hp_scsisig,
5665 				   (RD_HARPOON(p_port + hp_scsisig) &
5666 				    ~(SCSI_BSY | SCSI_SEL)));
5667 			return 0;
5668 		}
5669 	}
5670 
5671 	WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
5672 					   & ~ACTdeassert));
5673 	WR_HARPOON(p_port + hp_scsireset, SCAM_EN);
5674 	WR_HARPOON(p_port + hp_scsidata_0, 0x00);
5675 	WR_HARPOON(p_port + hp_scsidata_1, 0x00);
5676 	WR_HARPOON(p_port + hp_portctrl_0, SCSI_BUS_EN);
5677 
5678 	WR_HARPOON(p_port + hp_scsisig,
5679 		   (RD_HARPOON(p_port + hp_scsisig) | SCSI_MSG));
5680 
5681 	WR_HARPOON(p_port + hp_scsisig, (RD_HARPOON(p_port + hp_scsisig)
5682 					 & ~SCSI_BSY));
5683 
5684 	FPT_Wait(p_port, TO_250ms);
5685 
5686 	return 1;
5687 }
5688 
5689 /*---------------------------------------------------------------------
5690  *
5691  * Function: FPT_scbusf
5692  *
5693  * Description: Release the SCSI bus and disable SCAM selection.
5694  *
5695  *---------------------------------------------------------------------*/
5696 
5697 static void FPT_scbusf(u32 p_port)
5698 {
5699 	WR_HARPOON(p_port + hp_page_ctrl,
5700 		   (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
5701 
5702 	WR_HARPOON(p_port + hp_scsidata_0, 0x00);
5703 
5704 	WR_HARPOON(p_port + hp_portctrl_0, (RD_HARPOON(p_port + hp_portctrl_0)
5705 					    & ~SCSI_BUS_EN));
5706 
5707 	WR_HARPOON(p_port + hp_scsisig, 0x00);
5708 
5709 	WR_HARPOON(p_port + hp_scsireset, (RD_HARPOON(p_port + hp_scsireset)
5710 					   & ~SCAM_EN));
5711 
5712 	WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
5713 					   | ACTdeassert));
5714 
5715 	WRW_HARPOON((p_port + hp_intstat), (BUS_FREE | AUTO_INT | SCAM_SEL));
5716 
5717 	WR_HARPOON(p_port + hp_page_ctrl,
5718 		   (RD_HARPOON(p_port + hp_page_ctrl) & ~G_INT_DISABLE));
5719 }
5720 
5721 /*---------------------------------------------------------------------
5722  *
5723  * Function: FPT_scasid
5724  *
5725  * Description: Assign an ID to all the SCAM devices.
5726  *
5727  *---------------------------------------------------------------------*/
5728 
5729 static void FPT_scasid(unsigned char p_card, u32 p_port)
5730 {
5731 	unsigned char temp_id_string[ID_STRING_LENGTH];
5732 
5733 	unsigned char i, k, scam_id;
5734 	unsigned char crcBytes[3];
5735 	struct nvram_info *pCurrNvRam;
5736 	unsigned short *pCrcBytes;
5737 
5738 	pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
5739 
5740 	i = 0;
5741 
5742 	while (!i) {
5743 
5744 		for (k = 0; k < ID_STRING_LENGTH; k++) {
5745 			temp_id_string[k] = (unsigned char)0x00;
5746 		}
5747 
5748 		FPT_scxferc(p_port, SYNC_PTRN);
5749 		FPT_scxferc(p_port, ASSIGN_ID);
5750 
5751 		if (!(FPT_sciso(p_port, &temp_id_string[0]))) {
5752 			if (pCurrNvRam) {
5753 				pCrcBytes = (unsigned short *)&crcBytes[0];
5754 				*pCrcBytes = FPT_CalcCrc16(&temp_id_string[0]);
5755 				crcBytes[2] = FPT_CalcLrc(&temp_id_string[0]);
5756 				temp_id_string[1] = crcBytes[2];
5757 				temp_id_string[2] = crcBytes[0];
5758 				temp_id_string[3] = crcBytes[1];
5759 				for (k = 4; k < ID_STRING_LENGTH; k++)
5760 					temp_id_string[k] = (unsigned char)0x00;
5761 			}
5762 			i = FPT_scmachid(p_card, temp_id_string);
5763 
5764 			if (i == CLR_PRIORITY) {
5765 				FPT_scxferc(p_port, MISC_CODE);
5766 				FPT_scxferc(p_port, CLR_P_FLAG);
5767 				i = 0;	/*Not the last ID yet. */
5768 			}
5769 
5770 			else if (i != NO_ID_AVAIL) {
5771 				if (i < 8)
5772 					FPT_scxferc(p_port, ID_0_7);
5773 				else
5774 					FPT_scxferc(p_port, ID_8_F);
5775 
5776 				scam_id = (i & (unsigned char)0x07);
5777 
5778 				for (k = 1; k < 0x08; k <<= 1)
5779 					if (!(k & i))
5780 						scam_id += 0x08;	/*Count number of zeros in DB0-3. */
5781 
5782 				FPT_scxferc(p_port, scam_id);
5783 
5784 				i = 0;	/*Not the last ID yet. */
5785 			}
5786 		}
5787 
5788 		else {
5789 			i = 1;
5790 		}
5791 
5792 	}			/*End while */
5793 
5794 	FPT_scxferc(p_port, SYNC_PTRN);
5795 	FPT_scxferc(p_port, CFG_CMPLT);
5796 }
5797 
5798 /*---------------------------------------------------------------------
5799  *
5800  * Function: FPT_scsel
5801  *
5802  * Description: Select all the SCAM devices.
5803  *
5804  *---------------------------------------------------------------------*/
5805 
5806 static void FPT_scsel(u32 p_port)
5807 {
5808 
5809 	WR_HARPOON(p_port + hp_scsisig, SCSI_SEL);
5810 	FPT_scwiros(p_port, SCSI_MSG);
5811 
5812 	WR_HARPOON(p_port + hp_scsisig, (SCSI_SEL | SCSI_BSY));
5813 
5814 	WR_HARPOON(p_port + hp_scsisig,
5815 		   (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5816 	WR_HARPOON(p_port + hp_scsidata_0,
5817 		   (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) |
5818 				   (unsigned char)(BIT(7) + BIT(6))));
5819 
5820 	WR_HARPOON(p_port + hp_scsisig, (SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5821 	FPT_scwiros(p_port, SCSI_SEL);
5822 
5823 	WR_HARPOON(p_port + hp_scsidata_0,
5824 		   (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) &
5825 				   ~(unsigned char)BIT(6)));
5826 	FPT_scwirod(p_port, BIT(6));
5827 
5828 	WR_HARPOON(p_port + hp_scsisig,
5829 		   (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5830 }
5831 
5832 /*---------------------------------------------------------------------
5833  *
5834  * Function: FPT_scxferc
5835  *
5836  * Description: Handshake the p_data (DB4-0) across the bus.
5837  *
5838  *---------------------------------------------------------------------*/
5839 
5840 static unsigned char FPT_scxferc(u32 p_port, unsigned char p_data)
5841 {
5842 	unsigned char curr_data, ret_data;
5843 
5844 	curr_data = p_data | BIT(7) | BIT(5);	/*Start with DB7 & DB5 asserted. */
5845 
5846 	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5847 
5848 	curr_data &= ~BIT(7);
5849 
5850 	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5851 
5852 	FPT_scwirod(p_port, BIT(7));	/*Wait for DB7 to be released. */
5853 	while (!(RD_HARPOON(p_port + hp_scsidata_0) & BIT(5))) ;
5854 
5855 	ret_data = (RD_HARPOON(p_port + hp_scsidata_0) & (unsigned char)0x1F);
5856 
5857 	curr_data |= BIT(6);
5858 
5859 	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5860 
5861 	curr_data &= ~BIT(5);
5862 
5863 	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5864 
5865 	FPT_scwirod(p_port, BIT(5));	/*Wait for DB5 to be released. */
5866 
5867 	curr_data &= ~(BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));	/*Release data bits */
5868 	curr_data |= BIT(7);
5869 
5870 	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5871 
5872 	curr_data &= ~BIT(6);
5873 
5874 	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5875 
5876 	FPT_scwirod(p_port, BIT(6));	/*Wait for DB6 to be released. */
5877 
5878 	return ret_data;
5879 }
5880 
5881 /*---------------------------------------------------------------------
5882  *
5883  * Function: FPT_scsendi
5884  *
5885  * Description: Transfer our Identification string to determine if we
5886  *              will be the dominant master.
5887  *
5888  *---------------------------------------------------------------------*/
5889 
5890 static unsigned char FPT_scsendi(u32 p_port, unsigned char p_id_string[])
5891 {
5892 	unsigned char ret_data, byte_cnt, bit_cnt, defer;
5893 
5894 	defer = 0;
5895 
5896 	for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
5897 
5898 		for (bit_cnt = 0x80; bit_cnt != 0; bit_cnt >>= 1) {
5899 
5900 			if (defer)
5901 				ret_data = FPT_scxferc(p_port, 00);
5902 
5903 			else if (p_id_string[byte_cnt] & bit_cnt)
5904 
5905 				ret_data = FPT_scxferc(p_port, 02);
5906 
5907 			else {
5908 
5909 				ret_data = FPT_scxferc(p_port, 01);
5910 				if (ret_data & 02)
5911 					defer = 1;
5912 			}
5913 
5914 			if ((ret_data & 0x1C) == 0x10)
5915 				return 0x00;	/*End of isolation stage, we won! */
5916 
5917 			if (ret_data & 0x1C)
5918 				return 0xFF;
5919 
5920 			if ((defer) && (!(ret_data & 0x1F)))
5921 				return 0x01;	/*End of isolation stage, we lost. */
5922 
5923 		}		/*bit loop */
5924 
5925 	}			/*byte loop */
5926 
5927 	if (defer)
5928 		return 0x01;	/*We lost */
5929 	else
5930 		return 0;	/*We WON! Yeeessss! */
5931 }
5932 
5933 /*---------------------------------------------------------------------
5934  *
5935  * Function: FPT_sciso
5936  *
5937  * Description: Transfer the Identification string.
5938  *
5939  *---------------------------------------------------------------------*/
5940 
5941 static unsigned char FPT_sciso(u32 p_port, unsigned char p_id_string[])
5942 {
5943 	unsigned char ret_data, the_data, byte_cnt, bit_cnt;
5944 
5945 	the_data = 0;
5946 
5947 	for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
5948 
5949 		for (bit_cnt = 0; bit_cnt < 8; bit_cnt++) {
5950 
5951 			ret_data = FPT_scxferc(p_port, 0);
5952 
5953 			if (ret_data & 0xFC)
5954 				return 0xFF;
5955 
5956 			else {
5957 
5958 				the_data <<= 1;
5959 				if (ret_data & BIT(1)) {
5960 					the_data |= 1;
5961 				}
5962 			}
5963 
5964 			if ((ret_data & 0x1F) == 0) {
5965 /*
5966 				if(bit_cnt != 0 || bit_cnt != 8)
5967 				{
5968 					byte_cnt = 0;
5969 					bit_cnt = 0;
5970 					FPT_scxferc(p_port, SYNC_PTRN);
5971 					FPT_scxferc(p_port, ASSIGN_ID);
5972 					continue;
5973 				}
5974 */
5975 				if (byte_cnt)
5976 					return 0x00;
5977 				else
5978 					return 0xFF;
5979 			}
5980 
5981 		}		/*bit loop */
5982 
5983 		p_id_string[byte_cnt] = the_data;
5984 
5985 	}			/*byte loop */
5986 
5987 	return 0;
5988 }
5989 
5990 /*---------------------------------------------------------------------
5991  *
5992  * Function: FPT_scwirod
5993  *
5994  * Description: Sample the SCSI data bus making sure the signal has been
5995  *              deasserted for the correct number of consecutive samples.
5996  *
5997  *---------------------------------------------------------------------*/
5998 
5999 static void FPT_scwirod(u32 p_port, unsigned char p_data_bit)
6000 {
6001 	unsigned char i;
6002 
6003 	i = 0;
6004 	while (i < MAX_SCSI_TAR) {
6005 
6006 		if (RD_HARPOON(p_port + hp_scsidata_0) & p_data_bit)
6007 
6008 			i = 0;
6009 
6010 		else
6011 
6012 			i++;
6013 
6014 	}
6015 }
6016 
6017 /*---------------------------------------------------------------------
6018  *
6019  * Function: FPT_scwiros
6020  *
6021  * Description: Sample the SCSI Signal lines making sure the signal has been
6022  *              deasserted for the correct number of consecutive samples.
6023  *
6024  *---------------------------------------------------------------------*/
6025 
6026 static void FPT_scwiros(u32 p_port, unsigned char p_data_bit)
6027 {
6028 	unsigned char i;
6029 
6030 	i = 0;
6031 	while (i < MAX_SCSI_TAR) {
6032 
6033 		if (RD_HARPOON(p_port + hp_scsisig) & p_data_bit)
6034 
6035 			i = 0;
6036 
6037 		else
6038 
6039 			i++;
6040 
6041 	}
6042 }
6043 
6044 /*---------------------------------------------------------------------
6045  *
6046  * Function: FPT_scvalq
6047  *
6048  * Description: Make sure we received a valid data byte.
6049  *
6050  *---------------------------------------------------------------------*/
6051 
6052 static unsigned char FPT_scvalq(unsigned char p_quintet)
6053 {
6054 	unsigned char count;
6055 
6056 	for (count = 1; count < 0x08; count <<= 1) {
6057 		if (!(p_quintet & count))
6058 			p_quintet -= 0x80;
6059 	}
6060 
6061 	if (p_quintet & 0x18)
6062 		return 0;
6063 
6064 	else
6065 		return 1;
6066 }
6067 
6068 /*---------------------------------------------------------------------
6069  *
6070  * Function: FPT_scsell
6071  *
6072  * Description: Select the specified device ID using a selection timeout
6073  *              less than 4ms.  If somebody responds then it is a legacy
6074  *              drive and this ID must be marked as such.
6075  *
6076  *---------------------------------------------------------------------*/
6077 
6078 static unsigned char FPT_scsell(u32 p_port, unsigned char targ_id)
6079 {
6080 	unsigned long i;
6081 
6082 	WR_HARPOON(p_port + hp_page_ctrl,
6083 		   (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
6084 
6085 	ARAM_ACCESS(p_port);
6086 
6087 	WR_HARPOON(p_port + hp_addstat,
6088 		   (RD_HARPOON(p_port + hp_addstat) | SCAM_TIMER));
6089 	WR_HARPOON(p_port + hp_seltimeout, TO_4ms);
6090 
6091 	for (i = p_port + CMD_STRT; i < p_port + CMD_STRT + 12; i += 2) {
6092 		WRW_HARPOON(i, (MPM_OP + ACOMMAND));
6093 	}
6094 	WRW_HARPOON(i, (BRH_OP + ALWAYS + NP));
6095 
6096 	WRW_HARPOON((p_port + hp_intstat),
6097 		    (RESET | TIMEOUT | SEL | BUS_FREE | AUTO_INT));
6098 
6099 	WR_HARPOON(p_port + hp_select_id, targ_id);
6100 
6101 	WR_HARPOON(p_port + hp_portctrl_0, SCSI_PORT);
6102 	WR_HARPOON(p_port + hp_autostart_3, (SELECT | CMD_ONLY_STRT));
6103 	WR_HARPOON(p_port + hp_scsictrl_0, (SEL_TAR | ENA_RESEL));
6104 
6105 	while (!(RDW_HARPOON((p_port + hp_intstat)) &
6106 		 (RESET | PROG_HLT | TIMEOUT | AUTO_INT))) {
6107 	}
6108 
6109 	if (RDW_HARPOON((p_port + hp_intstat)) & RESET)
6110 		FPT_Wait(p_port, TO_250ms);
6111 
6112 	DISABLE_AUTO(p_port);
6113 
6114 	WR_HARPOON(p_port + hp_addstat,
6115 		   (RD_HARPOON(p_port + hp_addstat) & ~SCAM_TIMER));
6116 	WR_HARPOON(p_port + hp_seltimeout, TO_290ms);
6117 
6118 	SGRAM_ACCESS(p_port);
6119 
6120 	if (RDW_HARPOON((p_port + hp_intstat)) & (RESET | TIMEOUT)) {
6121 
6122 		WRW_HARPOON((p_port + hp_intstat),
6123 			    (RESET | TIMEOUT | SEL | BUS_FREE | PHASE));
6124 
6125 		WR_HARPOON(p_port + hp_page_ctrl,
6126 			   (RD_HARPOON(p_port + hp_page_ctrl) &
6127 			    ~G_INT_DISABLE));
6128 
6129 		return 0;	/*No legacy device */
6130 	}
6131 
6132 	else {
6133 
6134 		while (!(RDW_HARPOON((p_port + hp_intstat)) & BUS_FREE)) {
6135 			if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ) {
6136 				WR_HARPOON(p_port + hp_scsisig,
6137 					   (SCSI_ACK + S_ILL_PH));
6138 				ACCEPT_MSG(p_port);
6139 			}
6140 		}
6141 
6142 		WRW_HARPOON((p_port + hp_intstat), CLR_ALL_INT_1);
6143 
6144 		WR_HARPOON(p_port + hp_page_ctrl,
6145 			   (RD_HARPOON(p_port + hp_page_ctrl) &
6146 			    ~G_INT_DISABLE));
6147 
6148 		return 1;	/*Found one of them oldies! */
6149 	}
6150 }
6151 
6152 /*---------------------------------------------------------------------
6153  *
6154  * Function: FPT_scwtsel
6155  *
6156  * Description: Wait to be selected by another SCAM initiator.
6157  *
6158  *---------------------------------------------------------------------*/
6159 
6160 static void FPT_scwtsel(u32 p_port)
6161 {
6162 	while (!(RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL)) {
6163 	}
6164 }
6165 
6166 /*---------------------------------------------------------------------
6167  *
6168  * Function: FPT_inisci
6169  *
6170  * Description: Setup the data Structure with the info from the EEPROM.
6171  *
6172  *---------------------------------------------------------------------*/
6173 
6174 static void FPT_inisci(unsigned char p_card, u32 p_port, unsigned char p_our_id)
6175 {
6176 	unsigned char i, k, max_id;
6177 	unsigned short ee_data;
6178 	struct nvram_info *pCurrNvRam;
6179 
6180 	pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
6181 
6182 	if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6183 		max_id = 0x08;
6184 
6185 	else
6186 		max_id = 0x10;
6187 
6188 	if (pCurrNvRam) {
6189 		for (i = 0; i < max_id; i++) {
6190 
6191 			for (k = 0; k < 4; k++)
6192 				FPT_scamInfo[i].id_string[k] =
6193 				    pCurrNvRam->niScamTbl[i][k];
6194 			for (k = 4; k < ID_STRING_LENGTH; k++)
6195 				FPT_scamInfo[i].id_string[k] =
6196 				    (unsigned char)0x00;
6197 
6198 			if (FPT_scamInfo[i].id_string[0] == 0x00)
6199 				FPT_scamInfo[i].state = ID_UNUSED;	/*Default to unused ID. */
6200 			else
6201 				FPT_scamInfo[i].state = ID_UNASSIGNED;	/*Default to unassigned ID. */
6202 
6203 		}
6204 	} else {
6205 		for (i = 0; i < max_id; i++) {
6206 			for (k = 0; k < ID_STRING_LENGTH; k += 2) {
6207 				ee_data =
6208 				    FPT_utilEERead(p_port,
6209 						   (unsigned
6210 						    short)((EE_SCAMBASE / 2) +
6211 							   (unsigned short)(i *
6212 									    ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
6213 				FPT_scamInfo[i].id_string[k] =
6214 				    (unsigned char)ee_data;
6215 				ee_data >>= 8;
6216 				FPT_scamInfo[i].id_string[k + 1] =
6217 				    (unsigned char)ee_data;
6218 			}
6219 
6220 			if ((FPT_scamInfo[i].id_string[0] == 0x00) ||
6221 			    (FPT_scamInfo[i].id_string[0] == 0xFF))
6222 
6223 				FPT_scamInfo[i].state = ID_UNUSED;	/*Default to unused ID. */
6224 
6225 			else
6226 				FPT_scamInfo[i].state = ID_UNASSIGNED;	/*Default to unassigned ID. */
6227 
6228 		}
6229 	}
6230 	for (k = 0; k < ID_STRING_LENGTH; k++)
6231 		FPT_scamInfo[p_our_id].id_string[k] = FPT_scamHAString[k];
6232 
6233 }
6234 
6235 /*---------------------------------------------------------------------
6236  *
6237  * Function: FPT_scmachid
6238  *
6239  * Description: Match the Device ID string with our values stored in
6240  *              the EEPROM.
6241  *
6242  *---------------------------------------------------------------------*/
6243 
6244 static unsigned char FPT_scmachid(unsigned char p_card,
6245 				  unsigned char p_id_string[])
6246 {
6247 
6248 	unsigned char i, k, match;
6249 
6250 	for (i = 0; i < MAX_SCSI_TAR; i++) {
6251 
6252 		match = 1;
6253 
6254 		for (k = 0; k < ID_STRING_LENGTH; k++) {
6255 			if (p_id_string[k] != FPT_scamInfo[i].id_string[k])
6256 				match = 0;
6257 		}
6258 
6259 		if (match) {
6260 			FPT_scamInfo[i].state = ID_ASSIGNED;
6261 			return i;
6262 		}
6263 
6264 	}
6265 
6266 	if (p_id_string[0] & BIT(5))
6267 		i = 8;
6268 	else
6269 		i = MAX_SCSI_TAR;
6270 
6271 	if (((p_id_string[0] & 0x06) == 0x02)
6272 	    || ((p_id_string[0] & 0x06) == 0x04))
6273 		match = p_id_string[1] & (unsigned char)0x1F;
6274 	else
6275 		match = 7;
6276 
6277 	while (i > 0) {
6278 		i--;
6279 
6280 		if (FPT_scamInfo[match].state == ID_UNUSED) {
6281 			for (k = 0; k < ID_STRING_LENGTH; k++) {
6282 				FPT_scamInfo[match].id_string[k] =
6283 				    p_id_string[k];
6284 			}
6285 
6286 			FPT_scamInfo[match].state = ID_ASSIGNED;
6287 
6288 			if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
6289 				FPT_BL_Card[p_card].globalFlags |=
6290 				    F_UPDATE_EEPROM;
6291 			return match;
6292 
6293 		}
6294 
6295 		match--;
6296 
6297 		if (match == 0xFF) {
6298 			if (p_id_string[0] & BIT(5))
6299 				match = 7;
6300 			else
6301 				match = MAX_SCSI_TAR - 1;
6302 		}
6303 	}
6304 
6305 	if (p_id_string[0] & BIT(7)) {
6306 		return CLR_PRIORITY;
6307 	}
6308 
6309 	if (p_id_string[0] & BIT(5))
6310 		i = 8;
6311 	else
6312 		i = MAX_SCSI_TAR;
6313 
6314 	if (((p_id_string[0] & 0x06) == 0x02)
6315 	    || ((p_id_string[0] & 0x06) == 0x04))
6316 		match = p_id_string[1] & (unsigned char)0x1F;
6317 	else
6318 		match = 7;
6319 
6320 	while (i > 0) {
6321 
6322 		i--;
6323 
6324 		if (FPT_scamInfo[match].state == ID_UNASSIGNED) {
6325 			for (k = 0; k < ID_STRING_LENGTH; k++) {
6326 				FPT_scamInfo[match].id_string[k] =
6327 				    p_id_string[k];
6328 			}
6329 
6330 			FPT_scamInfo[match].id_string[0] |= BIT(7);
6331 			FPT_scamInfo[match].state = ID_ASSIGNED;
6332 			if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
6333 				FPT_BL_Card[p_card].globalFlags |=
6334 				    F_UPDATE_EEPROM;
6335 			return match;
6336 
6337 		}
6338 
6339 		match--;
6340 
6341 		if (match == 0xFF) {
6342 			if (p_id_string[0] & BIT(5))
6343 				match = 7;
6344 			else
6345 				match = MAX_SCSI_TAR - 1;
6346 		}
6347 	}
6348 
6349 	return NO_ID_AVAIL;
6350 }
6351 
6352 /*---------------------------------------------------------------------
6353  *
6354  * Function: FPT_scsavdi
6355  *
6356  * Description: Save off the device SCAM ID strings.
6357  *
6358  *---------------------------------------------------------------------*/
6359 
6360 static void FPT_scsavdi(unsigned char p_card, u32 p_port)
6361 {
6362 	unsigned char i, k, max_id;
6363 	unsigned short ee_data, sum_data;
6364 
6365 	sum_data = 0x0000;
6366 
6367 	for (i = 1; i < EE_SCAMBASE / 2; i++) {
6368 		sum_data += FPT_utilEERead(p_port, i);
6369 	}
6370 
6371 	FPT_utilEEWriteOnOff(p_port, 1);	/* Enable write access to the EEPROM */
6372 
6373 	if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6374 		max_id = 0x08;
6375 
6376 	else
6377 		max_id = 0x10;
6378 
6379 	for (i = 0; i < max_id; i++) {
6380 
6381 		for (k = 0; k < ID_STRING_LENGTH; k += 2) {
6382 			ee_data = FPT_scamInfo[i].id_string[k + 1];
6383 			ee_data <<= 8;
6384 			ee_data |= FPT_scamInfo[i].id_string[k];
6385 			sum_data += ee_data;
6386 			FPT_utilEEWrite(p_port, ee_data,
6387 					(unsigned short)((EE_SCAMBASE / 2) +
6388 							 (unsigned short)(i *
6389 									  ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
6390 		}
6391 	}
6392 
6393 	FPT_utilEEWrite(p_port, sum_data, EEPROM_CHECK_SUM / 2);
6394 	FPT_utilEEWriteOnOff(p_port, 0);	/* Turn off write access */
6395 }
6396 
6397 /*---------------------------------------------------------------------
6398  *
6399  * Function: FPT_XbowInit
6400  *
6401  * Description: Setup the Xbow for normal operation.
6402  *
6403  *---------------------------------------------------------------------*/
6404 
6405 static void FPT_XbowInit(u32 port, unsigned char ScamFlg)
6406 {
6407 	unsigned char i;
6408 
6409 	i = RD_HARPOON(port + hp_page_ctrl);
6410 	WR_HARPOON(port + hp_page_ctrl, (unsigned char)(i | G_INT_DISABLE));
6411 
6412 	WR_HARPOON(port + hp_scsireset, 0x00);
6413 	WR_HARPOON(port + hp_portctrl_1, HOST_MODE8);
6414 
6415 	WR_HARPOON(port + hp_scsireset, (DMA_RESET | HPSCSI_RESET | PROG_RESET |
6416 					 FIFO_CLR));
6417 
6418 	WR_HARPOON(port + hp_scsireset, SCSI_INI);
6419 
6420 	WR_HARPOON(port + hp_clkctrl_0, CLKCTRL_DEFAULT);
6421 
6422 	WR_HARPOON(port + hp_scsisig, 0x00);	/*  Clear any signals we might */
6423 	WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
6424 
6425 	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
6426 
6427 	FPT_default_intena = RESET | RSEL | PROG_HLT | TIMEOUT |
6428 	    BUS_FREE | XFER_CNT_0 | AUTO_INT;
6429 
6430 	if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2))
6431 		FPT_default_intena |= SCAM_SEL;
6432 
6433 	WRW_HARPOON((port + hp_intena), FPT_default_intena);
6434 
6435 	WR_HARPOON(port + hp_seltimeout, TO_290ms);
6436 
6437 	/* Turn on SCSI_MODE8 for narrow cards to fix the
6438 	   strapping issue with the DUAL CHANNEL card */
6439 	if (RD_HARPOON(port + hp_page_ctrl) & NARROW_SCSI_CARD)
6440 		WR_HARPOON(port + hp_addstat, SCSI_MODE8);
6441 
6442 	WR_HARPOON(port + hp_page_ctrl, i);
6443 
6444 }
6445 
6446 /*---------------------------------------------------------------------
6447  *
6448  * Function: FPT_BusMasterInit
6449  *
6450  * Description: Initialize the BusMaster for normal operations.
6451  *
6452  *---------------------------------------------------------------------*/
6453 
6454 static void FPT_BusMasterInit(u32 p_port)
6455 {
6456 
6457 	WR_HARPOON(p_port + hp_sys_ctrl, DRVR_RST);
6458 	WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
6459 
6460 	WR_HARPOON(p_port + hp_host_blk_cnt, XFER_BLK64);
6461 
6462 	WR_HARPOON(p_port + hp_bm_ctrl, (BMCTRL_DEFAULT));
6463 
6464 	WR_HARPOON(p_port + hp_ee_ctrl, (SCSI_TERM_ENA_H));
6465 
6466 	RD_HARPOON(p_port + hp_int_status);	/*Clear interrupts. */
6467 	WR_HARPOON(p_port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
6468 	WR_HARPOON(p_port + hp_page_ctrl, (RD_HARPOON(p_port + hp_page_ctrl) &
6469 					   ~SCATTER_EN));
6470 }
6471 
6472 /*---------------------------------------------------------------------
6473  *
6474  * Function: FPT_DiagEEPROM
6475  *
6476  * Description: Verfiy checksum and 'Key' and initialize the EEPROM if
6477  *              necessary.
6478  *
6479  *---------------------------------------------------------------------*/
6480 
6481 static void FPT_DiagEEPROM(u32 p_port)
6482 {
6483 	unsigned short index, temp, max_wd_cnt;
6484 
6485 	if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6486 		max_wd_cnt = EEPROM_WD_CNT;
6487 	else
6488 		max_wd_cnt = EEPROM_WD_CNT * 2;
6489 
6490 	temp = FPT_utilEERead(p_port, FW_SIGNATURE / 2);
6491 
6492 	if (temp == 0x4641) {
6493 
6494 		for (index = 2; index < max_wd_cnt; index++) {
6495 
6496 			temp += FPT_utilEERead(p_port, index);
6497 
6498 		}
6499 
6500 		if (temp == FPT_utilEERead(p_port, EEPROM_CHECK_SUM / 2)) {
6501 
6502 			return;	/*EEPROM is Okay so return now! */
6503 		}
6504 	}
6505 
6506 	FPT_utilEEWriteOnOff(p_port, (unsigned char)1);
6507 
6508 	for (index = 0; index < max_wd_cnt; index++) {
6509 
6510 		FPT_utilEEWrite(p_port, 0x0000, index);
6511 	}
6512 
6513 	temp = 0;
6514 
6515 	FPT_utilEEWrite(p_port, 0x4641, FW_SIGNATURE / 2);
6516 	temp += 0x4641;
6517 	FPT_utilEEWrite(p_port, 0x3920, MODEL_NUMB_0 / 2);
6518 	temp += 0x3920;
6519 	FPT_utilEEWrite(p_port, 0x3033, MODEL_NUMB_2 / 2);
6520 	temp += 0x3033;
6521 	FPT_utilEEWrite(p_port, 0x2020, MODEL_NUMB_4 / 2);
6522 	temp += 0x2020;
6523 	FPT_utilEEWrite(p_port, 0x70D3, SYSTEM_CONFIG / 2);
6524 	temp += 0x70D3;
6525 	FPT_utilEEWrite(p_port, 0x0010, BIOS_CONFIG / 2);
6526 	temp += 0x0010;
6527 	FPT_utilEEWrite(p_port, 0x0003, SCAM_CONFIG / 2);
6528 	temp += 0x0003;
6529 	FPT_utilEEWrite(p_port, 0x0007, ADAPTER_SCSI_ID / 2);
6530 	temp += 0x0007;
6531 
6532 	FPT_utilEEWrite(p_port, 0x0000, IGNORE_B_SCAN / 2);
6533 	temp += 0x0000;
6534 	FPT_utilEEWrite(p_port, 0x0000, SEND_START_ENA / 2);
6535 	temp += 0x0000;
6536 	FPT_utilEEWrite(p_port, 0x0000, DEVICE_ENABLE / 2);
6537 	temp += 0x0000;
6538 
6539 	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL01 / 2);
6540 	temp += 0x4242;
6541 	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL23 / 2);
6542 	temp += 0x4242;
6543 	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL45 / 2);
6544 	temp += 0x4242;
6545 	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL67 / 2);
6546 	temp += 0x4242;
6547 	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL89 / 2);
6548 	temp += 0x4242;
6549 	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLab / 2);
6550 	temp += 0x4242;
6551 	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLcd / 2);
6552 	temp += 0x4242;
6553 	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLef / 2);
6554 	temp += 0x4242;
6555 
6556 	FPT_utilEEWrite(p_port, 0x6C46, 64 / 2);	/*PRODUCT ID */
6557 	temp += 0x6C46;
6558 	FPT_utilEEWrite(p_port, 0x7361, 66 / 2);	/* FlashPoint LT   */
6559 	temp += 0x7361;
6560 	FPT_utilEEWrite(p_port, 0x5068, 68 / 2);
6561 	temp += 0x5068;
6562 	FPT_utilEEWrite(p_port, 0x696F, 70 / 2);
6563 	temp += 0x696F;
6564 	FPT_utilEEWrite(p_port, 0x746E, 72 / 2);
6565 	temp += 0x746E;
6566 	FPT_utilEEWrite(p_port, 0x4C20, 74 / 2);
6567 	temp += 0x4C20;
6568 	FPT_utilEEWrite(p_port, 0x2054, 76 / 2);
6569 	temp += 0x2054;
6570 	FPT_utilEEWrite(p_port, 0x2020, 78 / 2);
6571 	temp += 0x2020;
6572 
6573 	index = ((EE_SCAMBASE / 2) + (7 * 16));
6574 	FPT_utilEEWrite(p_port, (0x0700 + TYPE_CODE0), index);
6575 	temp += (0x0700 + TYPE_CODE0);
6576 	index++;
6577 	FPT_utilEEWrite(p_port, 0x5542, index);	/*Vendor ID code */
6578 	temp += 0x5542;		/* BUSLOGIC      */
6579 	index++;
6580 	FPT_utilEEWrite(p_port, 0x4C53, index);
6581 	temp += 0x4C53;
6582 	index++;
6583 	FPT_utilEEWrite(p_port, 0x474F, index);
6584 	temp += 0x474F;
6585 	index++;
6586 	FPT_utilEEWrite(p_port, 0x4349, index);
6587 	temp += 0x4349;
6588 	index++;
6589 	FPT_utilEEWrite(p_port, 0x5442, index);	/*Vendor unique code */
6590 	temp += 0x5442;		/* BT- 930           */
6591 	index++;
6592 	FPT_utilEEWrite(p_port, 0x202D, index);
6593 	temp += 0x202D;
6594 	index++;
6595 	FPT_utilEEWrite(p_port, 0x3339, index);
6596 	temp += 0x3339;
6597 	index++;		/*Serial #          */
6598 	FPT_utilEEWrite(p_port, 0x2030, index);	/* 01234567         */
6599 	temp += 0x2030;
6600 	index++;
6601 	FPT_utilEEWrite(p_port, 0x5453, index);
6602 	temp += 0x5453;
6603 	index++;
6604 	FPT_utilEEWrite(p_port, 0x5645, index);
6605 	temp += 0x5645;
6606 	index++;
6607 	FPT_utilEEWrite(p_port, 0x2045, index);
6608 	temp += 0x2045;
6609 	index++;
6610 	FPT_utilEEWrite(p_port, 0x202F, index);
6611 	temp += 0x202F;
6612 	index++;
6613 	FPT_utilEEWrite(p_port, 0x4F4A, index);
6614 	temp += 0x4F4A;
6615 	index++;
6616 	FPT_utilEEWrite(p_port, 0x204E, index);
6617 	temp += 0x204E;
6618 	index++;
6619 	FPT_utilEEWrite(p_port, 0x3539, index);
6620 	temp += 0x3539;
6621 
6622 	FPT_utilEEWrite(p_port, temp, EEPROM_CHECK_SUM / 2);
6623 
6624 	FPT_utilEEWriteOnOff(p_port, (unsigned char)0);
6625 
6626 }
6627 
6628 /*---------------------------------------------------------------------
6629  *
6630  * Function: Queue Search Select
6631  *
6632  * Description: Try to find a new command to execute.
6633  *
6634  *---------------------------------------------------------------------*/
6635 
6636 static void FPT_queueSearchSelect(struct sccb_card *pCurrCard,
6637 				  unsigned char p_card)
6638 {
6639 	unsigned char scan_ptr, lun;
6640 	struct sccb_mgr_tar_info *currTar_Info;
6641 	struct sccb *pOldSccb;
6642 
6643 	scan_ptr = pCurrCard->scanIndex;
6644 	do {
6645 		currTar_Info = &FPT_sccbMgrTbl[p_card][scan_ptr];
6646 		if ((pCurrCard->globalFlags & F_CONLUN_IO) &&
6647 		    ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
6648 		     TAG_Q_TRYING)) {
6649 			if (currTar_Info->TarSelQ_Cnt != 0) {
6650 
6651 				scan_ptr++;
6652 				if (scan_ptr == MAX_SCSI_TAR)
6653 					scan_ptr = 0;
6654 
6655 				for (lun = 0; lun < MAX_LUN; lun++) {
6656 					if (currTar_Info->TarLUNBusy[lun] == 0) {
6657 
6658 						pCurrCard->currentSCCB =
6659 						    currTar_Info->TarSelQ_Head;
6660 						pOldSccb = NULL;
6661 
6662 						while ((pCurrCard->
6663 							currentSCCB != NULL)
6664 						       && (lun !=
6665 							   pCurrCard->
6666 							   currentSCCB->Lun)) {
6667 							pOldSccb =
6668 							    pCurrCard->
6669 							    currentSCCB;
6670 							pCurrCard->currentSCCB =
6671 							    (struct sccb
6672 							     *)(pCurrCard->
6673 								currentSCCB)->
6674 							    Sccb_forwardlink;
6675 						}
6676 						if (pCurrCard->currentSCCB ==
6677 						    NULL)
6678 							continue;
6679 						if (pOldSccb != NULL) {
6680 							pOldSccb->
6681 							    Sccb_forwardlink =
6682 							    (struct sccb
6683 							     *)(pCurrCard->
6684 								currentSCCB)->
6685 							    Sccb_forwardlink;
6686 							pOldSccb->
6687 							    Sccb_backlink =
6688 							    (struct sccb
6689 							     *)(pCurrCard->
6690 								currentSCCB)->
6691 							    Sccb_backlink;
6692 							currTar_Info->
6693 							    TarSelQ_Cnt--;
6694 						} else {
6695 							currTar_Info->
6696 							    TarSelQ_Head =
6697 							    (struct sccb
6698 							     *)(pCurrCard->
6699 								currentSCCB)->
6700 							    Sccb_forwardlink;
6701 
6702 							if (currTar_Info->
6703 							    TarSelQ_Head ==
6704 							    NULL) {
6705 								currTar_Info->
6706 								    TarSelQ_Tail
6707 								    = NULL;
6708 								currTar_Info->
6709 								    TarSelQ_Cnt
6710 								    = 0;
6711 							} else {
6712 								currTar_Info->
6713 								    TarSelQ_Cnt--;
6714 								currTar_Info->
6715 								    TarSelQ_Head->
6716 								    Sccb_backlink
6717 								    =
6718 								    (struct sccb
6719 								     *)NULL;
6720 							}
6721 						}
6722 						pCurrCard->scanIndex = scan_ptr;
6723 
6724 						pCurrCard->globalFlags |=
6725 						    F_NEW_SCCB_CMD;
6726 
6727 						break;
6728 					}
6729 				}
6730 			}
6731 
6732 			else {
6733 				scan_ptr++;
6734 				if (scan_ptr == MAX_SCSI_TAR) {
6735 					scan_ptr = 0;
6736 				}
6737 			}
6738 
6739 		} else {
6740 			if ((currTar_Info->TarSelQ_Cnt != 0) &&
6741 			    (currTar_Info->TarLUNBusy[0] == 0)) {
6742 
6743 				pCurrCard->currentSCCB =
6744 				    currTar_Info->TarSelQ_Head;
6745 
6746 				currTar_Info->TarSelQ_Head =
6747 				    (struct sccb *)(pCurrCard->currentSCCB)->
6748 				    Sccb_forwardlink;
6749 
6750 				if (currTar_Info->TarSelQ_Head == NULL) {
6751 					currTar_Info->TarSelQ_Tail = NULL;
6752 					currTar_Info->TarSelQ_Cnt = 0;
6753 				} else {
6754 					currTar_Info->TarSelQ_Cnt--;
6755 					currTar_Info->TarSelQ_Head->
6756 					    Sccb_backlink = (struct sccb *)NULL;
6757 				}
6758 
6759 				scan_ptr++;
6760 				if (scan_ptr == MAX_SCSI_TAR)
6761 					scan_ptr = 0;
6762 
6763 				pCurrCard->scanIndex = scan_ptr;
6764 
6765 				pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
6766 
6767 				break;
6768 			}
6769 
6770 			else {
6771 				scan_ptr++;
6772 				if (scan_ptr == MAX_SCSI_TAR) {
6773 					scan_ptr = 0;
6774 				}
6775 			}
6776 		}
6777 	} while (scan_ptr != pCurrCard->scanIndex);
6778 }
6779 
6780 /*---------------------------------------------------------------------
6781  *
6782  * Function: Queue Select Fail
6783  *
6784  * Description: Add the current SCCB to the head of the Queue.
6785  *
6786  *---------------------------------------------------------------------*/
6787 
6788 static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
6789 				unsigned char p_card)
6790 {
6791 	unsigned char thisTarg;
6792 	struct sccb_mgr_tar_info *currTar_Info;
6793 
6794 	if (pCurrCard->currentSCCB != NULL) {
6795 		thisTarg =
6796 		    (unsigned char)(((struct sccb *)(pCurrCard->currentSCCB))->
6797 				    TargID);
6798 		currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
6799 
6800 		pCurrCard->currentSCCB->Sccb_backlink = (struct sccb *)NULL;
6801 
6802 		pCurrCard->currentSCCB->Sccb_forwardlink =
6803 		    currTar_Info->TarSelQ_Head;
6804 
6805 		if (currTar_Info->TarSelQ_Cnt == 0) {
6806 			currTar_Info->TarSelQ_Tail = pCurrCard->currentSCCB;
6807 		}
6808 
6809 		else {
6810 			currTar_Info->TarSelQ_Head->Sccb_backlink =
6811 			    pCurrCard->currentSCCB;
6812 		}
6813 
6814 		currTar_Info->TarSelQ_Head = pCurrCard->currentSCCB;
6815 
6816 		pCurrCard->currentSCCB = NULL;
6817 		currTar_Info->TarSelQ_Cnt++;
6818 	}
6819 }
6820 
6821 /*---------------------------------------------------------------------
6822  *
6823  * Function: Queue Command Complete
6824  *
6825  * Description: Call the callback function with the current SCCB.
6826  *
6827  *---------------------------------------------------------------------*/
6828 
6829 static void FPT_queueCmdComplete(struct sccb_card *pCurrCard,
6830 				 struct sccb *p_sccb, unsigned char p_card)
6831 {
6832 
6833 	unsigned char i, SCSIcmd;
6834 	CALL_BK_FN callback;
6835 	struct sccb_mgr_tar_info *currTar_Info;
6836 
6837 	SCSIcmd = p_sccb->Cdb[0];
6838 
6839 	if (!(p_sccb->Sccb_XferState & F_ALL_XFERRED)) {
6840 
6841 		if ((p_sccb->
6842 		     ControlByte & (SCCB_DATA_XFER_OUT | SCCB_DATA_XFER_IN))
6843 		    && (p_sccb->HostStatus == SCCB_COMPLETE)
6844 		    && (p_sccb->TargetStatus != SAM_STAT_CHECK_CONDITION))
6845 
6846 			if ((SCSIcmd == READ_6) ||
6847 			    (SCSIcmd == WRITE_6) ||
6848 			    (SCSIcmd == READ_10) ||
6849 			    (SCSIcmd == WRITE_10) ||
6850 			    (SCSIcmd == WRITE_VERIFY) ||
6851 			    (SCSIcmd == START_STOP) ||
6852 			    (pCurrCard->globalFlags & F_NO_FILTER)
6853 			    )
6854 				p_sccb->HostStatus = SCCB_DATA_UNDER_RUN;
6855 	}
6856 
6857 	if (p_sccb->SccbStatus == SCCB_IN_PROCESS) {
6858 		if (p_sccb->HostStatus || p_sccb->TargetStatus)
6859 			p_sccb->SccbStatus = SCCB_ERROR;
6860 		else
6861 			p_sccb->SccbStatus = SCCB_SUCCESS;
6862 	}
6863 
6864 	if (p_sccb->Sccb_XferState & F_AUTO_SENSE) {
6865 
6866 		p_sccb->CdbLength = p_sccb->Save_CdbLen;
6867 		for (i = 0; i < 6; i++) {
6868 			p_sccb->Cdb[i] = p_sccb->Save_Cdb[i];
6869 		}
6870 	}
6871 
6872 	if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) ||
6873 	    (p_sccb->OperationCode == RESIDUAL_COMMAND)) {
6874 
6875 		FPT_utilUpdateResidual(p_sccb);
6876 	}
6877 
6878 	pCurrCard->cmdCounter--;
6879 	if (!pCurrCard->cmdCounter) {
6880 
6881 		if (pCurrCard->globalFlags & F_GREEN_PC) {
6882 			WR_HARPOON(pCurrCard->ioPort + hp_clkctrl_0,
6883 				   (PWR_DWN | CLKCTRL_DEFAULT));
6884 			WR_HARPOON(pCurrCard->ioPort + hp_sys_ctrl, STOP_CLK);
6885 		}
6886 
6887 		WR_HARPOON(pCurrCard->ioPort + hp_semaphore,
6888 			   (RD_HARPOON(pCurrCard->ioPort + hp_semaphore) &
6889 			    ~SCCB_MGR_ACTIVE));
6890 
6891 	}
6892 
6893 	if (pCurrCard->discQCount != 0) {
6894 		currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
6895 		if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
6896 		     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
6897 		      TAG_Q_TRYING))) {
6898 			pCurrCard->discQCount--;
6899 			pCurrCard->discQ_Tbl[currTar_Info->
6900 					     LunDiscQ_Idx[p_sccb->Lun]] = NULL;
6901 		} else {
6902 			if (p_sccb->Sccb_tag) {
6903 				pCurrCard->discQCount--;
6904 				pCurrCard->discQ_Tbl[p_sccb->Sccb_tag] = NULL;
6905 			} else {
6906 				pCurrCard->discQCount--;
6907 				pCurrCard->discQ_Tbl[currTar_Info->
6908 						     LunDiscQ_Idx[0]] = NULL;
6909 			}
6910 		}
6911 
6912 	}
6913 
6914 	callback = (CALL_BK_FN) p_sccb->SccbCallback;
6915 	callback(p_sccb);
6916 	pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
6917 	pCurrCard->currentSCCB = NULL;
6918 }
6919 
6920 /*---------------------------------------------------------------------
6921  *
6922  * Function: Queue Disconnect
6923  *
6924  * Description: Add SCCB to our disconnect array.
6925  *
6926  *---------------------------------------------------------------------*/
6927 static void FPT_queueDisconnect(struct sccb *p_sccb, unsigned char p_card)
6928 {
6929 	struct sccb_mgr_tar_info *currTar_Info;
6930 
6931 	currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
6932 
6933 	if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
6934 	     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
6935 		FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
6936 					      LunDiscQ_Idx[p_sccb->Lun]] =
6937 		    p_sccb;
6938 	} else {
6939 		if (p_sccb->Sccb_tag) {
6940 			FPT_BL_Card[p_card].discQ_Tbl[p_sccb->Sccb_tag] =
6941 			    p_sccb;
6942 			FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarLUNBusy[0] =
6943 			    0;
6944 			FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarTagQ_Cnt++;
6945 		} else {
6946 			FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
6947 						      LunDiscQ_Idx[0]] = p_sccb;
6948 		}
6949 	}
6950 	FPT_BL_Card[p_card].currentSCCB = NULL;
6951 }
6952 
6953 /*---------------------------------------------------------------------
6954  *
6955  * Function: Queue Flush SCCB
6956  *
6957  * Description: Flush all SCCB's back to the host driver for this target.
6958  *
6959  *---------------------------------------------------------------------*/
6960 
6961 static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code)
6962 {
6963 	unsigned char qtag, thisTarg;
6964 	struct sccb *currSCCB;
6965 	struct sccb_mgr_tar_info *currTar_Info;
6966 
6967 	currSCCB = FPT_BL_Card[p_card].currentSCCB;
6968 	if (currSCCB != NULL) {
6969 		thisTarg = (unsigned char)currSCCB->TargID;
6970 		currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
6971 
6972 		for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
6973 
6974 			if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
6975 			    (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
6976 			     thisTarg)) {
6977 
6978 				FPT_BL_Card[p_card].discQ_Tbl[qtag]->
6979 				    HostStatus = (unsigned char)error_code;
6980 
6981 				FPT_queueCmdComplete(&FPT_BL_Card[p_card],
6982 						     FPT_BL_Card[p_card].
6983 						     discQ_Tbl[qtag], p_card);
6984 
6985 				FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
6986 				currTar_Info->TarTagQ_Cnt--;
6987 
6988 			}
6989 		}
6990 	}
6991 
6992 }
6993 
6994 /*---------------------------------------------------------------------
6995  *
6996  * Function: Queue Flush Target SCCB
6997  *
6998  * Description: Flush all SCCB's back to the host driver for this target.
6999  *
7000  *---------------------------------------------------------------------*/
7001 
7002 static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
7003 				   unsigned char error_code)
7004 {
7005 	unsigned char qtag;
7006 	struct sccb_mgr_tar_info *currTar_Info;
7007 
7008 	currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
7009 
7010 	for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
7011 
7012 		if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
7013 		    (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg)) {
7014 
7015 			FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus =
7016 			    (unsigned char)error_code;
7017 
7018 			FPT_queueCmdComplete(&FPT_BL_Card[p_card],
7019 					     FPT_BL_Card[p_card].
7020 					     discQ_Tbl[qtag], p_card);
7021 
7022 			FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
7023 			currTar_Info->TarTagQ_Cnt--;
7024 
7025 		}
7026 	}
7027 
7028 }
7029 
7030 static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char p_card)
7031 {
7032 	struct sccb_mgr_tar_info *currTar_Info;
7033 	currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
7034 
7035 	p_SCCB->Sccb_forwardlink = NULL;
7036 
7037 	p_SCCB->Sccb_backlink = currTar_Info->TarSelQ_Tail;
7038 
7039 	if (currTar_Info->TarSelQ_Cnt == 0) {
7040 
7041 		currTar_Info->TarSelQ_Head = p_SCCB;
7042 	}
7043 
7044 	else {
7045 
7046 		currTar_Info->TarSelQ_Tail->Sccb_forwardlink = p_SCCB;
7047 	}
7048 
7049 	currTar_Info->TarSelQ_Tail = p_SCCB;
7050 	currTar_Info->TarSelQ_Cnt++;
7051 }
7052 
7053 /*---------------------------------------------------------------------
7054  *
7055  * Function: Queue Find SCCB
7056  *
7057  * Description: Search the target select Queue for this SCCB, and
7058  *              remove it if found.
7059  *
7060  *---------------------------------------------------------------------*/
7061 
7062 static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB,
7063 				       unsigned char p_card)
7064 {
7065 	struct sccb *q_ptr;
7066 	struct sccb_mgr_tar_info *currTar_Info;
7067 
7068 	currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
7069 
7070 	q_ptr = currTar_Info->TarSelQ_Head;
7071 
7072 	while (q_ptr != NULL) {
7073 
7074 		if (q_ptr == p_SCCB) {
7075 
7076 			if (currTar_Info->TarSelQ_Head == q_ptr) {
7077 
7078 				currTar_Info->TarSelQ_Head =
7079 				    q_ptr->Sccb_forwardlink;
7080 			}
7081 
7082 			if (currTar_Info->TarSelQ_Tail == q_ptr) {
7083 
7084 				currTar_Info->TarSelQ_Tail =
7085 				    q_ptr->Sccb_backlink;
7086 			}
7087 
7088 			if (q_ptr->Sccb_forwardlink != NULL) {
7089 				q_ptr->Sccb_forwardlink->Sccb_backlink =
7090 				    q_ptr->Sccb_backlink;
7091 			}
7092 
7093 			if (q_ptr->Sccb_backlink != NULL) {
7094 				q_ptr->Sccb_backlink->Sccb_forwardlink =
7095 				    q_ptr->Sccb_forwardlink;
7096 			}
7097 
7098 			currTar_Info->TarSelQ_Cnt--;
7099 
7100 			return 1;
7101 		}
7102 
7103 		else {
7104 			q_ptr = q_ptr->Sccb_forwardlink;
7105 		}
7106 	}
7107 
7108 	return 0;
7109 
7110 }
7111 
7112 /*---------------------------------------------------------------------
7113  *
7114  * Function: Utility Update Residual Count
7115  *
7116  * Description: Update the XferCnt to the remaining byte count.
7117  *              If we transferred all the data then just write zero.
7118  *              If Non-SG transfer then report Total Cnt - Actual Transfer
7119  *              Cnt.  For SG transfers add the count fields of all
7120  *              remaining SG elements, as well as any partial remaining
7121  *              element.
7122  *
7123  *---------------------------------------------------------------------*/
7124 
7125 static void FPT_utilUpdateResidual(struct sccb *p_SCCB)
7126 {
7127 	unsigned long partial_cnt;
7128 	unsigned int sg_index;
7129 	struct blogic_sg_seg *segp;
7130 
7131 	if (p_SCCB->Sccb_XferState & F_ALL_XFERRED) {
7132 
7133 		p_SCCB->DataLength = 0x0000;
7134 	}
7135 
7136 	else if (p_SCCB->Sccb_XferState & F_SG_XFER) {
7137 
7138 		partial_cnt = 0x0000;
7139 
7140 		sg_index = p_SCCB->Sccb_sgseg;
7141 
7142 
7143 		if (p_SCCB->Sccb_SGoffset) {
7144 
7145 			partial_cnt = p_SCCB->Sccb_SGoffset;
7146 			sg_index++;
7147 		}
7148 
7149 		while (((unsigned long)sg_index *
7150 			(unsigned long)SG_ELEMENT_SIZE) < p_SCCB->DataLength) {
7151 			segp = (struct blogic_sg_seg *)(p_SCCB->DataPointer) +
7152 					(sg_index * 2);
7153 			partial_cnt += segp->segbytes;
7154 			sg_index++;
7155 		}
7156 
7157 		p_SCCB->DataLength = partial_cnt;
7158 	}
7159 
7160 	else {
7161 
7162 		p_SCCB->DataLength -= p_SCCB->Sccb_ATC;
7163 	}
7164 }
7165 
7166 /*---------------------------------------------------------------------
7167  *
7168  * Function: Wait 1 Second
7169  *
7170  * Description: Wait for 1 second.
7171  *
7172  *---------------------------------------------------------------------*/
7173 
7174 static void FPT_Wait1Second(u32 p_port)
7175 {
7176 	unsigned char i;
7177 
7178 	for (i = 0; i < 4; i++) {
7179 
7180 		FPT_Wait(p_port, TO_250ms);
7181 
7182 		if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
7183 			break;
7184 
7185 		if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
7186 			break;
7187 	}
7188 }
7189 
7190 /*---------------------------------------------------------------------
7191  *
7192  * Function: FPT_Wait
7193  *
7194  * Description: Wait the desired delay.
7195  *
7196  *---------------------------------------------------------------------*/
7197 
7198 static void FPT_Wait(u32 p_port, unsigned char p_delay)
7199 {
7200 	unsigned char old_timer;
7201 	unsigned char green_flag;
7202 
7203 	old_timer = RD_HARPOON(p_port + hp_seltimeout);
7204 
7205 	green_flag = RD_HARPOON(p_port + hp_clkctrl_0);
7206 	WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
7207 
7208 	WR_HARPOON(p_port + hp_seltimeout, p_delay);
7209 	WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
7210 	WRW_HARPOON((p_port + hp_intena), (FPT_default_intena & ~TIMEOUT));
7211 
7212 	WR_HARPOON(p_port + hp_portctrl_0,
7213 		   (RD_HARPOON(p_port + hp_portctrl_0) | START_TO));
7214 
7215 	while (!(RDW_HARPOON((p_port + hp_intstat)) & TIMEOUT)) {
7216 
7217 		if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
7218 			break;
7219 
7220 		if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
7221 			break;
7222 	}
7223 
7224 	WR_HARPOON(p_port + hp_portctrl_0,
7225 		   (RD_HARPOON(p_port + hp_portctrl_0) & ~START_TO));
7226 
7227 	WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
7228 	WRW_HARPOON((p_port + hp_intena), FPT_default_intena);
7229 
7230 	WR_HARPOON(p_port + hp_clkctrl_0, green_flag);
7231 
7232 	WR_HARPOON(p_port + hp_seltimeout, old_timer);
7233 }
7234 
7235 /*---------------------------------------------------------------------
7236  *
7237  * Function: Enable/Disable Write to EEPROM
7238  *
7239  * Description: The EEPROM must first be enabled for writes
7240  *              A total of 9 clocks are needed.
7241  *
7242  *---------------------------------------------------------------------*/
7243 
7244 static void FPT_utilEEWriteOnOff(u32 p_port, unsigned char p_mode)
7245 {
7246 	unsigned char ee_value;
7247 
7248 	ee_value =
7249 	    (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
7250 			    (EXT_ARB_ACK | SCSI_TERM_ENA_H));
7251 
7252 	if (p_mode)
7253 
7254 		FPT_utilEESendCmdAddr(p_port, EWEN, EWEN_ADDR);
7255 
7256 	else
7257 
7258 		FPT_utilEESendCmdAddr(p_port, EWDS, EWDS_ADDR);
7259 
7260 	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));	/*Turn off CS */
7261 	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);	/*Turn off Master Select */
7262 }
7263 
7264 /*---------------------------------------------------------------------
7265  *
7266  * Function: Write EEPROM
7267  *
7268  * Description: Write a word to the EEPROM at the specified
7269  *              address.
7270  *
7271  *---------------------------------------------------------------------*/
7272 
7273 static void FPT_utilEEWrite(u32 p_port, unsigned short ee_data,
7274 			    unsigned short ee_addr)
7275 {
7276 
7277 	unsigned char ee_value;
7278 	unsigned short i;
7279 
7280 	ee_value =
7281 	    (unsigned
7282 	     char)((RD_HARPOON(p_port + hp_ee_ctrl) &
7283 		    (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
7284 
7285 	FPT_utilEESendCmdAddr(p_port, EE_WRITE, ee_addr);
7286 
7287 	ee_value |= (SEE_MS + SEE_CS);
7288 
7289 	for (i = 0x8000; i != 0; i >>= 1) {
7290 
7291 		if (i & ee_data)
7292 			ee_value |= SEE_DO;
7293 		else
7294 			ee_value &= ~SEE_DO;
7295 
7296 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7297 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7298 		ee_value |= SEE_CLK;	/* Clock  data! */
7299 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7300 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7301 		ee_value &= ~SEE_CLK;
7302 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7303 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7304 	}
7305 	ee_value &= (EXT_ARB_ACK | SCSI_TERM_ENA_H);
7306 	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));
7307 
7308 	FPT_Wait(p_port, TO_10ms);
7309 
7310 	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS | SEE_CS));	/* Set CS to EEPROM */
7311 	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));	/* Turn off CS */
7312 	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);	/* Turn off Master Select */
7313 }
7314 
7315 /*---------------------------------------------------------------------
7316  *
7317  * Function: Read EEPROM
7318  *
7319  * Description: Read a word from the EEPROM at the desired
7320  *              address.
7321  *
7322  *---------------------------------------------------------------------*/
7323 
7324 static unsigned short FPT_utilEERead(u32 p_port,
7325 				     unsigned short ee_addr)
7326 {
7327 	unsigned short i, ee_data1, ee_data2;
7328 
7329 	i = 0;
7330 	ee_data1 = FPT_utilEEReadOrg(p_port, ee_addr);
7331 	do {
7332 		ee_data2 = FPT_utilEEReadOrg(p_port, ee_addr);
7333 
7334 		if (ee_data1 == ee_data2)
7335 			return ee_data1;
7336 
7337 		ee_data1 = ee_data2;
7338 		i++;
7339 
7340 	} while (i < 4);
7341 
7342 	return ee_data1;
7343 }
7344 
7345 /*---------------------------------------------------------------------
7346  *
7347  * Function: Read EEPROM Original
7348  *
7349  * Description: Read a word from the EEPROM at the desired
7350  *              address.
7351  *
7352  *---------------------------------------------------------------------*/
7353 
7354 static unsigned short FPT_utilEEReadOrg(u32 p_port, unsigned short ee_addr)
7355 {
7356 
7357 	unsigned char ee_value;
7358 	unsigned short i, ee_data;
7359 
7360 	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));
7364 
7365 	FPT_utilEESendCmdAddr(p_port, EE_READ, ee_addr);
7366 
7367 	ee_value |= (SEE_MS + SEE_CS);
7368 	ee_data = 0;
7369 
7370 	for (i = 1; i <= 16; i++) {
7371 
7372 		ee_value |= SEE_CLK;	/* Clock  data! */
7373 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7374 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7375 		ee_value &= ~SEE_CLK;
7376 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7377 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7378 
7379 		ee_data <<= 1;
7380 
7381 		if (RD_HARPOON(p_port + hp_ee_ctrl) & SEE_DI)
7382 			ee_data |= 1;
7383 	}
7384 
7385 	ee_value &= ~(SEE_MS + SEE_CS);
7386 	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));	/*Turn off CS */
7387 	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);	/*Turn off Master Select */
7388 
7389 	return ee_data;
7390 }
7391 
7392 /*---------------------------------------------------------------------
7393  *
7394  * Function: Send EE command and Address to the EEPROM
7395  *
7396  * Description: Transfers the correct command and sends the address
7397  *              to the eeprom.
7398  *
7399  *---------------------------------------------------------------------*/
7400 
7401 static void FPT_utilEESendCmdAddr(u32 p_port, unsigned char ee_cmd,
7402 				  unsigned short ee_addr)
7403 {
7404 	unsigned char ee_value;
7405 	unsigned char narrow_flg;
7406 
7407 	unsigned short i;
7408 
7409 	narrow_flg =
7410 	    (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
7411 			    NARROW_SCSI_CARD);
7412 
7413 	ee_value = SEE_MS;
7414 	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7415 
7416 	ee_value |= SEE_CS;	/* Set CS to EEPROM */
7417 	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7418 
7419 	for (i = 0x04; i != 0; i >>= 1) {
7420 
7421 		if (i & ee_cmd)
7422 			ee_value |= SEE_DO;
7423 		else
7424 			ee_value &= ~SEE_DO;
7425 
7426 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7427 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7428 		ee_value |= SEE_CLK;	/* Clock  data! */
7429 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7430 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7431 		ee_value &= ~SEE_CLK;
7432 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7433 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7434 	}
7435 
7436 	if (narrow_flg)
7437 		i = 0x0080;
7438 
7439 	else
7440 		i = 0x0200;
7441 
7442 	while (i != 0) {
7443 
7444 		if (i & ee_addr)
7445 			ee_value |= SEE_DO;
7446 		else
7447 			ee_value &= ~SEE_DO;
7448 
7449 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7450 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7451 		ee_value |= SEE_CLK;	/* Clock  data! */
7452 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7453 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7454 		ee_value &= ~SEE_CLK;
7455 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7456 		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7457 
7458 		i >>= 1;
7459 	}
7460 }
7461 
7462 static unsigned short FPT_CalcCrc16(unsigned char buffer[])
7463 {
7464 	unsigned short crc = 0;
7465 	int i, j;
7466 	unsigned short ch;
7467 	for (i = 0; i < ID_STRING_LENGTH; i++) {
7468 		ch = (unsigned short)buffer[i];
7469 		for (j = 0; j < 8; j++) {
7470 			if ((crc ^ ch) & 1)
7471 				crc = (crc >> 1) ^ CRCMASK;
7472 			else
7473 				crc >>= 1;
7474 			ch >>= 1;
7475 		}
7476 	}
7477 	return crc;
7478 }
7479 
7480 static unsigned char FPT_CalcLrc(unsigned char buffer[])
7481 {
7482 	int i;
7483 	unsigned char lrc;
7484 	lrc = 0;
7485 	for (i = 0; i < ID_STRING_LENGTH; i++)
7486 		lrc ^= buffer[i];
7487 	return lrc;
7488 }
7489 
7490 /*
7491   The following inline definitions avoid type conflicts.
7492 */
7493 
7494 static inline unsigned char
7495 FlashPoint__ProbeHostAdapter(struct fpoint_info *FlashPointInfo)
7496 {
7497 	return FlashPoint_ProbeHostAdapter((struct sccb_mgr_info *)
7498 					   FlashPointInfo);
7499 }
7500 
7501 static inline void *
7502 FlashPoint__HardwareResetHostAdapter(struct fpoint_info *FlashPointInfo)
7503 {
7504 	return FlashPoint_HardwareResetHostAdapter((struct sccb_mgr_info *)
7505 						   FlashPointInfo);
7506 }
7507 
7508 static inline void
7509 FlashPoint__ReleaseHostAdapter(void *CardHandle)
7510 {
7511 	FlashPoint_ReleaseHostAdapter(CardHandle);
7512 }
7513 
7514 static inline void
7515 FlashPoint__StartCCB(void *CardHandle, struct blogic_ccb *CCB)
7516 {
7517 	FlashPoint_StartCCB(CardHandle, (struct sccb *)CCB);
7518 }
7519 
7520 static inline void
7521 FlashPoint__AbortCCB(void *CardHandle, struct blogic_ccb *CCB)
7522 {
7523 	FlashPoint_AbortCCB(CardHandle, (struct sccb *)CCB);
7524 }
7525 
7526 static inline bool
7527 FlashPoint__InterruptPending(void *CardHandle)
7528 {
7529 	return FlashPoint_InterruptPending(CardHandle);
7530 }
7531 
7532 static inline int
7533 FlashPoint__HandleInterrupt(void *CardHandle)
7534 {
7535 	return FlashPoint_HandleInterrupt(CardHandle);
7536 }
7537 
7538 #define FlashPoint_ProbeHostAdapter	    FlashPoint__ProbeHostAdapter
7539 #define FlashPoint_HardwareResetHostAdapter FlashPoint__HardwareResetHostAdapter
7540 #define FlashPoint_ReleaseHostAdapter	    FlashPoint__ReleaseHostAdapter
7541 #define FlashPoint_StartCCB		    FlashPoint__StartCCB
7542 #define FlashPoint_AbortCCB		    FlashPoint__AbortCCB
7543 #define FlashPoint_InterruptPending	    FlashPoint__InterruptPending
7544 #define FlashPoint_HandleInterrupt	    FlashPoint__HandleInterrupt
7545 
7546 #else				/* !CONFIG_SCSI_FLASHPOINT */
7547 
7548 /*
7549   Define prototypes for the FlashPoint SCCB Manager Functions.
7550 */
7551 
7552 extern unsigned char FlashPoint_ProbeHostAdapter(struct fpoint_info *);
7553 extern void *FlashPoint_HardwareResetHostAdapter(struct fpoint_info *);
7554 extern void FlashPoint_StartCCB(void *, struct blogic_ccb *);
7555 extern int FlashPoint_AbortCCB(void *, struct blogic_ccb *);
7556 extern bool FlashPoint_InterruptPending(void *);
7557 extern int FlashPoint_HandleInterrupt(void *);
7558 extern void FlashPoint_ReleaseHostAdapter(void *);
7559 
7560 #endif				/* CONFIG_SCSI_FLASHPOINT */
7561