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