Linux Audio

Check our new training course

Loading...
v3.1
   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				/* Harpoon problem some SCSI target device respond to selection
1915				   with short BUSY pulse (<400ns) this will make the Harpoon is not able
1916				   to latch the correct Target ID into reg. x53.
1917				   The work around require to correct this reg. But when write to this
1918				   reg. (0x53) also increment the FIFO write addr reg (0x6f), thus we
1919				   need to read this reg first then restore it later. After update to 0x53 */
1920
1921				i = (unsigned
1922				     char)(RD_HARPOON(ioport + hp_fifowrite));
1923				target =
1924				    (unsigned
1925				     char)(RD_HARPOON(ioport + hp_gp_reg_3));
1926				WR_HARPOON(ioport + hp_xfer_pad,
1927					   (unsigned char)ID_UNLOCK);
1928				WR_HARPOON(ioport + hp_select_id,
1929					   (unsigned char)(target | target <<
1930							   4));
1931				WR_HARPOON(ioport + hp_xfer_pad,
1932					   (unsigned char)0x00);
1933				WR_HARPOON(ioport + hp_fifowrite, i);
1934				WR_HARPOON(ioport + hp_autostart_3,
1935					   (AUTO_IMMED + TAG_STRT));
1936			}
1937		}
1938
1939		else if (hp_int & XFER_CNT_0) {
1940
1941			WRW_HARPOON((ioport + hp_intstat), XFER_CNT_0);
1942
1943			FPT_schkdd(ioport, thisCard);
1944
1945		}
1946
1947		else if (hp_int & BUS_FREE) {
1948
1949			WRW_HARPOON((ioport + hp_intstat), BUS_FREE);
1950
1951			if (((struct sccb_card *)pCurrCard)->
1952			    globalFlags & F_HOST_XFER_ACT) {
1953
1954				FPT_hostDataXferAbort(ioport, thisCard,
1955						      currSCCB);
1956			}
1957
1958			FPT_phaseBusFree(ioport, thisCard);
1959		}
1960
1961		else if (hp_int & ITICKLE) {
1962
1963			WRW_HARPOON((ioport + hp_intstat), ITICKLE);
1964			((struct sccb_card *)pCurrCard)->globalFlags |=
1965			    F_NEW_SCCB_CMD;
1966		}
1967
1968		if (((struct sccb_card *)pCurrCard)->
1969		    globalFlags & F_NEW_SCCB_CMD) {
1970
1971			((struct sccb_card *)pCurrCard)->globalFlags &=
1972			    ~F_NEW_SCCB_CMD;
1973
1974			if (((struct sccb_card *)pCurrCard)->currentSCCB ==
1975			    NULL) {
1976
1977				FPT_queueSearchSelect(((struct sccb_card *)
1978						       pCurrCard), thisCard);
1979			}
1980
1981			if (((struct sccb_card *)pCurrCard)->currentSCCB !=
1982			    NULL) {
1983				((struct sccb_card *)pCurrCard)->globalFlags &=
1984				    ~F_NEW_SCCB_CMD;
1985				FPT_ssel(ioport, thisCard);
1986			}
1987
1988			break;
1989
1990		}
1991
1992	}			/*end while */
1993
1994	MENABLE_INT(ioport);
1995
1996	return 0;
1997}
1998
1999/*---------------------------------------------------------------------
2000 *
2001 * Function: Sccb_bad_isr
2002 *
2003 * Description: Some type of interrupt has occurred which is slightly
2004 *              out of the ordinary.  We will now decode it fully, in
2005 *              this routine.  This is broken up in an attempt to save
2006 *              processing time.
2007 *
2008 *---------------------------------------------------------------------*/
2009static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port,
2010					 unsigned char p_card,
2011					 struct sccb_card *pCurrCard,
2012					 unsigned short p_int)
2013{
2014	unsigned char temp, ScamFlg;
2015	struct sccb_mgr_tar_info *currTar_Info;
2016	struct nvram_info *pCurrNvRam;
2017
2018	if (RD_HARPOON(p_port + hp_ext_status) &
2019	    (BM_FORCE_OFF | PCI_DEV_TMOUT | BM_PARITY_ERR | PIO_OVERRUN)) {
2020
2021		if (pCurrCard->globalFlags & F_HOST_XFER_ACT) {
2022
2023			FPT_hostDataXferAbort(p_port, p_card,
2024					      pCurrCard->currentSCCB);
2025		}
2026
2027		if (RD_HARPOON(p_port + hp_pci_stat_cfg) & REC_MASTER_ABORT)
2028		{
2029			WR_HARPOON(p_port + hp_pci_stat_cfg,
2030				   (RD_HARPOON(p_port + hp_pci_stat_cfg) &
2031				    ~REC_MASTER_ABORT));
2032
2033			WR_HARPOON(p_port + hp_host_blk_cnt, 0x00);
2034
2035		}
2036
2037		if (pCurrCard->currentSCCB != NULL) {
2038
2039			if (!pCurrCard->currentSCCB->HostStatus)
2040				pCurrCard->currentSCCB->HostStatus =
2041				    SCCB_BM_ERR;
2042
2043			FPT_sxfrp(p_port, p_card);
2044
2045			temp = (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
2046					       (EXT_ARB_ACK | SCSI_TERM_ENA_H));
2047			WR_HARPOON(p_port + hp_ee_ctrl,
2048				   ((unsigned char)temp | SEE_MS | SEE_CS));
2049			WR_HARPOON(p_port + hp_ee_ctrl, temp);
2050
2051			if (!
2052			    (RDW_HARPOON((p_port + hp_intstat)) &
2053			     (BUS_FREE | RESET))) {
2054				FPT_phaseDecode(p_port, p_card);
2055			}
2056		}
2057	}
2058
2059	else if (p_int & RESET) {
2060
2061		WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
2062		WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
2063		if (pCurrCard->currentSCCB != NULL) {
2064
2065			if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
2066
2067				FPT_hostDataXferAbort(p_port, p_card,
2068						      pCurrCard->currentSCCB);
2069		}
2070
2071		DISABLE_AUTO(p_port);
2072
2073		FPT_sresb(p_port, p_card);
2074
2075		while (RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST) {
2076		}
2077
2078		pCurrNvRam = pCurrCard->pNvRamInfo;
2079		if (pCurrNvRam) {
2080			ScamFlg = pCurrNvRam->niScamConf;
2081		} else {
2082			ScamFlg =
2083			    (unsigned char)FPT_utilEERead(p_port,
2084							  SCAM_CONFIG / 2);
2085		}
2086
2087		FPT_XbowInit(p_port, ScamFlg);
2088
2089		FPT_scini(p_card, pCurrCard->ourId, 0);
2090
2091		return 0xFF;
2092	}
2093
2094	else if (p_int & FIFO) {
2095
2096		WRW_HARPOON((p_port + hp_intstat), FIFO);
2097
2098		if (pCurrCard->currentSCCB != NULL)
2099			FPT_sxfrp(p_port, p_card);
2100	}
2101
2102	else if (p_int & TIMEOUT) {
2103
2104		DISABLE_AUTO(p_port);
2105
2106		WRW_HARPOON((p_port + hp_intstat),
2107			    (PROG_HLT | TIMEOUT | SEL | BUS_FREE | PHASE |
2108			     IUNKWN));
2109
2110		pCurrCard->currentSCCB->HostStatus = SCCB_SELECTION_TIMEOUT;
2111
2112		currTar_Info =
2113		    &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
2114		if ((pCurrCard->globalFlags & F_CONLUN_IO)
2115		    && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
2116			TAG_Q_TRYING))
2117			currTar_Info->TarLUNBusy[pCurrCard->currentSCCB->Lun] =
2118			    0;
2119		else
2120			currTar_Info->TarLUNBusy[0] = 0;
2121
2122		if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
2123			currTar_Info->TarSyncCtrl = 0;
2124			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2125		}
2126
2127		if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
2128			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2129		}
2130
2131		FPT_sssyncv(p_port, pCurrCard->currentSCCB->TargID, NARROW_SCSI,
2132			    currTar_Info);
2133
2134		FPT_queueCmdComplete(pCurrCard, pCurrCard->currentSCCB, p_card);
2135
2136	}
2137
2138	else if (p_int & SCAM_SEL) {
2139
2140		FPT_scarb(p_port, LEVEL2_TAR);
2141		FPT_scsel(p_port);
2142		FPT_scasid(p_card, p_port);
2143
2144		FPT_scbusf(p_port);
2145
2146		WRW_HARPOON((p_port + hp_intstat), SCAM_SEL);
2147	}
2148
2149	return 0x00;
2150}
2151
2152/*---------------------------------------------------------------------
2153 *
2154 * Function: SccbMgrTableInit
2155 *
2156 * Description: Initialize all Sccb manager data structures.
2157 *
2158 *---------------------------------------------------------------------*/
2159
2160static void FPT_SccbMgrTableInitAll()
2161{
2162	unsigned char thisCard;
2163
2164	for (thisCard = 0; thisCard < MAX_CARDS; thisCard++) {
2165		FPT_SccbMgrTableInitCard(&FPT_BL_Card[thisCard], thisCard);
2166
2167		FPT_BL_Card[thisCard].ioPort = 0x00;
2168		FPT_BL_Card[thisCard].cardInfo = NULL;
2169		FPT_BL_Card[thisCard].cardIndex = 0xFF;
2170		FPT_BL_Card[thisCard].ourId = 0x00;
2171		FPT_BL_Card[thisCard].pNvRamInfo = NULL;
2172	}
2173}
2174
2175/*---------------------------------------------------------------------
2176 *
2177 * Function: SccbMgrTableInit
2178 *
2179 * Description: Initialize all Sccb manager data structures.
2180 *
2181 *---------------------------------------------------------------------*/
2182
2183static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard,
2184				     unsigned char p_card)
2185{
2186	unsigned char scsiID, qtag;
2187
2188	for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
2189		FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
2190	}
2191
2192	for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
2193		FPT_sccbMgrTbl[p_card][scsiID].TarStatus = 0;
2194		FPT_sccbMgrTbl[p_card][scsiID].TarEEValue = 0;
2195		FPT_SccbMgrTableInitTarget(p_card, scsiID);
2196	}
2197
2198	pCurrCard->scanIndex = 0x00;
2199	pCurrCard->currentSCCB = NULL;
2200	pCurrCard->globalFlags = 0x00;
2201	pCurrCard->cmdCounter = 0x00;
2202	pCurrCard->tagQ_Lst = 0x01;
2203	pCurrCard->discQCount = 0;
2204
2205}
2206
2207/*---------------------------------------------------------------------
2208 *
2209 * Function: SccbMgrTableInit
2210 *
2211 * Description: Initialize all Sccb manager data structures.
2212 *
2213 *---------------------------------------------------------------------*/
2214
2215static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
2216				       unsigned char target)
2217{
2218
2219	unsigned char lun, qtag;
2220	struct sccb_mgr_tar_info *currTar_Info;
2221
2222	currTar_Info = &FPT_sccbMgrTbl[p_card][target];
2223
2224	currTar_Info->TarSelQ_Cnt = 0;
2225	currTar_Info->TarSyncCtrl = 0;
2226
2227	currTar_Info->TarSelQ_Head = NULL;
2228	currTar_Info->TarSelQ_Tail = NULL;
2229	currTar_Info->TarTagQ_Cnt = 0;
2230	currTar_Info->TarLUN_CA = 0;
2231
2232	for (lun = 0; lun < MAX_LUN; lun++) {
2233		currTar_Info->TarLUNBusy[lun] = 0;
2234		currTar_Info->LunDiscQ_Idx[lun] = 0;
2235	}
2236
2237	for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
2238		if (FPT_BL_Card[p_card].discQ_Tbl[qtag] != NULL) {
2239			if (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
2240			    target) {
2241				FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
2242				FPT_BL_Card[p_card].discQCount--;
2243			}
2244		}
2245	}
2246}
2247
2248/*---------------------------------------------------------------------
2249 *
2250 * Function: sfetm
2251 *
2252 * Description: Read in a message byte from the SCSI bus, and check
2253 *              for a parity error.
2254 *
2255 *---------------------------------------------------------------------*/
2256
2257static unsigned char FPT_sfm(unsigned long port, struct sccb *pCurrSCCB)
2258{
2259	unsigned char message;
2260	unsigned short TimeOutLoop;
2261
2262	TimeOutLoop = 0;
2263	while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2264	       (TimeOutLoop++ < 20000)) {
2265	}
2266
2267	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
2268
2269	message = RD_HARPOON(port + hp_scsidata_0);
2270
2271	WR_HARPOON(port + hp_scsisig, SCSI_ACK + S_MSGI_PH);
2272
2273	if (TimeOutLoop > 20000)
2274		message = 0x00;	/* force message byte = 0 if Time Out on Req */
2275
2276	if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
2277	    (RD_HARPOON(port + hp_addstat) & SCSI_PAR_ERR)) {
2278		WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2279		WR_HARPOON(port + hp_xferstat, 0);
2280		WR_HARPOON(port + hp_fiforead, 0);
2281		WR_HARPOON(port + hp_fifowrite, 0);
2282		if (pCurrSCCB != NULL) {
2283			pCurrSCCB->Sccb_scsimsg = SMPARITY;
2284		}
2285		message = 0x00;
2286		do {
2287			ACCEPT_MSG_ATN(port);
2288			TimeOutLoop = 0;
2289			while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2290			       (TimeOutLoop++ < 20000)) {
2291			}
2292			if (TimeOutLoop > 20000) {
2293				WRW_HARPOON((port + hp_intstat), PARITY);
2294				return message;
2295			}
2296			if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) !=
2297			    S_MSGI_PH) {
2298				WRW_HARPOON((port + hp_intstat), PARITY);
2299				return message;
2300			}
2301			WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
2302
2303			RD_HARPOON(port + hp_scsidata_0);
2304
2305			WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2306
2307		} while (1);
2308
2309	}
2310	WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2311	WR_HARPOON(port + hp_xferstat, 0);
2312	WR_HARPOON(port + hp_fiforead, 0);
2313	WR_HARPOON(port + hp_fifowrite, 0);
2314	return message;
2315}
2316
2317/*---------------------------------------------------------------------
2318 *
2319 * Function: FPT_ssel
2320 *
2321 * Description: Load up automation and select target device.
2322 *
2323 *---------------------------------------------------------------------*/
2324
2325static void FPT_ssel(unsigned long port, unsigned char p_card)
2326{
2327
2328	unsigned char auto_loaded, i, target, *theCCB;
2329
2330	unsigned long cdb_reg;
2331	struct sccb_card *CurrCard;
2332	struct sccb *currSCCB;
2333	struct sccb_mgr_tar_info *currTar_Info;
2334	unsigned char lastTag, lun;
2335
2336	CurrCard = &FPT_BL_Card[p_card];
2337	currSCCB = CurrCard->currentSCCB;
2338	target = currSCCB->TargID;
2339	currTar_Info = &FPT_sccbMgrTbl[p_card][target];
2340	lastTag = CurrCard->tagQ_Lst;
2341
2342	ARAM_ACCESS(port);
2343
2344	if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
2345		currSCCB->ControlByte &= ~F_USE_CMD_Q;
2346
2347	if (((CurrCard->globalFlags & F_CONLUN_IO) &&
2348	     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
2349
2350		lun = currSCCB->Lun;
2351	else
2352		lun = 0;
2353
2354	if (CurrCard->globalFlags & F_TAG_STARTED) {
2355		if (!(currSCCB->ControlByte & F_USE_CMD_Q)) {
2356			if ((currTar_Info->TarLUN_CA == 0)
2357			    && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
2358				== TAG_Q_TRYING)) {
2359
2360				if (currTar_Info->TarTagQ_Cnt != 0) {
2361					currTar_Info->TarLUNBusy[lun] = 1;
2362					FPT_queueSelectFail(CurrCard, p_card);
2363					SGRAM_ACCESS(port);
2364					return;
2365				}
2366
2367				else {
2368					currTar_Info->TarLUNBusy[lun] = 1;
2369				}
2370
2371			}
2372			/*End non-tagged */
2373			else {
2374				currTar_Info->TarLUNBusy[lun] = 1;
2375			}
2376
2377		}
2378		/*!Use cmd Q Tagged */
2379		else {
2380			if (currTar_Info->TarLUN_CA == 1) {
2381				FPT_queueSelectFail(CurrCard, p_card);
2382				SGRAM_ACCESS(port);
2383				return;
2384			}
2385
2386			currTar_Info->TarLUNBusy[lun] = 1;
2387
2388		}		/*else use cmd Q tagged */
2389
2390	}
2391	/*if glob tagged started */
2392	else {
2393		currTar_Info->TarLUNBusy[lun] = 1;
2394	}
2395
2396	if ((((CurrCard->globalFlags & F_CONLUN_IO) &&
2397	      ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
2398	     || (!(currSCCB->ControlByte & F_USE_CMD_Q)))) {
2399		if (CurrCard->discQCount >= QUEUE_DEPTH) {
2400			currTar_Info->TarLUNBusy[lun] = 1;
2401			FPT_queueSelectFail(CurrCard, p_card);
2402			SGRAM_ACCESS(port);
2403			return;
2404		}
2405		for (i = 1; i < QUEUE_DEPTH; i++) {
2406			if (++lastTag >= QUEUE_DEPTH)
2407				lastTag = 1;
2408			if (CurrCard->discQ_Tbl[lastTag] == NULL) {
2409				CurrCard->tagQ_Lst = lastTag;
2410				currTar_Info->LunDiscQ_Idx[lun] = lastTag;
2411				CurrCard->discQ_Tbl[lastTag] = currSCCB;
2412				CurrCard->discQCount++;
2413				break;
2414			}
2415		}
2416		if (i == QUEUE_DEPTH) {
2417			currTar_Info->TarLUNBusy[lun] = 1;
2418			FPT_queueSelectFail(CurrCard, p_card);
2419			SGRAM_ACCESS(port);
2420			return;
2421		}
2422	}
2423
2424	auto_loaded = 0;
2425
2426	WR_HARPOON(port + hp_select_id, target);
2427	WR_HARPOON(port + hp_gp_reg_3, target);	/* Use by new automation logic */
2428
2429	if (currSCCB->OperationCode == RESET_COMMAND) {
2430		WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
2431						   (currSCCB->
2432						    Sccb_idmsg & ~DISC_PRIV)));
2433
2434		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + NP);
2435
2436		currSCCB->Sccb_scsimsg = SMDEV_RESET;
2437
2438		WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
2439		auto_loaded = 1;
2440		currSCCB->Sccb_scsistat = SELECT_BDR_ST;
2441
2442		if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
2443			currTar_Info->TarSyncCtrl = 0;
2444			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2445		}
2446
2447		if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
2448			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2449		}
2450
2451		FPT_sssyncv(port, target, NARROW_SCSI, currTar_Info);
2452		FPT_SccbMgrTableInitTarget(p_card, target);
2453
2454	}
2455
2456	else if (currSCCB->Sccb_scsistat == ABORT_ST) {
2457		WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
2458						   (currSCCB->
2459						    Sccb_idmsg & ~DISC_PRIV)));
2460
2461		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
2462
2463		WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT +
2464						     (((unsigned
2465							char)(currSCCB->
2466							      ControlByte &
2467							      TAG_TYPE_MASK)
2468						       >> 6) | (unsigned char)
2469						      0x20)));
2470		WRW_HARPOON((port + SYNC_MSGS + 2),
2471			    (MPM_OP + AMSG_OUT + currSCCB->Sccb_tag));
2472		WRW_HARPOON((port + SYNC_MSGS + 4), (BRH_OP + ALWAYS + NP));
2473
2474		WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
2475		auto_loaded = 1;
2476
2477	}
2478
2479	else if (!(currTar_Info->TarStatus & WIDE_NEGOCIATED)) {
2480		auto_loaded = FPT_siwidn(port, p_card);
2481		currSCCB->Sccb_scsistat = SELECT_WN_ST;
2482	}
2483
2484	else if (!((currTar_Info->TarStatus & TAR_SYNC_MASK)
2485		   == SYNC_SUPPORTED)) {
2486		auto_loaded = FPT_sisyncn(port, p_card, 0);
2487		currSCCB->Sccb_scsistat = SELECT_SN_ST;
2488	}
2489
2490	if (!auto_loaded) {
2491
2492		if (currSCCB->ControlByte & F_USE_CMD_Q) {
2493
2494			CurrCard->globalFlags |= F_TAG_STARTED;
2495
2496			if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
2497			    == TAG_Q_REJECT) {
2498				currSCCB->ControlByte &= ~F_USE_CMD_Q;
2499
2500				/* Fix up the start instruction with a jump to
2501				   Non-Tag-CMD handling */
2502				WRW_HARPOON((port + ID_MSG_STRT),
2503					    BRH_OP + ALWAYS + NTCMD);
2504
2505				WRW_HARPOON((port + NON_TAG_ID_MSG),
2506					    (MPM_OP + AMSG_OUT +
2507					     currSCCB->Sccb_idmsg));
2508
2509				WR_HARPOON(port + hp_autostart_3,
2510					   (SELECT + SELCHK_STRT));
2511
2512				/* Setup our STATE so we know what happened when
2513				   the wheels fall off. */
2514				currSCCB->Sccb_scsistat = SELECT_ST;
2515
2516				currTar_Info->TarLUNBusy[lun] = 1;
2517			}
2518
2519			else {
2520				WRW_HARPOON((port + ID_MSG_STRT),
2521					    (MPM_OP + AMSG_OUT +
2522					     currSCCB->Sccb_idmsg));
2523
2524				WRW_HARPOON((port + ID_MSG_STRT + 2),
2525					    (MPM_OP + AMSG_OUT +
2526					     (((unsigned char)(currSCCB->
2527							       ControlByte &
2528							       TAG_TYPE_MASK)
2529					       >> 6) | (unsigned char)0x20)));
2530
2531				for (i = 1; i < QUEUE_DEPTH; i++) {
2532					if (++lastTag >= QUEUE_DEPTH)
2533						lastTag = 1;
2534					if (CurrCard->discQ_Tbl[lastTag] ==
2535					    NULL) {
2536						WRW_HARPOON((port +
2537							     ID_MSG_STRT + 6),
2538							    (MPM_OP + AMSG_OUT +
2539							     lastTag));
2540						CurrCard->tagQ_Lst = lastTag;
2541						currSCCB->Sccb_tag = lastTag;
2542						CurrCard->discQ_Tbl[lastTag] =
2543						    currSCCB;
2544						CurrCard->discQCount++;
2545						break;
2546					}
2547				}
2548
2549				if (i == QUEUE_DEPTH) {
2550					currTar_Info->TarLUNBusy[lun] = 1;
2551					FPT_queueSelectFail(CurrCard, p_card);
2552					SGRAM_ACCESS(port);
2553					return;
2554				}
2555
2556				currSCCB->Sccb_scsistat = SELECT_Q_ST;
2557
2558				WR_HARPOON(port + hp_autostart_3,
2559					   (SELECT + SELCHK_STRT));
2560			}
2561		}
2562
2563		else {
2564
2565			WRW_HARPOON((port + ID_MSG_STRT),
2566				    BRH_OP + ALWAYS + NTCMD);
2567
2568			WRW_HARPOON((port + NON_TAG_ID_MSG),
2569				    (MPM_OP + AMSG_OUT + currSCCB->Sccb_idmsg));
2570
2571			currSCCB->Sccb_scsistat = SELECT_ST;
2572
2573			WR_HARPOON(port + hp_autostart_3,
2574				   (SELECT + SELCHK_STRT));
2575		}
2576
2577		theCCB = (unsigned char *)&currSCCB->Cdb[0];
2578
2579		cdb_reg = port + CMD_STRT;
2580
2581		for (i = 0; i < currSCCB->CdbLength; i++) {
2582			WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + *theCCB));
2583			cdb_reg += 2;
2584			theCCB++;
2585		}
2586
2587		if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
2588			WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
2589
2590	}
2591	/* auto_loaded */
2592	WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
2593	WR_HARPOON(port + hp_xferstat, 0x00);
2594
2595	WRW_HARPOON((port + hp_intstat), (PROG_HLT | TIMEOUT | SEL | BUS_FREE));
2596
2597	WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT));
2598
2599	if (!(currSCCB->Sccb_MGRFlags & F_DEV_SELECTED)) {
2600		WR_HARPOON(port + hp_scsictrl_0,
2601			   (SEL_TAR | ENA_ATN | ENA_RESEL | ENA_SCAM_SEL));
2602	} else {
2603
2604/*      auto_loaded =  (RD_HARPOON(port+hp_autostart_3) & (unsigned char)0x1F);
2605      auto_loaded |= AUTO_IMMED; */
2606		auto_loaded = AUTO_IMMED;
2607
2608		DISABLE_AUTO(port);
2609
2610		WR_HARPOON(port + hp_autostart_3, auto_loaded);
2611	}
2612
2613	SGRAM_ACCESS(port);
2614}
2615
2616/*---------------------------------------------------------------------
2617 *
2618 * Function: FPT_sres
2619 *
2620 * Description: Hookup the correct CCB and handle the incoming messages.
2621 *
2622 *---------------------------------------------------------------------*/
2623
2624static void FPT_sres(unsigned long port, unsigned char p_card,
2625		     struct sccb_card *pCurrCard)
2626{
2627
2628	unsigned char our_target, message, lun = 0, tag, msgRetryCount;
2629
2630	struct sccb_mgr_tar_info *currTar_Info;
2631	struct sccb *currSCCB;
2632
2633	if (pCurrCard->currentSCCB != NULL) {
2634		currTar_Info =
2635		    &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
2636		DISABLE_AUTO(port);
2637
2638		WR_HARPOON((port + hp_scsictrl_0), (ENA_RESEL | ENA_SCAM_SEL));
2639
2640		currSCCB = pCurrCard->currentSCCB;
2641		if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
2642			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2643			currSCCB->Sccb_scsistat = BUS_FREE_ST;
2644		}
2645		if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
2646			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2647			currSCCB->Sccb_scsistat = BUS_FREE_ST;
2648		}
2649		if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
2650		     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
2651		      TAG_Q_TRYING))) {
2652			currTar_Info->TarLUNBusy[currSCCB->Lun] = 0;
2653			if (currSCCB->Sccb_scsistat != ABORT_ST) {
2654				pCurrCard->discQCount--;
2655				pCurrCard->discQ_Tbl[currTar_Info->
2656						     LunDiscQ_Idx[currSCCB->
2657								  Lun]]
2658				    = NULL;
2659			}
2660		} else {
2661			currTar_Info->TarLUNBusy[0] = 0;
2662			if (currSCCB->Sccb_tag) {
2663				if (currSCCB->Sccb_scsistat != ABORT_ST) {
2664					pCurrCard->discQCount--;
2665					pCurrCard->discQ_Tbl[currSCCB->
2666							     Sccb_tag] = NULL;
2667				}
2668			} else {
2669				if (currSCCB->Sccb_scsistat != ABORT_ST) {
2670					pCurrCard->discQCount--;
2671					pCurrCard->discQ_Tbl[currTar_Info->
2672							     LunDiscQ_Idx[0]] =
2673					    NULL;
2674				}
2675			}
2676		}
2677
2678		FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
2679	}
2680
2681	WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
2682
2683	our_target = (unsigned char)(RD_HARPOON(port + hp_select_id) >> 4);
2684	currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
2685
2686	msgRetryCount = 0;
2687	do {
2688
2689		currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
2690		tag = 0;
2691
2692		while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
2693			if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
2694
2695				WRW_HARPOON((port + hp_intstat), PHASE);
2696				return;
2697			}
2698		}
2699
2700		WRW_HARPOON((port + hp_intstat), PHASE);
2701		if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH) {
2702
2703			message = FPT_sfm(port, pCurrCard->currentSCCB);
2704			if (message) {
2705
2706				if (message <= (0x80 | LUN_MASK)) {
2707					lun = message & (unsigned char)LUN_MASK;
2708
2709					if ((currTar_Info->
2710					     TarStatus & TAR_TAG_Q_MASK) ==
2711					    TAG_Q_TRYING) {
2712						if (currTar_Info->TarTagQ_Cnt !=
2713						    0) {
2714
2715							if (!
2716							    (currTar_Info->
2717							     TarLUN_CA)) {
2718								ACCEPT_MSG(port);	/*Release the ACK for ID msg. */
2719
2720								message =
2721								    FPT_sfm
2722								    (port,
2723								     pCurrCard->
2724								     currentSCCB);
2725								if (message) {
2726									ACCEPT_MSG
2727									    (port);
2728								}
2729
2730								else
2731									message
2732									    = 0;
2733
2734								if (message !=
2735								    0) {
2736									tag =
2737									    FPT_sfm
2738									    (port,
2739									     pCurrCard->
2740									     currentSCCB);
2741
2742									if (!
2743									    (tag))
2744										message
2745										    =
2746										    0;
2747								}
2748
2749							}
2750							/*C.A. exists! */
2751						}
2752						/*End Q cnt != 0 */
2753					}
2754					/*End Tag cmds supported! */
2755				}
2756				/*End valid ID message.  */
2757				else {
2758
2759					ACCEPT_MSG_ATN(port);
2760				}
2761
2762			}
2763			/* End good id message. */
2764			else {
2765
2766				message = 0;
2767			}
2768		} else {
2769			ACCEPT_MSG_ATN(port);
2770
2771			while (!
2772			       (RDW_HARPOON((port + hp_intstat)) &
2773				(PHASE | RESET))
2774			       && !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
2775			       && (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
2776
2777			return;
2778		}
2779
2780		if (message == 0) {
2781			msgRetryCount++;
2782			if (msgRetryCount == 1) {
2783				FPT_SendMsg(port, SMPARITY);
2784			} else {
2785				FPT_SendMsg(port, SMDEV_RESET);
2786
2787				FPT_sssyncv(port, our_target, NARROW_SCSI,
2788					    currTar_Info);
2789
2790				if (FPT_sccbMgrTbl[p_card][our_target].
2791				    TarEEValue & EE_SYNC_MASK) {
2792
2793					FPT_sccbMgrTbl[p_card][our_target].
2794					    TarStatus &= ~TAR_SYNC_MASK;
2795
2796				}
2797
2798				if (FPT_sccbMgrTbl[p_card][our_target].
2799				    TarEEValue & EE_WIDE_SCSI) {
2800
2801					FPT_sccbMgrTbl[p_card][our_target].
2802					    TarStatus &= ~TAR_WIDE_MASK;
2803				}
2804
2805				FPT_queueFlushTargSccb(p_card, our_target,
2806						       SCCB_COMPLETE);
2807				FPT_SccbMgrTableInitTarget(p_card, our_target);
2808				return;
2809			}
2810		}
2811	} while (message == 0);
2812
2813	if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
2814	     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
2815		currTar_Info->TarLUNBusy[lun] = 1;
2816		pCurrCard->currentSCCB =
2817		    pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[lun]];
2818		if (pCurrCard->currentSCCB != NULL) {
2819			ACCEPT_MSG(port);
2820		} else {
2821			ACCEPT_MSG_ATN(port);
2822		}
2823	} else {
2824		currTar_Info->TarLUNBusy[0] = 1;
2825
2826		if (tag) {
2827			if (pCurrCard->discQ_Tbl[tag] != NULL) {
2828				pCurrCard->currentSCCB =
2829				    pCurrCard->discQ_Tbl[tag];
2830				currTar_Info->TarTagQ_Cnt--;
2831				ACCEPT_MSG(port);
2832			} else {
2833				ACCEPT_MSG_ATN(port);
2834			}
2835		} else {
2836			pCurrCard->currentSCCB =
2837			    pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]];
2838			if (pCurrCard->currentSCCB != NULL) {
2839				ACCEPT_MSG(port);
2840			} else {
2841				ACCEPT_MSG_ATN(port);
2842			}
2843		}
2844	}
2845
2846	if (pCurrCard->currentSCCB != NULL) {
2847		if (pCurrCard->currentSCCB->Sccb_scsistat == ABORT_ST) {
2848			/* During Abort Tag command, the target could have got re-selected
2849			   and completed the command. Check the select Q and remove the CCB
2850			   if it is in the Select Q */
2851			FPT_queueFindSccb(pCurrCard->currentSCCB, p_card);
2852		}
2853	}
2854
2855	while (!(RDW_HARPOON((port + hp_intstat)) & (PHASE | RESET)) &&
2856	       !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ) &&
2857	       (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
2858}
2859
2860static void FPT_SendMsg(unsigned long port, unsigned char message)
2861{
2862	while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
2863		if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
2864
2865			WRW_HARPOON((port + hp_intstat), PHASE);
2866			return;
2867		}
2868	}
2869
2870	WRW_HARPOON((port + hp_intstat), PHASE);
2871	if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGO_PH) {
2872		WRW_HARPOON((port + hp_intstat),
2873			    (BUS_FREE | PHASE | XFER_CNT_0));
2874
2875		WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
2876
2877		WR_HARPOON(port + hp_scsidata_0, message);
2878
2879		WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2880
2881		ACCEPT_MSG(port);
2882
2883		WR_HARPOON(port + hp_portctrl_0, 0x00);
2884
2885		if ((message == SMABORT) || (message == SMDEV_RESET) ||
2886		    (message == SMABORT_TAG)) {
2887			while (!
2888			       (RDW_HARPOON((port + hp_intstat)) &
2889				(BUS_FREE | PHASE))) {
2890			}
2891
2892			if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
2893				WRW_HARPOON((port + hp_intstat), BUS_FREE);
2894			}
2895		}
2896	}
2897}
2898
2899/*---------------------------------------------------------------------
2900 *
2901 * Function: FPT_sdecm
2902 *
2903 * Description: Determine the proper response to the message from the
2904 *              target device.
2905 *
2906 *---------------------------------------------------------------------*/
2907static void FPT_sdecm(unsigned char message, unsigned long port,
2908		      unsigned char p_card)
2909{
2910	struct sccb *currSCCB;
2911	struct sccb_card *CurrCard;
2912	struct sccb_mgr_tar_info *currTar_Info;
2913
2914	CurrCard = &FPT_BL_Card[p_card];
2915	currSCCB = CurrCard->currentSCCB;
2916
2917	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
2918
2919	if (message == SMREST_DATA_PTR) {
2920		if (!(currSCCB->Sccb_XferState & F_NO_DATA_YET)) {
2921			currSCCB->Sccb_ATC = currSCCB->Sccb_savedATC;
2922
2923			FPT_hostDataXferRestart(currSCCB);
2924		}
2925
2926		ACCEPT_MSG(port);
2927		WR_HARPOON(port + hp_autostart_1,
2928			   (AUTO_IMMED + DISCONNECT_START));
2929	}
2930
2931	else if (message == SMCMD_COMP) {
2932
2933		if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
2934			currTar_Info->TarStatus &=
2935			    ~(unsigned char)TAR_TAG_Q_MASK;
2936			currTar_Info->TarStatus |= (unsigned char)TAG_Q_REJECT;
2937		}
2938
2939		ACCEPT_MSG(port);
2940
2941	}
2942
2943	else if ((message == SMNO_OP) || (message >= SMIDENT)
2944		 || (message == SMINIT_RECOVERY) || (message == SMREL_RECOVERY)) {
2945
2946		ACCEPT_MSG(port);
2947		WR_HARPOON(port + hp_autostart_1,
2948			   (AUTO_IMMED + DISCONNECT_START));
2949	}
2950
2951	else if (message == SMREJECT) {
2952
2953		if ((currSCCB->Sccb_scsistat == SELECT_SN_ST) ||
2954		    (currSCCB->Sccb_scsistat == SELECT_WN_ST) ||
2955		    ((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)
2956		    || ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) ==
2957			TAG_Q_TRYING))
2958		{
2959			WRW_HARPOON((port + hp_intstat), BUS_FREE);
2960
2961			ACCEPT_MSG(port);
2962
2963			while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2964			       (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
2965			{
2966			}
2967
2968			if (currSCCB->Lun == 0x00) {
2969				if ((currSCCB->Sccb_scsistat == SELECT_SN_ST)) {
2970
2971					currTar_Info->TarStatus |=
2972					    (unsigned char)SYNC_SUPPORTED;
2973
2974					currTar_Info->TarEEValue &=
2975					    ~EE_SYNC_MASK;
2976				}
2977
2978				else if ((currSCCB->Sccb_scsistat ==
2979					  SELECT_WN_ST)) {
2980
2981					currTar_Info->TarStatus =
2982					    (currTar_Info->
2983					     TarStatus & ~WIDE_ENABLED) |
2984					    WIDE_NEGOCIATED;
2985
2986					currTar_Info->TarEEValue &=
2987					    ~EE_WIDE_SCSI;
2988
2989				}
2990
2991				else if ((currTar_Info->
2992					  TarStatus & TAR_TAG_Q_MASK) ==
2993					 TAG_Q_TRYING) {
2994					currTar_Info->TarStatus =
2995					    (currTar_Info->
2996					     TarStatus & ~(unsigned char)
2997					     TAR_TAG_Q_MASK) | TAG_Q_REJECT;
2998
2999					currSCCB->ControlByte &= ~F_USE_CMD_Q;
3000					CurrCard->discQCount--;
3001					CurrCard->discQ_Tbl[currSCCB->
3002							    Sccb_tag] = NULL;
3003					currSCCB->Sccb_tag = 0x00;
3004
3005				}
3006			}
3007
3008			if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
3009
3010				if (currSCCB->Lun == 0x00) {
3011					WRW_HARPOON((port + hp_intstat),
3012						    BUS_FREE);
3013					CurrCard->globalFlags |= F_NEW_SCCB_CMD;
3014				}
3015			}
3016
3017			else {
3018
3019				if ((CurrCard->globalFlags & F_CONLUN_IO) &&
3020				    ((currTar_Info->
3021				      TarStatus & TAR_TAG_Q_MASK) !=
3022				     TAG_Q_TRYING))
3023					currTar_Info->TarLUNBusy[currSCCB->
3024								 Lun] = 1;
3025				else
3026					currTar_Info->TarLUNBusy[0] = 1;
3027
3028				currSCCB->ControlByte &=
3029				    ~(unsigned char)F_USE_CMD_Q;
3030
3031				WR_HARPOON(port + hp_autostart_1,
3032					   (AUTO_IMMED + DISCONNECT_START));
3033
3034			}
3035		}
3036
3037		else {
3038			ACCEPT_MSG(port);
3039
3040			while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
3041			       (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
3042			{
3043			}
3044
3045			if (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)) {
3046				WR_HARPOON(port + hp_autostart_1,
3047					   (AUTO_IMMED + DISCONNECT_START));
3048			}
3049		}
3050	}
3051
3052	else if (message == SMEXT) {
3053
3054		ACCEPT_MSG(port);
3055		FPT_shandem(port, p_card, currSCCB);
3056	}
3057
3058	else if (message == SMIGNORWR) {
3059
3060		ACCEPT_MSG(port);	/* ACK the RESIDUE MSG */
3061
3062		message = FPT_sfm(port, currSCCB);
3063
3064		if (currSCCB->Sccb_scsimsg != SMPARITY)
3065			ACCEPT_MSG(port);
3066		WR_HARPOON(port + hp_autostart_1,
3067			   (AUTO_IMMED + DISCONNECT_START));
3068	}
3069
3070	else {
3071
3072		currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
3073		currSCCB->Sccb_scsimsg = SMREJECT;
3074
3075		ACCEPT_MSG_ATN(port);
3076		WR_HARPOON(port + hp_autostart_1,
3077			   (AUTO_IMMED + DISCONNECT_START));
3078	}
3079}
3080
3081/*---------------------------------------------------------------------
3082 *
3083 * Function: FPT_shandem
3084 *
3085 * Description: Decide what to do with the extended message.
3086 *
3087 *---------------------------------------------------------------------*/
3088static void FPT_shandem(unsigned long port, unsigned char p_card,
3089			struct sccb *pCurrSCCB)
3090{
3091	unsigned char length, message;
3092
3093	length = FPT_sfm(port, pCurrSCCB);
3094	if (length) {
3095
3096		ACCEPT_MSG(port);
3097		message = FPT_sfm(port, pCurrSCCB);
3098		if (message) {
3099
3100			if (message == SMSYNC) {
3101
3102				if (length == 0x03) {
3103
3104					ACCEPT_MSG(port);
3105					FPT_stsyncn(port, p_card);
3106				} else {
3107
3108					pCurrSCCB->Sccb_scsimsg = SMREJECT;
3109					ACCEPT_MSG_ATN(port);
3110				}
3111			} else if (message == SMWDTR) {
3112
3113				if (length == 0x02) {
3114
3115					ACCEPT_MSG(port);
3116					FPT_stwidn(port, p_card);
3117				} else {
3118
3119					pCurrSCCB->Sccb_scsimsg = SMREJECT;
3120					ACCEPT_MSG_ATN(port);
3121
3122					WR_HARPOON(port + hp_autostart_1,
3123						   (AUTO_IMMED +
3124						    DISCONNECT_START));
3125				}
3126			} else {
3127
3128				pCurrSCCB->Sccb_scsimsg = SMREJECT;
3129				ACCEPT_MSG_ATN(port);
3130
3131				WR_HARPOON(port + hp_autostart_1,
3132					   (AUTO_IMMED + DISCONNECT_START));
3133			}
3134		} else {
3135			if (pCurrSCCB->Sccb_scsimsg != SMPARITY)
3136				ACCEPT_MSG(port);
3137			WR_HARPOON(port + hp_autostart_1,
3138				   (AUTO_IMMED + DISCONNECT_START));
3139		}
3140	} else {
3141		if (pCurrSCCB->Sccb_scsimsg == SMPARITY)
3142			WR_HARPOON(port + hp_autostart_1,
3143				   (AUTO_IMMED + DISCONNECT_START));
3144	}
3145}
3146
3147/*---------------------------------------------------------------------
3148 *
3149 * Function: FPT_sisyncn
3150 *
3151 * Description: Read in a message byte from the SCSI bus, and check
3152 *              for a parity error.
3153 *
3154 *---------------------------------------------------------------------*/
3155
3156static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card,
3157				 unsigned char syncFlag)
3158{
3159	struct sccb *currSCCB;
3160	struct sccb_mgr_tar_info *currTar_Info;
3161
3162	currSCCB = FPT_BL_Card[p_card].currentSCCB;
3163	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
3164
3165	if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)) {
3166
3167		WRW_HARPOON((port + ID_MSG_STRT),
3168			    (MPM_OP + AMSG_OUT +
3169			     (currSCCB->
3170			      Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
3171
3172		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
3173
3174		WRW_HARPOON((port + SYNC_MSGS + 0),
3175			    (MPM_OP + AMSG_OUT + SMEXT));
3176		WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
3177		WRW_HARPOON((port + SYNC_MSGS + 4),
3178			    (MPM_OP + AMSG_OUT + SMSYNC));
3179
3180		if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
3181
3182			WRW_HARPOON((port + SYNC_MSGS + 6),
3183				    (MPM_OP + AMSG_OUT + 12));
3184
3185		else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
3186			 EE_SYNC_10MB)
3187
3188			WRW_HARPOON((port + SYNC_MSGS + 6),
3189				    (MPM_OP + AMSG_OUT + 25));
3190
3191		else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
3192			 EE_SYNC_5MB)
3193
3194			WRW_HARPOON((port + SYNC_MSGS + 6),
3195				    (MPM_OP + AMSG_OUT + 50));
3196
3197		else
3198			WRW_HARPOON((port + SYNC_MSGS + 6),
3199				    (MPM_OP + AMSG_OUT + 00));
3200
3201		WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
3202		WRW_HARPOON((port + SYNC_MSGS + 10),
3203			    (MPM_OP + AMSG_OUT + DEFAULT_OFFSET));
3204		WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
3205
3206		if (syncFlag == 0) {
3207			WR_HARPOON(port + hp_autostart_3,
3208				   (SELECT + SELCHK_STRT));
3209			currTar_Info->TarStatus =
3210			    ((currTar_Info->
3211			      TarStatus & ~(unsigned char)TAR_SYNC_MASK) |
3212			     (unsigned char)SYNC_TRYING);
3213		} else {
3214			WR_HARPOON(port + hp_autostart_3,
3215				   (AUTO_IMMED + CMD_ONLY_STRT));
3216		}
3217
3218		return 1;
3219	}
3220
3221	else {
3222
3223		currTar_Info->TarStatus |= (unsigned char)SYNC_SUPPORTED;
3224		currTar_Info->TarEEValue &= ~EE_SYNC_MASK;
3225		return 0;
3226	}
3227}
3228
3229/*---------------------------------------------------------------------
3230 *
3231 * Function: FPT_stsyncn
3232 *
3233 * Description: The has sent us a Sync Nego message so handle it as
3234 *              necessary.
3235 *
3236 *---------------------------------------------------------------------*/
3237static void FPT_stsyncn(unsigned long port, unsigned char p_card)
3238{
3239	unsigned char sync_msg, offset, sync_reg, our_sync_msg;
3240	struct sccb *currSCCB;
3241	struct sccb_mgr_tar_info *currTar_Info;
3242
3243	currSCCB = FPT_BL_Card[p_card].currentSCCB;
3244	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
3245
3246	sync_msg = FPT_sfm(port, currSCCB);
3247
3248	if ((sync_msg == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3249		WR_HARPOON(port + hp_autostart_1,
3250			   (AUTO_IMMED + DISCONNECT_START));
3251		return;
3252	}
3253
3254	ACCEPT_MSG(port);
3255
3256	offset = FPT_sfm(port, currSCCB);
3257
3258	if ((offset == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3259		WR_HARPOON(port + hp_autostart_1,
3260			   (AUTO_IMMED + DISCONNECT_START));
3261		return;
3262	}
3263
3264	if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
3265
3266		our_sync_msg = 12;	/* Setup our Message to 20mb/s */
3267
3268	else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_10MB)
3269
3270		our_sync_msg = 25;	/* Setup our Message to 10mb/s */
3271
3272	else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_5MB)
3273
3274		our_sync_msg = 50;	/* Setup our Message to 5mb/s */
3275	else
3276
3277		our_sync_msg = 0;	/* Message = Async */
3278
3279	if (sync_msg < our_sync_msg) {
3280		sync_msg = our_sync_msg;	/*if faster, then set to max. */
3281	}
3282
3283	if (offset == ASYNC)
3284		sync_msg = ASYNC;
3285
3286	if (offset > MAX_OFFSET)
3287		offset = MAX_OFFSET;
3288
3289	sync_reg = 0x00;
3290
3291	if (sync_msg > 12)
3292
3293		sync_reg = 0x20;	/* Use 10MB/s */
3294
3295	if (sync_msg > 25)
3296
3297		sync_reg = 0x40;	/* Use 6.6MB/s */
3298
3299	if (sync_msg > 38)
3300
3301		sync_reg = 0x60;	/* Use 5MB/s */
3302
3303	if (sync_msg > 50)
3304
3305		sync_reg = 0x80;	/* Use 4MB/s */
3306
3307	if (sync_msg > 62)
3308
3309		sync_reg = 0xA0;	/* Use 3.33MB/s */
3310
3311	if (sync_msg > 75)
3312
3313		sync_reg = 0xC0;	/* Use 2.85MB/s */
3314
3315	if (sync_msg > 87)
3316
3317		sync_reg = 0xE0;	/* Use 2.5MB/s */
3318
3319	if (sync_msg > 100) {
3320
3321		sync_reg = 0x00;	/* Use ASYNC */
3322		offset = 0x00;
3323	}
3324
3325	if (currTar_Info->TarStatus & WIDE_ENABLED)
3326
3327		sync_reg |= offset;
3328
3329	else
3330
3331		sync_reg |= (offset | NARROW_SCSI);
3332
3333	FPT_sssyncv(port, currSCCB->TargID, sync_reg, currTar_Info);
3334
3335	if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
3336
3337		ACCEPT_MSG(port);
3338
3339		currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3340					    ~(unsigned char)TAR_SYNC_MASK) |
3341					   (unsigned char)SYNC_SUPPORTED);
3342
3343		WR_HARPOON(port + hp_autostart_1,
3344			   (AUTO_IMMED + DISCONNECT_START));
3345	}
3346
3347	else {
3348
3349		ACCEPT_MSG_ATN(port);
3350
3351		FPT_sisyncr(port, sync_msg, offset);
3352
3353		currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3354					    ~(unsigned char)TAR_SYNC_MASK) |
3355					   (unsigned char)SYNC_SUPPORTED);
3356	}
3357}
3358
3359/*---------------------------------------------------------------------
3360 *
3361 * Function: FPT_sisyncr
3362 *
3363 * Description: Answer the targets sync message.
3364 *
3365 *---------------------------------------------------------------------*/
3366static void FPT_sisyncr(unsigned long port, unsigned char sync_pulse,
3367			unsigned char offset)
3368{
3369	ARAM_ACCESS(port);
3370	WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT));
3371	WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
3372	WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMSYNC));
3373	WRW_HARPOON((port + SYNC_MSGS + 6), (MPM_OP + AMSG_OUT + sync_pulse));
3374	WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
3375	WRW_HARPOON((port + SYNC_MSGS + 10), (MPM_OP + AMSG_OUT + offset));
3376	WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
3377	SGRAM_ACCESS(port);
3378
3379	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3380	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
3381
3382	WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
3383
3384	while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
3385	}
3386}
3387
3388/*---------------------------------------------------------------------
3389 *
3390 * Function: FPT_siwidn
3391 *
3392 * Description: Read in a message byte from the SCSI bus, and check
3393 *              for a parity error.
3394 *
3395 *---------------------------------------------------------------------*/
3396
3397static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card)
3398{
3399	struct sccb *currSCCB;
3400	struct sccb_mgr_tar_info *currTar_Info;
3401
3402	currSCCB = FPT_BL_Card[p_card].currentSCCB;
3403	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
3404
3405	if (!((currTar_Info->TarStatus & TAR_WIDE_MASK) == WIDE_NEGOCIATED)) {
3406
3407		WRW_HARPOON((port + ID_MSG_STRT),
3408			    (MPM_OP + AMSG_OUT +
3409			     (currSCCB->
3410			      Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
3411
3412		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
3413
3414		WRW_HARPOON((port + SYNC_MSGS + 0),
3415			    (MPM_OP + AMSG_OUT + SMEXT));
3416		WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
3417		WRW_HARPOON((port + SYNC_MSGS + 4),
3418			    (MPM_OP + AMSG_OUT + SMWDTR));
3419		WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
3420		WRW_HARPOON((port + SYNC_MSGS + 8),
3421			    (MPM_OP + AMSG_OUT + SM16BIT));
3422		WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
3423
3424		WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
3425
3426		currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3427					    ~(unsigned char)TAR_WIDE_MASK) |
3428					   (unsigned char)WIDE_ENABLED);
3429
3430		return 1;
3431	}
3432
3433	else {
3434
3435		currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3436					    ~(unsigned char)TAR_WIDE_MASK) |
3437					   WIDE_NEGOCIATED);
3438
3439		currTar_Info->TarEEValue &= ~EE_WIDE_SCSI;
3440		return 0;
3441	}
3442}
3443
3444/*---------------------------------------------------------------------
3445 *
3446 * Function: FPT_stwidn
3447 *
3448 * Description: The has sent us a Wide Nego message so handle it as
3449 *              necessary.
3450 *
3451 *---------------------------------------------------------------------*/
3452static void FPT_stwidn(unsigned long port, unsigned char p_card)
3453{
3454	unsigned char width;
3455	struct sccb *currSCCB;
3456	struct sccb_mgr_tar_info *currTar_Info;
3457
3458	currSCCB = FPT_BL_Card[p_card].currentSCCB;
3459	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
3460
3461	width = FPT_sfm(port, currSCCB);
3462
3463	if ((width == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3464		WR_HARPOON(port + hp_autostart_1,
3465			   (AUTO_IMMED + DISCONNECT_START));
3466		return;
3467	}
3468
3469	if (!(currTar_Info->TarEEValue & EE_WIDE_SCSI))
3470		width = 0;
3471
3472	if (width) {
3473		currTar_Info->TarStatus |= WIDE_ENABLED;
3474		width = 0;
3475	} else {
3476		width = NARROW_SCSI;
3477		currTar_Info->TarStatus &= ~WIDE_ENABLED;
3478	}
3479
3480	FPT_sssyncv(port, currSCCB->TargID, width, currTar_Info);
3481
3482	if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
3483
3484		currTar_Info->TarStatus |= WIDE_NEGOCIATED;
3485
3486		if (!
3487		    ((currTar_Info->TarStatus & TAR_SYNC_MASK) ==
3488		     SYNC_SUPPORTED)) {
3489			ACCEPT_MSG_ATN(port);
3490			ARAM_ACCESS(port);
3491			FPT_sisyncn(port, p_card, 1);
3492			currSCCB->Sccb_scsistat = SELECT_SN_ST;
3493			SGRAM_ACCESS(port);
3494		} else {
3495			ACCEPT_MSG(port);
3496			WR_HARPOON(port + hp_autostart_1,
3497				   (AUTO_IMMED + DISCONNECT_START));
3498		}
3499	}
3500
3501	else {
3502
3503		ACCEPT_MSG_ATN(port);
3504
3505		if (currTar_Info->TarEEValue & EE_WIDE_SCSI)
3506			width = SM16BIT;
3507		else
3508			width = SM8BIT;
3509
3510		FPT_siwidr(port, width);
3511
3512		currTar_Info->TarStatus |= (WIDE_NEGOCIATED | WIDE_ENABLED);
3513	}
3514}
3515
3516/*---------------------------------------------------------------------
3517 *
3518 * Function: FPT_siwidr
3519 *
3520 * Description: Answer the targets Wide nego message.
3521 *
3522 *---------------------------------------------------------------------*/
3523static void FPT_siwidr(unsigned long port, unsigned char width)
3524{
3525	ARAM_ACCESS(port);
3526	WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT));
3527	WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
3528	WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMWDTR));
3529	WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
3530	WRW_HARPOON((port + SYNC_MSGS + 8), (MPM_OP + AMSG_OUT + width));
3531	WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
3532	SGRAM_ACCESS(port);
3533
3534	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3535	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
3536
3537	WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
3538
3539	while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
3540	}
3541}
3542
3543/*---------------------------------------------------------------------
3544 *
3545 * Function: FPT_sssyncv
3546 *
3547 * Description: Write the desired value to the Sync Register for the
3548 *              ID specified.
3549 *
3550 *---------------------------------------------------------------------*/
3551static void FPT_sssyncv(unsigned long p_port, unsigned char p_id,
3552			unsigned char p_sync_value,
3553			struct sccb_mgr_tar_info *currTar_Info)
3554{
3555	unsigned char index;
3556
3557	index = p_id;
3558
3559	switch (index) {
3560
3561	case 0:
3562		index = 12;	/* hp_synctarg_0 */
3563		break;
3564	case 1:
3565		index = 13;	/* hp_synctarg_1 */
3566		break;
3567	case 2:
3568		index = 14;	/* hp_synctarg_2 */
3569		break;
3570	case 3:
3571		index = 15;	/* hp_synctarg_3 */
3572		break;
3573	case 4:
3574		index = 8;	/* hp_synctarg_4 */
3575		break;
3576	case 5:
3577		index = 9;	/* hp_synctarg_5 */
3578		break;
3579	case 6:
3580		index = 10;	/* hp_synctarg_6 */
3581		break;
3582	case 7:
3583		index = 11;	/* hp_synctarg_7 */
3584		break;
3585	case 8:
3586		index = 4;	/* hp_synctarg_8 */
3587		break;
3588	case 9:
3589		index = 5;	/* hp_synctarg_9 */
3590		break;
3591	case 10:
3592		index = 6;	/* hp_synctarg_10 */
3593		break;
3594	case 11:
3595		index = 7;	/* hp_synctarg_11 */
3596		break;
3597	case 12:
3598		index = 0;	/* hp_synctarg_12 */
3599		break;
3600	case 13:
3601		index = 1;	/* hp_synctarg_13 */
3602		break;
3603	case 14:
3604		index = 2;	/* hp_synctarg_14 */
3605		break;
3606	case 15:
3607		index = 3;	/* hp_synctarg_15 */
3608
3609	}
3610
3611	WR_HARPOON(p_port + hp_synctarg_base + index, p_sync_value);
3612
3613	currTar_Info->TarSyncCtrl = p_sync_value;
3614}
3615
3616/*---------------------------------------------------------------------
3617 *
3618 * Function: FPT_sresb
3619 *
3620 * Description: Reset the desired card's SCSI bus.
3621 *
3622 *---------------------------------------------------------------------*/
3623static void FPT_sresb(unsigned long port, unsigned char p_card)
3624{
3625	unsigned char scsiID, i;
3626
3627	struct sccb_mgr_tar_info *currTar_Info;
3628
3629	WR_HARPOON(port + hp_page_ctrl,
3630		   (RD_HARPOON(port + hp_page_ctrl) | G_INT_DISABLE));
3631	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
3632
3633	WR_HARPOON(port + hp_scsictrl_0, SCSI_RST);
3634
3635	scsiID = RD_HARPOON(port + hp_seltimeout);
3636	WR_HARPOON(port + hp_seltimeout, TO_5ms);
3637	WRW_HARPOON((port + hp_intstat), TIMEOUT);
3638
3639	WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT | START_TO));
3640
3641	while (!(RDW_HARPOON((port + hp_intstat)) & TIMEOUT)) {
3642	}
3643
3644	WR_HARPOON(port + hp_seltimeout, scsiID);
3645
3646	WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
3647
3648	FPT_Wait(port, TO_5ms);
3649
3650	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
3651
3652	WR_HARPOON(port + hp_int_mask, (RD_HARPOON(port + hp_int_mask) | 0x00));
3653
3654	for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
3655		currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
3656
3657		if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
3658			currTar_Info->TarSyncCtrl = 0;
3659			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
3660		}
3661
3662		if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
3663			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
3664		}
3665
3666		FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
3667
3668		FPT_SccbMgrTableInitTarget(p_card, scsiID);
3669	}
3670
3671	FPT_BL_Card[p_card].scanIndex = 0x00;
3672	FPT_BL_Card[p_card].currentSCCB = NULL;
3673	FPT_BL_Card[p_card].globalFlags &= ~(F_TAG_STARTED | F_HOST_XFER_ACT
3674					     | F_NEW_SCCB_CMD);
3675	FPT_BL_Card[p_card].cmdCounter = 0x00;
3676	FPT_BL_Card[p_card].discQCount = 0x00;
3677	FPT_BL_Card[p_card].tagQ_Lst = 0x01;
3678
3679	for (i = 0; i < QUEUE_DEPTH; i++)
3680		FPT_BL_Card[p_card].discQ_Tbl[i] = NULL;
3681
3682	WR_HARPOON(port + hp_page_ctrl,
3683		   (RD_HARPOON(port + hp_page_ctrl) & ~G_INT_DISABLE));
3684
3685}
3686
3687/*---------------------------------------------------------------------
3688 *
3689 * Function: FPT_ssenss
3690 *
3691 * Description: Setup for the Auto Sense command.
3692 *
3693 *---------------------------------------------------------------------*/
3694static void FPT_ssenss(struct sccb_card *pCurrCard)
3695{
3696	unsigned char i;
3697	struct sccb *currSCCB;
3698
3699	currSCCB = pCurrCard->currentSCCB;
3700
3701	currSCCB->Save_CdbLen = currSCCB->CdbLength;
3702
3703	for (i = 0; i < 6; i++) {
3704
3705		currSCCB->Save_Cdb[i] = currSCCB->Cdb[i];
3706	}
3707
3708	currSCCB->CdbLength = SIX_BYTE_CMD;
3709	currSCCB->Cdb[0] = SCSI_REQUEST_SENSE;
3710	currSCCB->Cdb[1] = currSCCB->Cdb[1] & (unsigned char)0xE0;	/*Keep LUN. */
3711	currSCCB->Cdb[2] = 0x00;
3712	currSCCB->Cdb[3] = 0x00;
3713	currSCCB->Cdb[4] = currSCCB->RequestSenseLength;
3714	currSCCB->Cdb[5] = 0x00;
3715
3716	currSCCB->Sccb_XferCnt = (unsigned long)currSCCB->RequestSenseLength;
3717
3718	currSCCB->Sccb_ATC = 0x00;
3719
3720	currSCCB->Sccb_XferState |= F_AUTO_SENSE;
3721
3722	currSCCB->Sccb_XferState &= ~F_SG_XFER;
3723
3724	currSCCB->Sccb_idmsg = currSCCB->Sccb_idmsg & ~(unsigned char)DISC_PRIV;
3725
3726	currSCCB->ControlByte = 0x00;
3727
3728	currSCCB->Sccb_MGRFlags &= F_STATUSLOADED;
3729}
3730
3731/*---------------------------------------------------------------------
3732 *
3733 * Function: FPT_sxfrp
3734 *
3735 * Description: Transfer data into the bit bucket until the device
3736 *              decides to switch phase.
3737 *
3738 *---------------------------------------------------------------------*/
3739
3740static void FPT_sxfrp(unsigned long p_port, unsigned char p_card)
3741{
3742	unsigned char curr_phz;
3743
3744	DISABLE_AUTO(p_port);
3745
3746	if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
3747
3748		FPT_hostDataXferAbort(p_port, p_card,
3749				      FPT_BL_Card[p_card].currentSCCB);
3750
3751	}
3752
3753	/* If the Automation handled the end of the transfer then do not
3754	   match the phase or we will get out of sync with the ISR.       */
3755
3756	if (RDW_HARPOON((p_port + hp_intstat)) &
3757	    (BUS_FREE | XFER_CNT_0 | AUTO_INT))
3758		return;
3759
3760	WR_HARPOON(p_port + hp_xfercnt_0, 0x00);
3761
3762	curr_phz = RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ;
3763
3764	WRW_HARPOON((p_port + hp_intstat), XFER_CNT_0);
3765
3766	WR_HARPOON(p_port + hp_scsisig, curr_phz);
3767
3768	while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET)) &&
3769	       (curr_phz ==
3770		(RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ)))
3771	{
3772		if (curr_phz & (unsigned char)SCSI_IOBIT) {
3773			WR_HARPOON(p_port + hp_portctrl_0,
3774				   (SCSI_PORT | HOST_PORT | SCSI_INBIT));
3775
3776			if (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
3777				RD_HARPOON(p_port + hp_fifodata_0);
3778			}
3779		} else {
3780			WR_HARPOON(p_port + hp_portctrl_0,
3781				   (SCSI_PORT | HOST_PORT | HOST_WRT));
3782			if (RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY) {
3783				WR_HARPOON(p_port + hp_fifodata_0, 0xFA);
3784			}
3785		}
3786	}			/* End of While loop for padding data I/O phase */
3787
3788	while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
3789		if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ)
3790			break;
3791	}
3792
3793	WR_HARPOON(p_port + hp_portctrl_0,
3794		   (SCSI_PORT | HOST_PORT | SCSI_INBIT));
3795	while (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
3796		RD_HARPOON(p_port + hp_fifodata_0);
3797	}
3798
3799	if (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
3800		WR_HARPOON(p_port + hp_autostart_0,
3801			   (AUTO_IMMED + DISCONNECT_START));
3802		while (!(RDW_HARPOON((p_port + hp_intstat)) & AUTO_INT)) {
3803		}
3804
3805		if (RDW_HARPOON((p_port + hp_intstat)) &
3806		    (ICMD_COMP | ITAR_DISC))
3807			while (!
3808			       (RDW_HARPOON((p_port + hp_intstat)) &
3809				(BUS_FREE | RSEL))) ;
3810	}
3811}
3812
3813/*---------------------------------------------------------------------
3814 *
3815 * Function: FPT_schkdd
3816 *
3817 * Description: Make sure data has been flushed from both FIFOs and abort
3818 *              the operations if necessary.
3819 *
3820 *---------------------------------------------------------------------*/
3821
3822static void FPT_schkdd(unsigned long port, unsigned char p_card)
3823{
3824	unsigned short TimeOutLoop;
3825	unsigned char sPhase;
3826
3827	struct sccb *currSCCB;
3828
3829	currSCCB = FPT_BL_Card[p_card].currentSCCB;
3830
3831	if ((currSCCB->Sccb_scsistat != DATA_OUT_ST) &&
3832	    (currSCCB->Sccb_scsistat != DATA_IN_ST)) {
3833		return;
3834	}
3835
3836	if (currSCCB->Sccb_XferState & F_ODD_BALL_CNT) {
3837
3838		currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - 1);
3839
3840		currSCCB->Sccb_XferCnt = 1;
3841
3842		currSCCB->Sccb_XferState &= ~F_ODD_BALL_CNT;
3843		WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
3844		WR_HARPOON(port + hp_xferstat, 0x00);
3845	}
3846
3847	else {
3848
3849		currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
3850
3851		currSCCB->Sccb_XferCnt = 0;
3852	}
3853
3854	if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
3855	    (currSCCB->HostStatus == SCCB_COMPLETE)) {
3856
3857		currSCCB->HostStatus = SCCB_PARITY_ERR;
3858		WRW_HARPOON((port + hp_intstat), PARITY);
3859	}
3860
3861	FPT_hostDataXferAbort(port, p_card, currSCCB);
3862
3863	while (RD_HARPOON(port + hp_scsisig) & SCSI_ACK) {
3864	}
3865
3866	TimeOutLoop = 0;
3867
3868	while (RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY) {
3869		if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
3870			return;
3871		}
3872		if (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) {
3873			break;
3874		}
3875		if (RDW_HARPOON((port + hp_intstat)) & RESET) {
3876			return;
3877		}
3878		if ((RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
3879		    || (TimeOutLoop++ > 0x3000))
3880			break;
3881	}
3882
3883	sPhase = RD_HARPOON(port + hp_scsisig) & (SCSI_BSY | S_SCSI_PHZ);
3884	if ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) ||
3885	    (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) ||
3886	    (sPhase == (SCSI_BSY | S_DATAO_PH)) ||
3887	    (sPhase == (SCSI_BSY | S_DATAI_PH))) {
3888
3889		WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3890
3891		if (!(currSCCB->Sccb_XferState & F_ALL_XFERRED)) {
3892			if (currSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
3893				FPT_phaseDataIn(port, p_card);
3894			}
3895
3896			else {
3897				FPT_phaseDataOut(port, p_card);
3898			}
3899		} else {
3900			FPT_sxfrp(port, p_card);
3901			if (!(RDW_HARPOON((port + hp_intstat)) &
3902			      (BUS_FREE | ICMD_COMP | ITAR_DISC | RESET))) {
3903				WRW_HARPOON((port + hp_intstat), AUTO_INT);
3904				FPT_phaseDecode(port, p_card);
3905			}
3906		}
3907
3908	}
3909
3910	else {
3911		WR_HARPOON(port + hp_portctrl_0, 0x00);
3912	}
3913}
3914
3915/*---------------------------------------------------------------------
3916 *
3917 * Function: FPT_sinits
3918 *
3919 * Description: Setup SCCB manager fields in this SCCB.
3920 *
3921 *---------------------------------------------------------------------*/
3922
3923static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card)
3924{
3925	struct sccb_mgr_tar_info *currTar_Info;
3926
3927	if ((p_sccb->TargID >= MAX_SCSI_TAR) || (p_sccb->Lun >= MAX_LUN)) {
3928		return;
3929	}
3930	currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
3931
3932	p_sccb->Sccb_XferState = 0x00;
3933	p_sccb->Sccb_XferCnt = p_sccb->DataLength;
3934
3935	if ((p_sccb->OperationCode == SCATTER_GATHER_COMMAND) ||
3936	    (p_sccb->OperationCode == RESIDUAL_SG_COMMAND)) {
3937
3938		p_sccb->Sccb_SGoffset = 0;
3939		p_sccb->Sccb_XferState = F_SG_XFER;
3940		p_sccb->Sccb_XferCnt = 0x00;
3941	}
3942
3943	if (p_sccb->DataLength == 0x00)
3944
3945		p_sccb->Sccb_XferState |= F_ALL_XFERRED;
3946
3947	if (p_sccb->ControlByte & F_USE_CMD_Q) {
3948		if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
3949			p_sccb->ControlByte &= ~F_USE_CMD_Q;
3950
3951		else
3952			currTar_Info->TarStatus |= TAG_Q_TRYING;
3953	}
3954
3955/*      For !single SCSI device in system  & device allow Disconnect
3956	or command is tag_q type then send Cmd with Disconnect Enable
3957	else send Cmd with Disconnect Disable */
3958
3959/*
3960   if (((!(FPT_BL_Card[p_card].globalFlags & F_SINGLE_DEVICE)) &&
3961      (currTar_Info->TarStatus & TAR_ALLOW_DISC)) ||
3962      (currTar_Info->TarStatus & TAG_Q_TRYING)) {
3963*/
3964	if ((currTar_Info->TarStatus & TAR_ALLOW_DISC) ||
3965	    (currTar_Info->TarStatus & TAG_Q_TRYING)) {
3966		p_sccb->Sccb_idmsg =
3967		    (unsigned char)(SMIDENT | DISC_PRIV) | p_sccb->Lun;
3968	}
3969
3970	else {
3971
3972		p_sccb->Sccb_idmsg = (unsigned char)SMIDENT | p_sccb->Lun;
3973	}
3974
3975	p_sccb->HostStatus = 0x00;
3976	p_sccb->TargetStatus = 0x00;
3977	p_sccb->Sccb_tag = 0x00;
3978	p_sccb->Sccb_MGRFlags = 0x00;
3979	p_sccb->Sccb_sgseg = 0x00;
3980	p_sccb->Sccb_ATC = 0x00;
3981	p_sccb->Sccb_savedATC = 0x00;
3982/*
3983   p_sccb->SccbVirtDataPtr    = 0x00;
3984   p_sccb->Sccb_forwardlink   = NULL;
3985   p_sccb->Sccb_backlink      = NULL;
3986 */
3987	p_sccb->Sccb_scsistat = BUS_FREE_ST;
3988	p_sccb->SccbStatus = SCCB_IN_PROCESS;
3989	p_sccb->Sccb_scsimsg = SMNO_OP;
3990
3991}
3992
3993/*---------------------------------------------------------------------
3994 *
3995 * Function: Phase Decode
3996 *
3997 * Description: Determine the phase and call the appropriate function.
3998 *
3999 *---------------------------------------------------------------------*/
4000
4001static void FPT_phaseDecode(unsigned long p_port, unsigned char p_card)
4002{
4003	unsigned char phase_ref;
4004	void (*phase) (unsigned long, unsigned char);
4005
4006	DISABLE_AUTO(p_port);
4007
4008	phase_ref =
4009	    (unsigned char)(RD_HARPOON(p_port + hp_scsisig) & S_SCSI_PHZ);
4010
4011	phase = FPT_s_PhaseTbl[phase_ref];
4012
4013	(*phase) (p_port, p_card);	/* Call the correct phase func */
4014}
4015
4016/*---------------------------------------------------------------------
4017 *
4018 * Function: Data Out Phase
4019 *
4020 * Description: Start up both the BusMaster and Xbow.
4021 *
4022 *---------------------------------------------------------------------*/
4023
4024static void FPT_phaseDataOut(unsigned long port, unsigned char p_card)
4025{
4026
4027	struct sccb *currSCCB;
4028
4029	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4030	if (currSCCB == NULL) {
4031		return;		/* Exit if No SCCB record */
4032	}
4033
4034	currSCCB->Sccb_scsistat = DATA_OUT_ST;
4035	currSCCB->Sccb_XferState &= ~(F_HOST_XFER_DIR | F_NO_DATA_YET);
4036
4037	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
4038
4039	WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
4040
4041	WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
4042
4043	FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
4044
4045	if (currSCCB->Sccb_XferCnt == 0) {
4046
4047		if ((currSCCB->ControlByte & SCCB_DATA_XFER_OUT) &&
4048		    (currSCCB->HostStatus == SCCB_COMPLETE))
4049			currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
4050
4051		FPT_sxfrp(port, p_card);
4052		if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
4053			FPT_phaseDecode(port, p_card);
4054	}
4055}
4056
4057/*---------------------------------------------------------------------
4058 *
4059 * Function: Data In Phase
4060 *
4061 * Description: Startup the BusMaster and the XBOW.
4062 *
4063 *---------------------------------------------------------------------*/
4064
4065static void FPT_phaseDataIn(unsigned long port, unsigned char p_card)
4066{
4067
4068	struct sccb *currSCCB;
4069
4070	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4071
4072	if (currSCCB == NULL) {
4073		return;		/* Exit if No SCCB record */
4074	}
4075
4076	currSCCB->Sccb_scsistat = DATA_IN_ST;
4077	currSCCB->Sccb_XferState |= F_HOST_XFER_DIR;
4078	currSCCB->Sccb_XferState &= ~F_NO_DATA_YET;
4079
4080	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
4081
4082	WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
4083
4084	WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
4085
4086	FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
4087
4088	if (currSCCB->Sccb_XferCnt == 0) {
4089
4090		if ((currSCCB->ControlByte & SCCB_DATA_XFER_IN) &&
4091		    (currSCCB->HostStatus == SCCB_COMPLETE))
4092			currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
4093
4094		FPT_sxfrp(port, p_card);
4095		if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
4096			FPT_phaseDecode(port, p_card);
4097
4098	}
4099}
4100
4101/*---------------------------------------------------------------------
4102 *
4103 * Function: Command Phase
4104 *
4105 * Description: Load the CDB into the automation and start it up.
4106 *
4107 *---------------------------------------------------------------------*/
4108
4109static void FPT_phaseCommand(unsigned long p_port, unsigned char p_card)
4110{
4111	struct sccb *currSCCB;
4112	unsigned long cdb_reg;
4113	unsigned char i;
4114
4115	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4116
4117	if (currSCCB->OperationCode == RESET_COMMAND) {
4118
4119		currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4120		currSCCB->CdbLength = SIX_BYTE_CMD;
4121	}
4122
4123	WR_HARPOON(p_port + hp_scsisig, 0x00);
4124
4125	ARAM_ACCESS(p_port);
4126
4127	cdb_reg = p_port + CMD_STRT;
4128
4129	for (i = 0; i < currSCCB->CdbLength; i++) {
4130
4131		if (currSCCB->OperationCode == RESET_COMMAND)
4132
4133			WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + 0x00));
4134
4135		else
4136			WRW_HARPOON(cdb_reg,
4137				    (MPM_OP + ACOMMAND + currSCCB->Cdb[i]));
4138		cdb_reg += 2;
4139	}
4140
4141	if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
4142		WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
4143
4144	WR_HARPOON(p_port + hp_portctrl_0, (SCSI_PORT));
4145
4146	currSCCB->Sccb_scsistat = COMMAND_ST;
4147
4148	WR_HARPOON(p_port + hp_autostart_3, (AUTO_IMMED | CMD_ONLY_STRT));
4149	SGRAM_ACCESS(p_port);
4150}
4151
4152/*---------------------------------------------------------------------
4153 *
4154 * Function: Status phase
4155 *
4156 * Description: Bring in the status and command complete message bytes
4157 *
4158 *---------------------------------------------------------------------*/
4159
4160static void FPT_phaseStatus(unsigned long port, unsigned char p_card)
4161{
4162	/* Start-up the automation to finish off this command and let the
4163	   isr handle the interrupt for command complete when it comes in.
4164	   We could wait here for the interrupt to be generated?
4165	 */
4166
4167	WR_HARPOON(port + hp_scsisig, 0x00);
4168
4169	WR_HARPOON(port + hp_autostart_0, (AUTO_IMMED + END_DATA_START));
4170}
4171
4172/*---------------------------------------------------------------------
4173 *
4174 * Function: Phase Message Out
4175 *
4176 * Description: Send out our message (if we have one) and handle whatever
4177 *              else is involed.
4178 *
4179 *---------------------------------------------------------------------*/
4180
4181static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card)
4182{
4183	unsigned char message, scsiID;
4184	struct sccb *currSCCB;
4185	struct sccb_mgr_tar_info *currTar_Info;
4186
4187	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4188
4189	if (currSCCB != NULL) {
4190
4191		message = currSCCB->Sccb_scsimsg;
4192		scsiID = currSCCB->TargID;
4193
4194		if (message == SMDEV_RESET) {
4195
4196			currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
4197			currTar_Info->TarSyncCtrl = 0;
4198			FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
4199
4200			if (FPT_sccbMgrTbl[p_card][scsiID].
4201			    TarEEValue & EE_SYNC_MASK) {
4202
4203				FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
4204				    ~TAR_SYNC_MASK;
4205
4206			}
4207
4208			if (FPT_sccbMgrTbl[p_card][scsiID].
4209			    TarEEValue & EE_WIDE_SCSI) {
4210
4211				FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
4212				    ~TAR_WIDE_MASK;
4213			}
4214
4215			FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
4216			FPT_SccbMgrTableInitTarget(p_card, scsiID);
4217		} else if (currSCCB->Sccb_scsistat == ABORT_ST) {
4218			currSCCB->HostStatus = SCCB_COMPLETE;
4219			if (FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] !=
4220			    NULL) {
4221				FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4222							      Sccb_tag] = NULL;
4223				FPT_sccbMgrTbl[p_card][scsiID].TarTagQ_Cnt--;
4224			}
4225
4226		}
4227
4228		else if (currSCCB->Sccb_scsistat < COMMAND_ST) {
4229
4230			if (message == SMNO_OP) {
4231				currSCCB->Sccb_MGRFlags |= F_DEV_SELECTED;
4232
4233				FPT_ssel(port, p_card);
4234				return;
4235			}
4236		} else {
4237
4238			if (message == SMABORT)
4239
4240				FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
4241		}
4242
4243	} else {
4244		message = SMABORT;
4245	}
4246
4247	WRW_HARPOON((port + hp_intstat), (BUS_FREE | PHASE | XFER_CNT_0));
4248
4249	WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
4250
4251	WR_HARPOON(port + hp_scsidata_0, message);
4252
4253	WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
4254
4255	ACCEPT_MSG(port);
4256
4257	WR_HARPOON(port + hp_portctrl_0, 0x00);
4258
4259	if ((message == SMABORT) || (message == SMDEV_RESET) ||
4260	    (message == SMABORT_TAG)) {
4261
4262		while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | PHASE))) {
4263		}
4264
4265		if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
4266			WRW_HARPOON((port + hp_intstat), BUS_FREE);
4267
4268			if (currSCCB != NULL) {
4269
4270				if ((FPT_BL_Card[p_card].
4271				     globalFlags & F_CONLUN_IO)
4272				    &&
4273				    ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4274				      TarStatus & TAR_TAG_Q_MASK) !=
4275				     TAG_Q_TRYING))
4276					FPT_sccbMgrTbl[p_card][currSCCB->
4277							       TargID].
4278					    TarLUNBusy[currSCCB->Lun] = 0;
4279				else
4280					FPT_sccbMgrTbl[p_card][currSCCB->
4281							       TargID].
4282					    TarLUNBusy[0] = 0;
4283
4284				FPT_queueCmdComplete(&FPT_BL_Card[p_card],
4285						     currSCCB, p_card);
4286			}
4287
4288			else {
4289				FPT_BL_Card[p_card].globalFlags |=
4290				    F_NEW_SCCB_CMD;
4291			}
4292		}
4293
4294		else {
4295
4296			FPT_sxfrp(port, p_card);
4297		}
4298	}
4299
4300	else {
4301
4302		if (message == SMPARITY) {
4303			currSCCB->Sccb_scsimsg = SMNO_OP;
4304			WR_HARPOON(port + hp_autostart_1,
4305				   (AUTO_IMMED + DISCONNECT_START));
4306		} else {
4307			FPT_sxfrp(port, p_card);
4308		}
4309	}
4310}
4311
4312/*---------------------------------------------------------------------
4313 *
4314 * Function: Message In phase
4315 *
4316 * Description: Bring in the message and determine what to do with it.
4317 *
4318 *---------------------------------------------------------------------*/
4319
4320static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card)
4321{
4322	unsigned char message;
4323	struct sccb *currSCCB;
4324
4325	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4326
4327	if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
4328
4329		FPT_phaseChkFifo(port, p_card);
4330	}
4331
4332	message = RD_HARPOON(port + hp_scsidata_0);
4333	if ((message == SMDISC) || (message == SMSAVE_DATA_PTR)) {
4334
4335		WR_HARPOON(port + hp_autostart_1,
4336			   (AUTO_IMMED + END_DATA_START));
4337
4338	}
4339
4340	else {
4341
4342		message = FPT_sfm(port, currSCCB);
4343		if (message) {
4344
4345			FPT_sdecm(message, port, p_card);
4346
4347		} else {
4348			if (currSCCB->Sccb_scsimsg != SMPARITY)
4349				ACCEPT_MSG(port);
4350			WR_HARPOON(port + hp_autostart_1,
4351				   (AUTO_IMMED + DISCONNECT_START));
4352		}
4353	}
4354
4355}
4356
4357/*---------------------------------------------------------------------
4358 *
4359 * Function: Illegal phase
4360 *
4361 * Description: Target switched to some illegal phase, so all we can do
4362 *              is report an error back to the host (if that is possible)
4363 *              and send an ABORT message to the misbehaving target.
4364 *
4365 *---------------------------------------------------------------------*/
4366
4367static void FPT_phaseIllegal(unsigned long port, unsigned char p_card)
4368{
4369	struct sccb *currSCCB;
4370
4371	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4372
4373	WR_HARPOON(port + hp_scsisig, RD_HARPOON(port + hp_scsisig));
4374	if (currSCCB != NULL) {
4375
4376		currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4377		currSCCB->Sccb_scsistat = ABORT_ST;
4378		currSCCB->Sccb_scsimsg = SMABORT;
4379	}
4380
4381	ACCEPT_MSG_ATN(port);
4382}
4383
4384/*---------------------------------------------------------------------
4385 *
4386 * Function: Phase Check FIFO
4387 *
4388 * Description: Make sure data has been flushed from both FIFOs and abort
4389 *              the operations if necessary.
4390 *
4391 *---------------------------------------------------------------------*/
4392
4393static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card)
4394{
4395	unsigned long xfercnt;
4396	struct sccb *currSCCB;
4397
4398	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4399
4400	if (currSCCB->Sccb_scsistat == DATA_IN_ST) {
4401
4402		while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) &&
4403		       (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)) {
4404		}
4405
4406		if (!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) {
4407			currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
4408
4409			currSCCB->Sccb_XferCnt = 0;
4410
4411			if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
4412			    (currSCCB->HostStatus == SCCB_COMPLETE)) {
4413				currSCCB->HostStatus = SCCB_PARITY_ERR;
4414				WRW_HARPOON((port + hp_intstat), PARITY);
4415			}
4416
4417			FPT_hostDataXferAbort(port, p_card, currSCCB);
4418
4419			FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
4420
4421			while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY))
4422			       && (RD_HARPOON(port + hp_ext_status) &
4423				   BM_CMD_BUSY)) {
4424			}
4425
4426		}
4427	}
4428
4429	/*End Data In specific code. */
4430	GET_XFER_CNT(port, xfercnt);
4431
4432	WR_HARPOON(port + hp_xfercnt_0, 0x00);
4433
4434	WR_HARPOON(port + hp_portctrl_0, 0x00);
4435
4436	currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - xfercnt);
4437
4438	currSCCB->Sccb_XferCnt = xfercnt;
4439
4440	if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
4441	    (currSCCB->HostStatus == SCCB_COMPLETE)) {
4442
4443		currSCCB->HostStatus = SCCB_PARITY_ERR;
4444		WRW_HARPOON((port + hp_intstat), PARITY);
4445	}
4446
4447	FPT_hostDataXferAbort(port, p_card, currSCCB);
4448
4449	WR_HARPOON(port + hp_fifowrite, 0x00);
4450	WR_HARPOON(port + hp_fiforead, 0x00);
4451	WR_HARPOON(port + hp_xferstat, 0x00);
4452
4453	WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
4454}
4455
4456/*---------------------------------------------------------------------
4457 *
4458 * Function: Phase Bus Free
4459 *
4460 * Description: We just went bus free so figure out if it was
4461 *              because of command complete or from a disconnect.
4462 *
4463 *---------------------------------------------------------------------*/
4464static void FPT_phaseBusFree(unsigned long port, unsigned char p_card)
4465{
4466	struct sccb *currSCCB;
4467
4468	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4469
4470	if (currSCCB != NULL) {
4471
4472		DISABLE_AUTO(port);
4473
4474		if (currSCCB->OperationCode == RESET_COMMAND) {
4475
4476			if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4477			    ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4478			      TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4479				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4480				    TarLUNBusy[currSCCB->Lun] = 0;
4481			else
4482				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4483				    TarLUNBusy[0] = 0;
4484
4485			FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
4486					     p_card);
4487
4488			FPT_queueSearchSelect(&FPT_BL_Card[p_card], p_card);
4489
4490		}
4491
4492		else if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
4493			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4494			    (unsigned char)SYNC_SUPPORTED;
4495			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4496			    ~EE_SYNC_MASK;
4497		}
4498
4499		else if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
4500			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
4501			    (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4502			     TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
4503
4504			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4505			    ~EE_WIDE_SCSI;
4506		}
4507
4508		else if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
4509			/* Make sure this is not a phony BUS_FREE.  If we were
4510			   reselected or if BUSY is NOT on then this is a
4511			   valid BUS FREE.  SRR Wednesday, 5/10/1995.     */
4512
4513			if ((!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ||
4514			    (RDW_HARPOON((port + hp_intstat)) & RSEL)) {
4515				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4516				    TarStatus &= ~TAR_TAG_Q_MASK;
4517				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4518				    TarStatus |= TAG_Q_REJECT;
4519			}
4520
4521			else {
4522				return;
4523			}
4524		}
4525
4526		else {
4527
4528			currSCCB->Sccb_scsistat = BUS_FREE_ST;
4529
4530			if (!currSCCB->HostStatus) {
4531				currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4532			}
4533
4534			if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4535			    ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4536			      TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4537				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4538				    TarLUNBusy[currSCCB->Lun] = 0;
4539			else
4540				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4541				    TarLUNBusy[0] = 0;
4542
4543			FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
4544					     p_card);
4545			return;
4546		}
4547
4548		FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
4549
4550	}			/*end if !=null */
4551}
4552
4553/*---------------------------------------------------------------------
4554 *
4555 * Function: Auto Load Default Map
4556 *
4557 * Description: Load the Automation RAM with the defualt map values.
4558 *
4559 *---------------------------------------------------------------------*/
4560static void FPT_autoLoadDefaultMap(unsigned long p_port)
4561{
4562	unsigned long map_addr;
4563
4564	ARAM_ACCESS(p_port);
4565	map_addr = p_port + hp_aramBase;
4566
4567	WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0xC0));	/*ID MESSAGE */
4568	map_addr += 2;
4569	WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x20));	/*SIMPLE TAG QUEUEING MSG */
4570	map_addr += 2;
4571	WRW_HARPOON(map_addr, RAT_OP);	/*RESET ATTENTION */
4572	map_addr += 2;
4573	WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x00));	/*TAG ID MSG */
4574	map_addr += 2;
4575	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 0 */
4576	map_addr += 2;
4577	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 1 */
4578	map_addr += 2;
4579	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 2 */
4580	map_addr += 2;
4581	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 3 */
4582	map_addr += 2;
4583	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 4 */
4584	map_addr += 2;
4585	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 5 */
4586	map_addr += 2;
4587	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 6 */
4588	map_addr += 2;
4589	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 7 */
4590	map_addr += 2;
4591	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 8 */
4592	map_addr += 2;
4593	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 9 */
4594	map_addr += 2;
4595	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 10 */
4596	map_addr += 2;
4597	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 11 */
4598	map_addr += 2;
4599	WRW_HARPOON(map_addr, (CPE_OP + ADATA_OUT + DINT));	/*JUMP IF DATA OUT */
4600	map_addr += 2;
4601	WRW_HARPOON(map_addr, (TCB_OP + FIFO_0 + DI));	/*JUMP IF NO DATA IN FIFO */
4602	map_addr += 2;		/*This means AYNC DATA IN */
4603	WRW_HARPOON(map_addr, (SSI_OP + SSI_IDO_STRT));	/*STOP AND INTERRUPT */
4604	map_addr += 2;
4605	WRW_HARPOON(map_addr, (CPE_OP + ADATA_IN + DINT));	/*JUMP IF NOT DATA IN PHZ */
4606	map_addr += 2;
4607	WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST));	/*IF NOT MSG IN CHECK 4 DATA IN */
4608	map_addr += 2;
4609	WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x02));	/*SAVE DATA PTR MSG? */
4610	map_addr += 2;
4611	WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + DC));	/*GO CHECK FOR DISCONNECT MSG */
4612	map_addr += 2;
4613	WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR1));	/*SAVE DATA PTRS MSG */
4614	map_addr += 2;
4615	WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST));	/*IF NOT MSG IN CHECK DATA IN */
4616	map_addr += 2;
4617	WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x04));	/*DISCONNECT MSG? */
4618	map_addr += 2;
4619	WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + UNKNWN));	/*UKNKNOWN MSG */
4620	map_addr += 2;
4621	WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET));	/*XFER DISCONNECT MSG */
4622	map_addr += 2;
4623	WRW_HARPOON(map_addr, (SSI_OP + SSI_ITAR_DISC));	/*STOP AND INTERRUPT */
4624	map_addr += 2;
4625	WRW_HARPOON(map_addr, (CPN_OP + ASTATUS + UNKNWN));	/*JUMP IF NOT STATUS PHZ. */
4626	map_addr += 2;
4627	WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR0));	/*GET STATUS BYTE */
4628	map_addr += 2;
4629	WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + CC));	/*ERROR IF NOT MSG IN PHZ */
4630	map_addr += 2;
4631	WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x00));	/*CHECK FOR CMD COMPLETE MSG. */
4632	map_addr += 2;
4633	WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + CC));	/*ERROR IF NOT CMD COMPLETE MSG. */
4634	map_addr += 2;
4635	WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET));	/*GET CMD COMPLETE MSG */
4636	map_addr += 2;
4637	WRW_HARPOON(map_addr, (SSI_OP + SSI_ICMD_COMP));	/*END OF COMMAND */
4638	map_addr += 2;
4639
4640	WRW_HARPOON(map_addr, (SSI_OP + SSI_IUNKWN));	/*RECEIVED UNKNOWN MSG BYTE */
4641	map_addr += 2;
4642	WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC));	/*NO COMMAND COMPLETE AFTER STATUS */
4643	map_addr += 2;
4644	WRW_HARPOON(map_addr, (SSI_OP + SSI_ITICKLE));	/*BIOS Tickled the Mgr */
4645	map_addr += 2;
4646	WRW_HARPOON(map_addr, (SSI_OP + SSI_IRFAIL));	/*EXPECTED ID/TAG MESSAGES AND */
4647	map_addr += 2;		/* DIDN'T GET ONE */
4648	WRW_HARPOON(map_addr, (CRR_OP + AR3 + S_IDREG));	/* comp SCSI SEL ID & AR3 */
4649	map_addr += 2;
4650	WRW_HARPOON(map_addr, (BRH_OP + EQUAL + 0x00));	/*SEL ID OK then Conti. */
4651	map_addr += 2;
4652	WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC));	/*NO COMMAND COMPLETE AFTER STATUS */
4653
4654	SGRAM_ACCESS(p_port);
4655}
4656
4657/*---------------------------------------------------------------------
4658 *
4659 * Function: Auto Command Complete
4660 *
4661 * Description: Post command back to host and find another command
4662 *              to execute.
4663 *
4664 *---------------------------------------------------------------------*/
4665
4666static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card)
4667{
4668	struct sccb *currSCCB;
4669	unsigned char status_byte;
4670
4671	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4672
4673	status_byte = RD_HARPOON(p_port + hp_gp_reg_0);
4674
4675	FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA = 0;
4676
4677	if (status_byte != SSGOOD) {
4678
4679		if (status_byte == SSQ_FULL) {
4680
4681			if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4682			     ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4683			       TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4684				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4685				    TarLUNBusy[currSCCB->Lun] = 1;
4686				if (FPT_BL_Card[p_card].discQCount != 0)
4687					FPT_BL_Card[p_card].discQCount--;
4688				FPT_BL_Card[p_card].
4689				    discQ_Tbl[FPT_sccbMgrTbl[p_card]
4690					      [currSCCB->TargID].
4691					      LunDiscQ_Idx[currSCCB->Lun]] =
4692				    NULL;
4693			} else {
4694				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4695				    TarLUNBusy[0] = 1;
4696				if (currSCCB->Sccb_tag) {
4697					if (FPT_BL_Card[p_card].discQCount != 0)
4698						FPT_BL_Card[p_card].
4699						    discQCount--;
4700					FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4701								      Sccb_tag]
4702					    = NULL;
4703				} else {
4704					if (FPT_BL_Card[p_card].discQCount != 0)
4705						FPT_BL_Card[p_card].
4706						    discQCount--;
4707					FPT_BL_Card[p_card].
4708					    discQ_Tbl[FPT_sccbMgrTbl[p_card]
4709						      [currSCCB->TargID].
4710						      LunDiscQ_Idx[0]] = NULL;
4711				}
4712			}
4713
4714			currSCCB->Sccb_MGRFlags |= F_STATUSLOADED;
4715
4716			FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
4717
4718			return;
4719		}
4720
4721		if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
4722			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4723			    (unsigned char)SYNC_SUPPORTED;
4724
4725			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4726			    ~EE_SYNC_MASK;
4727			FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
4728
4729			if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4730			     ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4731			       TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4732				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4733				    TarLUNBusy[currSCCB->Lun] = 1;
4734				if (FPT_BL_Card[p_card].discQCount != 0)
4735					FPT_BL_Card[p_card].discQCount--;
4736				FPT_BL_Card[p_card].
4737				    discQ_Tbl[FPT_sccbMgrTbl[p_card]
4738					      [currSCCB->TargID].
4739					      LunDiscQ_Idx[currSCCB->Lun]] =
4740				    NULL;
4741			} else {
4742				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4743				    TarLUNBusy[0] = 1;
4744				if (currSCCB->Sccb_tag) {
4745					if (FPT_BL_Card[p_card].discQCount != 0)
4746						FPT_BL_Card[p_card].
4747						    discQCount--;
4748					FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4749								      Sccb_tag]
4750					    = NULL;
4751				} else {
4752					if (FPT_BL_Card[p_card].discQCount != 0)
4753						FPT_BL_Card[p_card].
4754						    discQCount--;
4755					FPT_BL_Card[p_card].
4756					    discQ_Tbl[FPT_sccbMgrTbl[p_card]
4757						      [currSCCB->TargID].
4758						      LunDiscQ_Idx[0]] = NULL;
4759				}
4760			}
4761			return;
4762
4763		}
4764
4765		if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
4766
4767			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
4768			    (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4769			     TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
4770
4771			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4772			    ~EE_WIDE_SCSI;
4773			FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
4774
4775			if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4776			     ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4777			       TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4778				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4779				    TarLUNBusy[currSCCB->Lun] = 1;
4780				if (FPT_BL_Card[p_card].discQCount != 0)
4781					FPT_BL_Card[p_card].discQCount--;
4782				FPT_BL_Card[p_card].
4783				    discQ_Tbl[FPT_sccbMgrTbl[p_card]
4784					      [currSCCB->TargID].
4785					      LunDiscQ_Idx[currSCCB->Lun]] =
4786				    NULL;
4787			} else {
4788				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4789				    TarLUNBusy[0] = 1;
4790				if (currSCCB->Sccb_tag) {
4791					if (FPT_BL_Card[p_card].discQCount != 0)
4792						FPT_BL_Card[p_card].
4793						    discQCount--;
4794					FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4795								      Sccb_tag]
4796					    = NULL;
4797				} else {
4798					if (FPT_BL_Card[p_card].discQCount != 0)
4799						FPT_BL_Card[p_card].
4800						    discQCount--;
4801					FPT_BL_Card[p_card].
4802					    discQ_Tbl[FPT_sccbMgrTbl[p_card]
4803						      [currSCCB->TargID].
4804						      LunDiscQ_Idx[0]] = NULL;
4805				}
4806			}
4807			return;
4808
4809		}
4810
4811		if (status_byte == SSCHECK) {
4812			if (FPT_BL_Card[p_card].globalFlags & F_DO_RENEGO) {
4813				if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4814				    TarEEValue & EE_SYNC_MASK) {
4815					FPT_sccbMgrTbl[p_card][currSCCB->
4816							       TargID].
4817					    TarStatus &= ~TAR_SYNC_MASK;
4818				}
4819				if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4820				    TarEEValue & EE_WIDE_SCSI) {
4821					FPT_sccbMgrTbl[p_card][currSCCB->
4822							       TargID].
4823					    TarStatus &= ~TAR_WIDE_MASK;
4824				}
4825			}
4826		}
4827
4828		if (!(currSCCB->Sccb_XferState & F_AUTO_SENSE)) {
4829
4830			currSCCB->SccbStatus = SCCB_ERROR;
4831			currSCCB->TargetStatus = status_byte;
4832
4833			if (status_byte == SSCHECK) {
4834
4835				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4836				    TarLUN_CA = 1;
4837
4838				if (currSCCB->RequestSenseLength !=
4839				    NO_AUTO_REQUEST_SENSE) {
4840
4841					if (currSCCB->RequestSenseLength == 0)
4842						currSCCB->RequestSenseLength =
4843						    14;
4844
4845					FPT_ssenss(&FPT_BL_Card[p_card]);
4846					FPT_BL_Card[p_card].globalFlags |=
4847					    F_NEW_SCCB_CMD;
4848
4849					if (((FPT_BL_Card[p_card].
4850					      globalFlags & F_CONLUN_IO)
4851					     &&
4852					     ((FPT_sccbMgrTbl[p_card]
4853					       [currSCCB->TargID].
4854					       TarStatus & TAR_TAG_Q_MASK) !=
4855					      TAG_Q_TRYING))) {
4856						FPT_sccbMgrTbl[p_card]
4857						    [currSCCB->TargID].
4858						    TarLUNBusy[currSCCB->Lun] =
4859						    1;
4860						if (FPT_BL_Card[p_card].
4861						    discQCount != 0)
4862							FPT_BL_Card[p_card].
4863							    discQCount--;
4864						FPT_BL_Card[p_card].
4865						    discQ_Tbl[FPT_sccbMgrTbl
4866							      [p_card]
4867							      [currSCCB->
4868							       TargID].
4869							      LunDiscQ_Idx
4870							      [currSCCB->Lun]] =
4871						    NULL;
4872					} else {
4873						FPT_sccbMgrTbl[p_card]
4874						    [currSCCB->TargID].
4875						    TarLUNBusy[0] = 1;
4876						if (currSCCB->Sccb_tag) {
4877							if (FPT_BL_Card[p_card].
4878							    discQCount != 0)
4879								FPT_BL_Card
4880								    [p_card].
4881								    discQCount--;
4882							FPT_BL_Card[p_card].
4883							    discQ_Tbl[currSCCB->
4884								      Sccb_tag]
4885							    = NULL;
4886						} else {
4887							if (FPT_BL_Card[p_card].
4888							    discQCount != 0)
4889								FPT_BL_Card
4890								    [p_card].
4891								    discQCount--;
4892							FPT_BL_Card[p_card].
4893							    discQ_Tbl
4894							    [FPT_sccbMgrTbl
4895							     [p_card][currSCCB->
4896								      TargID].
4897							     LunDiscQ_Idx[0]] =
4898							    NULL;
4899						}
4900					}
4901					return;
4902				}
4903			}
4904		}
4905	}
4906
4907	if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4908	    ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4909	      TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4910		FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->
4911								    Lun] = 0;
4912	else
4913		FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0;
4914
4915	FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, p_card);
4916}
4917
4918#define SHORT_WAIT   0x0000000F
4919#define LONG_WAIT    0x0000FFFFL
4920
4921/*---------------------------------------------------------------------
4922 *
4923 * Function: Data Transfer Processor
4924 *
4925 * Description: This routine performs two tasks.
4926 *              (1) Start data transfer by calling HOST_DATA_XFER_START
4927 *              function.  Once data transfer is started, (2) Depends
4928 *              on the type of data transfer mode Scatter/Gather mode
4929 *              or NON Scatter/Gather mode.  In NON Scatter/Gather mode,
4930 *              this routine checks Sccb_MGRFlag (F_HOST_XFER_ACT bit) for
4931 *              data transfer done.  In Scatter/Gather mode, this routine
4932 *              checks bus master command complete and dual rank busy
4933 *              bit to keep chaining SC transfer command.  Similarly,
4934 *              in Scatter/Gather mode, it checks Sccb_MGRFlag
4935 *              (F_HOST_XFER_ACT bit) for data transfer done.
4936 *              
4937 *---------------------------------------------------------------------*/
4938
4939static void FPT_dataXferProcessor(unsigned long port,
4940				  struct sccb_card *pCurrCard)
4941{
4942	struct sccb *currSCCB;
4943
4944	currSCCB = pCurrCard->currentSCCB;
4945
4946	if (currSCCB->Sccb_XferState & F_SG_XFER) {
4947		if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
4948		{
4949			currSCCB->Sccb_sgseg += (unsigned char)SG_BUF_CNT;
4950			currSCCB->Sccb_SGoffset = 0x00;
4951		}
4952		pCurrCard->globalFlags |= F_HOST_XFER_ACT;
4953
4954		FPT_busMstrSGDataXferStart(port, currSCCB);
4955	}
4956
4957	else {
4958		if (!(pCurrCard->globalFlags & F_HOST_XFER_ACT)) {
4959			pCurrCard->globalFlags |= F_HOST_XFER_ACT;
4960
4961			FPT_busMstrDataXferStart(port, currSCCB);
4962		}
4963	}
4964}
4965
4966/*---------------------------------------------------------------------
4967 *
4968 * Function: BusMaster Scatter Gather Data Transfer Start
4969 *
4970 * Description:
4971 *
4972 *---------------------------------------------------------------------*/
4973static void FPT_busMstrSGDataXferStart(unsigned long p_port,
4974				       struct sccb *pcurrSCCB)
4975{
4976	unsigned long count, addr, tmpSGCnt;
4977	unsigned int sg_index;
4978	unsigned char sg_count, i;
4979	unsigned long reg_offset;
4980
4981	if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
4982
4983		count = ((unsigned long)HOST_RD_CMD) << 24;
4984	}
4985
4986	else {
4987		count = ((unsigned long)HOST_WRT_CMD) << 24;
4988	}
4989
4990	sg_count = 0;
4991	tmpSGCnt = 0;
4992	sg_index = pcurrSCCB->Sccb_sgseg;
4993	reg_offset = hp_aramBase;
4994
4995	i = (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
4996			    ~(SGRAM_ARAM | SCATTER_EN));
4997
4998	WR_HARPOON(p_port + hp_page_ctrl, i);
4999
5000	while ((sg_count < (unsigned char)SG_BUF_CNT) &&
5001	       ((unsigned long)(sg_index * (unsigned int)SG_ELEMENT_SIZE) <
5002		pcurrSCCB->DataLength)) {
5003
5004		tmpSGCnt += *(((unsigned long *)pcurrSCCB->DataPointer) +
5005			      (sg_index * 2));
5006
5007		count |= *(((unsigned long *)pcurrSCCB->DataPointer) +
5008			   (sg_index * 2));
5009
5010		addr = *(((unsigned long *)pcurrSCCB->DataPointer) +
5011			 ((sg_index * 2) + 1));
5012
5013		if ((!sg_count) && (pcurrSCCB->Sccb_SGoffset)) {
5014
5015			addr +=
5016			    ((count & 0x00FFFFFFL) - pcurrSCCB->Sccb_SGoffset);
5017			count =
5018			    (count & 0xFF000000L) | pcurrSCCB->Sccb_SGoffset;
5019
5020			tmpSGCnt = count & 0x00FFFFFFL;
5021		}
5022
5023		WR_HARP32(p_port, reg_offset, addr);
5024		reg_offset += 4;
5025
5026		WR_HARP32(p_port, reg_offset, count);
5027		reg_offset += 4;
5028
5029		count &= 0xFF000000L;
5030		sg_index++;
5031		sg_count++;
5032
5033	}			/*End While */
5034
5035	pcurrSCCB->Sccb_XferCnt = tmpSGCnt;
5036
5037	WR_HARPOON(p_port + hp_sg_addr, (sg_count << 4));
5038
5039	if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
5040
5041		WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
5042
5043		WR_HARPOON(p_port + hp_portctrl_0,
5044			   (DMA_PORT | SCSI_PORT | SCSI_INBIT));
5045		WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
5046	}
5047
5048	else {
5049
5050		if ((!(RD_HARPOON(p_port + hp_synctarg_0) & NARROW_SCSI)) &&
5051		    (tmpSGCnt & 0x000000001)) {
5052
5053			pcurrSCCB->Sccb_XferState |= F_ODD_BALL_CNT;
5054			tmpSGCnt--;
5055		}
5056
5057		WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
5058
5059		WR_HARPOON(p_port + hp_portctrl_0,
5060			   (SCSI_PORT | DMA_PORT | DMA_RD));
5061		WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
5062	}
5063
5064	WR_HARPOON(p_port + hp_page_ctrl, (unsigned char)(i | SCATTER_EN));
5065
5066}
5067
5068/*---------------------------------------------------------------------
5069 *
5070 * Function: BusMaster Data Transfer Start
5071 *
5072 * Description: 
5073 *
5074 *---------------------------------------------------------------------*/
5075static void FPT_busMstrDataXferStart(unsigned long p_port,
5076				     struct sccb *pcurrSCCB)
5077{
5078	unsigned long addr, count;
5079
5080	if (!(pcurrSCCB->Sccb_XferState & F_AUTO_SENSE)) {
5081
5082		count = pcurrSCCB->Sccb_XferCnt;
5083
5084		addr =
5085		    (unsigned long)pcurrSCCB->DataPointer + pcurrSCCB->Sccb_ATC;
5086	}
5087
5088	else {
5089		addr = pcurrSCCB->SensePointer;
5090		count = pcurrSCCB->RequestSenseLength;
5091
5092	}
5093
5094	HP_SETUP_ADDR_CNT(p_port, addr, count);
5095
5096	if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
5097
5098		WR_HARPOON(p_port + hp_portctrl_0,
5099			   (DMA_PORT | SCSI_PORT | SCSI_INBIT));
5100		WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
5101
5102		WR_HARPOON(p_port + hp_xfer_cmd,
5103			   (XFER_DMA_HOST | XFER_HOST_AUTO | XFER_DMA_8BIT));
5104	}
5105
5106	else {
5107
5108		WR_HARPOON(p_port + hp_portctrl_0,
5109			   (SCSI_PORT | DMA_PORT | DMA_RD));
5110		WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
5111
5112		WR_HARPOON(p_port + hp_xfer_cmd,
5113			   (XFER_HOST_DMA | XFER_HOST_AUTO | XFER_DMA_8BIT));
5114
5115	}
5116}
5117
5118/*---------------------------------------------------------------------
5119 *
5120 * Function: BusMaster Timeout Handler
5121 *
5122 * Description: This function is called after a bus master command busy time
5123 *               out is detected.  This routines issue halt state machine
5124 *               with a software time out for command busy.  If command busy
5125 *               is still asserted at the end of the time out, it issues
5126 *               hard abort with another software time out.  It hard abort
5127 *               command busy is also time out, it'll just give up.
5128 *
5129 *---------------------------------------------------------------------*/
5130static unsigned char FPT_busMstrTimeOut(unsigned long p_port)
5131{
5132	unsigned long timeout;
5133
5134	timeout = LONG_WAIT;
5135
5136	WR_HARPOON(p_port + hp_sys_ctrl, HALT_MACH);
5137
5138	while ((!(RD_HARPOON(p_port + hp_ext_status) & CMD_ABORTED))
5139	       && timeout--) {
5140	}
5141
5142	if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
5143		WR_HARPOON(p_port + hp_sys_ctrl, HARD_ABORT);
5144
5145		timeout = LONG_WAIT;
5146		while ((RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY)
5147		       && timeout--) {
5148		}
5149	}
5150
5151	RD_HARPOON(p_port + hp_int_status);	/*Clear command complete */
5152
5153	if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
5154		return 1;
5155	}
5156
5157	else {
5158		return 0;
5159	}
5160}
5161
5162/*---------------------------------------------------------------------
5163 *
5164 * Function: Host Data Transfer Abort
5165 *
5166 * Description: Abort any in progress transfer.
5167 *
5168 *---------------------------------------------------------------------*/
5169static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card,
5170				  struct sccb *pCurrSCCB)
5171{
5172
5173	unsigned long timeout;
5174	unsigned long remain_cnt;
5175	unsigned int sg_ptr;
5176
5177	FPT_BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT;
5178
5179	if (pCurrSCCB->Sccb_XferState & F_AUTO_SENSE) {
5180
5181		if (!(RD_HARPOON(port + hp_int_status) & INT_CMD_COMPL)) {
5182
5183			WR_HARPOON(port + hp_bm_ctrl,
5184				   (RD_HARPOON(port + hp_bm_ctrl) |
5185				    FLUSH_XFER_CNTR));
5186			timeout = LONG_WAIT;
5187
5188			while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
5189			       && timeout--) {
5190			}
5191
5192			WR_HARPOON(port + hp_bm_ctrl,
5193				   (RD_HARPOON(port + hp_bm_ctrl) &
5194				    ~FLUSH_XFER_CNTR));
5195
5196			if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
5197
5198				if (FPT_busMstrTimeOut(port)) {
5199
5200					if (pCurrSCCB->HostStatus == 0x00)
5201
5202						pCurrSCCB->HostStatus =
5203						    SCCB_BM_ERR;
5204
5205				}
5206
5207				if (RD_HARPOON(port + hp_int_status) &
5208				    INT_EXT_STATUS)
5209
5210					if (RD_HARPOON(port + hp_ext_status) &
5211					    BAD_EXT_STATUS)
5212
5213						if (pCurrSCCB->HostStatus ==
5214						    0x00)
5215						{
5216							pCurrSCCB->HostStatus =
5217							    SCCB_BM_ERR;
5218						}
5219			}
5220		}
5221	}
5222
5223	else if (pCurrSCCB->Sccb_XferCnt) {
5224
5225		if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
5226
5227			WR_HARPOON(port + hp_page_ctrl,
5228				   (RD_HARPOON(port + hp_page_ctrl) &
5229				    ~SCATTER_EN));
5230
5231			WR_HARPOON(port + hp_sg_addr, 0x00);
5232
5233			sg_ptr = pCurrSCCB->Sccb_sgseg + SG_BUF_CNT;
5234
5235			if (sg_ptr >
5236			    (unsigned int)(pCurrSCCB->DataLength /
5237					   SG_ELEMENT_SIZE)) {
5238
5239				sg_ptr =
5240				    (unsigned int)(pCurrSCCB->DataLength /
5241						   SG_ELEMENT_SIZE);
5242			}
5243
5244			remain_cnt = pCurrSCCB->Sccb_XferCnt;
5245
5246			while (remain_cnt < 0x01000000L) {
5247
5248				sg_ptr--;
5249
5250				if (remain_cnt >
5251				    (unsigned
5252				     long)(*(((unsigned long *)pCurrSCCB->
5253					      DataPointer) + (sg_ptr * 2)))) {
5254
5255					remain_cnt -=
5256					    (unsigned
5257					     long)(*(((unsigned long *)
5258						      pCurrSCCB->DataPointer) +
5259						     (sg_ptr * 2)));
5260				}
5261
5262				else {
5263
5264					break;
5265				}
5266			}
5267
5268			if (remain_cnt < 0x01000000L) {
5269
5270				pCurrSCCB->Sccb_SGoffset = remain_cnt;
5271
5272				pCurrSCCB->Sccb_sgseg = (unsigned short)sg_ptr;
5273
5274				if ((unsigned long)(sg_ptr * SG_ELEMENT_SIZE) ==
5275				    pCurrSCCB->DataLength && (remain_cnt == 0))
5276
5277					pCurrSCCB->Sccb_XferState |=
5278					    F_ALL_XFERRED;
5279			}
5280
5281			else {
5282
5283				if (pCurrSCCB->HostStatus == 0x00) {
5284
5285					pCurrSCCB->HostStatus =
5286					    SCCB_GROSS_FW_ERR;
5287				}
5288			}
5289		}
5290
5291		if (!(pCurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)) {
5292
5293			if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
5294
5295				FPT_busMstrTimeOut(port);
5296			}
5297
5298			else {
5299
5300				if (RD_HARPOON(port + hp_int_status) &
5301				    INT_EXT_STATUS) {
5302
5303					if (RD_HARPOON(port + hp_ext_status) &
5304					    BAD_EXT_STATUS) {
5305
5306						if (pCurrSCCB->HostStatus ==
5307						    0x00) {
5308
5309							pCurrSCCB->HostStatus =
5310							    SCCB_BM_ERR;
5311						}
5312					}
5313				}
5314
5315			}
5316		}
5317
5318		else {
5319
5320			if ((RD_HARPOON(port + hp_fifo_cnt)) >= BM_THRESHOLD) {
5321
5322				timeout = SHORT_WAIT;
5323
5324				while ((RD_HARPOON(port + hp_ext_status) &
5325					BM_CMD_BUSY)
5326				       && ((RD_HARPOON(port + hp_fifo_cnt)) >=
5327					   BM_THRESHOLD) && timeout--) {
5328				}
5329			}
5330
5331			if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
5332
5333				WR_HARPOON(port + hp_bm_ctrl,
5334					   (RD_HARPOON(port + hp_bm_ctrl) |
5335					    FLUSH_XFER_CNTR));
5336
5337				timeout = LONG_WAIT;
5338
5339				while ((RD_HARPOON(port + hp_ext_status) &
5340					BM_CMD_BUSY) && timeout--) {
5341				}
5342
5343				WR_HARPOON(port + hp_bm_ctrl,
5344					   (RD_HARPOON(port + hp_bm_ctrl) &
5345					    ~FLUSH_XFER_CNTR));
5346
5347				if (RD_HARPOON(port + hp_ext_status) &
5348				    BM_CMD_BUSY) {
5349
5350					if (pCurrSCCB->HostStatus == 0x00) {
5351
5352						pCurrSCCB->HostStatus =
5353						    SCCB_BM_ERR;
5354					}
5355
5356					FPT_busMstrTimeOut(port);
5357				}
5358			}
5359
5360			if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
5361
5362				if (RD_HARPOON(port + hp_ext_status) &
5363				    BAD_EXT_STATUS) {
5364
5365					if (pCurrSCCB->HostStatus == 0x00) {
5366
5367						pCurrSCCB->HostStatus =
5368						    SCCB_BM_ERR;
5369					}
5370				}
5371			}
5372		}
5373
5374	}
5375
5376	else {
5377
5378		if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
5379
5380			timeout = LONG_WAIT;
5381
5382			while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
5383			       && timeout--) {
5384			}
5385
5386			if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
5387
5388				if (pCurrSCCB->HostStatus == 0x00) {
5389
5390					pCurrSCCB->HostStatus = SCCB_BM_ERR;
5391				}
5392
5393				FPT_busMstrTimeOut(port);
5394			}
5395		}
5396
5397		if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
5398
5399			if (RD_HARPOON(port + hp_ext_status) & BAD_EXT_STATUS) {
5400
5401				if (pCurrSCCB->HostStatus == 0x00) {
5402
5403					pCurrSCCB->HostStatus = SCCB_BM_ERR;
5404				}
5405			}
5406
5407		}
5408
5409		if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
5410
5411			WR_HARPOON(port + hp_page_ctrl,
5412				   (RD_HARPOON(port + hp_page_ctrl) &
5413				    ~SCATTER_EN));
5414
5415			WR_HARPOON(port + hp_sg_addr, 0x00);
5416
5417			pCurrSCCB->Sccb_sgseg += SG_BUF_CNT;
5418
5419			pCurrSCCB->Sccb_SGoffset = 0x00;
5420
5421			if ((unsigned long)(pCurrSCCB->Sccb_sgseg *
5422					    SG_ELEMENT_SIZE) >=
5423			    pCurrSCCB->DataLength) {
5424
5425				pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
5426
5427				pCurrSCCB->Sccb_sgseg =
5428				    (unsigned short)(pCurrSCCB->DataLength /
5429						     SG_ELEMENT_SIZE);
5430
5431			}
5432		}
5433
5434		else {
5435
5436			if (!(pCurrSCCB->Sccb_XferState & F_AUTO_SENSE))
5437
5438				pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
5439		}
5440	}
5441
5442	WR_HARPOON(port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
5443}
5444
5445/*---------------------------------------------------------------------
5446 *
5447 * Function: Host Data Transfer Restart
5448 *
5449 * Description: Reset the available count due to a restore data
5450 *              pointers message.
5451 *
5452 *---------------------------------------------------------------------*/
5453static void FPT_hostDataXferRestart(struct sccb *currSCCB)
5454{
5455	unsigned long data_count;
5456	unsigned int sg_index;
5457	unsigned long *sg_ptr;
5458
5459	if (currSCCB->Sccb_XferState & F_SG_XFER) {
5460
5461		currSCCB->Sccb_XferCnt = 0;
5462
5463		sg_index = 0xffff;	/*Index by long words into sg list. */
5464		data_count = 0;	/*Running count of SG xfer counts. */
5465
5466		sg_ptr = (unsigned long *)currSCCB->DataPointer;
5467
5468		while (data_count < currSCCB->Sccb_ATC) {
5469
5470			sg_index++;
5471			data_count += *(sg_ptr + (sg_index * 2));
5472		}
5473
5474		if (data_count == currSCCB->Sccb_ATC) {
5475
5476			currSCCB->Sccb_SGoffset = 0;
5477			sg_index++;
5478		}
5479
5480		else {
5481			currSCCB->Sccb_SGoffset =
5482			    data_count - currSCCB->Sccb_ATC;
5483		}
5484
5485		currSCCB->Sccb_sgseg = (unsigned short)sg_index;
5486	}
5487
5488	else {
5489		currSCCB->Sccb_XferCnt =
5490		    currSCCB->DataLength - currSCCB->Sccb_ATC;
5491	}
5492}
5493
5494/*---------------------------------------------------------------------
5495 *
5496 * Function: FPT_scini
5497 *
5498 * Description: Setup all data structures necessary for SCAM selection.
5499 *
5500 *---------------------------------------------------------------------*/
5501
5502static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
5503		      unsigned char p_power_up)
5504{
5505
5506	unsigned char loser, assigned_id;
5507	unsigned long p_port;
5508
5509	unsigned char i, k, ScamFlg;
5510	struct sccb_card *currCard;
5511	struct nvram_info *pCurrNvRam;
5512
5513	currCard = &FPT_BL_Card[p_card];
5514	p_port = currCard->ioPort;
5515	pCurrNvRam = currCard->pNvRamInfo;
5516
5517	if (pCurrNvRam) {
5518		ScamFlg = pCurrNvRam->niScamConf;
5519		i = pCurrNvRam->niSysConf;
5520	} else {
5521		ScamFlg =
5522		    (unsigned char)FPT_utilEERead(p_port, SCAM_CONFIG / 2);
5523		i = (unsigned
5524		     char)(FPT_utilEERead(p_port, (SYSTEM_CONFIG / 2)));
5525	}
5526	if (!(i & 0x02))	/* check if reset bus in AutoSCSI parameter set */
5527		return;
5528
5529	FPT_inisci(p_card, p_port, p_our_id);
5530
5531	/* Force to wait 1 sec after SCSI bus reset. Some SCAM device FW
5532	   too slow to return to SCAM selection */
5533
5534	/* if (p_power_up)
5535	   FPT_Wait1Second(p_port);
5536	   else
5537	   FPT_Wait(p_port, TO_250ms); */
5538
5539	FPT_Wait1Second(p_port);
5540
5541	if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2)) {
5542		while (!(FPT_scarb(p_port, INIT_SELTD))) {
5543		}
5544
5545		FPT_scsel(p_port);
5546
5547		do {
5548			FPT_scxferc(p_port, SYNC_PTRN);
5549			FPT_scxferc(p_port, DOM_MSTR);
5550			loser =
5551			    FPT_scsendi(p_port,
5552					&FPT_scamInfo[p_our_id].id_string[0]);
5553		} while (loser == 0xFF);
5554
5555		FPT_scbusf(p_port);
5556
5557		if ((p_power_up) && (!loser)) {
5558			FPT_sresb(p_port, p_card);
5559			FPT_Wait(p_port, TO_250ms);
5560
5561			while (!(FPT_scarb(p_port, INIT_SELTD))) {
5562			}
5563
5564			FPT_scsel(p_port);
5565
5566			do {
5567				FPT_scxferc(p_port, SYNC_PTRN);
5568				FPT_scxferc(p_port, DOM_MSTR);
5569				loser =
5570				    FPT_scsendi(p_port,
5571						&FPT_scamInfo[p_our_id].
5572						id_string[0]);
5573			} while (loser == 0xFF);
5574
5575			FPT_scbusf(p_port);
5576		}
5577	}
5578
5579	else {
5580		loser = 0;
5581	}
5582
5583	if (!loser) {
5584
5585		FPT_scamInfo[p_our_id].state = ID_ASSIGNED;
5586
5587		if (ScamFlg & SCAM_ENABLED) {
5588
5589			for (i = 0; i < MAX_SCSI_TAR; i++) {
5590				if ((FPT_scamInfo[i].state == ID_UNASSIGNED) ||
5591				    (FPT_scamInfo[i].state == ID_UNUSED)) {
5592					if (FPT_scsell(p_port, i)) {
5593						FPT_scamInfo[i].state = LEGACY;
5594						if ((FPT_scamInfo[i].
5595						     id_string[0] != 0xFF)
5596						    || (FPT_scamInfo[i].
5597							id_string[1] != 0xFA)) {
5598
5599							FPT_scamInfo[i].
5600							    id_string[0] = 0xFF;
5601							FPT_scamInfo[i].
5602							    id_string[1] = 0xFA;
5603							if (pCurrNvRam == NULL)
5604								currCard->
5605								    globalFlags
5606								    |=
5607								    F_UPDATE_EEPROM;
5608						}
5609					}
5610				}
5611			}
5612
5613			FPT_sresb(p_port, p_card);
5614			FPT_Wait1Second(p_port);
5615			while (!(FPT_scarb(p_port, INIT_SELTD))) {
5616			}
5617			FPT_scsel(p_port);
5618			FPT_scasid(p_card, p_port);
5619		}
5620
5621	}
5622
5623	else if ((loser) && (ScamFlg & SCAM_ENABLED)) {
5624		FPT_scamInfo[p_our_id].id_string[0] = SLV_TYPE_CODE0;
5625		assigned_id = 0;
5626		FPT_scwtsel(p_port);
5627
5628		do {
5629			while (FPT_scxferc(p_port, 0x00) != SYNC_PTRN) {
5630			}
5631
5632			i = FPT_scxferc(p_port, 0x00);
5633			if (i == ASSIGN_ID) {
5634				if (!
5635				    (FPT_scsendi
5636				     (p_port,
5637				      &FPT_scamInfo[p_our_id].id_string[0]))) {
5638					i = FPT_scxferc(p_port, 0x00);
5639					if (FPT_scvalq(i)) {
5640						k = FPT_scxferc(p_port, 0x00);
5641
5642						if (FPT_scvalq(k)) {
5643							currCard->ourId =
5644							    ((unsigned char)(i
5645									     <<
5646									     3)
5647							     +
5648							     (k &
5649							      (unsigned char)7))
5650							    & (unsigned char)
5651							    0x3F;
5652							FPT_inisci(p_card,
5653								   p_port,
5654								   p_our_id);
5655							FPT_scamInfo[currCard->
5656								     ourId].
5657							    state = ID_ASSIGNED;
5658							FPT_scamInfo[currCard->
5659								     ourId].
5660							    id_string[0]
5661							    = SLV_TYPE_CODE0;
5662							assigned_id = 1;
5663						}
5664					}
5665				}
5666			}
5667
5668			else if (i == SET_P_FLAG) {
5669				if (!(FPT_scsendi(p_port,
5670						  &FPT_scamInfo[p_our_id].
5671						  id_string[0])))
5672					FPT_scamInfo[p_our_id].id_string[0] |=
5673					    0x80;
5674			}
5675		} while (!assigned_id);
5676
5677		while (FPT_scxferc(p_port, 0x00) != CFG_CMPLT) {
5678		}
5679	}
5680
5681	if (ScamFlg & SCAM_ENABLED) {
5682		FPT_scbusf(p_port);
5683		if (currCard->globalFlags & F_UPDATE_EEPROM) {
5684			FPT_scsavdi(p_card, p_port);
5685			currCard->globalFlags &= ~F_UPDATE_EEPROM;
5686		}
5687	}
5688
5689/*
5690   for (i=0,k=0; i < MAX_SCSI_TAR; i++)
5691      {
5692      if ((FPT_scamInfo[i].state == ID_ASSIGNED) ||
5693         (FPT_scamInfo[i].state == LEGACY))
5694         k++;
5695      }
5696
5697   if (k==2)
5698      currCard->globalFlags |= F_SINGLE_DEVICE;
5699   else
5700      currCard->globalFlags &= ~F_SINGLE_DEVICE;
5701*/
5702}
5703
5704/*---------------------------------------------------------------------
5705 *
5706 * Function: FPT_scarb
5707 *
5708 * Description: Gain control of the bus and wait SCAM select time (250ms)
5709 *
5710 *---------------------------------------------------------------------*/
5711
5712static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type)
5713{
5714	if (p_sel_type == INIT_SELTD) {
5715
5716		while (RD_HARPOON(p_port + hp_scsisig) & (SCSI_SEL | SCSI_BSY)) {
5717		}
5718
5719		if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL)
5720			return 0;
5721
5722		if (RD_HARPOON(p_port + hp_scsidata_0) != 00)
5723			return 0;
5724
5725		WR_HARPOON(p_port + hp_scsisig,
5726			   (RD_HARPOON(p_port + hp_scsisig) | SCSI_BSY));
5727
5728		if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL) {
5729
5730			WR_HARPOON(p_port + hp_scsisig,
5731				   (RD_HARPOON(p_port + hp_scsisig) &
5732				    ~SCSI_BSY));
5733			return 0;
5734		}
5735
5736		WR_HARPOON(p_port + hp_scsisig,
5737			   (RD_HARPOON(p_port + hp_scsisig) | SCSI_SEL));
5738
5739		if (RD_HARPOON(p_port + hp_scsidata_0) != 00) {
5740
5741			WR_HARPOON(p_port + hp_scsisig,
5742				   (RD_HARPOON(p_port + hp_scsisig) &
5743				    ~(SCSI_BSY | SCSI_SEL)));
5744			return 0;
5745		}
5746	}
5747
5748	WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
5749					   & ~ACTdeassert));
5750	WR_HARPOON(p_port + hp_scsireset, SCAM_EN);
5751	WR_HARPOON(p_port + hp_scsidata_0, 0x00);
5752	WR_HARPOON(p_port + hp_scsidata_1, 0x00);
5753	WR_HARPOON(p_port + hp_portctrl_0, SCSI_BUS_EN);
5754
5755	WR_HARPOON(p_port + hp_scsisig,
5756		   (RD_HARPOON(p_port + hp_scsisig) | SCSI_MSG));
5757
5758	WR_HARPOON(p_port + hp_scsisig, (RD_HARPOON(p_port + hp_scsisig)
5759					 & ~SCSI_BSY));
5760
5761	FPT_Wait(p_port, TO_250ms);
5762
5763	return 1;
5764}
5765
5766/*---------------------------------------------------------------------
5767 *
5768 * Function: FPT_scbusf
5769 *
5770 * Description: Release the SCSI bus and disable SCAM selection.
5771 *
5772 *---------------------------------------------------------------------*/
5773
5774static void FPT_scbusf(unsigned long p_port)
5775{
5776	WR_HARPOON(p_port + hp_page_ctrl,
5777		   (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
5778
5779	WR_HARPOON(p_port + hp_scsidata_0, 0x00);
5780
5781	WR_HARPOON(p_port + hp_portctrl_0, (RD_HARPOON(p_port + hp_portctrl_0)
5782					    & ~SCSI_BUS_EN));
5783
5784	WR_HARPOON(p_port + hp_scsisig, 0x00);
5785
5786	WR_HARPOON(p_port + hp_scsireset, (RD_HARPOON(p_port + hp_scsireset)
5787					   & ~SCAM_EN));
5788
5789	WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
5790					   | ACTdeassert));
5791
5792	WRW_HARPOON((p_port + hp_intstat), (BUS_FREE | AUTO_INT | SCAM_SEL));
5793
5794	WR_HARPOON(p_port + hp_page_ctrl,
5795		   (RD_HARPOON(p_port + hp_page_ctrl) & ~G_INT_DISABLE));
5796}
5797
5798/*---------------------------------------------------------------------
5799 *
5800 * Function: FPT_scasid
5801 *
5802 * Description: Assign an ID to all the SCAM devices.
5803 *
5804 *---------------------------------------------------------------------*/
5805
5806static void FPT_scasid(unsigned char p_card, unsigned long p_port)
5807{
5808	unsigned char temp_id_string[ID_STRING_LENGTH];
5809
5810	unsigned char i, k, scam_id;
5811	unsigned char crcBytes[3];
5812	struct nvram_info *pCurrNvRam;
5813	unsigned short *pCrcBytes;
5814
5815	pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
5816
5817	i = 0;
5818
5819	while (!i) {
5820
5821		for (k = 0; k < ID_STRING_LENGTH; k++) {
5822			temp_id_string[k] = (unsigned char)0x00;
5823		}
5824
5825		FPT_scxferc(p_port, SYNC_PTRN);
5826		FPT_scxferc(p_port, ASSIGN_ID);
5827
5828		if (!(FPT_sciso(p_port, &temp_id_string[0]))) {
5829			if (pCurrNvRam) {
5830				pCrcBytes = (unsigned short *)&crcBytes[0];
5831				*pCrcBytes = FPT_CalcCrc16(&temp_id_string[0]);
5832				crcBytes[2] = FPT_CalcLrc(&temp_id_string[0]);
5833				temp_id_string[1] = crcBytes[2];
5834				temp_id_string[2] = crcBytes[0];
5835				temp_id_string[3] = crcBytes[1];
5836				for (k = 4; k < ID_STRING_LENGTH; k++)
5837					temp_id_string[k] = (unsigned char)0x00;
5838			}
5839			i = FPT_scmachid(p_card, temp_id_string);
5840
5841			if (i == CLR_PRIORITY) {
5842				FPT_scxferc(p_port, MISC_CODE);
5843				FPT_scxferc(p_port, CLR_P_FLAG);
5844				i = 0;	/*Not the last ID yet. */
5845			}
5846
5847			else if (i != NO_ID_AVAIL) {
5848				if (i < 8)
5849					FPT_scxferc(p_port, ID_0_7);
5850				else
5851					FPT_scxferc(p_port, ID_8_F);
5852
5853				scam_id = (i & (unsigned char)0x07);
5854
5855				for (k = 1; k < 0x08; k <<= 1)
5856					if (!(k & i))
5857						scam_id += 0x08;	/*Count number of zeros in DB0-3. */
5858
5859				FPT_scxferc(p_port, scam_id);
5860
5861				i = 0;	/*Not the last ID yet. */
5862			}
5863		}
5864
5865		else {
5866			i = 1;
5867		}
5868
5869	}			/*End while */
5870
5871	FPT_scxferc(p_port, SYNC_PTRN);
5872	FPT_scxferc(p_port, CFG_CMPLT);
5873}
5874
5875/*---------------------------------------------------------------------
5876 *
5877 * Function: FPT_scsel
5878 *
5879 * Description: Select all the SCAM devices.
5880 *
5881 *---------------------------------------------------------------------*/
5882
5883static void FPT_scsel(unsigned long p_port)
5884{
5885
5886	WR_HARPOON(p_port + hp_scsisig, SCSI_SEL);
5887	FPT_scwiros(p_port, SCSI_MSG);
5888
5889	WR_HARPOON(p_port + hp_scsisig, (SCSI_SEL | SCSI_BSY));
5890
5891	WR_HARPOON(p_port + hp_scsisig,
5892		   (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5893	WR_HARPOON(p_port + hp_scsidata_0,
5894		   (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) |
5895				   (unsigned char)(BIT(7) + BIT(6))));
5896
5897	WR_HARPOON(p_port + hp_scsisig, (SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5898	FPT_scwiros(p_port, SCSI_SEL);
5899
5900	WR_HARPOON(p_port + hp_scsidata_0,
5901		   (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) &
5902				   ~(unsigned char)BIT(6)));
5903	FPT_scwirod(p_port, BIT(6));
5904
5905	WR_HARPOON(p_port + hp_scsisig,
5906		   (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5907}
5908
5909/*---------------------------------------------------------------------
5910 *
5911 * Function: FPT_scxferc
5912 *
5913 * Description: Handshake the p_data (DB4-0) across the bus.
5914 *
5915 *---------------------------------------------------------------------*/
5916
5917static unsigned char FPT_scxferc(unsigned long p_port, unsigned char p_data)
5918{
5919	unsigned char curr_data, ret_data;
5920
5921	curr_data = p_data | BIT(7) | BIT(5);	/*Start with DB7 & DB5 asserted. */
5922
5923	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5924
5925	curr_data &= ~BIT(7);
5926
5927	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5928
5929	FPT_scwirod(p_port, BIT(7));	/*Wait for DB7 to be released. */
5930	while (!(RD_HARPOON(p_port + hp_scsidata_0) & BIT(5))) ;
5931
5932	ret_data = (RD_HARPOON(p_port + hp_scsidata_0) & (unsigned char)0x1F);
5933
5934	curr_data |= BIT(6);
5935
5936	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5937
5938	curr_data &= ~BIT(5);
5939
5940	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5941
5942	FPT_scwirod(p_port, BIT(5));	/*Wait for DB5 to be released. */
5943
5944	curr_data &= ~(BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));	/*Release data bits */
5945	curr_data |= BIT(7);
5946
5947	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5948
5949	curr_data &= ~BIT(6);
5950
5951	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5952
5953	FPT_scwirod(p_port, BIT(6));	/*Wait for DB6 to be released. */
5954
5955	return ret_data;
5956}
5957
5958/*---------------------------------------------------------------------
5959 *
5960 * Function: FPT_scsendi
5961 *
5962 * Description: Transfer our Identification string to determine if we
5963 *              will be the dominant master.
5964 *
5965 *---------------------------------------------------------------------*/
5966
5967static unsigned char FPT_scsendi(unsigned long p_port,
5968				 unsigned char p_id_string[])
5969{
5970	unsigned char ret_data, byte_cnt, bit_cnt, defer;
5971
5972	defer = 0;
5973
5974	for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
5975
5976		for (bit_cnt = 0x80; bit_cnt != 0; bit_cnt >>= 1) {
5977
5978			if (defer)
5979				ret_data = FPT_scxferc(p_port, 00);
5980
5981			else if (p_id_string[byte_cnt] & bit_cnt)
5982
5983				ret_data = FPT_scxferc(p_port, 02);
5984
5985			else {
5986
5987				ret_data = FPT_scxferc(p_port, 01);
5988				if (ret_data & 02)
5989					defer = 1;
5990			}
5991
5992			if ((ret_data & 0x1C) == 0x10)
5993				return 0x00;	/*End of isolation stage, we won! */
5994
5995			if (ret_data & 0x1C)
5996				return 0xFF;
5997
5998			if ((defer) && (!(ret_data & 0x1F)))
5999				return 0x01;	/*End of isolation stage, we lost. */
6000
6001		}		/*bit loop */
6002
6003	}			/*byte loop */
6004
6005	if (defer)
6006		return 0x01;	/*We lost */
6007	else
6008		return 0;	/*We WON! Yeeessss! */
6009}
6010
6011/*---------------------------------------------------------------------
6012 *
6013 * Function: FPT_sciso
6014 *
6015 * Description: Transfer the Identification string.
6016 *
6017 *---------------------------------------------------------------------*/
6018
6019static unsigned char FPT_sciso(unsigned long p_port,
6020			       unsigned char p_id_string[])
6021{
6022	unsigned char ret_data, the_data, byte_cnt, bit_cnt;
6023
6024	the_data = 0;
6025
6026	for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
6027
6028		for (bit_cnt = 0; bit_cnt < 8; bit_cnt++) {
6029
6030			ret_data = FPT_scxferc(p_port, 0);
6031
6032			if (ret_data & 0xFC)
6033				return 0xFF;
6034
6035			else {
6036
6037				the_data <<= 1;
6038				if (ret_data & BIT(1)) {
6039					the_data |= 1;
6040				}
6041			}
6042
6043			if ((ret_data & 0x1F) == 0) {
6044/*
6045				if(bit_cnt != 0 || bit_cnt != 8)
6046				{
6047					byte_cnt = 0;
6048					bit_cnt = 0;
6049					FPT_scxferc(p_port, SYNC_PTRN);
6050					FPT_scxferc(p_port, ASSIGN_ID);
6051					continue;
6052				}
6053*/
6054				if (byte_cnt)
6055					return 0x00;
6056				else
6057					return 0xFF;
6058			}
6059
6060		}		/*bit loop */
6061
6062		p_id_string[byte_cnt] = the_data;
6063
6064	}			/*byte loop */
6065
6066	return 0;
6067}
6068
6069/*---------------------------------------------------------------------
6070 *
6071 * Function: FPT_scwirod
6072 *
6073 * Description: Sample the SCSI data bus making sure the signal has been
6074 *              deasserted for the correct number of consecutive samples.
6075 *
6076 *---------------------------------------------------------------------*/
6077
6078static void FPT_scwirod(unsigned long p_port, unsigned char p_data_bit)
6079{
6080	unsigned char i;
6081
6082	i = 0;
6083	while (i < MAX_SCSI_TAR) {
6084
6085		if (RD_HARPOON(p_port + hp_scsidata_0) & p_data_bit)
6086
6087			i = 0;
6088
6089		else
6090
6091			i++;
6092
6093	}
6094}
6095
6096/*---------------------------------------------------------------------
6097 *
6098 * Function: FPT_scwiros
6099 *
6100 * Description: Sample the SCSI Signal lines making sure the signal has been
6101 *              deasserted for the correct number of consecutive samples.
6102 *
6103 *---------------------------------------------------------------------*/
6104
6105static void FPT_scwiros(unsigned long p_port, unsigned char p_data_bit)
6106{
6107	unsigned char i;
6108
6109	i = 0;
6110	while (i < MAX_SCSI_TAR) {
6111
6112		if (RD_HARPOON(p_port + hp_scsisig) & p_data_bit)
6113
6114			i = 0;
6115
6116		else
6117
6118			i++;
6119
6120	}
6121}
6122
6123/*---------------------------------------------------------------------
6124 *
6125 * Function: FPT_scvalq
6126 *
6127 * Description: Make sure we received a valid data byte.
6128 *
6129 *---------------------------------------------------------------------*/
6130
6131static unsigned char FPT_scvalq(unsigned char p_quintet)
6132{
6133	unsigned char count;
6134
6135	for (count = 1; count < 0x08; count <<= 1) {
6136		if (!(p_quintet & count))
6137			p_quintet -= 0x80;
6138	}
6139
6140	if (p_quintet & 0x18)
6141		return 0;
6142
6143	else
6144		return 1;
6145}
6146
6147/*---------------------------------------------------------------------
6148 *
6149 * Function: FPT_scsell
6150 *
6151 * Description: Select the specified device ID using a selection timeout
6152 *              less than 4ms.  If somebody responds then it is a legacy
6153 *              drive and this ID must be marked as such.
6154 *
6155 *---------------------------------------------------------------------*/
6156
6157static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id)
6158{
6159	unsigned long i;
6160
6161	WR_HARPOON(p_port + hp_page_ctrl,
6162		   (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
6163
6164	ARAM_ACCESS(p_port);
6165
6166	WR_HARPOON(p_port + hp_addstat,
6167		   (RD_HARPOON(p_port + hp_addstat) | SCAM_TIMER));
6168	WR_HARPOON(p_port + hp_seltimeout, TO_4ms);
6169
6170	for (i = p_port + CMD_STRT; i < p_port + CMD_STRT + 12; i += 2) {
6171		WRW_HARPOON(i, (MPM_OP + ACOMMAND));
6172	}
6173	WRW_HARPOON(i, (BRH_OP + ALWAYS + NP));
6174
6175	WRW_HARPOON((p_port + hp_intstat),
6176		    (RESET | TIMEOUT | SEL | BUS_FREE | AUTO_INT));
6177
6178	WR_HARPOON(p_port + hp_select_id, targ_id);
6179
6180	WR_HARPOON(p_port + hp_portctrl_0, SCSI_PORT);
6181	WR_HARPOON(p_port + hp_autostart_3, (SELECT | CMD_ONLY_STRT));
6182	WR_HARPOON(p_port + hp_scsictrl_0, (SEL_TAR | ENA_RESEL));
6183
6184	while (!(RDW_HARPOON((p_port + hp_intstat)) &
6185		 (RESET | PROG_HLT | TIMEOUT | AUTO_INT))) {
6186	}
6187
6188	if (RDW_HARPOON((p_port + hp_intstat)) & RESET)
6189		FPT_Wait(p_port, TO_250ms);
6190
6191	DISABLE_AUTO(p_port);
6192
6193	WR_HARPOON(p_port + hp_addstat,
6194		   (RD_HARPOON(p_port + hp_addstat) & ~SCAM_TIMER));
6195	WR_HARPOON(p_port + hp_seltimeout, TO_290ms);
6196
6197	SGRAM_ACCESS(p_port);
6198
6199	if (RDW_HARPOON((p_port + hp_intstat)) & (RESET | TIMEOUT)) {
6200
6201		WRW_HARPOON((p_port + hp_intstat),
6202			    (RESET | TIMEOUT | SEL | BUS_FREE | PHASE));
6203
6204		WR_HARPOON(p_port + hp_page_ctrl,
6205			   (RD_HARPOON(p_port + hp_page_ctrl) &
6206			    ~G_INT_DISABLE));
6207
6208		return 0;	/*No legacy device */
6209	}
6210
6211	else {
6212
6213		while (!(RDW_HARPOON((p_port + hp_intstat)) & BUS_FREE)) {
6214			if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ) {
6215				WR_HARPOON(p_port + hp_scsisig,
6216					   (SCSI_ACK + S_ILL_PH));
6217				ACCEPT_MSG(p_port);
6218			}
6219		}
6220
6221		WRW_HARPOON((p_port + hp_intstat), CLR_ALL_INT_1);
6222
6223		WR_HARPOON(p_port + hp_page_ctrl,
6224			   (RD_HARPOON(p_port + hp_page_ctrl) &
6225			    ~G_INT_DISABLE));
6226
6227		return 1;	/*Found one of them oldies! */
6228	}
6229}
6230
6231/*---------------------------------------------------------------------
6232 *
6233 * Function: FPT_scwtsel
6234 *
6235 * Description: Wait to be selected by another SCAM initiator.
6236 *
6237 *---------------------------------------------------------------------*/
6238
6239static void FPT_scwtsel(unsigned long p_port)
6240{
6241	while (!(RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL)) {
6242	}
6243}
6244
6245/*---------------------------------------------------------------------
6246 *
6247 * Function: FPT_inisci
6248 *
6249 * Description: Setup the data Structure with the info from the EEPROM.
6250 *
6251 *---------------------------------------------------------------------*/
6252
6253static void FPT_inisci(unsigned char p_card, unsigned long p_port,
6254		       unsigned char p_our_id)
6255{
6256	unsigned char i, k, max_id;
6257	unsigned short ee_data;
6258	struct nvram_info *pCurrNvRam;
6259
6260	pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
6261
6262	if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6263		max_id = 0x08;
6264
6265	else
6266		max_id = 0x10;
6267
6268	if (pCurrNvRam) {
6269		for (i = 0; i < max_id; i++) {
6270
6271			for (k = 0; k < 4; k++)
6272				FPT_scamInfo[i].id_string[k] =
6273				    pCurrNvRam->niScamTbl[i][k];
6274			for (k = 4; k < ID_STRING_LENGTH; k++)
6275				FPT_scamInfo[i].id_string[k] =
6276				    (unsigned char)0x00;
6277
6278			if (FPT_scamInfo[i].id_string[0] == 0x00)
6279				FPT_scamInfo[i].state = ID_UNUSED;	/*Default to unused ID. */
6280			else
6281				FPT_scamInfo[i].state = ID_UNASSIGNED;	/*Default to unassigned ID. */
6282
6283		}
6284	} else {
6285		for (i = 0; i < max_id; i++) {
6286			for (k = 0; k < ID_STRING_LENGTH; k += 2) {
6287				ee_data =
6288				    FPT_utilEERead(p_port,
6289						   (unsigned
6290						    short)((EE_SCAMBASE / 2) +
6291							   (unsigned short)(i *
6292									    ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
6293				FPT_scamInfo[i].id_string[k] =
6294				    (unsigned char)ee_data;
6295				ee_data >>= 8;
6296				FPT_scamInfo[i].id_string[k + 1] =
6297				    (unsigned char)ee_data;
6298			}
6299
6300			if ((FPT_scamInfo[i].id_string[0] == 0x00) ||
6301			    (FPT_scamInfo[i].id_string[0] == 0xFF))
6302
6303				FPT_scamInfo[i].state = ID_UNUSED;	/*Default to unused ID. */
6304
6305			else
6306				FPT_scamInfo[i].state = ID_UNASSIGNED;	/*Default to unassigned ID. */
6307
6308		}
6309	}
6310	for (k = 0; k < ID_STRING_LENGTH; k++)
6311		FPT_scamInfo[p_our_id].id_string[k] = FPT_scamHAString[k];
6312
6313}
6314
6315/*---------------------------------------------------------------------
6316 *
6317 * Function: FPT_scmachid
6318 *
6319 * Description: Match the Device ID string with our values stored in
6320 *              the EEPROM.
6321 *
6322 *---------------------------------------------------------------------*/
6323
6324static unsigned char FPT_scmachid(unsigned char p_card,
6325				  unsigned char p_id_string[])
6326{
6327
6328	unsigned char i, k, match;
6329
6330	for (i = 0; i < MAX_SCSI_TAR; i++) {
6331
6332		match = 1;
6333
6334		for (k = 0; k < ID_STRING_LENGTH; k++) {
6335			if (p_id_string[k] != FPT_scamInfo[i].id_string[k])
6336				match = 0;
6337		}
6338
6339		if (match) {
6340			FPT_scamInfo[i].state = ID_ASSIGNED;
6341			return i;
6342		}
6343
6344	}
6345
6346	if (p_id_string[0] & BIT(5))
6347		i = 8;
6348	else
6349		i = MAX_SCSI_TAR;
6350
6351	if (((p_id_string[0] & 0x06) == 0x02)
6352	    || ((p_id_string[0] & 0x06) == 0x04))
6353		match = p_id_string[1] & (unsigned char)0x1F;
6354	else
6355		match = 7;
6356
6357	while (i > 0) {
6358		i--;
6359
6360		if (FPT_scamInfo[match].state == ID_UNUSED) {
6361			for (k = 0; k < ID_STRING_LENGTH; k++) {
6362				FPT_scamInfo[match].id_string[k] =
6363				    p_id_string[k];
6364			}
6365
6366			FPT_scamInfo[match].state = ID_ASSIGNED;
6367
6368			if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
6369				FPT_BL_Card[p_card].globalFlags |=
6370				    F_UPDATE_EEPROM;
6371			return match;
6372
6373		}
6374
6375		match--;
6376
6377		if (match == 0xFF) {
6378			if (p_id_string[0] & BIT(5))
6379				match = 7;
6380			else
6381				match = MAX_SCSI_TAR - 1;
6382		}
6383	}
6384
6385	if (p_id_string[0] & BIT(7)) {
6386		return CLR_PRIORITY;
6387	}
6388
6389	if (p_id_string[0] & BIT(5))
6390		i = 8;
6391	else
6392		i = MAX_SCSI_TAR;
6393
6394	if (((p_id_string[0] & 0x06) == 0x02)
6395	    || ((p_id_string[0] & 0x06) == 0x04))
6396		match = p_id_string[1] & (unsigned char)0x1F;
6397	else
6398		match = 7;
6399
6400	while (i > 0) {
6401
6402		i--;
6403
6404		if (FPT_scamInfo[match].state == ID_UNASSIGNED) {
6405			for (k = 0; k < ID_STRING_LENGTH; k++) {
6406				FPT_scamInfo[match].id_string[k] =
6407				    p_id_string[k];
6408			}
6409
6410			FPT_scamInfo[match].id_string[0] |= BIT(7);
6411			FPT_scamInfo[match].state = ID_ASSIGNED;
6412			if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
6413				FPT_BL_Card[p_card].globalFlags |=
6414				    F_UPDATE_EEPROM;
6415			return match;
6416
6417		}
6418
6419		match--;
6420
6421		if (match == 0xFF) {
6422			if (p_id_string[0] & BIT(5))
6423				match = 7;
6424			else
6425				match = MAX_SCSI_TAR - 1;
6426		}
6427	}
6428
6429	return NO_ID_AVAIL;
6430}
6431
6432/*---------------------------------------------------------------------
6433 *
6434 * Function: FPT_scsavdi
6435 *
6436 * Description: Save off the device SCAM ID strings.
6437 *
6438 *---------------------------------------------------------------------*/
6439
6440static void FPT_scsavdi(unsigned char p_card, unsigned long p_port)
6441{
6442	unsigned char i, k, max_id;
6443	unsigned short ee_data, sum_data;
6444
6445	sum_data = 0x0000;
6446
6447	for (i = 1; i < EE_SCAMBASE / 2; i++) {
6448		sum_data += FPT_utilEERead(p_port, i);
6449	}
6450
6451	FPT_utilEEWriteOnOff(p_port, 1);	/* Enable write access to the EEPROM */
6452
6453	if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6454		max_id = 0x08;
6455
6456	else
6457		max_id = 0x10;
6458
6459	for (i = 0; i < max_id; i++) {
6460
6461		for (k = 0; k < ID_STRING_LENGTH; k += 2) {
6462			ee_data = FPT_scamInfo[i].id_string[k + 1];
6463			ee_data <<= 8;
6464			ee_data |= FPT_scamInfo[i].id_string[k];
6465			sum_data += ee_data;
6466			FPT_utilEEWrite(p_port, ee_data,
6467					(unsigned short)((EE_SCAMBASE / 2) +
6468							 (unsigned short)(i *
6469									  ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
6470		}
6471	}
6472
6473	FPT_utilEEWrite(p_port, sum_data, EEPROM_CHECK_SUM / 2);
6474	FPT_utilEEWriteOnOff(p_port, 0);	/* Turn off write access */
6475}
6476
6477/*---------------------------------------------------------------------
6478 *
6479 * Function: FPT_XbowInit
6480 *
6481 * Description: Setup the Xbow for normal operation.
6482 *
6483 *---------------------------------------------------------------------*/
6484
6485static void FPT_XbowInit(unsigned long port, unsigned char ScamFlg)
6486{
6487	unsigned char i;
6488
6489	i = RD_HARPOON(port + hp_page_ctrl);
6490	WR_HARPOON(port + hp_page_ctrl, (unsigned char)(i | G_INT_DISABLE));
6491
6492	WR_HARPOON(port + hp_scsireset, 0x00);
6493	WR_HARPOON(port + hp_portctrl_1, HOST_MODE8);
6494
6495	WR_HARPOON(port + hp_scsireset, (DMA_RESET | HPSCSI_RESET | PROG_RESET |
6496					 FIFO_CLR));
6497
6498	WR_HARPOON(port + hp_scsireset, SCSI_INI);
6499
6500	WR_HARPOON(port + hp_clkctrl_0, CLKCTRL_DEFAULT);
6501
6502	WR_HARPOON(port + hp_scsisig, 0x00);	/*  Clear any signals we might */
6503	WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
6504
6505	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
6506
6507	FPT_default_intena = RESET | RSEL | PROG_HLT | TIMEOUT |
6508	    BUS_FREE | XFER_CNT_0 | AUTO_INT;
6509
6510	if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2))
6511		FPT_default_intena |= SCAM_SEL;
6512
6513	WRW_HARPOON((port + hp_intena), FPT_default_intena);
6514
6515	WR_HARPOON(port + hp_seltimeout, TO_290ms);
6516
6517	/* Turn on SCSI_MODE8 for narrow cards to fix the
6518	   strapping issue with the DUAL CHANNEL card */
6519	if (RD_HARPOON(port + hp_page_ctrl) & NARROW_SCSI_CARD)
6520		WR_HARPOON(port + hp_addstat, SCSI_MODE8);
6521
6522	WR_HARPOON(port + hp_page_ctrl, i);
6523
6524}
6525
6526/*---------------------------------------------------------------------
6527 *
6528 * Function: FPT_BusMasterInit
6529 *
6530 * Description: Initialize the BusMaster for normal operations.
6531 *
6532 *---------------------------------------------------------------------*/
6533
6534static void FPT_BusMasterInit(unsigned long p_port)
6535{
6536
6537	WR_HARPOON(p_port + hp_sys_ctrl, DRVR_RST);
6538	WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
6539
6540	WR_HARPOON(p_port + hp_host_blk_cnt, XFER_BLK64);
6541
6542	WR_HARPOON(p_port + hp_bm_ctrl, (BMCTRL_DEFAULT));
6543
6544	WR_HARPOON(p_port + hp_ee_ctrl, (SCSI_TERM_ENA_H));
6545
6546	RD_HARPOON(p_port + hp_int_status);	/*Clear interrupts. */
6547	WR_HARPOON(p_port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
6548	WR_HARPOON(p_port + hp_page_ctrl, (RD_HARPOON(p_port + hp_page_ctrl) &
6549					   ~SCATTER_EN));
6550}
6551
6552/*---------------------------------------------------------------------
6553 *
6554 * Function: FPT_DiagEEPROM
6555 *
6556 * Description: Verfiy checksum and 'Key' and initialize the EEPROM if
6557 *              necessary.
6558 *
6559 *---------------------------------------------------------------------*/
6560
6561static void FPT_DiagEEPROM(unsigned long p_port)
6562{
6563	unsigned short index, temp, max_wd_cnt;
6564
6565	if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6566		max_wd_cnt = EEPROM_WD_CNT;
6567	else
6568		max_wd_cnt = EEPROM_WD_CNT * 2;
6569
6570	temp = FPT_utilEERead(p_port, FW_SIGNATURE / 2);
6571
6572	if (temp == 0x4641) {
6573
6574		for (index = 2; index < max_wd_cnt; index++) {
6575
6576			temp += FPT_utilEERead(p_port, index);
6577
6578		}
6579
6580		if (temp == FPT_utilEERead(p_port, EEPROM_CHECK_SUM / 2)) {
6581
6582			return;	/*EEPROM is Okay so return now! */
6583		}
6584	}
6585
6586	FPT_utilEEWriteOnOff(p_port, (unsigned char)1);
6587
6588	for (index = 0; index < max_wd_cnt; index++) {
6589
6590		FPT_utilEEWrite(p_port, 0x0000, index);
6591	}
6592
6593	temp = 0;
6594
6595	FPT_utilEEWrite(p_port, 0x4641, FW_SIGNATURE / 2);
6596	temp += 0x4641;
6597	FPT_utilEEWrite(p_port, 0x3920, MODEL_NUMB_0 / 2);
6598	temp += 0x3920;
6599	FPT_utilEEWrite(p_port, 0x3033, MODEL_NUMB_2 / 2);
6600	temp += 0x3033;
6601	FPT_utilEEWrite(p_port, 0x2020, MODEL_NUMB_4 / 2);
6602	temp += 0x2020;
6603	FPT_utilEEWrite(p_port, 0x70D3, SYSTEM_CONFIG / 2);
6604	temp += 0x70D3;
6605	FPT_utilEEWrite(p_port, 0x0010, BIOS_CONFIG / 2);
6606	temp += 0x0010;
6607	FPT_utilEEWrite(p_port, 0x0003, SCAM_CONFIG / 2);
6608	temp += 0x0003;
6609	FPT_utilEEWrite(p_port, 0x0007, ADAPTER_SCSI_ID / 2);
6610	temp += 0x0007;
6611
6612	FPT_utilEEWrite(p_port, 0x0000, IGNORE_B_SCAN / 2);
6613	temp += 0x0000;
6614	FPT_utilEEWrite(p_port, 0x0000, SEND_START_ENA / 2);
6615	temp += 0x0000;
6616	FPT_utilEEWrite(p_port, 0x0000, DEVICE_ENABLE / 2);
6617	temp += 0x0000;
6618
6619	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL01 / 2);
6620	temp += 0x4242;
6621	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL23 / 2);
6622	temp += 0x4242;
6623	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL45 / 2);
6624	temp += 0x4242;
6625	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL67 / 2);
6626	temp += 0x4242;
6627	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL89 / 2);
6628	temp += 0x4242;
6629	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLab / 2);
6630	temp += 0x4242;
6631	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLcd / 2);
6632	temp += 0x4242;
6633	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLef / 2);
6634	temp += 0x4242;
6635
6636	FPT_utilEEWrite(p_port, 0x6C46, 64 / 2);	/*PRODUCT ID */
6637	temp += 0x6C46;
6638	FPT_utilEEWrite(p_port, 0x7361, 66 / 2);	/* FlashPoint LT   */
6639	temp += 0x7361;
6640	FPT_utilEEWrite(p_port, 0x5068, 68 / 2);
6641	temp += 0x5068;
6642	FPT_utilEEWrite(p_port, 0x696F, 70 / 2);
6643	temp += 0x696F;
6644	FPT_utilEEWrite(p_port, 0x746E, 72 / 2);
6645	temp += 0x746E;
6646	FPT_utilEEWrite(p_port, 0x4C20, 74 / 2);
6647	temp += 0x4C20;
6648	FPT_utilEEWrite(p_port, 0x2054, 76 / 2);
6649	temp += 0x2054;
6650	FPT_utilEEWrite(p_port, 0x2020, 78 / 2);
6651	temp += 0x2020;
6652
6653	index = ((EE_SCAMBASE / 2) + (7 * 16));
6654	FPT_utilEEWrite(p_port, (0x0700 + TYPE_CODE0), index);
6655	temp += (0x0700 + TYPE_CODE0);
6656	index++;
6657	FPT_utilEEWrite(p_port, 0x5542, index);	/*Vendor ID code */
6658	temp += 0x5542;		/* BUSLOGIC      */
6659	index++;
6660	FPT_utilEEWrite(p_port, 0x4C53, index);
6661	temp += 0x4C53;
6662	index++;
6663	FPT_utilEEWrite(p_port, 0x474F, index);
6664	temp += 0x474F;
6665	index++;
6666	FPT_utilEEWrite(p_port, 0x4349, index);
6667	temp += 0x4349;
6668	index++;
6669	FPT_utilEEWrite(p_port, 0x5442, index);	/*Vendor unique code */
6670	temp += 0x5442;		/* BT- 930           */
6671	index++;
6672	FPT_utilEEWrite(p_port, 0x202D, index);
6673	temp += 0x202D;
6674	index++;
6675	FPT_utilEEWrite(p_port, 0x3339, index);
6676	temp += 0x3339;
6677	index++;		/*Serial #          */
6678	FPT_utilEEWrite(p_port, 0x2030, index);	/* 01234567         */
6679	temp += 0x2030;
6680	index++;
6681	FPT_utilEEWrite(p_port, 0x5453, index);
6682	temp += 0x5453;
6683	index++;
6684	FPT_utilEEWrite(p_port, 0x5645, index);
6685	temp += 0x5645;
6686	index++;
6687	FPT_utilEEWrite(p_port, 0x2045, index);
6688	temp += 0x2045;
6689	index++;
6690	FPT_utilEEWrite(p_port, 0x202F, index);
6691	temp += 0x202F;
6692	index++;
6693	FPT_utilEEWrite(p_port, 0x4F4A, index);
6694	temp += 0x4F4A;
6695	index++;
6696	FPT_utilEEWrite(p_port, 0x204E, index);
6697	temp += 0x204E;
6698	index++;
6699	FPT_utilEEWrite(p_port, 0x3539, index);
6700	temp += 0x3539;
6701
6702	FPT_utilEEWrite(p_port, temp, EEPROM_CHECK_SUM / 2);
6703
6704	FPT_utilEEWriteOnOff(p_port, (unsigned char)0);
6705
6706}
6707
6708/*---------------------------------------------------------------------
6709 *
6710 * Function: Queue Search Select
6711 *
6712 * Description: Try to find a new command to execute.
6713 *
6714 *---------------------------------------------------------------------*/
6715
6716static void FPT_queueSearchSelect(struct sccb_card *pCurrCard,
6717				  unsigned char p_card)
6718{
6719	unsigned char scan_ptr, lun;
6720	struct sccb_mgr_tar_info *currTar_Info;
6721	struct sccb *pOldSccb;
6722
6723	scan_ptr = pCurrCard->scanIndex;
6724	do {
6725		currTar_Info = &FPT_sccbMgrTbl[p_card][scan_ptr];
6726		if ((pCurrCard->globalFlags & F_CONLUN_IO) &&
6727		    ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
6728		     TAG_Q_TRYING)) {
6729			if (currTar_Info->TarSelQ_Cnt != 0) {
6730
6731				scan_ptr++;
6732				if (scan_ptr == MAX_SCSI_TAR)
6733					scan_ptr = 0;
6734
6735				for (lun = 0; lun < MAX_LUN; lun++) {
6736					if (currTar_Info->TarLUNBusy[lun] == 0) {
6737
6738						pCurrCard->currentSCCB =
6739						    currTar_Info->TarSelQ_Head;
6740						pOldSccb = NULL;
6741
6742						while ((pCurrCard->
6743							currentSCCB != NULL)
6744						       && (lun !=
6745							   pCurrCard->
6746							   currentSCCB->Lun)) {
6747							pOldSccb =
6748							    pCurrCard->
6749							    currentSCCB;
6750							pCurrCard->currentSCCB =
6751							    (struct sccb
6752							     *)(pCurrCard->
6753								currentSCCB)->
6754							    Sccb_forwardlink;
6755						}
6756						if (pCurrCard->currentSCCB ==
6757						    NULL)
6758							continue;
6759						if (pOldSccb != NULL) {
6760							pOldSccb->
6761							    Sccb_forwardlink =
6762							    (struct sccb
6763							     *)(pCurrCard->
6764								currentSCCB)->
6765							    Sccb_forwardlink;
6766							pOldSccb->
6767							    Sccb_backlink =
6768							    (struct sccb
6769							     *)(pCurrCard->
6770								currentSCCB)->
6771							    Sccb_backlink;
6772							currTar_Info->
6773							    TarSelQ_Cnt--;
6774						} else {
6775							currTar_Info->
6776							    TarSelQ_Head =
6777							    (struct sccb
6778							     *)(pCurrCard->
6779								currentSCCB)->
6780							    Sccb_forwardlink;
6781
6782							if (currTar_Info->
6783							    TarSelQ_Head ==
6784							    NULL) {
6785								currTar_Info->
6786								    TarSelQ_Tail
6787								    = NULL;
6788								currTar_Info->
6789								    TarSelQ_Cnt
6790								    = 0;
6791							} else {
6792								currTar_Info->
6793								    TarSelQ_Cnt--;
6794								currTar_Info->
6795								    TarSelQ_Head->
6796								    Sccb_backlink
6797								    =
6798								    (struct sccb
6799								     *)NULL;
6800							}
6801						}
6802						pCurrCard->scanIndex = scan_ptr;
6803
6804						pCurrCard->globalFlags |=
6805						    F_NEW_SCCB_CMD;
6806
6807						break;
6808					}
6809				}
6810			}
6811
6812			else {
6813				scan_ptr++;
6814				if (scan_ptr == MAX_SCSI_TAR) {
6815					scan_ptr = 0;
6816				}
6817			}
6818
6819		} else {
6820			if ((currTar_Info->TarSelQ_Cnt != 0) &&
6821			    (currTar_Info->TarLUNBusy[0] == 0)) {
6822
6823				pCurrCard->currentSCCB =
6824				    currTar_Info->TarSelQ_Head;
6825
6826				currTar_Info->TarSelQ_Head =
6827				    (struct sccb *)(pCurrCard->currentSCCB)->
6828				    Sccb_forwardlink;
6829
6830				if (currTar_Info->TarSelQ_Head == NULL) {
6831					currTar_Info->TarSelQ_Tail = NULL;
6832					currTar_Info->TarSelQ_Cnt = 0;
6833				} else {
6834					currTar_Info->TarSelQ_Cnt--;
6835					currTar_Info->TarSelQ_Head->
6836					    Sccb_backlink = (struct sccb *)NULL;
6837				}
6838
6839				scan_ptr++;
6840				if (scan_ptr == MAX_SCSI_TAR)
6841					scan_ptr = 0;
6842
6843				pCurrCard->scanIndex = scan_ptr;
6844
6845				pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
6846
6847				break;
6848			}
6849
6850			else {
6851				scan_ptr++;
6852				if (scan_ptr == MAX_SCSI_TAR) {
6853					scan_ptr = 0;
6854				}
6855			}
6856		}
6857	} while (scan_ptr != pCurrCard->scanIndex);
6858}
6859
6860/*---------------------------------------------------------------------
6861 *
6862 * Function: Queue Select Fail
6863 *
6864 * Description: Add the current SCCB to the head of the Queue.
6865 *
6866 *---------------------------------------------------------------------*/
6867
6868static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
6869				unsigned char p_card)
6870{
6871	unsigned char thisTarg;
6872	struct sccb_mgr_tar_info *currTar_Info;
6873
6874	if (pCurrCard->currentSCCB != NULL) {
6875		thisTarg =
6876		    (unsigned char)(((struct sccb *)(pCurrCard->currentSCCB))->
6877				    TargID);
6878		currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
6879
6880		pCurrCard->currentSCCB->Sccb_backlink = (struct sccb *)NULL;
6881
6882		pCurrCard->currentSCCB->Sccb_forwardlink =
6883		    currTar_Info->TarSelQ_Head;
6884
6885		if (currTar_Info->TarSelQ_Cnt == 0) {
6886			currTar_Info->TarSelQ_Tail = pCurrCard->currentSCCB;
6887		}
6888
6889		else {
6890			currTar_Info->TarSelQ_Head->Sccb_backlink =
6891			    pCurrCard->currentSCCB;
6892		}
6893
6894		currTar_Info->TarSelQ_Head = pCurrCard->currentSCCB;
6895
6896		pCurrCard->currentSCCB = NULL;
6897		currTar_Info->TarSelQ_Cnt++;
6898	}
6899}
6900
6901/*---------------------------------------------------------------------
6902 *
6903 * Function: Queue Command Complete
6904 *
6905 * Description: Call the callback function with the current SCCB.
6906 *
6907 *---------------------------------------------------------------------*/
6908
6909static void FPT_queueCmdComplete(struct sccb_card *pCurrCard,
6910				 struct sccb *p_sccb, unsigned char p_card)
6911{
6912
6913	unsigned char i, SCSIcmd;
6914	CALL_BK_FN callback;
6915	struct sccb_mgr_tar_info *currTar_Info;
6916
6917	SCSIcmd = p_sccb->Cdb[0];
6918
6919	if (!(p_sccb->Sccb_XferState & F_ALL_XFERRED)) {
6920
6921		if ((p_sccb->
6922		     ControlByte & (SCCB_DATA_XFER_OUT | SCCB_DATA_XFER_IN))
6923		    && (p_sccb->HostStatus == SCCB_COMPLETE)
6924		    && (p_sccb->TargetStatus != SSCHECK))
6925
6926			if ((SCSIcmd == SCSI_READ) ||
6927			    (SCSIcmd == SCSI_WRITE) ||
6928			    (SCSIcmd == SCSI_READ_EXTENDED) ||
6929			    (SCSIcmd == SCSI_WRITE_EXTENDED) ||
6930			    (SCSIcmd == SCSI_WRITE_AND_VERIFY) ||
6931			    (SCSIcmd == SCSI_START_STOP_UNIT) ||
6932			    (pCurrCard->globalFlags & F_NO_FILTER)
6933			    )
6934				p_sccb->HostStatus = SCCB_DATA_UNDER_RUN;
6935	}
6936
6937	if (p_sccb->SccbStatus == SCCB_IN_PROCESS) {
6938		if (p_sccb->HostStatus || p_sccb->TargetStatus)
6939			p_sccb->SccbStatus = SCCB_ERROR;
6940		else
6941			p_sccb->SccbStatus = SCCB_SUCCESS;
6942	}
6943
6944	if (p_sccb->Sccb_XferState & F_AUTO_SENSE) {
6945
6946		p_sccb->CdbLength = p_sccb->Save_CdbLen;
6947		for (i = 0; i < 6; i++) {
6948			p_sccb->Cdb[i] = p_sccb->Save_Cdb[i];
6949		}
6950	}
6951
6952	if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) ||
6953	    (p_sccb->OperationCode == RESIDUAL_COMMAND)) {
6954
6955		FPT_utilUpdateResidual(p_sccb);
6956	}
6957
6958	pCurrCard->cmdCounter--;
6959	if (!pCurrCard->cmdCounter) {
6960
6961		if (pCurrCard->globalFlags & F_GREEN_PC) {
6962			WR_HARPOON(pCurrCard->ioPort + hp_clkctrl_0,
6963				   (PWR_DWN | CLKCTRL_DEFAULT));
6964			WR_HARPOON(pCurrCard->ioPort + hp_sys_ctrl, STOP_CLK);
6965		}
6966
6967		WR_HARPOON(pCurrCard->ioPort + hp_semaphore,
6968			   (RD_HARPOON(pCurrCard->ioPort + hp_semaphore) &
6969			    ~SCCB_MGR_ACTIVE));
6970
6971	}
6972
6973	if (pCurrCard->discQCount != 0) {
6974		currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
6975		if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
6976		     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
6977		      TAG_Q_TRYING))) {
6978			pCurrCard->discQCount--;
6979			pCurrCard->discQ_Tbl[currTar_Info->
6980					     LunDiscQ_Idx[p_sccb->Lun]] = NULL;
6981		} else {
6982			if (p_sccb->Sccb_tag) {
6983				pCurrCard->discQCount--;
6984				pCurrCard->discQ_Tbl[p_sccb->Sccb_tag] = NULL;
6985			} else {
6986				pCurrCard->discQCount--;
6987				pCurrCard->discQ_Tbl[currTar_Info->
6988						     LunDiscQ_Idx[0]] = NULL;
6989			}
6990		}
6991
6992	}
6993
6994	callback = (CALL_BK_FN) p_sccb->SccbCallback;
6995	callback(p_sccb);
6996	pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
6997	pCurrCard->currentSCCB = NULL;
6998}
6999
7000/*---------------------------------------------------------------------
7001 *
7002 * Function: Queue Disconnect
7003 *
7004 * Description: Add SCCB to our disconnect array.
7005 *
7006 *---------------------------------------------------------------------*/
7007static void FPT_queueDisconnect(struct sccb *p_sccb, unsigned char p_card)
7008{
7009	struct sccb_mgr_tar_info *currTar_Info;
7010
7011	currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
7012
7013	if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
7014	     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
7015		FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
7016					      LunDiscQ_Idx[p_sccb->Lun]] =
7017		    p_sccb;
7018	} else {
7019		if (p_sccb->Sccb_tag) {
7020			FPT_BL_Card[p_card].discQ_Tbl[p_sccb->Sccb_tag] =
7021			    p_sccb;
7022			FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarLUNBusy[0] =
7023			    0;
7024			FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarTagQ_Cnt++;
7025		} else {
7026			FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
7027						      LunDiscQ_Idx[0]] = p_sccb;
7028		}
7029	}
7030	FPT_BL_Card[p_card].currentSCCB = NULL;
7031}
7032
7033/*---------------------------------------------------------------------
7034 *
7035 * Function: Queue Flush SCCB
7036 *
7037 * Description: Flush all SCCB's back to the host driver for this target.
7038 *
7039 *---------------------------------------------------------------------*/
7040
7041static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code)
7042{
7043	unsigned char qtag, thisTarg;
7044	struct sccb *currSCCB;
7045	struct sccb_mgr_tar_info *currTar_Info;
7046
7047	currSCCB = FPT_BL_Card[p_card].currentSCCB;
7048	if (currSCCB != NULL) {
7049		thisTarg = (unsigned char)currSCCB->TargID;
7050		currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
7051
7052		for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
7053
7054			if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
7055			    (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
7056			     thisTarg)) {
7057
7058				FPT_BL_Card[p_card].discQ_Tbl[qtag]->
7059				    HostStatus = (unsigned char)error_code;
7060
7061				FPT_queueCmdComplete(&FPT_BL_Card[p_card],
7062						     FPT_BL_Card[p_card].
7063						     discQ_Tbl[qtag], p_card);
7064
7065				FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
7066				currTar_Info->TarTagQ_Cnt--;
7067
7068			}
7069		}
7070	}
7071
7072}
7073
7074/*---------------------------------------------------------------------
7075 *
7076 * Function: Queue Flush Target SCCB
7077 *
7078 * Description: Flush all SCCB's back to the host driver for this target.
7079 *
7080 *---------------------------------------------------------------------*/
7081
7082static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
7083				   unsigned char error_code)
7084{
7085	unsigned char qtag;
7086	struct sccb_mgr_tar_info *currTar_Info;
7087
7088	currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
7089
7090	for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
7091
7092		if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
7093		    (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg)) {
7094
7095			FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus =
7096			    (unsigned char)error_code;
7097
7098			FPT_queueCmdComplete(&FPT_BL_Card[p_card],
7099					     FPT_BL_Card[p_card].
7100					     discQ_Tbl[qtag], p_card);
7101
7102			FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
7103			currTar_Info->TarTagQ_Cnt--;
7104
7105		}
7106	}
7107
7108}
7109
7110static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char p_card)
7111{
7112	struct sccb_mgr_tar_info *currTar_Info;
7113	currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
7114
7115	p_SCCB->Sccb_forwardlink = NULL;
7116
7117	p_SCCB->Sccb_backlink = currTar_Info->TarSelQ_Tail;
7118
7119	if (currTar_Info->TarSelQ_Cnt == 0) {
7120
7121		currTar_Info->TarSelQ_Head = p_SCCB;
7122	}
7123
7124	else {
7125
7126		currTar_Info->TarSelQ_Tail->Sccb_forwardlink = p_SCCB;
7127	}
7128
7129	currTar_Info->TarSelQ_Tail = p_SCCB;
7130	currTar_Info->TarSelQ_Cnt++;
7131}
7132
7133/*---------------------------------------------------------------------
7134 *
7135 * Function: Queue Find SCCB
7136 *
7137 * Description: Search the target select Queue for this SCCB, and
7138 *              remove it if found.
7139 *
7140 *---------------------------------------------------------------------*/
7141
7142static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB,
7143				       unsigned char p_card)
7144{
7145	struct sccb *q_ptr;
7146	struct sccb_mgr_tar_info *currTar_Info;
7147
7148	currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
7149
7150	q_ptr = currTar_Info->TarSelQ_Head;
7151
7152	while (q_ptr != NULL) {
7153
7154		if (q_ptr == p_SCCB) {
7155
7156			if (currTar_Info->TarSelQ_Head == q_ptr) {
7157
7158				currTar_Info->TarSelQ_Head =
7159				    q_ptr->Sccb_forwardlink;
7160			}
7161
7162			if (currTar_Info->TarSelQ_Tail == q_ptr) {
7163
7164				currTar_Info->TarSelQ_Tail =
7165				    q_ptr->Sccb_backlink;
7166			}
7167
7168			if (q_ptr->Sccb_forwardlink != NULL) {
7169				q_ptr->Sccb_forwardlink->Sccb_backlink =
7170				    q_ptr->Sccb_backlink;
7171			}
7172
7173			if (q_ptr->Sccb_backlink != NULL) {
7174				q_ptr->Sccb_backlink->Sccb_forwardlink =
7175				    q_ptr->Sccb_forwardlink;
7176			}
7177
7178			currTar_Info->TarSelQ_Cnt--;
7179
7180			return 1;
7181		}
7182
7183		else {
7184			q_ptr = q_ptr->Sccb_forwardlink;
7185		}
7186	}
7187
7188	return 0;
7189
7190}
7191
7192/*---------------------------------------------------------------------
7193 *
7194 * Function: Utility Update Residual Count
7195 *
7196 * Description: Update the XferCnt to the remaining byte count.
7197 *              If we transferred all the data then just write zero.
7198 *              If Non-SG transfer then report Total Cnt - Actual Transfer
7199 *              Cnt.  For SG transfers add the count fields of all
7200 *              remaining SG elements, as well as any partial remaining
7201 *              element.
7202 *
7203 *---------------------------------------------------------------------*/
7204
7205static void FPT_utilUpdateResidual(struct sccb *p_SCCB)
7206{
7207	unsigned long partial_cnt;
7208	unsigned int sg_index;
7209	unsigned long *sg_ptr;
7210
7211	if (p_SCCB->Sccb_XferState & F_ALL_XFERRED) {
7212
7213		p_SCCB->DataLength = 0x0000;
7214	}
7215
7216	else if (p_SCCB->Sccb_XferState & F_SG_XFER) {
7217
7218		partial_cnt = 0x0000;
7219
7220		sg_index = p_SCCB->Sccb_sgseg;
7221
7222		sg_ptr = (unsigned long *)p_SCCB->DataPointer;
7223
7224		if (p_SCCB->Sccb_SGoffset) {
7225
7226			partial_cnt = p_SCCB->Sccb_SGoffset;
7227			sg_index++;
7228		}
7229
7230		while (((unsigned long)sg_index *
7231			(unsigned long)SG_ELEMENT_SIZE) < p_SCCB->DataLength) {
7232
7233			partial_cnt += *(sg_ptr + (sg_index * 2));
7234			sg_index++;
7235		}
7236
7237		p_SCCB->DataLength = partial_cnt;
7238	}
7239
7240	else {
7241
7242		p_SCCB->DataLength -= p_SCCB->Sccb_ATC;
7243	}
7244}
7245
7246/*---------------------------------------------------------------------
7247 *
7248 * Function: Wait 1 Second
7249 *
7250 * Description: Wait for 1 second.
7251 *
7252 *---------------------------------------------------------------------*/
7253
7254static void FPT_Wait1Second(unsigned long p_port)
7255{
7256	unsigned char i;
7257
7258	for (i = 0; i < 4; i++) {
7259
7260		FPT_Wait(p_port, TO_250ms);
7261
7262		if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
7263			break;
7264
7265		if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
7266			break;
7267	}
7268}
7269
7270/*---------------------------------------------------------------------
7271 *
7272 * Function: FPT_Wait
7273 *
7274 * Description: Wait the desired delay.
7275 *
7276 *---------------------------------------------------------------------*/
7277
7278static void FPT_Wait(unsigned long p_port, unsigned char p_delay)
7279{
7280	unsigned char old_timer;
7281	unsigned char green_flag;
7282
7283	old_timer = RD_HARPOON(p_port + hp_seltimeout);
7284
7285	green_flag = RD_HARPOON(p_port + hp_clkctrl_0);
7286	WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
7287
7288	WR_HARPOON(p_port + hp_seltimeout, p_delay);
7289	WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
7290	WRW_HARPOON((p_port + hp_intena), (FPT_default_intena & ~TIMEOUT));
7291
7292	WR_HARPOON(p_port + hp_portctrl_0,
7293		   (RD_HARPOON(p_port + hp_portctrl_0) | START_TO));
7294
7295	while (!(RDW_HARPOON((p_port + hp_intstat)) & TIMEOUT)) {
7296
7297		if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
7298			break;
7299
7300		if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
7301			break;
7302	}
7303
7304	WR_HARPOON(p_port + hp_portctrl_0,
7305		   (RD_HARPOON(p_port + hp_portctrl_0) & ~START_TO));
7306
7307	WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
7308	WRW_HARPOON((p_port + hp_intena), FPT_default_intena);
7309
7310	WR_HARPOON(p_port + hp_clkctrl_0, green_flag);
7311
7312	WR_HARPOON(p_port + hp_seltimeout, old_timer);
7313}
7314
7315/*---------------------------------------------------------------------
7316 *
7317 * Function: Enable/Disable Write to EEPROM
7318 *
7319 * Description: The EEPROM must first be enabled for writes
7320 *              A total of 9 clocks are needed.
7321 *
7322 *---------------------------------------------------------------------*/
7323
7324static void FPT_utilEEWriteOnOff(unsigned long p_port, unsigned char p_mode)
7325{
7326	unsigned char ee_value;
7327
7328	ee_value =
7329	    (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
7330			    (EXT_ARB_ACK | SCSI_TERM_ENA_H));
7331
7332	if (p_mode)
7333
7334		FPT_utilEESendCmdAddr(p_port, EWEN, EWEN_ADDR);
7335
7336	else
7337
7338		FPT_utilEESendCmdAddr(p_port, EWDS, EWDS_ADDR);
7339
7340	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));	/*Turn off CS */
7341	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);	/*Turn off Master Select */
7342}
7343
7344/*---------------------------------------------------------------------
7345 *
7346 * Function: Write EEPROM
7347 *
7348 * Description: Write a word to the EEPROM at the specified
7349 *              address.
7350 *
7351 *---------------------------------------------------------------------*/
7352
7353static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data,
7354			    unsigned short ee_addr)
7355{
7356
7357	unsigned char ee_value;
7358	unsigned short i;
7359
7360	ee_value =
7361	    (unsigned
7362	     char)((RD_HARPOON(p_port + hp_ee_ctrl) &
7363		    (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
7364
7365	FPT_utilEESendCmdAddr(p_port, EE_WRITE, ee_addr);
7366
7367	ee_value |= (SEE_MS + SEE_CS);
7368
7369	for (i = 0x8000; i != 0; i >>= 1) {
7370
7371		if (i & ee_data)
7372			ee_value |= SEE_DO;
7373		else
7374			ee_value &= ~SEE_DO;
7375
7376		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7377		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7378		ee_value |= SEE_CLK;	/* Clock  data! */
7379		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7380		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7381		ee_value &= ~SEE_CLK;
7382		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7383		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7384	}
7385	ee_value &= (EXT_ARB_ACK | SCSI_TERM_ENA_H);
7386	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));
7387
7388	FPT_Wait(p_port, TO_10ms);
7389
7390	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS | SEE_CS));	/* Set CS to EEPROM */
7391	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));	/* Turn off CS */
7392	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);	/* Turn off Master Select */
7393}
7394
7395/*---------------------------------------------------------------------
7396 *
7397 * Function: Read EEPROM
7398 *
7399 * Description: Read a word from the EEPROM at the desired
7400 *              address.
7401 *
7402 *---------------------------------------------------------------------*/
7403
7404static unsigned short FPT_utilEERead(unsigned long p_port,
7405				     unsigned short ee_addr)
7406{
7407	unsigned short i, ee_data1, ee_data2;
7408
7409	i = 0;
7410	ee_data1 = FPT_utilEEReadOrg(p_port, ee_addr);
7411	do {
7412		ee_data2 = FPT_utilEEReadOrg(p_port, ee_addr);
7413
7414		if (ee_data1 == ee_data2)
7415			return ee_data1;
7416
7417		ee_data1 = ee_data2;
7418		i++;
7419
7420	} while (i < 4);
7421
7422	return ee_data1;
7423}
7424
7425/*---------------------------------------------------------------------
7426 *
7427 * Function: Read EEPROM Original 
7428 *
7429 * Description: Read a word from the EEPROM at the desired
7430 *              address.
7431 *
7432 *---------------------------------------------------------------------*/
7433
7434static unsigned short FPT_utilEEReadOrg(unsigned long p_port,
7435					unsigned short ee_addr)
7436{
7437
7438	unsigned char ee_value;
7439	unsigned short i, ee_data;
7440
7441	ee_value =
7442	    (unsigned
7443	     char)((RD_HARPOON(p_port + hp_ee_ctrl) &
7444		    (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
7445
7446	FPT_utilEESendCmdAddr(p_port, EE_READ, ee_addr);
7447
7448	ee_value |= (SEE_MS + SEE_CS);
7449	ee_data = 0;
7450
7451	for (i = 1; i <= 16; i++) {
7452
7453		ee_value |= SEE_CLK;	/* Clock  data! */
7454		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7455		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7456		ee_value &= ~SEE_CLK;
7457		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7458		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7459
7460		ee_data <<= 1;
7461
7462		if (RD_HARPOON(p_port + hp_ee_ctrl) & SEE_DI)
7463			ee_data |= 1;
7464	}
7465
7466	ee_value &= ~(SEE_MS + SEE_CS);
7467	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));	/*Turn off CS */
7468	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);	/*Turn off Master Select */
7469
7470	return ee_data;
7471}
7472
7473/*---------------------------------------------------------------------
7474 *
7475 * Function: Send EE command and Address to the EEPROM
7476 *
7477 * Description: Transfers the correct command and sends the address
7478 *              to the eeprom.
7479 *
7480 *---------------------------------------------------------------------*/
7481
7482static void FPT_utilEESendCmdAddr(unsigned long p_port, unsigned char ee_cmd,
7483				  unsigned short ee_addr)
7484{
7485	unsigned char ee_value;
7486	unsigned char narrow_flg;
7487
7488	unsigned short i;
7489
7490	narrow_flg =
7491	    (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
7492			    NARROW_SCSI_CARD);
7493
7494	ee_value = SEE_MS;
7495	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7496
7497	ee_value |= SEE_CS;	/* Set CS to EEPROM */
7498	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7499
7500	for (i = 0x04; i != 0; i >>= 1) {
7501
7502		if (i & ee_cmd)
7503			ee_value |= SEE_DO;
7504		else
7505			ee_value &= ~SEE_DO;
7506
7507		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7508		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7509		ee_value |= SEE_CLK;	/* Clock  data! */
7510		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7511		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7512		ee_value &= ~SEE_CLK;
7513		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7514		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7515	}
7516
7517	if (narrow_flg)
7518		i = 0x0080;
7519
7520	else
7521		i = 0x0200;
7522
7523	while (i != 0) {
7524
7525		if (i & ee_addr)
7526			ee_value |= SEE_DO;
7527		else
7528			ee_value &= ~SEE_DO;
7529
7530		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7531		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7532		ee_value |= SEE_CLK;	/* Clock  data! */
7533		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7534		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7535		ee_value &= ~SEE_CLK;
7536		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7537		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7538
7539		i >>= 1;
7540	}
7541}
7542
7543static unsigned short FPT_CalcCrc16(unsigned char buffer[])
7544{
7545	unsigned short crc = 0;
7546	int i, j;
7547	unsigned short ch;
7548	for (i = 0; i < ID_STRING_LENGTH; i++) {
7549		ch = (unsigned short)buffer[i];
7550		for (j = 0; j < 8; j++) {
7551			if ((crc ^ ch) & 1)
7552				crc = (crc >> 1) ^ CRCMASK;
7553			else
7554				crc >>= 1;
7555			ch >>= 1;
7556		}
7557	}
7558	return crc;
7559}
7560
7561static unsigned char FPT_CalcLrc(unsigned char buffer[])
7562{
7563	int i;
7564	unsigned char lrc;
7565	lrc = 0;
7566	for (i = 0; i < ID_STRING_LENGTH; i++)
7567		lrc ^= buffer[i];
7568	return lrc;
7569}
7570
7571/*
7572  The following inline definitions avoid type conflicts.
7573*/
7574
7575static inline unsigned char
7576FlashPoint__ProbeHostAdapter(struct FlashPoint_Info *FlashPointInfo)
7577{
7578	return FlashPoint_ProbeHostAdapter((struct sccb_mgr_info *)
7579					   FlashPointInfo);
7580}
7581
7582static inline FlashPoint_CardHandle_T
7583FlashPoint__HardwareResetHostAdapter(struct FlashPoint_Info *FlashPointInfo)
7584{
7585	return FlashPoint_HardwareResetHostAdapter((struct sccb_mgr_info *)
7586						   FlashPointInfo);
7587}
7588
7589static inline void
7590FlashPoint__ReleaseHostAdapter(FlashPoint_CardHandle_T CardHandle)
7591{
7592	FlashPoint_ReleaseHostAdapter(CardHandle);
7593}
7594
7595static inline void
7596FlashPoint__StartCCB(FlashPoint_CardHandle_T CardHandle,
7597		     struct BusLogic_CCB *CCB)
7598{
7599	FlashPoint_StartCCB(CardHandle, (struct sccb *)CCB);
7600}
7601
7602static inline void
7603FlashPoint__AbortCCB(FlashPoint_CardHandle_T CardHandle,
7604		     struct BusLogic_CCB *CCB)
7605{
7606	FlashPoint_AbortCCB(CardHandle, (struct sccb *)CCB);
7607}
7608
7609static inline bool
7610FlashPoint__InterruptPending(FlashPoint_CardHandle_T CardHandle)
7611{
7612	return FlashPoint_InterruptPending(CardHandle);
7613}
7614
7615static inline int
7616FlashPoint__HandleInterrupt(FlashPoint_CardHandle_T CardHandle)
7617{
7618	return FlashPoint_HandleInterrupt(CardHandle);
7619}
7620
7621#define FlashPoint_ProbeHostAdapter	    FlashPoint__ProbeHostAdapter
7622#define FlashPoint_HardwareResetHostAdapter FlashPoint__HardwareResetHostAdapter
7623#define FlashPoint_ReleaseHostAdapter	    FlashPoint__ReleaseHostAdapter
7624#define FlashPoint_StartCCB		    FlashPoint__StartCCB
7625#define FlashPoint_AbortCCB		    FlashPoint__AbortCCB
7626#define FlashPoint_InterruptPending	    FlashPoint__InterruptPending
7627#define FlashPoint_HandleInterrupt	    FlashPoint__HandleInterrupt
7628
7629#else				/* !CONFIG_SCSI_FLASHPOINT */
7630
7631/*
7632  Define prototypes for the FlashPoint SCCB Manager Functions.
7633*/
7634
7635extern unsigned char FlashPoint_ProbeHostAdapter(struct FlashPoint_Info *);
7636extern FlashPoint_CardHandle_T
7637FlashPoint_HardwareResetHostAdapter(struct FlashPoint_Info *);
7638extern void FlashPoint_StartCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *);
7639extern int FlashPoint_AbortCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *);
7640extern bool FlashPoint_InterruptPending(FlashPoint_CardHandle_T);
7641extern int FlashPoint_HandleInterrupt(FlashPoint_CardHandle_T);
7642extern void FlashPoint_ReleaseHostAdapter(FlashPoint_CardHandle_T);
7643
7644#endif				/* CONFIG_SCSI_FLASHPOINT */
v3.5.6
   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				/* Harpoon problem some SCSI target device respond to selection
1915				   with short BUSY pulse (<400ns) this will make the Harpoon is not able
1916				   to latch the correct Target ID into reg. x53.
1917				   The work around require to correct this reg. But when write to this
1918				   reg. (0x53) also increment the FIFO write addr reg (0x6f), thus we
1919				   need to read this reg first then restore it later. After update to 0x53 */
1920
1921				i = (unsigned
1922				     char)(RD_HARPOON(ioport + hp_fifowrite));
1923				target =
1924				    (unsigned
1925				     char)(RD_HARPOON(ioport + hp_gp_reg_3));
1926				WR_HARPOON(ioport + hp_xfer_pad,
1927					   (unsigned char)ID_UNLOCK);
1928				WR_HARPOON(ioport + hp_select_id,
1929					   (unsigned char)(target | target <<
1930							   4));
1931				WR_HARPOON(ioport + hp_xfer_pad,
1932					   (unsigned char)0x00);
1933				WR_HARPOON(ioport + hp_fifowrite, i);
1934				WR_HARPOON(ioport + hp_autostart_3,
1935					   (AUTO_IMMED + TAG_STRT));
1936			}
1937		}
1938
1939		else if (hp_int & XFER_CNT_0) {
1940
1941			WRW_HARPOON((ioport + hp_intstat), XFER_CNT_0);
1942
1943			FPT_schkdd(ioport, thisCard);
1944
1945		}
1946
1947		else if (hp_int & BUS_FREE) {
1948
1949			WRW_HARPOON((ioport + hp_intstat), BUS_FREE);
1950
1951			if (((struct sccb_card *)pCurrCard)->
1952			    globalFlags & F_HOST_XFER_ACT) {
1953
1954				FPT_hostDataXferAbort(ioport, thisCard,
1955						      currSCCB);
1956			}
1957
1958			FPT_phaseBusFree(ioport, thisCard);
1959		}
1960
1961		else if (hp_int & ITICKLE) {
1962
1963			WRW_HARPOON((ioport + hp_intstat), ITICKLE);
1964			((struct sccb_card *)pCurrCard)->globalFlags |=
1965			    F_NEW_SCCB_CMD;
1966		}
1967
1968		if (((struct sccb_card *)pCurrCard)->
1969		    globalFlags & F_NEW_SCCB_CMD) {
1970
1971			((struct sccb_card *)pCurrCard)->globalFlags &=
1972			    ~F_NEW_SCCB_CMD;
1973
1974			if (((struct sccb_card *)pCurrCard)->currentSCCB ==
1975			    NULL) {
1976
1977				FPT_queueSearchSelect(((struct sccb_card *)
1978						       pCurrCard), thisCard);
1979			}
1980
1981			if (((struct sccb_card *)pCurrCard)->currentSCCB !=
1982			    NULL) {
1983				((struct sccb_card *)pCurrCard)->globalFlags &=
1984				    ~F_NEW_SCCB_CMD;
1985				FPT_ssel(ioport, thisCard);
1986			}
1987
1988			break;
1989
1990		}
1991
1992	}			/*end while */
1993
1994	MENABLE_INT(ioport);
1995
1996	return 0;
1997}
1998
1999/*---------------------------------------------------------------------
2000 *
2001 * Function: Sccb_bad_isr
2002 *
2003 * Description: Some type of interrupt has occurred which is slightly
2004 *              out of the ordinary.  We will now decode it fully, in
2005 *              this routine.  This is broken up in an attempt to save
2006 *              processing time.
2007 *
2008 *---------------------------------------------------------------------*/
2009static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port,
2010					 unsigned char p_card,
2011					 struct sccb_card *pCurrCard,
2012					 unsigned short p_int)
2013{
2014	unsigned char temp, ScamFlg;
2015	struct sccb_mgr_tar_info *currTar_Info;
2016	struct nvram_info *pCurrNvRam;
2017
2018	if (RD_HARPOON(p_port + hp_ext_status) &
2019	    (BM_FORCE_OFF | PCI_DEV_TMOUT | BM_PARITY_ERR | PIO_OVERRUN)) {
2020
2021		if (pCurrCard->globalFlags & F_HOST_XFER_ACT) {
2022
2023			FPT_hostDataXferAbort(p_port, p_card,
2024					      pCurrCard->currentSCCB);
2025		}
2026
2027		if (RD_HARPOON(p_port + hp_pci_stat_cfg) & REC_MASTER_ABORT)
2028		{
2029			WR_HARPOON(p_port + hp_pci_stat_cfg,
2030				   (RD_HARPOON(p_port + hp_pci_stat_cfg) &
2031				    ~REC_MASTER_ABORT));
2032
2033			WR_HARPOON(p_port + hp_host_blk_cnt, 0x00);
2034
2035		}
2036
2037		if (pCurrCard->currentSCCB != NULL) {
2038
2039			if (!pCurrCard->currentSCCB->HostStatus)
2040				pCurrCard->currentSCCB->HostStatus =
2041				    SCCB_BM_ERR;
2042
2043			FPT_sxfrp(p_port, p_card);
2044
2045			temp = (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
2046					       (EXT_ARB_ACK | SCSI_TERM_ENA_H));
2047			WR_HARPOON(p_port + hp_ee_ctrl,
2048				   ((unsigned char)temp | SEE_MS | SEE_CS));
2049			WR_HARPOON(p_port + hp_ee_ctrl, temp);
2050
2051			if (!
2052			    (RDW_HARPOON((p_port + hp_intstat)) &
2053			     (BUS_FREE | RESET))) {
2054				FPT_phaseDecode(p_port, p_card);
2055			}
2056		}
2057	}
2058
2059	else if (p_int & RESET) {
2060
2061		WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
2062		WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
2063		if (pCurrCard->currentSCCB != NULL) {
2064
2065			if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
2066
2067				FPT_hostDataXferAbort(p_port, p_card,
2068						      pCurrCard->currentSCCB);
2069		}
2070
2071		DISABLE_AUTO(p_port);
2072
2073		FPT_sresb(p_port, p_card);
2074
2075		while (RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST) {
2076		}
2077
2078		pCurrNvRam = pCurrCard->pNvRamInfo;
2079		if (pCurrNvRam) {
2080			ScamFlg = pCurrNvRam->niScamConf;
2081		} else {
2082			ScamFlg =
2083			    (unsigned char)FPT_utilEERead(p_port,
2084							  SCAM_CONFIG / 2);
2085		}
2086
2087		FPT_XbowInit(p_port, ScamFlg);
2088
2089		FPT_scini(p_card, pCurrCard->ourId, 0);
2090
2091		return 0xFF;
2092	}
2093
2094	else if (p_int & FIFO) {
2095
2096		WRW_HARPOON((p_port + hp_intstat), FIFO);
2097
2098		if (pCurrCard->currentSCCB != NULL)
2099			FPT_sxfrp(p_port, p_card);
2100	}
2101
2102	else if (p_int & TIMEOUT) {
2103
2104		DISABLE_AUTO(p_port);
2105
2106		WRW_HARPOON((p_port + hp_intstat),
2107			    (PROG_HLT | TIMEOUT | SEL | BUS_FREE | PHASE |
2108			     IUNKWN));
2109
2110		pCurrCard->currentSCCB->HostStatus = SCCB_SELECTION_TIMEOUT;
2111
2112		currTar_Info =
2113		    &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
2114		if ((pCurrCard->globalFlags & F_CONLUN_IO)
2115		    && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
2116			TAG_Q_TRYING))
2117			currTar_Info->TarLUNBusy[pCurrCard->currentSCCB->Lun] =
2118			    0;
2119		else
2120			currTar_Info->TarLUNBusy[0] = 0;
2121
2122		if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
2123			currTar_Info->TarSyncCtrl = 0;
2124			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2125		}
2126
2127		if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
2128			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2129		}
2130
2131		FPT_sssyncv(p_port, pCurrCard->currentSCCB->TargID, NARROW_SCSI,
2132			    currTar_Info);
2133
2134		FPT_queueCmdComplete(pCurrCard, pCurrCard->currentSCCB, p_card);
2135
2136	}
2137
2138	else if (p_int & SCAM_SEL) {
2139
2140		FPT_scarb(p_port, LEVEL2_TAR);
2141		FPT_scsel(p_port);
2142		FPT_scasid(p_card, p_port);
2143
2144		FPT_scbusf(p_port);
2145
2146		WRW_HARPOON((p_port + hp_intstat), SCAM_SEL);
2147	}
2148
2149	return 0x00;
2150}
2151
2152/*---------------------------------------------------------------------
2153 *
2154 * Function: SccbMgrTableInit
2155 *
2156 * Description: Initialize all Sccb manager data structures.
2157 *
2158 *---------------------------------------------------------------------*/
2159
2160static void FPT_SccbMgrTableInitAll()
2161{
2162	unsigned char thisCard;
2163
2164	for (thisCard = 0; thisCard < MAX_CARDS; thisCard++) {
2165		FPT_SccbMgrTableInitCard(&FPT_BL_Card[thisCard], thisCard);
2166
2167		FPT_BL_Card[thisCard].ioPort = 0x00;
2168		FPT_BL_Card[thisCard].cardInfo = NULL;
2169		FPT_BL_Card[thisCard].cardIndex = 0xFF;
2170		FPT_BL_Card[thisCard].ourId = 0x00;
2171		FPT_BL_Card[thisCard].pNvRamInfo = NULL;
2172	}
2173}
2174
2175/*---------------------------------------------------------------------
2176 *
2177 * Function: SccbMgrTableInit
2178 *
2179 * Description: Initialize all Sccb manager data structures.
2180 *
2181 *---------------------------------------------------------------------*/
2182
2183static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard,
2184				     unsigned char p_card)
2185{
2186	unsigned char scsiID, qtag;
2187
2188	for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
2189		FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
2190	}
2191
2192	for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
2193		FPT_sccbMgrTbl[p_card][scsiID].TarStatus = 0;
2194		FPT_sccbMgrTbl[p_card][scsiID].TarEEValue = 0;
2195		FPT_SccbMgrTableInitTarget(p_card, scsiID);
2196	}
2197
2198	pCurrCard->scanIndex = 0x00;
2199	pCurrCard->currentSCCB = NULL;
2200	pCurrCard->globalFlags = 0x00;
2201	pCurrCard->cmdCounter = 0x00;
2202	pCurrCard->tagQ_Lst = 0x01;
2203	pCurrCard->discQCount = 0;
2204
2205}
2206
2207/*---------------------------------------------------------------------
2208 *
2209 * Function: SccbMgrTableInit
2210 *
2211 * Description: Initialize all Sccb manager data structures.
2212 *
2213 *---------------------------------------------------------------------*/
2214
2215static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
2216				       unsigned char target)
2217{
2218
2219	unsigned char lun, qtag;
2220	struct sccb_mgr_tar_info *currTar_Info;
2221
2222	currTar_Info = &FPT_sccbMgrTbl[p_card][target];
2223
2224	currTar_Info->TarSelQ_Cnt = 0;
2225	currTar_Info->TarSyncCtrl = 0;
2226
2227	currTar_Info->TarSelQ_Head = NULL;
2228	currTar_Info->TarSelQ_Tail = NULL;
2229	currTar_Info->TarTagQ_Cnt = 0;
2230	currTar_Info->TarLUN_CA = 0;
2231
2232	for (lun = 0; lun < MAX_LUN; lun++) {
2233		currTar_Info->TarLUNBusy[lun] = 0;
2234		currTar_Info->LunDiscQ_Idx[lun] = 0;
2235	}
2236
2237	for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
2238		if (FPT_BL_Card[p_card].discQ_Tbl[qtag] != NULL) {
2239			if (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
2240			    target) {
2241				FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
2242				FPT_BL_Card[p_card].discQCount--;
2243			}
2244		}
2245	}
2246}
2247
2248/*---------------------------------------------------------------------
2249 *
2250 * Function: sfetm
2251 *
2252 * Description: Read in a message byte from the SCSI bus, and check
2253 *              for a parity error.
2254 *
2255 *---------------------------------------------------------------------*/
2256
2257static unsigned char FPT_sfm(unsigned long port, struct sccb *pCurrSCCB)
2258{
2259	unsigned char message;
2260	unsigned short TimeOutLoop;
2261
2262	TimeOutLoop = 0;
2263	while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2264	       (TimeOutLoop++ < 20000)) {
2265	}
2266
2267	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
2268
2269	message = RD_HARPOON(port + hp_scsidata_0);
2270
2271	WR_HARPOON(port + hp_scsisig, SCSI_ACK + S_MSGI_PH);
2272
2273	if (TimeOutLoop > 20000)
2274		message = 0x00;	/* force message byte = 0 if Time Out on Req */
2275
2276	if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
2277	    (RD_HARPOON(port + hp_addstat) & SCSI_PAR_ERR)) {
2278		WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2279		WR_HARPOON(port + hp_xferstat, 0);
2280		WR_HARPOON(port + hp_fiforead, 0);
2281		WR_HARPOON(port + hp_fifowrite, 0);
2282		if (pCurrSCCB != NULL) {
2283			pCurrSCCB->Sccb_scsimsg = SMPARITY;
2284		}
2285		message = 0x00;
2286		do {
2287			ACCEPT_MSG_ATN(port);
2288			TimeOutLoop = 0;
2289			while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2290			       (TimeOutLoop++ < 20000)) {
2291			}
2292			if (TimeOutLoop > 20000) {
2293				WRW_HARPOON((port + hp_intstat), PARITY);
2294				return message;
2295			}
2296			if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) !=
2297			    S_MSGI_PH) {
2298				WRW_HARPOON((port + hp_intstat), PARITY);
2299				return message;
2300			}
2301			WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
2302
2303			RD_HARPOON(port + hp_scsidata_0);
2304
2305			WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2306
2307		} while (1);
2308
2309	}
2310	WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2311	WR_HARPOON(port + hp_xferstat, 0);
2312	WR_HARPOON(port + hp_fiforead, 0);
2313	WR_HARPOON(port + hp_fifowrite, 0);
2314	return message;
2315}
2316
2317/*---------------------------------------------------------------------
2318 *
2319 * Function: FPT_ssel
2320 *
2321 * Description: Load up automation and select target device.
2322 *
2323 *---------------------------------------------------------------------*/
2324
2325static void FPT_ssel(unsigned long port, unsigned char p_card)
2326{
2327
2328	unsigned char auto_loaded, i, target, *theCCB;
2329
2330	unsigned long cdb_reg;
2331	struct sccb_card *CurrCard;
2332	struct sccb *currSCCB;
2333	struct sccb_mgr_tar_info *currTar_Info;
2334	unsigned char lastTag, lun;
2335
2336	CurrCard = &FPT_BL_Card[p_card];
2337	currSCCB = CurrCard->currentSCCB;
2338	target = currSCCB->TargID;
2339	currTar_Info = &FPT_sccbMgrTbl[p_card][target];
2340	lastTag = CurrCard->tagQ_Lst;
2341
2342	ARAM_ACCESS(port);
2343
2344	if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
2345		currSCCB->ControlByte &= ~F_USE_CMD_Q;
2346
2347	if (((CurrCard->globalFlags & F_CONLUN_IO) &&
2348	     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
2349
2350		lun = currSCCB->Lun;
2351	else
2352		lun = 0;
2353
2354	if (CurrCard->globalFlags & F_TAG_STARTED) {
2355		if (!(currSCCB->ControlByte & F_USE_CMD_Q)) {
2356			if ((currTar_Info->TarLUN_CA == 0)
2357			    && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
2358				== TAG_Q_TRYING)) {
2359
2360				if (currTar_Info->TarTagQ_Cnt != 0) {
2361					currTar_Info->TarLUNBusy[lun] = 1;
2362					FPT_queueSelectFail(CurrCard, p_card);
2363					SGRAM_ACCESS(port);
2364					return;
2365				}
2366
2367				else {
2368					currTar_Info->TarLUNBusy[lun] = 1;
2369				}
2370
2371			}
2372			/*End non-tagged */
2373			else {
2374				currTar_Info->TarLUNBusy[lun] = 1;
2375			}
2376
2377		}
2378		/*!Use cmd Q Tagged */
2379		else {
2380			if (currTar_Info->TarLUN_CA == 1) {
2381				FPT_queueSelectFail(CurrCard, p_card);
2382				SGRAM_ACCESS(port);
2383				return;
2384			}
2385
2386			currTar_Info->TarLUNBusy[lun] = 1;
2387
2388		}		/*else use cmd Q tagged */
2389
2390	}
2391	/*if glob tagged started */
2392	else {
2393		currTar_Info->TarLUNBusy[lun] = 1;
2394	}
2395
2396	if ((((CurrCard->globalFlags & F_CONLUN_IO) &&
2397	      ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
2398	     || (!(currSCCB->ControlByte & F_USE_CMD_Q)))) {
2399		if (CurrCard->discQCount >= QUEUE_DEPTH) {
2400			currTar_Info->TarLUNBusy[lun] = 1;
2401			FPT_queueSelectFail(CurrCard, p_card);
2402			SGRAM_ACCESS(port);
2403			return;
2404		}
2405		for (i = 1; i < QUEUE_DEPTH; i++) {
2406			if (++lastTag >= QUEUE_DEPTH)
2407				lastTag = 1;
2408			if (CurrCard->discQ_Tbl[lastTag] == NULL) {
2409				CurrCard->tagQ_Lst = lastTag;
2410				currTar_Info->LunDiscQ_Idx[lun] = lastTag;
2411				CurrCard->discQ_Tbl[lastTag] = currSCCB;
2412				CurrCard->discQCount++;
2413				break;
2414			}
2415		}
2416		if (i == QUEUE_DEPTH) {
2417			currTar_Info->TarLUNBusy[lun] = 1;
2418			FPT_queueSelectFail(CurrCard, p_card);
2419			SGRAM_ACCESS(port);
2420			return;
2421		}
2422	}
2423
2424	auto_loaded = 0;
2425
2426	WR_HARPOON(port + hp_select_id, target);
2427	WR_HARPOON(port + hp_gp_reg_3, target);	/* Use by new automation logic */
2428
2429	if (currSCCB->OperationCode == RESET_COMMAND) {
2430		WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
2431						   (currSCCB->
2432						    Sccb_idmsg & ~DISC_PRIV)));
2433
2434		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + NP);
2435
2436		currSCCB->Sccb_scsimsg = SMDEV_RESET;
2437
2438		WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
2439		auto_loaded = 1;
2440		currSCCB->Sccb_scsistat = SELECT_BDR_ST;
2441
2442		if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
2443			currTar_Info->TarSyncCtrl = 0;
2444			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2445		}
2446
2447		if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
2448			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2449		}
2450
2451		FPT_sssyncv(port, target, NARROW_SCSI, currTar_Info);
2452		FPT_SccbMgrTableInitTarget(p_card, target);
2453
2454	}
2455
2456	else if (currSCCB->Sccb_scsistat == ABORT_ST) {
2457		WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
2458						   (currSCCB->
2459						    Sccb_idmsg & ~DISC_PRIV)));
2460
2461		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
2462
2463		WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT +
2464						     (((unsigned
2465							char)(currSCCB->
2466							      ControlByte &
2467							      TAG_TYPE_MASK)
2468						       >> 6) | (unsigned char)
2469						      0x20)));
2470		WRW_HARPOON((port + SYNC_MSGS + 2),
2471			    (MPM_OP + AMSG_OUT + currSCCB->Sccb_tag));
2472		WRW_HARPOON((port + SYNC_MSGS + 4), (BRH_OP + ALWAYS + NP));
2473
2474		WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
2475		auto_loaded = 1;
2476
2477	}
2478
2479	else if (!(currTar_Info->TarStatus & WIDE_NEGOCIATED)) {
2480		auto_loaded = FPT_siwidn(port, p_card);
2481		currSCCB->Sccb_scsistat = SELECT_WN_ST;
2482	}
2483
2484	else if (!((currTar_Info->TarStatus & TAR_SYNC_MASK)
2485		   == SYNC_SUPPORTED)) {
2486		auto_loaded = FPT_sisyncn(port, p_card, 0);
2487		currSCCB->Sccb_scsistat = SELECT_SN_ST;
2488	}
2489
2490	if (!auto_loaded) {
2491
2492		if (currSCCB->ControlByte & F_USE_CMD_Q) {
2493
2494			CurrCard->globalFlags |= F_TAG_STARTED;
2495
2496			if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
2497			    == TAG_Q_REJECT) {
2498				currSCCB->ControlByte &= ~F_USE_CMD_Q;
2499
2500				/* Fix up the start instruction with a jump to
2501				   Non-Tag-CMD handling */
2502				WRW_HARPOON((port + ID_MSG_STRT),
2503					    BRH_OP + ALWAYS + NTCMD);
2504
2505				WRW_HARPOON((port + NON_TAG_ID_MSG),
2506					    (MPM_OP + AMSG_OUT +
2507					     currSCCB->Sccb_idmsg));
2508
2509				WR_HARPOON(port + hp_autostart_3,
2510					   (SELECT + SELCHK_STRT));
2511
2512				/* Setup our STATE so we know what happened when
2513				   the wheels fall off. */
2514				currSCCB->Sccb_scsistat = SELECT_ST;
2515
2516				currTar_Info->TarLUNBusy[lun] = 1;
2517			}
2518
2519			else {
2520				WRW_HARPOON((port + ID_MSG_STRT),
2521					    (MPM_OP + AMSG_OUT +
2522					     currSCCB->Sccb_idmsg));
2523
2524				WRW_HARPOON((port + ID_MSG_STRT + 2),
2525					    (MPM_OP + AMSG_OUT +
2526					     (((unsigned char)(currSCCB->
2527							       ControlByte &
2528							       TAG_TYPE_MASK)
2529					       >> 6) | (unsigned char)0x20)));
2530
2531				for (i = 1; i < QUEUE_DEPTH; i++) {
2532					if (++lastTag >= QUEUE_DEPTH)
2533						lastTag = 1;
2534					if (CurrCard->discQ_Tbl[lastTag] ==
2535					    NULL) {
2536						WRW_HARPOON((port +
2537							     ID_MSG_STRT + 6),
2538							    (MPM_OP + AMSG_OUT +
2539							     lastTag));
2540						CurrCard->tagQ_Lst = lastTag;
2541						currSCCB->Sccb_tag = lastTag;
2542						CurrCard->discQ_Tbl[lastTag] =
2543						    currSCCB;
2544						CurrCard->discQCount++;
2545						break;
2546					}
2547				}
2548
2549				if (i == QUEUE_DEPTH) {
2550					currTar_Info->TarLUNBusy[lun] = 1;
2551					FPT_queueSelectFail(CurrCard, p_card);
2552					SGRAM_ACCESS(port);
2553					return;
2554				}
2555
2556				currSCCB->Sccb_scsistat = SELECT_Q_ST;
2557
2558				WR_HARPOON(port + hp_autostart_3,
2559					   (SELECT + SELCHK_STRT));
2560			}
2561		}
2562
2563		else {
2564
2565			WRW_HARPOON((port + ID_MSG_STRT),
2566				    BRH_OP + ALWAYS + NTCMD);
2567
2568			WRW_HARPOON((port + NON_TAG_ID_MSG),
2569				    (MPM_OP + AMSG_OUT + currSCCB->Sccb_idmsg));
2570
2571			currSCCB->Sccb_scsistat = SELECT_ST;
2572
2573			WR_HARPOON(port + hp_autostart_3,
2574				   (SELECT + SELCHK_STRT));
2575		}
2576
2577		theCCB = (unsigned char *)&currSCCB->Cdb[0];
2578
2579		cdb_reg = port + CMD_STRT;
2580
2581		for (i = 0; i < currSCCB->CdbLength; i++) {
2582			WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + *theCCB));
2583			cdb_reg += 2;
2584			theCCB++;
2585		}
2586
2587		if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
2588			WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
2589
2590	}
2591	/* auto_loaded */
2592	WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
2593	WR_HARPOON(port + hp_xferstat, 0x00);
2594
2595	WRW_HARPOON((port + hp_intstat), (PROG_HLT | TIMEOUT | SEL | BUS_FREE));
2596
2597	WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT));
2598
2599	if (!(currSCCB->Sccb_MGRFlags & F_DEV_SELECTED)) {
2600		WR_HARPOON(port + hp_scsictrl_0,
2601			   (SEL_TAR | ENA_ATN | ENA_RESEL | ENA_SCAM_SEL));
2602	} else {
2603
2604/*      auto_loaded =  (RD_HARPOON(port+hp_autostart_3) & (unsigned char)0x1F);
2605      auto_loaded |= AUTO_IMMED; */
2606		auto_loaded = AUTO_IMMED;
2607
2608		DISABLE_AUTO(port);
2609
2610		WR_HARPOON(port + hp_autostart_3, auto_loaded);
2611	}
2612
2613	SGRAM_ACCESS(port);
2614}
2615
2616/*---------------------------------------------------------------------
2617 *
2618 * Function: FPT_sres
2619 *
2620 * Description: Hookup the correct CCB and handle the incoming messages.
2621 *
2622 *---------------------------------------------------------------------*/
2623
2624static void FPT_sres(unsigned long port, unsigned char p_card,
2625		     struct sccb_card *pCurrCard)
2626{
2627
2628	unsigned char our_target, message, lun = 0, tag, msgRetryCount;
2629
2630	struct sccb_mgr_tar_info *currTar_Info;
2631	struct sccb *currSCCB;
2632
2633	if (pCurrCard->currentSCCB != NULL) {
2634		currTar_Info =
2635		    &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
2636		DISABLE_AUTO(port);
2637
2638		WR_HARPOON((port + hp_scsictrl_0), (ENA_RESEL | ENA_SCAM_SEL));
2639
2640		currSCCB = pCurrCard->currentSCCB;
2641		if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
2642			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2643			currSCCB->Sccb_scsistat = BUS_FREE_ST;
2644		}
2645		if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
2646			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2647			currSCCB->Sccb_scsistat = BUS_FREE_ST;
2648		}
2649		if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
2650		     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
2651		      TAG_Q_TRYING))) {
2652			currTar_Info->TarLUNBusy[currSCCB->Lun] = 0;
2653			if (currSCCB->Sccb_scsistat != ABORT_ST) {
2654				pCurrCard->discQCount--;
2655				pCurrCard->discQ_Tbl[currTar_Info->
2656						     LunDiscQ_Idx[currSCCB->
2657								  Lun]]
2658				    = NULL;
2659			}
2660		} else {
2661			currTar_Info->TarLUNBusy[0] = 0;
2662			if (currSCCB->Sccb_tag) {
2663				if (currSCCB->Sccb_scsistat != ABORT_ST) {
2664					pCurrCard->discQCount--;
2665					pCurrCard->discQ_Tbl[currSCCB->
2666							     Sccb_tag] = NULL;
2667				}
2668			} else {
2669				if (currSCCB->Sccb_scsistat != ABORT_ST) {
2670					pCurrCard->discQCount--;
2671					pCurrCard->discQ_Tbl[currTar_Info->
2672							     LunDiscQ_Idx[0]] =
2673					    NULL;
2674				}
2675			}
2676		}
2677
2678		FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
2679	}
2680
2681	WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
2682
2683	our_target = (unsigned char)(RD_HARPOON(port + hp_select_id) >> 4);
2684	currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
2685
2686	msgRetryCount = 0;
2687	do {
2688
2689		currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
2690		tag = 0;
2691
2692		while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
2693			if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
2694
2695				WRW_HARPOON((port + hp_intstat), PHASE);
2696				return;
2697			}
2698		}
2699
2700		WRW_HARPOON((port + hp_intstat), PHASE);
2701		if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH) {
2702
2703			message = FPT_sfm(port, pCurrCard->currentSCCB);
2704			if (message) {
2705
2706				if (message <= (0x80 | LUN_MASK)) {
2707					lun = message & (unsigned char)LUN_MASK;
2708
2709					if ((currTar_Info->
2710					     TarStatus & TAR_TAG_Q_MASK) ==
2711					    TAG_Q_TRYING) {
2712						if (currTar_Info->TarTagQ_Cnt !=
2713						    0) {
2714
2715							if (!
2716							    (currTar_Info->
2717							     TarLUN_CA)) {
2718								ACCEPT_MSG(port);	/*Release the ACK for ID msg. */
2719
2720								message =
2721								    FPT_sfm
2722								    (port,
2723								     pCurrCard->
2724								     currentSCCB);
2725								if (message) {
2726									ACCEPT_MSG
2727									    (port);
2728								}
2729
2730								else
2731									message
2732									    = 0;
2733
2734								if (message !=
2735								    0) {
2736									tag =
2737									    FPT_sfm
2738									    (port,
2739									     pCurrCard->
2740									     currentSCCB);
2741
2742									if (!
2743									    (tag))
2744										message
2745										    =
2746										    0;
2747								}
2748
2749							}
2750							/*C.A. exists! */
2751						}
2752						/*End Q cnt != 0 */
2753					}
2754					/*End Tag cmds supported! */
2755				}
2756				/*End valid ID message.  */
2757				else {
2758
2759					ACCEPT_MSG_ATN(port);
2760				}
2761
2762			}
2763			/* End good id message. */
2764			else {
2765
2766				message = 0;
2767			}
2768		} else {
2769			ACCEPT_MSG_ATN(port);
2770
2771			while (!
2772			       (RDW_HARPOON((port + hp_intstat)) &
2773				(PHASE | RESET))
2774			       && !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
2775			       && (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
2776
2777			return;
2778		}
2779
2780		if (message == 0) {
2781			msgRetryCount++;
2782			if (msgRetryCount == 1) {
2783				FPT_SendMsg(port, SMPARITY);
2784			} else {
2785				FPT_SendMsg(port, SMDEV_RESET);
2786
2787				FPT_sssyncv(port, our_target, NARROW_SCSI,
2788					    currTar_Info);
2789
2790				if (FPT_sccbMgrTbl[p_card][our_target].
2791				    TarEEValue & EE_SYNC_MASK) {
2792
2793					FPT_sccbMgrTbl[p_card][our_target].
2794					    TarStatus &= ~TAR_SYNC_MASK;
2795
2796				}
2797
2798				if (FPT_sccbMgrTbl[p_card][our_target].
2799				    TarEEValue & EE_WIDE_SCSI) {
2800
2801					FPT_sccbMgrTbl[p_card][our_target].
2802					    TarStatus &= ~TAR_WIDE_MASK;
2803				}
2804
2805				FPT_queueFlushTargSccb(p_card, our_target,
2806						       SCCB_COMPLETE);
2807				FPT_SccbMgrTableInitTarget(p_card, our_target);
2808				return;
2809			}
2810		}
2811	} while (message == 0);
2812
2813	if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
2814	     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
2815		currTar_Info->TarLUNBusy[lun] = 1;
2816		pCurrCard->currentSCCB =
2817		    pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[lun]];
2818		if (pCurrCard->currentSCCB != NULL) {
2819			ACCEPT_MSG(port);
2820		} else {
2821			ACCEPT_MSG_ATN(port);
2822		}
2823	} else {
2824		currTar_Info->TarLUNBusy[0] = 1;
2825
2826		if (tag) {
2827			if (pCurrCard->discQ_Tbl[tag] != NULL) {
2828				pCurrCard->currentSCCB =
2829				    pCurrCard->discQ_Tbl[tag];
2830				currTar_Info->TarTagQ_Cnt--;
2831				ACCEPT_MSG(port);
2832			} else {
2833				ACCEPT_MSG_ATN(port);
2834			}
2835		} else {
2836			pCurrCard->currentSCCB =
2837			    pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]];
2838			if (pCurrCard->currentSCCB != NULL) {
2839				ACCEPT_MSG(port);
2840			} else {
2841				ACCEPT_MSG_ATN(port);
2842			}
2843		}
2844	}
2845
2846	if (pCurrCard->currentSCCB != NULL) {
2847		if (pCurrCard->currentSCCB->Sccb_scsistat == ABORT_ST) {
2848			/* During Abort Tag command, the target could have got re-selected
2849			   and completed the command. Check the select Q and remove the CCB
2850			   if it is in the Select Q */
2851			FPT_queueFindSccb(pCurrCard->currentSCCB, p_card);
2852		}
2853	}
2854
2855	while (!(RDW_HARPOON((port + hp_intstat)) & (PHASE | RESET)) &&
2856	       !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ) &&
2857	       (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
2858}
2859
2860static void FPT_SendMsg(unsigned long port, unsigned char message)
2861{
2862	while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
2863		if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
2864
2865			WRW_HARPOON((port + hp_intstat), PHASE);
2866			return;
2867		}
2868	}
2869
2870	WRW_HARPOON((port + hp_intstat), PHASE);
2871	if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGO_PH) {
2872		WRW_HARPOON((port + hp_intstat),
2873			    (BUS_FREE | PHASE | XFER_CNT_0));
2874
2875		WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
2876
2877		WR_HARPOON(port + hp_scsidata_0, message);
2878
2879		WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2880
2881		ACCEPT_MSG(port);
2882
2883		WR_HARPOON(port + hp_portctrl_0, 0x00);
2884
2885		if ((message == SMABORT) || (message == SMDEV_RESET) ||
2886		    (message == SMABORT_TAG)) {
2887			while (!
2888			       (RDW_HARPOON((port + hp_intstat)) &
2889				(BUS_FREE | PHASE))) {
2890			}
2891
2892			if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
2893				WRW_HARPOON((port + hp_intstat), BUS_FREE);
2894			}
2895		}
2896	}
2897}
2898
2899/*---------------------------------------------------------------------
2900 *
2901 * Function: FPT_sdecm
2902 *
2903 * Description: Determine the proper response to the message from the
2904 *              target device.
2905 *
2906 *---------------------------------------------------------------------*/
2907static void FPT_sdecm(unsigned char message, unsigned long port,
2908		      unsigned char p_card)
2909{
2910	struct sccb *currSCCB;
2911	struct sccb_card *CurrCard;
2912	struct sccb_mgr_tar_info *currTar_Info;
2913
2914	CurrCard = &FPT_BL_Card[p_card];
2915	currSCCB = CurrCard->currentSCCB;
2916
2917	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
2918
2919	if (message == SMREST_DATA_PTR) {
2920		if (!(currSCCB->Sccb_XferState & F_NO_DATA_YET)) {
2921			currSCCB->Sccb_ATC = currSCCB->Sccb_savedATC;
2922
2923			FPT_hostDataXferRestart(currSCCB);
2924		}
2925
2926		ACCEPT_MSG(port);
2927		WR_HARPOON(port + hp_autostart_1,
2928			   (AUTO_IMMED + DISCONNECT_START));
2929	}
2930
2931	else if (message == SMCMD_COMP) {
2932
2933		if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
2934			currTar_Info->TarStatus &=
2935			    ~(unsigned char)TAR_TAG_Q_MASK;
2936			currTar_Info->TarStatus |= (unsigned char)TAG_Q_REJECT;
2937		}
2938
2939		ACCEPT_MSG(port);
2940
2941	}
2942
2943	else if ((message == SMNO_OP) || (message >= SMIDENT)
2944		 || (message == SMINIT_RECOVERY) || (message == SMREL_RECOVERY)) {
2945
2946		ACCEPT_MSG(port);
2947		WR_HARPOON(port + hp_autostart_1,
2948			   (AUTO_IMMED + DISCONNECT_START));
2949	}
2950
2951	else if (message == SMREJECT) {
2952
2953		if ((currSCCB->Sccb_scsistat == SELECT_SN_ST) ||
2954		    (currSCCB->Sccb_scsistat == SELECT_WN_ST) ||
2955		    ((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)
2956		    || ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) ==
2957			TAG_Q_TRYING))
2958		{
2959			WRW_HARPOON((port + hp_intstat), BUS_FREE);
2960
2961			ACCEPT_MSG(port);
2962
2963			while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2964			       (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
2965			{
2966			}
2967
2968			if (currSCCB->Lun == 0x00) {
2969				if ((currSCCB->Sccb_scsistat == SELECT_SN_ST)) {
2970
2971					currTar_Info->TarStatus |=
2972					    (unsigned char)SYNC_SUPPORTED;
2973
2974					currTar_Info->TarEEValue &=
2975					    ~EE_SYNC_MASK;
2976				}
2977
2978				else if ((currSCCB->Sccb_scsistat ==
2979					  SELECT_WN_ST)) {
2980
2981					currTar_Info->TarStatus =
2982					    (currTar_Info->
2983					     TarStatus & ~WIDE_ENABLED) |
2984					    WIDE_NEGOCIATED;
2985
2986					currTar_Info->TarEEValue &=
2987					    ~EE_WIDE_SCSI;
2988
2989				}
2990
2991				else if ((currTar_Info->
2992					  TarStatus & TAR_TAG_Q_MASK) ==
2993					 TAG_Q_TRYING) {
2994					currTar_Info->TarStatus =
2995					    (currTar_Info->
2996					     TarStatus & ~(unsigned char)
2997					     TAR_TAG_Q_MASK) | TAG_Q_REJECT;
2998
2999					currSCCB->ControlByte &= ~F_USE_CMD_Q;
3000					CurrCard->discQCount--;
3001					CurrCard->discQ_Tbl[currSCCB->
3002							    Sccb_tag] = NULL;
3003					currSCCB->Sccb_tag = 0x00;
3004
3005				}
3006			}
3007
3008			if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
3009
3010				if (currSCCB->Lun == 0x00) {
3011					WRW_HARPOON((port + hp_intstat),
3012						    BUS_FREE);
3013					CurrCard->globalFlags |= F_NEW_SCCB_CMD;
3014				}
3015			}
3016
3017			else {
3018
3019				if ((CurrCard->globalFlags & F_CONLUN_IO) &&
3020				    ((currTar_Info->
3021				      TarStatus & TAR_TAG_Q_MASK) !=
3022				     TAG_Q_TRYING))
3023					currTar_Info->TarLUNBusy[currSCCB->
3024								 Lun] = 1;
3025				else
3026					currTar_Info->TarLUNBusy[0] = 1;
3027
3028				currSCCB->ControlByte &=
3029				    ~(unsigned char)F_USE_CMD_Q;
3030
3031				WR_HARPOON(port + hp_autostart_1,
3032					   (AUTO_IMMED + DISCONNECT_START));
3033
3034			}
3035		}
3036
3037		else {
3038			ACCEPT_MSG(port);
3039
3040			while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
3041			       (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
3042			{
3043			}
3044
3045			if (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)) {
3046				WR_HARPOON(port + hp_autostart_1,
3047					   (AUTO_IMMED + DISCONNECT_START));
3048			}
3049		}
3050	}
3051
3052	else if (message == SMEXT) {
3053
3054		ACCEPT_MSG(port);
3055		FPT_shandem(port, p_card, currSCCB);
3056	}
3057
3058	else if (message == SMIGNORWR) {
3059
3060		ACCEPT_MSG(port);	/* ACK the RESIDUE MSG */
3061
3062		message = FPT_sfm(port, currSCCB);
3063
3064		if (currSCCB->Sccb_scsimsg != SMPARITY)
3065			ACCEPT_MSG(port);
3066		WR_HARPOON(port + hp_autostart_1,
3067			   (AUTO_IMMED + DISCONNECT_START));
3068	}
3069
3070	else {
3071
3072		currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
3073		currSCCB->Sccb_scsimsg = SMREJECT;
3074
3075		ACCEPT_MSG_ATN(port);
3076		WR_HARPOON(port + hp_autostart_1,
3077			   (AUTO_IMMED + DISCONNECT_START));
3078	}
3079}
3080
3081/*---------------------------------------------------------------------
3082 *
3083 * Function: FPT_shandem
3084 *
3085 * Description: Decide what to do with the extended message.
3086 *
3087 *---------------------------------------------------------------------*/
3088static void FPT_shandem(unsigned long port, unsigned char p_card,
3089			struct sccb *pCurrSCCB)
3090{
3091	unsigned char length, message;
3092
3093	length = FPT_sfm(port, pCurrSCCB);
3094	if (length) {
3095
3096		ACCEPT_MSG(port);
3097		message = FPT_sfm(port, pCurrSCCB);
3098		if (message) {
3099
3100			if (message == SMSYNC) {
3101
3102				if (length == 0x03) {
3103
3104					ACCEPT_MSG(port);
3105					FPT_stsyncn(port, p_card);
3106				} else {
3107
3108					pCurrSCCB->Sccb_scsimsg = SMREJECT;
3109					ACCEPT_MSG_ATN(port);
3110				}
3111			} else if (message == SMWDTR) {
3112
3113				if (length == 0x02) {
3114
3115					ACCEPT_MSG(port);
3116					FPT_stwidn(port, p_card);
3117				} else {
3118
3119					pCurrSCCB->Sccb_scsimsg = SMREJECT;
3120					ACCEPT_MSG_ATN(port);
3121
3122					WR_HARPOON(port + hp_autostart_1,
3123						   (AUTO_IMMED +
3124						    DISCONNECT_START));
3125				}
3126			} else {
3127
3128				pCurrSCCB->Sccb_scsimsg = SMREJECT;
3129				ACCEPT_MSG_ATN(port);
3130
3131				WR_HARPOON(port + hp_autostart_1,
3132					   (AUTO_IMMED + DISCONNECT_START));
3133			}
3134		} else {
3135			if (pCurrSCCB->Sccb_scsimsg != SMPARITY)
3136				ACCEPT_MSG(port);
3137			WR_HARPOON(port + hp_autostart_1,
3138				   (AUTO_IMMED + DISCONNECT_START));
3139		}
3140	} else {
3141		if (pCurrSCCB->Sccb_scsimsg == SMPARITY)
3142			WR_HARPOON(port + hp_autostart_1,
3143				   (AUTO_IMMED + DISCONNECT_START));
3144	}
3145}
3146
3147/*---------------------------------------------------------------------
3148 *
3149 * Function: FPT_sisyncn
3150 *
3151 * Description: Read in a message byte from the SCSI bus, and check
3152 *              for a parity error.
3153 *
3154 *---------------------------------------------------------------------*/
3155
3156static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card,
3157				 unsigned char syncFlag)
3158{
3159	struct sccb *currSCCB;
3160	struct sccb_mgr_tar_info *currTar_Info;
3161
3162	currSCCB = FPT_BL_Card[p_card].currentSCCB;
3163	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
3164
3165	if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)) {
3166
3167		WRW_HARPOON((port + ID_MSG_STRT),
3168			    (MPM_OP + AMSG_OUT +
3169			     (currSCCB->
3170			      Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
3171
3172		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
3173
3174		WRW_HARPOON((port + SYNC_MSGS + 0),
3175			    (MPM_OP + AMSG_OUT + SMEXT));
3176		WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
3177		WRW_HARPOON((port + SYNC_MSGS + 4),
3178			    (MPM_OP + AMSG_OUT + SMSYNC));
3179
3180		if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
3181
3182			WRW_HARPOON((port + SYNC_MSGS + 6),
3183				    (MPM_OP + AMSG_OUT + 12));
3184
3185		else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
3186			 EE_SYNC_10MB)
3187
3188			WRW_HARPOON((port + SYNC_MSGS + 6),
3189				    (MPM_OP + AMSG_OUT + 25));
3190
3191		else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
3192			 EE_SYNC_5MB)
3193
3194			WRW_HARPOON((port + SYNC_MSGS + 6),
3195				    (MPM_OP + AMSG_OUT + 50));
3196
3197		else
3198			WRW_HARPOON((port + SYNC_MSGS + 6),
3199				    (MPM_OP + AMSG_OUT + 00));
3200
3201		WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
3202		WRW_HARPOON((port + SYNC_MSGS + 10),
3203			    (MPM_OP + AMSG_OUT + DEFAULT_OFFSET));
3204		WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
3205
3206		if (syncFlag == 0) {
3207			WR_HARPOON(port + hp_autostart_3,
3208				   (SELECT + SELCHK_STRT));
3209			currTar_Info->TarStatus =
3210			    ((currTar_Info->
3211			      TarStatus & ~(unsigned char)TAR_SYNC_MASK) |
3212			     (unsigned char)SYNC_TRYING);
3213		} else {
3214			WR_HARPOON(port + hp_autostart_3,
3215				   (AUTO_IMMED + CMD_ONLY_STRT));
3216		}
3217
3218		return 1;
3219	}
3220
3221	else {
3222
3223		currTar_Info->TarStatus |= (unsigned char)SYNC_SUPPORTED;
3224		currTar_Info->TarEEValue &= ~EE_SYNC_MASK;
3225		return 0;
3226	}
3227}
3228
3229/*---------------------------------------------------------------------
3230 *
3231 * Function: FPT_stsyncn
3232 *
3233 * Description: The has sent us a Sync Nego message so handle it as
3234 *              necessary.
3235 *
3236 *---------------------------------------------------------------------*/
3237static void FPT_stsyncn(unsigned long port, unsigned char p_card)
3238{
3239	unsigned char sync_msg, offset, sync_reg, our_sync_msg;
3240	struct sccb *currSCCB;
3241	struct sccb_mgr_tar_info *currTar_Info;
3242
3243	currSCCB = FPT_BL_Card[p_card].currentSCCB;
3244	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
3245
3246	sync_msg = FPT_sfm(port, currSCCB);
3247
3248	if ((sync_msg == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3249		WR_HARPOON(port + hp_autostart_1,
3250			   (AUTO_IMMED + DISCONNECT_START));
3251		return;
3252	}
3253
3254	ACCEPT_MSG(port);
3255
3256	offset = FPT_sfm(port, currSCCB);
3257
3258	if ((offset == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3259		WR_HARPOON(port + hp_autostart_1,
3260			   (AUTO_IMMED + DISCONNECT_START));
3261		return;
3262	}
3263
3264	if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
3265
3266		our_sync_msg = 12;	/* Setup our Message to 20mb/s */
3267
3268	else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_10MB)
3269
3270		our_sync_msg = 25;	/* Setup our Message to 10mb/s */
3271
3272	else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_5MB)
3273
3274		our_sync_msg = 50;	/* Setup our Message to 5mb/s */
3275	else
3276
3277		our_sync_msg = 0;	/* Message = Async */
3278
3279	if (sync_msg < our_sync_msg) {
3280		sync_msg = our_sync_msg;	/*if faster, then set to max. */
3281	}
3282
3283	if (offset == ASYNC)
3284		sync_msg = ASYNC;
3285
3286	if (offset > MAX_OFFSET)
3287		offset = MAX_OFFSET;
3288
3289	sync_reg = 0x00;
3290
3291	if (sync_msg > 12)
3292
3293		sync_reg = 0x20;	/* Use 10MB/s */
3294
3295	if (sync_msg > 25)
3296
3297		sync_reg = 0x40;	/* Use 6.6MB/s */
3298
3299	if (sync_msg > 38)
3300
3301		sync_reg = 0x60;	/* Use 5MB/s */
3302
3303	if (sync_msg > 50)
3304
3305		sync_reg = 0x80;	/* Use 4MB/s */
3306
3307	if (sync_msg > 62)
3308
3309		sync_reg = 0xA0;	/* Use 3.33MB/s */
3310
3311	if (sync_msg > 75)
3312
3313		sync_reg = 0xC0;	/* Use 2.85MB/s */
3314
3315	if (sync_msg > 87)
3316
3317		sync_reg = 0xE0;	/* Use 2.5MB/s */
3318
3319	if (sync_msg > 100) {
3320
3321		sync_reg = 0x00;	/* Use ASYNC */
3322		offset = 0x00;
3323	}
3324
3325	if (currTar_Info->TarStatus & WIDE_ENABLED)
3326
3327		sync_reg |= offset;
3328
3329	else
3330
3331		sync_reg |= (offset | NARROW_SCSI);
3332
3333	FPT_sssyncv(port, currSCCB->TargID, sync_reg, currTar_Info);
3334
3335	if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
3336
3337		ACCEPT_MSG(port);
3338
3339		currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3340					    ~(unsigned char)TAR_SYNC_MASK) |
3341					   (unsigned char)SYNC_SUPPORTED);
3342
3343		WR_HARPOON(port + hp_autostart_1,
3344			   (AUTO_IMMED + DISCONNECT_START));
3345	}
3346
3347	else {
3348
3349		ACCEPT_MSG_ATN(port);
3350
3351		FPT_sisyncr(port, sync_msg, offset);
3352
3353		currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3354					    ~(unsigned char)TAR_SYNC_MASK) |
3355					   (unsigned char)SYNC_SUPPORTED);
3356	}
3357}
3358
3359/*---------------------------------------------------------------------
3360 *
3361 * Function: FPT_sisyncr
3362 *
3363 * Description: Answer the targets sync message.
3364 *
3365 *---------------------------------------------------------------------*/
3366static void FPT_sisyncr(unsigned long port, unsigned char sync_pulse,
3367			unsigned char offset)
3368{
3369	ARAM_ACCESS(port);
3370	WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT));
3371	WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
3372	WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMSYNC));
3373	WRW_HARPOON((port + SYNC_MSGS + 6), (MPM_OP + AMSG_OUT + sync_pulse));
3374	WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
3375	WRW_HARPOON((port + SYNC_MSGS + 10), (MPM_OP + AMSG_OUT + offset));
3376	WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
3377	SGRAM_ACCESS(port);
3378
3379	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3380	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
3381
3382	WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
3383
3384	while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
3385	}
3386}
3387
3388/*---------------------------------------------------------------------
3389 *
3390 * Function: FPT_siwidn
3391 *
3392 * Description: Read in a message byte from the SCSI bus, and check
3393 *              for a parity error.
3394 *
3395 *---------------------------------------------------------------------*/
3396
3397static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card)
3398{
3399	struct sccb *currSCCB;
3400	struct sccb_mgr_tar_info *currTar_Info;
3401
3402	currSCCB = FPT_BL_Card[p_card].currentSCCB;
3403	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
3404
3405	if (!((currTar_Info->TarStatus & TAR_WIDE_MASK) == WIDE_NEGOCIATED)) {
3406
3407		WRW_HARPOON((port + ID_MSG_STRT),
3408			    (MPM_OP + AMSG_OUT +
3409			     (currSCCB->
3410			      Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
3411
3412		WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
3413
3414		WRW_HARPOON((port + SYNC_MSGS + 0),
3415			    (MPM_OP + AMSG_OUT + SMEXT));
3416		WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
3417		WRW_HARPOON((port + SYNC_MSGS + 4),
3418			    (MPM_OP + AMSG_OUT + SMWDTR));
3419		WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
3420		WRW_HARPOON((port + SYNC_MSGS + 8),
3421			    (MPM_OP + AMSG_OUT + SM16BIT));
3422		WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
3423
3424		WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
3425
3426		currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3427					    ~(unsigned char)TAR_WIDE_MASK) |
3428					   (unsigned char)WIDE_ENABLED);
3429
3430		return 1;
3431	}
3432
3433	else {
3434
3435		currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3436					    ~(unsigned char)TAR_WIDE_MASK) |
3437					   WIDE_NEGOCIATED);
3438
3439		currTar_Info->TarEEValue &= ~EE_WIDE_SCSI;
3440		return 0;
3441	}
3442}
3443
3444/*---------------------------------------------------------------------
3445 *
3446 * Function: FPT_stwidn
3447 *
3448 * Description: The has sent us a Wide Nego message so handle it as
3449 *              necessary.
3450 *
3451 *---------------------------------------------------------------------*/
3452static void FPT_stwidn(unsigned long port, unsigned char p_card)
3453{
3454	unsigned char width;
3455	struct sccb *currSCCB;
3456	struct sccb_mgr_tar_info *currTar_Info;
3457
3458	currSCCB = FPT_BL_Card[p_card].currentSCCB;
3459	currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
3460
3461	width = FPT_sfm(port, currSCCB);
3462
3463	if ((width == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3464		WR_HARPOON(port + hp_autostart_1,
3465			   (AUTO_IMMED + DISCONNECT_START));
3466		return;
3467	}
3468
3469	if (!(currTar_Info->TarEEValue & EE_WIDE_SCSI))
3470		width = 0;
3471
3472	if (width) {
3473		currTar_Info->TarStatus |= WIDE_ENABLED;
3474		width = 0;
3475	} else {
3476		width = NARROW_SCSI;
3477		currTar_Info->TarStatus &= ~WIDE_ENABLED;
3478	}
3479
3480	FPT_sssyncv(port, currSCCB->TargID, width, currTar_Info);
3481
3482	if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
3483
3484		currTar_Info->TarStatus |= WIDE_NEGOCIATED;
3485
3486		if (!
3487		    ((currTar_Info->TarStatus & TAR_SYNC_MASK) ==
3488		     SYNC_SUPPORTED)) {
3489			ACCEPT_MSG_ATN(port);
3490			ARAM_ACCESS(port);
3491			FPT_sisyncn(port, p_card, 1);
3492			currSCCB->Sccb_scsistat = SELECT_SN_ST;
3493			SGRAM_ACCESS(port);
3494		} else {
3495			ACCEPT_MSG(port);
3496			WR_HARPOON(port + hp_autostart_1,
3497				   (AUTO_IMMED + DISCONNECT_START));
3498		}
3499	}
3500
3501	else {
3502
3503		ACCEPT_MSG_ATN(port);
3504
3505		if (currTar_Info->TarEEValue & EE_WIDE_SCSI)
3506			width = SM16BIT;
3507		else
3508			width = SM8BIT;
3509
3510		FPT_siwidr(port, width);
3511
3512		currTar_Info->TarStatus |= (WIDE_NEGOCIATED | WIDE_ENABLED);
3513	}
3514}
3515
3516/*---------------------------------------------------------------------
3517 *
3518 * Function: FPT_siwidr
3519 *
3520 * Description: Answer the targets Wide nego message.
3521 *
3522 *---------------------------------------------------------------------*/
3523static void FPT_siwidr(unsigned long port, unsigned char width)
3524{
3525	ARAM_ACCESS(port);
3526	WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT));
3527	WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
3528	WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMWDTR));
3529	WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
3530	WRW_HARPOON((port + SYNC_MSGS + 8), (MPM_OP + AMSG_OUT + width));
3531	WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
3532	SGRAM_ACCESS(port);
3533
3534	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3535	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
3536
3537	WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
3538
3539	while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
3540	}
3541}
3542
3543/*---------------------------------------------------------------------
3544 *
3545 * Function: FPT_sssyncv
3546 *
3547 * Description: Write the desired value to the Sync Register for the
3548 *              ID specified.
3549 *
3550 *---------------------------------------------------------------------*/
3551static void FPT_sssyncv(unsigned long p_port, unsigned char p_id,
3552			unsigned char p_sync_value,
3553			struct sccb_mgr_tar_info *currTar_Info)
3554{
3555	unsigned char index;
3556
3557	index = p_id;
3558
3559	switch (index) {
3560
3561	case 0:
3562		index = 12;	/* hp_synctarg_0 */
3563		break;
3564	case 1:
3565		index = 13;	/* hp_synctarg_1 */
3566		break;
3567	case 2:
3568		index = 14;	/* hp_synctarg_2 */
3569		break;
3570	case 3:
3571		index = 15;	/* hp_synctarg_3 */
3572		break;
3573	case 4:
3574		index = 8;	/* hp_synctarg_4 */
3575		break;
3576	case 5:
3577		index = 9;	/* hp_synctarg_5 */
3578		break;
3579	case 6:
3580		index = 10;	/* hp_synctarg_6 */
3581		break;
3582	case 7:
3583		index = 11;	/* hp_synctarg_7 */
3584		break;
3585	case 8:
3586		index = 4;	/* hp_synctarg_8 */
3587		break;
3588	case 9:
3589		index = 5;	/* hp_synctarg_9 */
3590		break;
3591	case 10:
3592		index = 6;	/* hp_synctarg_10 */
3593		break;
3594	case 11:
3595		index = 7;	/* hp_synctarg_11 */
3596		break;
3597	case 12:
3598		index = 0;	/* hp_synctarg_12 */
3599		break;
3600	case 13:
3601		index = 1;	/* hp_synctarg_13 */
3602		break;
3603	case 14:
3604		index = 2;	/* hp_synctarg_14 */
3605		break;
3606	case 15:
3607		index = 3;	/* hp_synctarg_15 */
3608
3609	}
3610
3611	WR_HARPOON(p_port + hp_synctarg_base + index, p_sync_value);
3612
3613	currTar_Info->TarSyncCtrl = p_sync_value;
3614}
3615
3616/*---------------------------------------------------------------------
3617 *
3618 * Function: FPT_sresb
3619 *
3620 * Description: Reset the desired card's SCSI bus.
3621 *
3622 *---------------------------------------------------------------------*/
3623static void FPT_sresb(unsigned long port, unsigned char p_card)
3624{
3625	unsigned char scsiID, i;
3626
3627	struct sccb_mgr_tar_info *currTar_Info;
3628
3629	WR_HARPOON(port + hp_page_ctrl,
3630		   (RD_HARPOON(port + hp_page_ctrl) | G_INT_DISABLE));
3631	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
3632
3633	WR_HARPOON(port + hp_scsictrl_0, SCSI_RST);
3634
3635	scsiID = RD_HARPOON(port + hp_seltimeout);
3636	WR_HARPOON(port + hp_seltimeout, TO_5ms);
3637	WRW_HARPOON((port + hp_intstat), TIMEOUT);
3638
3639	WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT | START_TO));
3640
3641	while (!(RDW_HARPOON((port + hp_intstat)) & TIMEOUT)) {
3642	}
3643
3644	WR_HARPOON(port + hp_seltimeout, scsiID);
3645
3646	WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
3647
3648	FPT_Wait(port, TO_5ms);
3649
3650	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
3651
3652	WR_HARPOON(port + hp_int_mask, (RD_HARPOON(port + hp_int_mask) | 0x00));
3653
3654	for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
3655		currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
3656
3657		if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
3658			currTar_Info->TarSyncCtrl = 0;
3659			currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
3660		}
3661
3662		if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
3663			currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
3664		}
3665
3666		FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
3667
3668		FPT_SccbMgrTableInitTarget(p_card, scsiID);
3669	}
3670
3671	FPT_BL_Card[p_card].scanIndex = 0x00;
3672	FPT_BL_Card[p_card].currentSCCB = NULL;
3673	FPT_BL_Card[p_card].globalFlags &= ~(F_TAG_STARTED | F_HOST_XFER_ACT
3674					     | F_NEW_SCCB_CMD);
3675	FPT_BL_Card[p_card].cmdCounter = 0x00;
3676	FPT_BL_Card[p_card].discQCount = 0x00;
3677	FPT_BL_Card[p_card].tagQ_Lst = 0x01;
3678
3679	for (i = 0; i < QUEUE_DEPTH; i++)
3680		FPT_BL_Card[p_card].discQ_Tbl[i] = NULL;
3681
3682	WR_HARPOON(port + hp_page_ctrl,
3683		   (RD_HARPOON(port + hp_page_ctrl) & ~G_INT_DISABLE));
3684
3685}
3686
3687/*---------------------------------------------------------------------
3688 *
3689 * Function: FPT_ssenss
3690 *
3691 * Description: Setup for the Auto Sense command.
3692 *
3693 *---------------------------------------------------------------------*/
3694static void FPT_ssenss(struct sccb_card *pCurrCard)
3695{
3696	unsigned char i;
3697	struct sccb *currSCCB;
3698
3699	currSCCB = pCurrCard->currentSCCB;
3700
3701	currSCCB->Save_CdbLen = currSCCB->CdbLength;
3702
3703	for (i = 0; i < 6; i++) {
3704
3705		currSCCB->Save_Cdb[i] = currSCCB->Cdb[i];
3706	}
3707
3708	currSCCB->CdbLength = SIX_BYTE_CMD;
3709	currSCCB->Cdb[0] = SCSI_REQUEST_SENSE;
3710	currSCCB->Cdb[1] = currSCCB->Cdb[1] & (unsigned char)0xE0;	/*Keep LUN. */
3711	currSCCB->Cdb[2] = 0x00;
3712	currSCCB->Cdb[3] = 0x00;
3713	currSCCB->Cdb[4] = currSCCB->RequestSenseLength;
3714	currSCCB->Cdb[5] = 0x00;
3715
3716	currSCCB->Sccb_XferCnt = (unsigned long)currSCCB->RequestSenseLength;
3717
3718	currSCCB->Sccb_ATC = 0x00;
3719
3720	currSCCB->Sccb_XferState |= F_AUTO_SENSE;
3721
3722	currSCCB->Sccb_XferState &= ~F_SG_XFER;
3723
3724	currSCCB->Sccb_idmsg = currSCCB->Sccb_idmsg & ~(unsigned char)DISC_PRIV;
3725
3726	currSCCB->ControlByte = 0x00;
3727
3728	currSCCB->Sccb_MGRFlags &= F_STATUSLOADED;
3729}
3730
3731/*---------------------------------------------------------------------
3732 *
3733 * Function: FPT_sxfrp
3734 *
3735 * Description: Transfer data into the bit bucket until the device
3736 *              decides to switch phase.
3737 *
3738 *---------------------------------------------------------------------*/
3739
3740static void FPT_sxfrp(unsigned long p_port, unsigned char p_card)
3741{
3742	unsigned char curr_phz;
3743
3744	DISABLE_AUTO(p_port);
3745
3746	if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
3747
3748		FPT_hostDataXferAbort(p_port, p_card,
3749				      FPT_BL_Card[p_card].currentSCCB);
3750
3751	}
3752
3753	/* If the Automation handled the end of the transfer then do not
3754	   match the phase or we will get out of sync with the ISR.       */
3755
3756	if (RDW_HARPOON((p_port + hp_intstat)) &
3757	    (BUS_FREE | XFER_CNT_0 | AUTO_INT))
3758		return;
3759
3760	WR_HARPOON(p_port + hp_xfercnt_0, 0x00);
3761
3762	curr_phz = RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ;
3763
3764	WRW_HARPOON((p_port + hp_intstat), XFER_CNT_0);
3765
3766	WR_HARPOON(p_port + hp_scsisig, curr_phz);
3767
3768	while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET)) &&
3769	       (curr_phz ==
3770		(RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ)))
3771	{
3772		if (curr_phz & (unsigned char)SCSI_IOBIT) {
3773			WR_HARPOON(p_port + hp_portctrl_0,
3774				   (SCSI_PORT | HOST_PORT | SCSI_INBIT));
3775
3776			if (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
3777				RD_HARPOON(p_port + hp_fifodata_0);
3778			}
3779		} else {
3780			WR_HARPOON(p_port + hp_portctrl_0,
3781				   (SCSI_PORT | HOST_PORT | HOST_WRT));
3782			if (RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY) {
3783				WR_HARPOON(p_port + hp_fifodata_0, 0xFA);
3784			}
3785		}
3786	}			/* End of While loop for padding data I/O phase */
3787
3788	while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
3789		if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ)
3790			break;
3791	}
3792
3793	WR_HARPOON(p_port + hp_portctrl_0,
3794		   (SCSI_PORT | HOST_PORT | SCSI_INBIT));
3795	while (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
3796		RD_HARPOON(p_port + hp_fifodata_0);
3797	}
3798
3799	if (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
3800		WR_HARPOON(p_port + hp_autostart_0,
3801			   (AUTO_IMMED + DISCONNECT_START));
3802		while (!(RDW_HARPOON((p_port + hp_intstat)) & AUTO_INT)) {
3803		}
3804
3805		if (RDW_HARPOON((p_port + hp_intstat)) &
3806		    (ICMD_COMP | ITAR_DISC))
3807			while (!
3808			       (RDW_HARPOON((p_port + hp_intstat)) &
3809				(BUS_FREE | RSEL))) ;
3810	}
3811}
3812
3813/*---------------------------------------------------------------------
3814 *
3815 * Function: FPT_schkdd
3816 *
3817 * Description: Make sure data has been flushed from both FIFOs and abort
3818 *              the operations if necessary.
3819 *
3820 *---------------------------------------------------------------------*/
3821
3822static void FPT_schkdd(unsigned long port, unsigned char p_card)
3823{
3824	unsigned short TimeOutLoop;
3825	unsigned char sPhase;
3826
3827	struct sccb *currSCCB;
3828
3829	currSCCB = FPT_BL_Card[p_card].currentSCCB;
3830
3831	if ((currSCCB->Sccb_scsistat != DATA_OUT_ST) &&
3832	    (currSCCB->Sccb_scsistat != DATA_IN_ST)) {
3833		return;
3834	}
3835
3836	if (currSCCB->Sccb_XferState & F_ODD_BALL_CNT) {
3837
3838		currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - 1);
3839
3840		currSCCB->Sccb_XferCnt = 1;
3841
3842		currSCCB->Sccb_XferState &= ~F_ODD_BALL_CNT;
3843		WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
3844		WR_HARPOON(port + hp_xferstat, 0x00);
3845	}
3846
3847	else {
3848
3849		currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
3850
3851		currSCCB->Sccb_XferCnt = 0;
3852	}
3853
3854	if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
3855	    (currSCCB->HostStatus == SCCB_COMPLETE)) {
3856
3857		currSCCB->HostStatus = SCCB_PARITY_ERR;
3858		WRW_HARPOON((port + hp_intstat), PARITY);
3859	}
3860
3861	FPT_hostDataXferAbort(port, p_card, currSCCB);
3862
3863	while (RD_HARPOON(port + hp_scsisig) & SCSI_ACK) {
3864	}
3865
3866	TimeOutLoop = 0;
3867
3868	while (RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY) {
3869		if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
3870			return;
3871		}
3872		if (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) {
3873			break;
3874		}
3875		if (RDW_HARPOON((port + hp_intstat)) & RESET) {
3876			return;
3877		}
3878		if ((RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
3879		    || (TimeOutLoop++ > 0x3000))
3880			break;
3881	}
3882
3883	sPhase = RD_HARPOON(port + hp_scsisig) & (SCSI_BSY | S_SCSI_PHZ);
3884	if ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) ||
3885	    (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) ||
3886	    (sPhase == (SCSI_BSY | S_DATAO_PH)) ||
3887	    (sPhase == (SCSI_BSY | S_DATAI_PH))) {
3888
3889		WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3890
3891		if (!(currSCCB->Sccb_XferState & F_ALL_XFERRED)) {
3892			if (currSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
3893				FPT_phaseDataIn(port, p_card);
3894			}
3895
3896			else {
3897				FPT_phaseDataOut(port, p_card);
3898			}
3899		} else {
3900			FPT_sxfrp(port, p_card);
3901			if (!(RDW_HARPOON((port + hp_intstat)) &
3902			      (BUS_FREE | ICMD_COMP | ITAR_DISC | RESET))) {
3903				WRW_HARPOON((port + hp_intstat), AUTO_INT);
3904				FPT_phaseDecode(port, p_card);
3905			}
3906		}
3907
3908	}
3909
3910	else {
3911		WR_HARPOON(port + hp_portctrl_0, 0x00);
3912	}
3913}
3914
3915/*---------------------------------------------------------------------
3916 *
3917 * Function: FPT_sinits
3918 *
3919 * Description: Setup SCCB manager fields in this SCCB.
3920 *
3921 *---------------------------------------------------------------------*/
3922
3923static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card)
3924{
3925	struct sccb_mgr_tar_info *currTar_Info;
3926
3927	if ((p_sccb->TargID >= MAX_SCSI_TAR) || (p_sccb->Lun >= MAX_LUN)) {
3928		return;
3929	}
3930	currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
3931
3932	p_sccb->Sccb_XferState = 0x00;
3933	p_sccb->Sccb_XferCnt = p_sccb->DataLength;
3934
3935	if ((p_sccb->OperationCode == SCATTER_GATHER_COMMAND) ||
3936	    (p_sccb->OperationCode == RESIDUAL_SG_COMMAND)) {
3937
3938		p_sccb->Sccb_SGoffset = 0;
3939		p_sccb->Sccb_XferState = F_SG_XFER;
3940		p_sccb->Sccb_XferCnt = 0x00;
3941	}
3942
3943	if (p_sccb->DataLength == 0x00)
3944
3945		p_sccb->Sccb_XferState |= F_ALL_XFERRED;
3946
3947	if (p_sccb->ControlByte & F_USE_CMD_Q) {
3948		if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
3949			p_sccb->ControlByte &= ~F_USE_CMD_Q;
3950
3951		else
3952			currTar_Info->TarStatus |= TAG_Q_TRYING;
3953	}
3954
3955/*      For !single SCSI device in system  & device allow Disconnect
3956	or command is tag_q type then send Cmd with Disconnect Enable
3957	else send Cmd with Disconnect Disable */
3958
3959/*
3960   if (((!(FPT_BL_Card[p_card].globalFlags & F_SINGLE_DEVICE)) &&
3961      (currTar_Info->TarStatus & TAR_ALLOW_DISC)) ||
3962      (currTar_Info->TarStatus & TAG_Q_TRYING)) {
3963*/
3964	if ((currTar_Info->TarStatus & TAR_ALLOW_DISC) ||
3965	    (currTar_Info->TarStatus & TAG_Q_TRYING)) {
3966		p_sccb->Sccb_idmsg =
3967		    (unsigned char)(SMIDENT | DISC_PRIV) | p_sccb->Lun;
3968	}
3969
3970	else {
3971
3972		p_sccb->Sccb_idmsg = (unsigned char)SMIDENT | p_sccb->Lun;
3973	}
3974
3975	p_sccb->HostStatus = 0x00;
3976	p_sccb->TargetStatus = 0x00;
3977	p_sccb->Sccb_tag = 0x00;
3978	p_sccb->Sccb_MGRFlags = 0x00;
3979	p_sccb->Sccb_sgseg = 0x00;
3980	p_sccb->Sccb_ATC = 0x00;
3981	p_sccb->Sccb_savedATC = 0x00;
3982/*
3983   p_sccb->SccbVirtDataPtr    = 0x00;
3984   p_sccb->Sccb_forwardlink   = NULL;
3985   p_sccb->Sccb_backlink      = NULL;
3986 */
3987	p_sccb->Sccb_scsistat = BUS_FREE_ST;
3988	p_sccb->SccbStatus = SCCB_IN_PROCESS;
3989	p_sccb->Sccb_scsimsg = SMNO_OP;
3990
3991}
3992
3993/*---------------------------------------------------------------------
3994 *
3995 * Function: Phase Decode
3996 *
3997 * Description: Determine the phase and call the appropriate function.
3998 *
3999 *---------------------------------------------------------------------*/
4000
4001static void FPT_phaseDecode(unsigned long p_port, unsigned char p_card)
4002{
4003	unsigned char phase_ref;
4004	void (*phase) (unsigned long, unsigned char);
4005
4006	DISABLE_AUTO(p_port);
4007
4008	phase_ref =
4009	    (unsigned char)(RD_HARPOON(p_port + hp_scsisig) & S_SCSI_PHZ);
4010
4011	phase = FPT_s_PhaseTbl[phase_ref];
4012
4013	(*phase) (p_port, p_card);	/* Call the correct phase func */
4014}
4015
4016/*---------------------------------------------------------------------
4017 *
4018 * Function: Data Out Phase
4019 *
4020 * Description: Start up both the BusMaster and Xbow.
4021 *
4022 *---------------------------------------------------------------------*/
4023
4024static void FPT_phaseDataOut(unsigned long port, unsigned char p_card)
4025{
4026
4027	struct sccb *currSCCB;
4028
4029	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4030	if (currSCCB == NULL) {
4031		return;		/* Exit if No SCCB record */
4032	}
4033
4034	currSCCB->Sccb_scsistat = DATA_OUT_ST;
4035	currSCCB->Sccb_XferState &= ~(F_HOST_XFER_DIR | F_NO_DATA_YET);
4036
4037	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
4038
4039	WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
4040
4041	WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
4042
4043	FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
4044
4045	if (currSCCB->Sccb_XferCnt == 0) {
4046
4047		if ((currSCCB->ControlByte & SCCB_DATA_XFER_OUT) &&
4048		    (currSCCB->HostStatus == SCCB_COMPLETE))
4049			currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
4050
4051		FPT_sxfrp(port, p_card);
4052		if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
4053			FPT_phaseDecode(port, p_card);
4054	}
4055}
4056
4057/*---------------------------------------------------------------------
4058 *
4059 * Function: Data In Phase
4060 *
4061 * Description: Startup the BusMaster and the XBOW.
4062 *
4063 *---------------------------------------------------------------------*/
4064
4065static void FPT_phaseDataIn(unsigned long port, unsigned char p_card)
4066{
4067
4068	struct sccb *currSCCB;
4069
4070	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4071
4072	if (currSCCB == NULL) {
4073		return;		/* Exit if No SCCB record */
4074	}
4075
4076	currSCCB->Sccb_scsistat = DATA_IN_ST;
4077	currSCCB->Sccb_XferState |= F_HOST_XFER_DIR;
4078	currSCCB->Sccb_XferState &= ~F_NO_DATA_YET;
4079
4080	WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
4081
4082	WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
4083
4084	WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
4085
4086	FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
4087
4088	if (currSCCB->Sccb_XferCnt == 0) {
4089
4090		if ((currSCCB->ControlByte & SCCB_DATA_XFER_IN) &&
4091		    (currSCCB->HostStatus == SCCB_COMPLETE))
4092			currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
4093
4094		FPT_sxfrp(port, p_card);
4095		if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
4096			FPT_phaseDecode(port, p_card);
4097
4098	}
4099}
4100
4101/*---------------------------------------------------------------------
4102 *
4103 * Function: Command Phase
4104 *
4105 * Description: Load the CDB into the automation and start it up.
4106 *
4107 *---------------------------------------------------------------------*/
4108
4109static void FPT_phaseCommand(unsigned long p_port, unsigned char p_card)
4110{
4111	struct sccb *currSCCB;
4112	unsigned long cdb_reg;
4113	unsigned char i;
4114
4115	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4116
4117	if (currSCCB->OperationCode == RESET_COMMAND) {
4118
4119		currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4120		currSCCB->CdbLength = SIX_BYTE_CMD;
4121	}
4122
4123	WR_HARPOON(p_port + hp_scsisig, 0x00);
4124
4125	ARAM_ACCESS(p_port);
4126
4127	cdb_reg = p_port + CMD_STRT;
4128
4129	for (i = 0; i < currSCCB->CdbLength; i++) {
4130
4131		if (currSCCB->OperationCode == RESET_COMMAND)
4132
4133			WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + 0x00));
4134
4135		else
4136			WRW_HARPOON(cdb_reg,
4137				    (MPM_OP + ACOMMAND + currSCCB->Cdb[i]));
4138		cdb_reg += 2;
4139	}
4140
4141	if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
4142		WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
4143
4144	WR_HARPOON(p_port + hp_portctrl_0, (SCSI_PORT));
4145
4146	currSCCB->Sccb_scsistat = COMMAND_ST;
4147
4148	WR_HARPOON(p_port + hp_autostart_3, (AUTO_IMMED | CMD_ONLY_STRT));
4149	SGRAM_ACCESS(p_port);
4150}
4151
4152/*---------------------------------------------------------------------
4153 *
4154 * Function: Status phase
4155 *
4156 * Description: Bring in the status and command complete message bytes
4157 *
4158 *---------------------------------------------------------------------*/
4159
4160static void FPT_phaseStatus(unsigned long port, unsigned char p_card)
4161{
4162	/* Start-up the automation to finish off this command and let the
4163	   isr handle the interrupt for command complete when it comes in.
4164	   We could wait here for the interrupt to be generated?
4165	 */
4166
4167	WR_HARPOON(port + hp_scsisig, 0x00);
4168
4169	WR_HARPOON(port + hp_autostart_0, (AUTO_IMMED + END_DATA_START));
4170}
4171
4172/*---------------------------------------------------------------------
4173 *
4174 * Function: Phase Message Out
4175 *
4176 * Description: Send out our message (if we have one) and handle whatever
4177 *              else is involed.
4178 *
4179 *---------------------------------------------------------------------*/
4180
4181static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card)
4182{
4183	unsigned char message, scsiID;
4184	struct sccb *currSCCB;
4185	struct sccb_mgr_tar_info *currTar_Info;
4186
4187	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4188
4189	if (currSCCB != NULL) {
4190
4191		message = currSCCB->Sccb_scsimsg;
4192		scsiID = currSCCB->TargID;
4193
4194		if (message == SMDEV_RESET) {
4195
4196			currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
4197			currTar_Info->TarSyncCtrl = 0;
4198			FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
4199
4200			if (FPT_sccbMgrTbl[p_card][scsiID].
4201			    TarEEValue & EE_SYNC_MASK) {
4202
4203				FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
4204				    ~TAR_SYNC_MASK;
4205
4206			}
4207
4208			if (FPT_sccbMgrTbl[p_card][scsiID].
4209			    TarEEValue & EE_WIDE_SCSI) {
4210
4211				FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
4212				    ~TAR_WIDE_MASK;
4213			}
4214
4215			FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
4216			FPT_SccbMgrTableInitTarget(p_card, scsiID);
4217		} else if (currSCCB->Sccb_scsistat == ABORT_ST) {
4218			currSCCB->HostStatus = SCCB_COMPLETE;
4219			if (FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] !=
4220			    NULL) {
4221				FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4222							      Sccb_tag] = NULL;
4223				FPT_sccbMgrTbl[p_card][scsiID].TarTagQ_Cnt--;
4224			}
4225
4226		}
4227
4228		else if (currSCCB->Sccb_scsistat < COMMAND_ST) {
4229
4230			if (message == SMNO_OP) {
4231				currSCCB->Sccb_MGRFlags |= F_DEV_SELECTED;
4232
4233				FPT_ssel(port, p_card);
4234				return;
4235			}
4236		} else {
4237
4238			if (message == SMABORT)
4239
4240				FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
4241		}
4242
4243	} else {
4244		message = SMABORT;
4245	}
4246
4247	WRW_HARPOON((port + hp_intstat), (BUS_FREE | PHASE | XFER_CNT_0));
4248
4249	WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
4250
4251	WR_HARPOON(port + hp_scsidata_0, message);
4252
4253	WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
4254
4255	ACCEPT_MSG(port);
4256
4257	WR_HARPOON(port + hp_portctrl_0, 0x00);
4258
4259	if ((message == SMABORT) || (message == SMDEV_RESET) ||
4260	    (message == SMABORT_TAG)) {
4261
4262		while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | PHASE))) {
4263		}
4264
4265		if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
4266			WRW_HARPOON((port + hp_intstat), BUS_FREE);
4267
4268			if (currSCCB != NULL) {
4269
4270				if ((FPT_BL_Card[p_card].
4271				     globalFlags & F_CONLUN_IO)
4272				    &&
4273				    ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4274				      TarStatus & TAR_TAG_Q_MASK) !=
4275				     TAG_Q_TRYING))
4276					FPT_sccbMgrTbl[p_card][currSCCB->
4277							       TargID].
4278					    TarLUNBusy[currSCCB->Lun] = 0;
4279				else
4280					FPT_sccbMgrTbl[p_card][currSCCB->
4281							       TargID].
4282					    TarLUNBusy[0] = 0;
4283
4284				FPT_queueCmdComplete(&FPT_BL_Card[p_card],
4285						     currSCCB, p_card);
4286			}
4287
4288			else {
4289				FPT_BL_Card[p_card].globalFlags |=
4290				    F_NEW_SCCB_CMD;
4291			}
4292		}
4293
4294		else {
4295
4296			FPT_sxfrp(port, p_card);
4297		}
4298	}
4299
4300	else {
4301
4302		if (message == SMPARITY) {
4303			currSCCB->Sccb_scsimsg = SMNO_OP;
4304			WR_HARPOON(port + hp_autostart_1,
4305				   (AUTO_IMMED + DISCONNECT_START));
4306		} else {
4307			FPT_sxfrp(port, p_card);
4308		}
4309	}
4310}
4311
4312/*---------------------------------------------------------------------
4313 *
4314 * Function: Message In phase
4315 *
4316 * Description: Bring in the message and determine what to do with it.
4317 *
4318 *---------------------------------------------------------------------*/
4319
4320static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card)
4321{
4322	unsigned char message;
4323	struct sccb *currSCCB;
4324
4325	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4326
4327	if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
4328
4329		FPT_phaseChkFifo(port, p_card);
4330	}
4331
4332	message = RD_HARPOON(port + hp_scsidata_0);
4333	if ((message == SMDISC) || (message == SMSAVE_DATA_PTR)) {
4334
4335		WR_HARPOON(port + hp_autostart_1,
4336			   (AUTO_IMMED + END_DATA_START));
4337
4338	}
4339
4340	else {
4341
4342		message = FPT_sfm(port, currSCCB);
4343		if (message) {
4344
4345			FPT_sdecm(message, port, p_card);
4346
4347		} else {
4348			if (currSCCB->Sccb_scsimsg != SMPARITY)
4349				ACCEPT_MSG(port);
4350			WR_HARPOON(port + hp_autostart_1,
4351				   (AUTO_IMMED + DISCONNECT_START));
4352		}
4353	}
4354
4355}
4356
4357/*---------------------------------------------------------------------
4358 *
4359 * Function: Illegal phase
4360 *
4361 * Description: Target switched to some illegal phase, so all we can do
4362 *              is report an error back to the host (if that is possible)
4363 *              and send an ABORT message to the misbehaving target.
4364 *
4365 *---------------------------------------------------------------------*/
4366
4367static void FPT_phaseIllegal(unsigned long port, unsigned char p_card)
4368{
4369	struct sccb *currSCCB;
4370
4371	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4372
4373	WR_HARPOON(port + hp_scsisig, RD_HARPOON(port + hp_scsisig));
4374	if (currSCCB != NULL) {
4375
4376		currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4377		currSCCB->Sccb_scsistat = ABORT_ST;
4378		currSCCB->Sccb_scsimsg = SMABORT;
4379	}
4380
4381	ACCEPT_MSG_ATN(port);
4382}
4383
4384/*---------------------------------------------------------------------
4385 *
4386 * Function: Phase Check FIFO
4387 *
4388 * Description: Make sure data has been flushed from both FIFOs and abort
4389 *              the operations if necessary.
4390 *
4391 *---------------------------------------------------------------------*/
4392
4393static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card)
4394{
4395	unsigned long xfercnt;
4396	struct sccb *currSCCB;
4397
4398	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4399
4400	if (currSCCB->Sccb_scsistat == DATA_IN_ST) {
4401
4402		while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) &&
4403		       (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)) {
4404		}
4405
4406		if (!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) {
4407			currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
4408
4409			currSCCB->Sccb_XferCnt = 0;
4410
4411			if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
4412			    (currSCCB->HostStatus == SCCB_COMPLETE)) {
4413				currSCCB->HostStatus = SCCB_PARITY_ERR;
4414				WRW_HARPOON((port + hp_intstat), PARITY);
4415			}
4416
4417			FPT_hostDataXferAbort(port, p_card, currSCCB);
4418
4419			FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
4420
4421			while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY))
4422			       && (RD_HARPOON(port + hp_ext_status) &
4423				   BM_CMD_BUSY)) {
4424			}
4425
4426		}
4427	}
4428
4429	/*End Data In specific code. */
4430	GET_XFER_CNT(port, xfercnt);
4431
4432	WR_HARPOON(port + hp_xfercnt_0, 0x00);
4433
4434	WR_HARPOON(port + hp_portctrl_0, 0x00);
4435
4436	currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - xfercnt);
4437
4438	currSCCB->Sccb_XferCnt = xfercnt;
4439
4440	if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
4441	    (currSCCB->HostStatus == SCCB_COMPLETE)) {
4442
4443		currSCCB->HostStatus = SCCB_PARITY_ERR;
4444		WRW_HARPOON((port + hp_intstat), PARITY);
4445	}
4446
4447	FPT_hostDataXferAbort(port, p_card, currSCCB);
4448
4449	WR_HARPOON(port + hp_fifowrite, 0x00);
4450	WR_HARPOON(port + hp_fiforead, 0x00);
4451	WR_HARPOON(port + hp_xferstat, 0x00);
4452
4453	WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
4454}
4455
4456/*---------------------------------------------------------------------
4457 *
4458 * Function: Phase Bus Free
4459 *
4460 * Description: We just went bus free so figure out if it was
4461 *              because of command complete or from a disconnect.
4462 *
4463 *---------------------------------------------------------------------*/
4464static void FPT_phaseBusFree(unsigned long port, unsigned char p_card)
4465{
4466	struct sccb *currSCCB;
4467
4468	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4469
4470	if (currSCCB != NULL) {
4471
4472		DISABLE_AUTO(port);
4473
4474		if (currSCCB->OperationCode == RESET_COMMAND) {
4475
4476			if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4477			    ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4478			      TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4479				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4480				    TarLUNBusy[currSCCB->Lun] = 0;
4481			else
4482				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4483				    TarLUNBusy[0] = 0;
4484
4485			FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
4486					     p_card);
4487
4488			FPT_queueSearchSelect(&FPT_BL_Card[p_card], p_card);
4489
4490		}
4491
4492		else if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
4493			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4494			    (unsigned char)SYNC_SUPPORTED;
4495			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4496			    ~EE_SYNC_MASK;
4497		}
4498
4499		else if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
4500			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
4501			    (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4502			     TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
4503
4504			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4505			    ~EE_WIDE_SCSI;
4506		}
4507
4508		else if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
4509			/* Make sure this is not a phony BUS_FREE.  If we were
4510			   reselected or if BUSY is NOT on then this is a
4511			   valid BUS FREE.  SRR Wednesday, 5/10/1995.     */
4512
4513			if ((!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ||
4514			    (RDW_HARPOON((port + hp_intstat)) & RSEL)) {
4515				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4516				    TarStatus &= ~TAR_TAG_Q_MASK;
4517				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4518				    TarStatus |= TAG_Q_REJECT;
4519			}
4520
4521			else {
4522				return;
4523			}
4524		}
4525
4526		else {
4527
4528			currSCCB->Sccb_scsistat = BUS_FREE_ST;
4529
4530			if (!currSCCB->HostStatus) {
4531				currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4532			}
4533
4534			if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4535			    ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4536			      TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4537				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4538				    TarLUNBusy[currSCCB->Lun] = 0;
4539			else
4540				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4541				    TarLUNBusy[0] = 0;
4542
4543			FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
4544					     p_card);
4545			return;
4546		}
4547
4548		FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
4549
4550	}			/*end if !=null */
4551}
4552
4553/*---------------------------------------------------------------------
4554 *
4555 * Function: Auto Load Default Map
4556 *
4557 * Description: Load the Automation RAM with the defualt map values.
4558 *
4559 *---------------------------------------------------------------------*/
4560static void FPT_autoLoadDefaultMap(unsigned long p_port)
4561{
4562	unsigned long map_addr;
4563
4564	ARAM_ACCESS(p_port);
4565	map_addr = p_port + hp_aramBase;
4566
4567	WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0xC0));	/*ID MESSAGE */
4568	map_addr += 2;
4569	WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x20));	/*SIMPLE TAG QUEUEING MSG */
4570	map_addr += 2;
4571	WRW_HARPOON(map_addr, RAT_OP);	/*RESET ATTENTION */
4572	map_addr += 2;
4573	WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x00));	/*TAG ID MSG */
4574	map_addr += 2;
4575	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 0 */
4576	map_addr += 2;
4577	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 1 */
4578	map_addr += 2;
4579	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 2 */
4580	map_addr += 2;
4581	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 3 */
4582	map_addr += 2;
4583	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 4 */
4584	map_addr += 2;
4585	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 5 */
4586	map_addr += 2;
4587	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 6 */
4588	map_addr += 2;
4589	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 7 */
4590	map_addr += 2;
4591	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 8 */
4592	map_addr += 2;
4593	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 9 */
4594	map_addr += 2;
4595	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 10 */
4596	map_addr += 2;
4597	WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00));	/*CDB BYTE 11 */
4598	map_addr += 2;
4599	WRW_HARPOON(map_addr, (CPE_OP + ADATA_OUT + DINT));	/*JUMP IF DATA OUT */
4600	map_addr += 2;
4601	WRW_HARPOON(map_addr, (TCB_OP + FIFO_0 + DI));	/*JUMP IF NO DATA IN FIFO */
4602	map_addr += 2;		/*This means AYNC DATA IN */
4603	WRW_HARPOON(map_addr, (SSI_OP + SSI_IDO_STRT));	/*STOP AND INTERRUPT */
4604	map_addr += 2;
4605	WRW_HARPOON(map_addr, (CPE_OP + ADATA_IN + DINT));	/*JUMP IF NOT DATA IN PHZ */
4606	map_addr += 2;
4607	WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST));	/*IF NOT MSG IN CHECK 4 DATA IN */
4608	map_addr += 2;
4609	WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x02));	/*SAVE DATA PTR MSG? */
4610	map_addr += 2;
4611	WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + DC));	/*GO CHECK FOR DISCONNECT MSG */
4612	map_addr += 2;
4613	WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR1));	/*SAVE DATA PTRS MSG */
4614	map_addr += 2;
4615	WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST));	/*IF NOT MSG IN CHECK DATA IN */
4616	map_addr += 2;
4617	WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x04));	/*DISCONNECT MSG? */
4618	map_addr += 2;
4619	WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + UNKNWN));	/*UKNKNOWN MSG */
4620	map_addr += 2;
4621	WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET));	/*XFER DISCONNECT MSG */
4622	map_addr += 2;
4623	WRW_HARPOON(map_addr, (SSI_OP + SSI_ITAR_DISC));	/*STOP AND INTERRUPT */
4624	map_addr += 2;
4625	WRW_HARPOON(map_addr, (CPN_OP + ASTATUS + UNKNWN));	/*JUMP IF NOT STATUS PHZ. */
4626	map_addr += 2;
4627	WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR0));	/*GET STATUS BYTE */
4628	map_addr += 2;
4629	WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + CC));	/*ERROR IF NOT MSG IN PHZ */
4630	map_addr += 2;
4631	WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x00));	/*CHECK FOR CMD COMPLETE MSG. */
4632	map_addr += 2;
4633	WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + CC));	/*ERROR IF NOT CMD COMPLETE MSG. */
4634	map_addr += 2;
4635	WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET));	/*GET CMD COMPLETE MSG */
4636	map_addr += 2;
4637	WRW_HARPOON(map_addr, (SSI_OP + SSI_ICMD_COMP));	/*END OF COMMAND */
4638	map_addr += 2;
4639
4640	WRW_HARPOON(map_addr, (SSI_OP + SSI_IUNKWN));	/*RECEIVED UNKNOWN MSG BYTE */
4641	map_addr += 2;
4642	WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC));	/*NO COMMAND COMPLETE AFTER STATUS */
4643	map_addr += 2;
4644	WRW_HARPOON(map_addr, (SSI_OP + SSI_ITICKLE));	/*BIOS Tickled the Mgr */
4645	map_addr += 2;
4646	WRW_HARPOON(map_addr, (SSI_OP + SSI_IRFAIL));	/*EXPECTED ID/TAG MESSAGES AND */
4647	map_addr += 2;		/* DIDN'T GET ONE */
4648	WRW_HARPOON(map_addr, (CRR_OP + AR3 + S_IDREG));	/* comp SCSI SEL ID & AR3 */
4649	map_addr += 2;
4650	WRW_HARPOON(map_addr, (BRH_OP + EQUAL + 0x00));	/*SEL ID OK then Conti. */
4651	map_addr += 2;
4652	WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC));	/*NO COMMAND COMPLETE AFTER STATUS */
4653
4654	SGRAM_ACCESS(p_port);
4655}
4656
4657/*---------------------------------------------------------------------
4658 *
4659 * Function: Auto Command Complete
4660 *
4661 * Description: Post command back to host and find another command
4662 *              to execute.
4663 *
4664 *---------------------------------------------------------------------*/
4665
4666static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card)
4667{
4668	struct sccb *currSCCB;
4669	unsigned char status_byte;
4670
4671	currSCCB = FPT_BL_Card[p_card].currentSCCB;
4672
4673	status_byte = RD_HARPOON(p_port + hp_gp_reg_0);
4674
4675	FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA = 0;
4676
4677	if (status_byte != SSGOOD) {
4678
4679		if (status_byte == SSQ_FULL) {
4680
4681			if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4682			     ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4683			       TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4684				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4685				    TarLUNBusy[currSCCB->Lun] = 1;
4686				if (FPT_BL_Card[p_card].discQCount != 0)
4687					FPT_BL_Card[p_card].discQCount--;
4688				FPT_BL_Card[p_card].
4689				    discQ_Tbl[FPT_sccbMgrTbl[p_card]
4690					      [currSCCB->TargID].
4691					      LunDiscQ_Idx[currSCCB->Lun]] =
4692				    NULL;
4693			} else {
4694				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4695				    TarLUNBusy[0] = 1;
4696				if (currSCCB->Sccb_tag) {
4697					if (FPT_BL_Card[p_card].discQCount != 0)
4698						FPT_BL_Card[p_card].
4699						    discQCount--;
4700					FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4701								      Sccb_tag]
4702					    = NULL;
4703				} else {
4704					if (FPT_BL_Card[p_card].discQCount != 0)
4705						FPT_BL_Card[p_card].
4706						    discQCount--;
4707					FPT_BL_Card[p_card].
4708					    discQ_Tbl[FPT_sccbMgrTbl[p_card]
4709						      [currSCCB->TargID].
4710						      LunDiscQ_Idx[0]] = NULL;
4711				}
4712			}
4713
4714			currSCCB->Sccb_MGRFlags |= F_STATUSLOADED;
4715
4716			FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
4717
4718			return;
4719		}
4720
4721		if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
4722			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4723			    (unsigned char)SYNC_SUPPORTED;
4724
4725			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4726			    ~EE_SYNC_MASK;
4727			FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
4728
4729			if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4730			     ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4731			       TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4732				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4733				    TarLUNBusy[currSCCB->Lun] = 1;
4734				if (FPT_BL_Card[p_card].discQCount != 0)
4735					FPT_BL_Card[p_card].discQCount--;
4736				FPT_BL_Card[p_card].
4737				    discQ_Tbl[FPT_sccbMgrTbl[p_card]
4738					      [currSCCB->TargID].
4739					      LunDiscQ_Idx[currSCCB->Lun]] =
4740				    NULL;
4741			} else {
4742				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4743				    TarLUNBusy[0] = 1;
4744				if (currSCCB->Sccb_tag) {
4745					if (FPT_BL_Card[p_card].discQCount != 0)
4746						FPT_BL_Card[p_card].
4747						    discQCount--;
4748					FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4749								      Sccb_tag]
4750					    = NULL;
4751				} else {
4752					if (FPT_BL_Card[p_card].discQCount != 0)
4753						FPT_BL_Card[p_card].
4754						    discQCount--;
4755					FPT_BL_Card[p_card].
4756					    discQ_Tbl[FPT_sccbMgrTbl[p_card]
4757						      [currSCCB->TargID].
4758						      LunDiscQ_Idx[0]] = NULL;
4759				}
4760			}
4761			return;
4762
4763		}
4764
4765		if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
4766
4767			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
4768			    (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4769			     TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
4770
4771			FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4772			    ~EE_WIDE_SCSI;
4773			FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
4774
4775			if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4776			     ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4777			       TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4778				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4779				    TarLUNBusy[currSCCB->Lun] = 1;
4780				if (FPT_BL_Card[p_card].discQCount != 0)
4781					FPT_BL_Card[p_card].discQCount--;
4782				FPT_BL_Card[p_card].
4783				    discQ_Tbl[FPT_sccbMgrTbl[p_card]
4784					      [currSCCB->TargID].
4785					      LunDiscQ_Idx[currSCCB->Lun]] =
4786				    NULL;
4787			} else {
4788				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4789				    TarLUNBusy[0] = 1;
4790				if (currSCCB->Sccb_tag) {
4791					if (FPT_BL_Card[p_card].discQCount != 0)
4792						FPT_BL_Card[p_card].
4793						    discQCount--;
4794					FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4795								      Sccb_tag]
4796					    = NULL;
4797				} else {
4798					if (FPT_BL_Card[p_card].discQCount != 0)
4799						FPT_BL_Card[p_card].
4800						    discQCount--;
4801					FPT_BL_Card[p_card].
4802					    discQ_Tbl[FPT_sccbMgrTbl[p_card]
4803						      [currSCCB->TargID].
4804						      LunDiscQ_Idx[0]] = NULL;
4805				}
4806			}
4807			return;
4808
4809		}
4810
4811		if (status_byte == SSCHECK) {
4812			if (FPT_BL_Card[p_card].globalFlags & F_DO_RENEGO) {
4813				if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4814				    TarEEValue & EE_SYNC_MASK) {
4815					FPT_sccbMgrTbl[p_card][currSCCB->
4816							       TargID].
4817					    TarStatus &= ~TAR_SYNC_MASK;
4818				}
4819				if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4820				    TarEEValue & EE_WIDE_SCSI) {
4821					FPT_sccbMgrTbl[p_card][currSCCB->
4822							       TargID].
4823					    TarStatus &= ~TAR_WIDE_MASK;
4824				}
4825			}
4826		}
4827
4828		if (!(currSCCB->Sccb_XferState & F_AUTO_SENSE)) {
4829
4830			currSCCB->SccbStatus = SCCB_ERROR;
4831			currSCCB->TargetStatus = status_byte;
4832
4833			if (status_byte == SSCHECK) {
4834
4835				FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4836				    TarLUN_CA = 1;
4837
4838				if (currSCCB->RequestSenseLength !=
4839				    NO_AUTO_REQUEST_SENSE) {
4840
4841					if (currSCCB->RequestSenseLength == 0)
4842						currSCCB->RequestSenseLength =
4843						    14;
4844
4845					FPT_ssenss(&FPT_BL_Card[p_card]);
4846					FPT_BL_Card[p_card].globalFlags |=
4847					    F_NEW_SCCB_CMD;
4848
4849					if (((FPT_BL_Card[p_card].
4850					      globalFlags & F_CONLUN_IO)
4851					     &&
4852					     ((FPT_sccbMgrTbl[p_card]
4853					       [currSCCB->TargID].
4854					       TarStatus & TAR_TAG_Q_MASK) !=
4855					      TAG_Q_TRYING))) {
4856						FPT_sccbMgrTbl[p_card]
4857						    [currSCCB->TargID].
4858						    TarLUNBusy[currSCCB->Lun] =
4859						    1;
4860						if (FPT_BL_Card[p_card].
4861						    discQCount != 0)
4862							FPT_BL_Card[p_card].
4863							    discQCount--;
4864						FPT_BL_Card[p_card].
4865						    discQ_Tbl[FPT_sccbMgrTbl
4866							      [p_card]
4867							      [currSCCB->
4868							       TargID].
4869							      LunDiscQ_Idx
4870							      [currSCCB->Lun]] =
4871						    NULL;
4872					} else {
4873						FPT_sccbMgrTbl[p_card]
4874						    [currSCCB->TargID].
4875						    TarLUNBusy[0] = 1;
4876						if (currSCCB->Sccb_tag) {
4877							if (FPT_BL_Card[p_card].
4878							    discQCount != 0)
4879								FPT_BL_Card
4880								    [p_card].
4881								    discQCount--;
4882							FPT_BL_Card[p_card].
4883							    discQ_Tbl[currSCCB->
4884								      Sccb_tag]
4885							    = NULL;
4886						} else {
4887							if (FPT_BL_Card[p_card].
4888							    discQCount != 0)
4889								FPT_BL_Card
4890								    [p_card].
4891								    discQCount--;
4892							FPT_BL_Card[p_card].
4893							    discQ_Tbl
4894							    [FPT_sccbMgrTbl
4895							     [p_card][currSCCB->
4896								      TargID].
4897							     LunDiscQ_Idx[0]] =
4898							    NULL;
4899						}
4900					}
4901					return;
4902				}
4903			}
4904		}
4905	}
4906
4907	if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4908	    ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4909	      TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4910		FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->
4911								    Lun] = 0;
4912	else
4913		FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0;
4914
4915	FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, p_card);
4916}
4917
4918#define SHORT_WAIT   0x0000000F
4919#define LONG_WAIT    0x0000FFFFL
4920
4921/*---------------------------------------------------------------------
4922 *
4923 * Function: Data Transfer Processor
4924 *
4925 * Description: This routine performs two tasks.
4926 *              (1) Start data transfer by calling HOST_DATA_XFER_START
4927 *              function.  Once data transfer is started, (2) Depends
4928 *              on the type of data transfer mode Scatter/Gather mode
4929 *              or NON Scatter/Gather mode.  In NON Scatter/Gather mode,
4930 *              this routine checks Sccb_MGRFlag (F_HOST_XFER_ACT bit) for
4931 *              data transfer done.  In Scatter/Gather mode, this routine
4932 *              checks bus master command complete and dual rank busy
4933 *              bit to keep chaining SC transfer command.  Similarly,
4934 *              in Scatter/Gather mode, it checks Sccb_MGRFlag
4935 *              (F_HOST_XFER_ACT bit) for data transfer done.
4936 *              
4937 *---------------------------------------------------------------------*/
4938
4939static void FPT_dataXferProcessor(unsigned long port,
4940				  struct sccb_card *pCurrCard)
4941{
4942	struct sccb *currSCCB;
4943
4944	currSCCB = pCurrCard->currentSCCB;
4945
4946	if (currSCCB->Sccb_XferState & F_SG_XFER) {
4947		if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
4948		{
4949			currSCCB->Sccb_sgseg += (unsigned char)SG_BUF_CNT;
4950			currSCCB->Sccb_SGoffset = 0x00;
4951		}
4952		pCurrCard->globalFlags |= F_HOST_XFER_ACT;
4953
4954		FPT_busMstrSGDataXferStart(port, currSCCB);
4955	}
4956
4957	else {
4958		if (!(pCurrCard->globalFlags & F_HOST_XFER_ACT)) {
4959			pCurrCard->globalFlags |= F_HOST_XFER_ACT;
4960
4961			FPT_busMstrDataXferStart(port, currSCCB);
4962		}
4963	}
4964}
4965
4966/*---------------------------------------------------------------------
4967 *
4968 * Function: BusMaster Scatter Gather Data Transfer Start
4969 *
4970 * Description:
4971 *
4972 *---------------------------------------------------------------------*/
4973static void FPT_busMstrSGDataXferStart(unsigned long p_port,
4974				       struct sccb *pcurrSCCB)
4975{
4976	unsigned long count, addr, tmpSGCnt;
4977	unsigned int sg_index;
4978	unsigned char sg_count, i;
4979	unsigned long reg_offset;
4980
4981	if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
4982
4983		count = ((unsigned long)HOST_RD_CMD) << 24;
4984	}
4985
4986	else {
4987		count = ((unsigned long)HOST_WRT_CMD) << 24;
4988	}
4989
4990	sg_count = 0;
4991	tmpSGCnt = 0;
4992	sg_index = pcurrSCCB->Sccb_sgseg;
4993	reg_offset = hp_aramBase;
4994
4995	i = (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
4996			    ~(SGRAM_ARAM | SCATTER_EN));
4997
4998	WR_HARPOON(p_port + hp_page_ctrl, i);
4999
5000	while ((sg_count < (unsigned char)SG_BUF_CNT) &&
5001	       ((unsigned long)(sg_index * (unsigned int)SG_ELEMENT_SIZE) <
5002		pcurrSCCB->DataLength)) {
5003
5004		tmpSGCnt += *(((unsigned long *)pcurrSCCB->DataPointer) +
5005			      (sg_index * 2));
5006
5007		count |= *(((unsigned long *)pcurrSCCB->DataPointer) +
5008			   (sg_index * 2));
5009
5010		addr = *(((unsigned long *)pcurrSCCB->DataPointer) +
5011			 ((sg_index * 2) + 1));
5012
5013		if ((!sg_count) && (pcurrSCCB->Sccb_SGoffset)) {
5014
5015			addr +=
5016			    ((count & 0x00FFFFFFL) - pcurrSCCB->Sccb_SGoffset);
5017			count =
5018			    (count & 0xFF000000L) | pcurrSCCB->Sccb_SGoffset;
5019
5020			tmpSGCnt = count & 0x00FFFFFFL;
5021		}
5022
5023		WR_HARP32(p_port, reg_offset, addr);
5024		reg_offset += 4;
5025
5026		WR_HARP32(p_port, reg_offset, count);
5027		reg_offset += 4;
5028
5029		count &= 0xFF000000L;
5030		sg_index++;
5031		sg_count++;
5032
5033	}			/*End While */
5034
5035	pcurrSCCB->Sccb_XferCnt = tmpSGCnt;
5036
5037	WR_HARPOON(p_port + hp_sg_addr, (sg_count << 4));
5038
5039	if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
5040
5041		WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
5042
5043		WR_HARPOON(p_port + hp_portctrl_0,
5044			   (DMA_PORT | SCSI_PORT | SCSI_INBIT));
5045		WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
5046	}
5047
5048	else {
5049
5050		if ((!(RD_HARPOON(p_port + hp_synctarg_0) & NARROW_SCSI)) &&
5051		    (tmpSGCnt & 0x000000001)) {
5052
5053			pcurrSCCB->Sccb_XferState |= F_ODD_BALL_CNT;
5054			tmpSGCnt--;
5055		}
5056
5057		WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
5058
5059		WR_HARPOON(p_port + hp_portctrl_0,
5060			   (SCSI_PORT | DMA_PORT | DMA_RD));
5061		WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
5062	}
5063
5064	WR_HARPOON(p_port + hp_page_ctrl, (unsigned char)(i | SCATTER_EN));
5065
5066}
5067
5068/*---------------------------------------------------------------------
5069 *
5070 * Function: BusMaster Data Transfer Start
5071 *
5072 * Description: 
5073 *
5074 *---------------------------------------------------------------------*/
5075static void FPT_busMstrDataXferStart(unsigned long p_port,
5076				     struct sccb *pcurrSCCB)
5077{
5078	unsigned long addr, count;
5079
5080	if (!(pcurrSCCB->Sccb_XferState & F_AUTO_SENSE)) {
5081
5082		count = pcurrSCCB->Sccb_XferCnt;
5083
5084		addr =
5085		    (unsigned long)pcurrSCCB->DataPointer + pcurrSCCB->Sccb_ATC;
5086	}
5087
5088	else {
5089		addr = pcurrSCCB->SensePointer;
5090		count = pcurrSCCB->RequestSenseLength;
5091
5092	}
5093
5094	HP_SETUP_ADDR_CNT(p_port, addr, count);
5095
5096	if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
5097
5098		WR_HARPOON(p_port + hp_portctrl_0,
5099			   (DMA_PORT | SCSI_PORT | SCSI_INBIT));
5100		WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
5101
5102		WR_HARPOON(p_port + hp_xfer_cmd,
5103			   (XFER_DMA_HOST | XFER_HOST_AUTO | XFER_DMA_8BIT));
5104	}
5105
5106	else {
5107
5108		WR_HARPOON(p_port + hp_portctrl_0,
5109			   (SCSI_PORT | DMA_PORT | DMA_RD));
5110		WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
5111
5112		WR_HARPOON(p_port + hp_xfer_cmd,
5113			   (XFER_HOST_DMA | XFER_HOST_AUTO | XFER_DMA_8BIT));
5114
5115	}
5116}
5117
5118/*---------------------------------------------------------------------
5119 *
5120 * Function: BusMaster Timeout Handler
5121 *
5122 * Description: This function is called after a bus master command busy time
5123 *               out is detected.  This routines issue halt state machine
5124 *               with a software time out for command busy.  If command busy
5125 *               is still asserted at the end of the time out, it issues
5126 *               hard abort with another software time out.  It hard abort
5127 *               command busy is also time out, it'll just give up.
5128 *
5129 *---------------------------------------------------------------------*/
5130static unsigned char FPT_busMstrTimeOut(unsigned long p_port)
5131{
5132	unsigned long timeout;
5133
5134	timeout = LONG_WAIT;
5135
5136	WR_HARPOON(p_port + hp_sys_ctrl, HALT_MACH);
5137
5138	while ((!(RD_HARPOON(p_port + hp_ext_status) & CMD_ABORTED))
5139	       && timeout--) {
5140	}
5141
5142	if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
5143		WR_HARPOON(p_port + hp_sys_ctrl, HARD_ABORT);
5144
5145		timeout = LONG_WAIT;
5146		while ((RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY)
5147		       && timeout--) {
5148		}
5149	}
5150
5151	RD_HARPOON(p_port + hp_int_status);	/*Clear command complete */
5152
5153	if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
5154		return 1;
5155	}
5156
5157	else {
5158		return 0;
5159	}
5160}
5161
5162/*---------------------------------------------------------------------
5163 *
5164 * Function: Host Data Transfer Abort
5165 *
5166 * Description: Abort any in progress transfer.
5167 *
5168 *---------------------------------------------------------------------*/
5169static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card,
5170				  struct sccb *pCurrSCCB)
5171{
5172
5173	unsigned long timeout;
5174	unsigned long remain_cnt;
5175	unsigned int sg_ptr;
5176
5177	FPT_BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT;
5178
5179	if (pCurrSCCB->Sccb_XferState & F_AUTO_SENSE) {
5180
5181		if (!(RD_HARPOON(port + hp_int_status) & INT_CMD_COMPL)) {
5182
5183			WR_HARPOON(port + hp_bm_ctrl,
5184				   (RD_HARPOON(port + hp_bm_ctrl) |
5185				    FLUSH_XFER_CNTR));
5186			timeout = LONG_WAIT;
5187
5188			while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
5189			       && timeout--) {
5190			}
5191
5192			WR_HARPOON(port + hp_bm_ctrl,
5193				   (RD_HARPOON(port + hp_bm_ctrl) &
5194				    ~FLUSH_XFER_CNTR));
5195
5196			if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
5197
5198				if (FPT_busMstrTimeOut(port)) {
5199
5200					if (pCurrSCCB->HostStatus == 0x00)
5201
5202						pCurrSCCB->HostStatus =
5203						    SCCB_BM_ERR;
5204
5205				}
5206
5207				if (RD_HARPOON(port + hp_int_status) &
5208				    INT_EXT_STATUS)
5209
5210					if (RD_HARPOON(port + hp_ext_status) &
5211					    BAD_EXT_STATUS)
5212
5213						if (pCurrSCCB->HostStatus ==
5214						    0x00)
5215						{
5216							pCurrSCCB->HostStatus =
5217							    SCCB_BM_ERR;
5218						}
5219			}
5220		}
5221	}
5222
5223	else if (pCurrSCCB->Sccb_XferCnt) {
5224
5225		if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
5226
5227			WR_HARPOON(port + hp_page_ctrl,
5228				   (RD_HARPOON(port + hp_page_ctrl) &
5229				    ~SCATTER_EN));
5230
5231			WR_HARPOON(port + hp_sg_addr, 0x00);
5232
5233			sg_ptr = pCurrSCCB->Sccb_sgseg + SG_BUF_CNT;
5234
5235			if (sg_ptr >
5236			    (unsigned int)(pCurrSCCB->DataLength /
5237					   SG_ELEMENT_SIZE)) {
5238
5239				sg_ptr =
5240				    (unsigned int)(pCurrSCCB->DataLength /
5241						   SG_ELEMENT_SIZE);
5242			}
5243
5244			remain_cnt = pCurrSCCB->Sccb_XferCnt;
5245
5246			while (remain_cnt < 0x01000000L) {
5247
5248				sg_ptr--;
5249
5250				if (remain_cnt >
5251				    (unsigned
5252				     long)(*(((unsigned long *)pCurrSCCB->
5253					      DataPointer) + (sg_ptr * 2)))) {
5254
5255					remain_cnt -=
5256					    (unsigned
5257					     long)(*(((unsigned long *)
5258						      pCurrSCCB->DataPointer) +
5259						     (sg_ptr * 2)));
5260				}
5261
5262				else {
5263
5264					break;
5265				}
5266			}
5267
5268			if (remain_cnt < 0x01000000L) {
5269
5270				pCurrSCCB->Sccb_SGoffset = remain_cnt;
5271
5272				pCurrSCCB->Sccb_sgseg = (unsigned short)sg_ptr;
5273
5274				if ((unsigned long)(sg_ptr * SG_ELEMENT_SIZE) ==
5275				    pCurrSCCB->DataLength && (remain_cnt == 0))
5276
5277					pCurrSCCB->Sccb_XferState |=
5278					    F_ALL_XFERRED;
5279			}
5280
5281			else {
5282
5283				if (pCurrSCCB->HostStatus == 0x00) {
5284
5285					pCurrSCCB->HostStatus =
5286					    SCCB_GROSS_FW_ERR;
5287				}
5288			}
5289		}
5290
5291		if (!(pCurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)) {
5292
5293			if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
5294
5295				FPT_busMstrTimeOut(port);
5296			}
5297
5298			else {
5299
5300				if (RD_HARPOON(port + hp_int_status) &
5301				    INT_EXT_STATUS) {
5302
5303					if (RD_HARPOON(port + hp_ext_status) &
5304					    BAD_EXT_STATUS) {
5305
5306						if (pCurrSCCB->HostStatus ==
5307						    0x00) {
5308
5309							pCurrSCCB->HostStatus =
5310							    SCCB_BM_ERR;
5311						}
5312					}
5313				}
5314
5315			}
5316		}
5317
5318		else {
5319
5320			if ((RD_HARPOON(port + hp_fifo_cnt)) >= BM_THRESHOLD) {
5321
5322				timeout = SHORT_WAIT;
5323
5324				while ((RD_HARPOON(port + hp_ext_status) &
5325					BM_CMD_BUSY)
5326				       && ((RD_HARPOON(port + hp_fifo_cnt)) >=
5327					   BM_THRESHOLD) && timeout--) {
5328				}
5329			}
5330
5331			if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
5332
5333				WR_HARPOON(port + hp_bm_ctrl,
5334					   (RD_HARPOON(port + hp_bm_ctrl) |
5335					    FLUSH_XFER_CNTR));
5336
5337				timeout = LONG_WAIT;
5338
5339				while ((RD_HARPOON(port + hp_ext_status) &
5340					BM_CMD_BUSY) && timeout--) {
5341				}
5342
5343				WR_HARPOON(port + hp_bm_ctrl,
5344					   (RD_HARPOON(port + hp_bm_ctrl) &
5345					    ~FLUSH_XFER_CNTR));
5346
5347				if (RD_HARPOON(port + hp_ext_status) &
5348				    BM_CMD_BUSY) {
5349
5350					if (pCurrSCCB->HostStatus == 0x00) {
5351
5352						pCurrSCCB->HostStatus =
5353						    SCCB_BM_ERR;
5354					}
5355
5356					FPT_busMstrTimeOut(port);
5357				}
5358			}
5359
5360			if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
5361
5362				if (RD_HARPOON(port + hp_ext_status) &
5363				    BAD_EXT_STATUS) {
5364
5365					if (pCurrSCCB->HostStatus == 0x00) {
5366
5367						pCurrSCCB->HostStatus =
5368						    SCCB_BM_ERR;
5369					}
5370				}
5371			}
5372		}
5373
5374	}
5375
5376	else {
5377
5378		if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
5379
5380			timeout = LONG_WAIT;
5381
5382			while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
5383			       && timeout--) {
5384			}
5385
5386			if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
5387
5388				if (pCurrSCCB->HostStatus == 0x00) {
5389
5390					pCurrSCCB->HostStatus = SCCB_BM_ERR;
5391				}
5392
5393				FPT_busMstrTimeOut(port);
5394			}
5395		}
5396
5397		if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
5398
5399			if (RD_HARPOON(port + hp_ext_status) & BAD_EXT_STATUS) {
5400
5401				if (pCurrSCCB->HostStatus == 0x00) {
5402
5403					pCurrSCCB->HostStatus = SCCB_BM_ERR;
5404				}
5405			}
5406
5407		}
5408
5409		if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
5410
5411			WR_HARPOON(port + hp_page_ctrl,
5412				   (RD_HARPOON(port + hp_page_ctrl) &
5413				    ~SCATTER_EN));
5414
5415			WR_HARPOON(port + hp_sg_addr, 0x00);
5416
5417			pCurrSCCB->Sccb_sgseg += SG_BUF_CNT;
5418
5419			pCurrSCCB->Sccb_SGoffset = 0x00;
5420
5421			if ((unsigned long)(pCurrSCCB->Sccb_sgseg *
5422					    SG_ELEMENT_SIZE) >=
5423			    pCurrSCCB->DataLength) {
5424
5425				pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
5426
5427				pCurrSCCB->Sccb_sgseg =
5428				    (unsigned short)(pCurrSCCB->DataLength /
5429						     SG_ELEMENT_SIZE);
5430
5431			}
5432		}
5433
5434		else {
5435
5436			if (!(pCurrSCCB->Sccb_XferState & F_AUTO_SENSE))
5437
5438				pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
5439		}
5440	}
5441
5442	WR_HARPOON(port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
5443}
5444
5445/*---------------------------------------------------------------------
5446 *
5447 * Function: Host Data Transfer Restart
5448 *
5449 * Description: Reset the available count due to a restore data
5450 *              pointers message.
5451 *
5452 *---------------------------------------------------------------------*/
5453static void FPT_hostDataXferRestart(struct sccb *currSCCB)
5454{
5455	unsigned long data_count;
5456	unsigned int sg_index;
5457	unsigned long *sg_ptr;
5458
5459	if (currSCCB->Sccb_XferState & F_SG_XFER) {
5460
5461		currSCCB->Sccb_XferCnt = 0;
5462
5463		sg_index = 0xffff;	/*Index by long words into sg list. */
5464		data_count = 0;	/*Running count of SG xfer counts. */
5465
5466		sg_ptr = (unsigned long *)currSCCB->DataPointer;
5467
5468		while (data_count < currSCCB->Sccb_ATC) {
5469
5470			sg_index++;
5471			data_count += *(sg_ptr + (sg_index * 2));
5472		}
5473
5474		if (data_count == currSCCB->Sccb_ATC) {
5475
5476			currSCCB->Sccb_SGoffset = 0;
5477			sg_index++;
5478		}
5479
5480		else {
5481			currSCCB->Sccb_SGoffset =
5482			    data_count - currSCCB->Sccb_ATC;
5483		}
5484
5485		currSCCB->Sccb_sgseg = (unsigned short)sg_index;
5486	}
5487
5488	else {
5489		currSCCB->Sccb_XferCnt =
5490		    currSCCB->DataLength - currSCCB->Sccb_ATC;
5491	}
5492}
5493
5494/*---------------------------------------------------------------------
5495 *
5496 * Function: FPT_scini
5497 *
5498 * Description: Setup all data structures necessary for SCAM selection.
5499 *
5500 *---------------------------------------------------------------------*/
5501
5502static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
5503		      unsigned char p_power_up)
5504{
5505
5506	unsigned char loser, assigned_id;
5507	unsigned long p_port;
5508
5509	unsigned char i, k, ScamFlg;
5510	struct sccb_card *currCard;
5511	struct nvram_info *pCurrNvRam;
5512
5513	currCard = &FPT_BL_Card[p_card];
5514	p_port = currCard->ioPort;
5515	pCurrNvRam = currCard->pNvRamInfo;
5516
5517	if (pCurrNvRam) {
5518		ScamFlg = pCurrNvRam->niScamConf;
5519		i = pCurrNvRam->niSysConf;
5520	} else {
5521		ScamFlg =
5522		    (unsigned char)FPT_utilEERead(p_port, SCAM_CONFIG / 2);
5523		i = (unsigned
5524		     char)(FPT_utilEERead(p_port, (SYSTEM_CONFIG / 2)));
5525	}
5526	if (!(i & 0x02))	/* check if reset bus in AutoSCSI parameter set */
5527		return;
5528
5529	FPT_inisci(p_card, p_port, p_our_id);
5530
5531	/* Force to wait 1 sec after SCSI bus reset. Some SCAM device FW
5532	   too slow to return to SCAM selection */
5533
5534	/* if (p_power_up)
5535	   FPT_Wait1Second(p_port);
5536	   else
5537	   FPT_Wait(p_port, TO_250ms); */
5538
5539	FPT_Wait1Second(p_port);
5540
5541	if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2)) {
5542		while (!(FPT_scarb(p_port, INIT_SELTD))) {
5543		}
5544
5545		FPT_scsel(p_port);
5546
5547		do {
5548			FPT_scxferc(p_port, SYNC_PTRN);
5549			FPT_scxferc(p_port, DOM_MSTR);
5550			loser =
5551			    FPT_scsendi(p_port,
5552					&FPT_scamInfo[p_our_id].id_string[0]);
5553		} while (loser == 0xFF);
5554
5555		FPT_scbusf(p_port);
5556
5557		if ((p_power_up) && (!loser)) {
5558			FPT_sresb(p_port, p_card);
5559			FPT_Wait(p_port, TO_250ms);
5560
5561			while (!(FPT_scarb(p_port, INIT_SELTD))) {
5562			}
5563
5564			FPT_scsel(p_port);
5565
5566			do {
5567				FPT_scxferc(p_port, SYNC_PTRN);
5568				FPT_scxferc(p_port, DOM_MSTR);
5569				loser =
5570				    FPT_scsendi(p_port,
5571						&FPT_scamInfo[p_our_id].
5572						id_string[0]);
5573			} while (loser == 0xFF);
5574
5575			FPT_scbusf(p_port);
5576		}
5577	}
5578
5579	else {
5580		loser = 0;
5581	}
5582
5583	if (!loser) {
5584
5585		FPT_scamInfo[p_our_id].state = ID_ASSIGNED;
5586
5587		if (ScamFlg & SCAM_ENABLED) {
5588
5589			for (i = 0; i < MAX_SCSI_TAR; i++) {
5590				if ((FPT_scamInfo[i].state == ID_UNASSIGNED) ||
5591				    (FPT_scamInfo[i].state == ID_UNUSED)) {
5592					if (FPT_scsell(p_port, i)) {
5593						FPT_scamInfo[i].state = LEGACY;
5594						if ((FPT_scamInfo[i].
5595						     id_string[0] != 0xFF)
5596						    || (FPT_scamInfo[i].
5597							id_string[1] != 0xFA)) {
5598
5599							FPT_scamInfo[i].
5600							    id_string[0] = 0xFF;
5601							FPT_scamInfo[i].
5602							    id_string[1] = 0xFA;
5603							if (pCurrNvRam == NULL)
5604								currCard->
5605								    globalFlags
5606								    |=
5607								    F_UPDATE_EEPROM;
5608						}
5609					}
5610				}
5611			}
5612
5613			FPT_sresb(p_port, p_card);
5614			FPT_Wait1Second(p_port);
5615			while (!(FPT_scarb(p_port, INIT_SELTD))) {
5616			}
5617			FPT_scsel(p_port);
5618			FPT_scasid(p_card, p_port);
5619		}
5620
5621	}
5622
5623	else if ((loser) && (ScamFlg & SCAM_ENABLED)) {
5624		FPT_scamInfo[p_our_id].id_string[0] = SLV_TYPE_CODE0;
5625		assigned_id = 0;
5626		FPT_scwtsel(p_port);
5627
5628		do {
5629			while (FPT_scxferc(p_port, 0x00) != SYNC_PTRN) {
5630			}
5631
5632			i = FPT_scxferc(p_port, 0x00);
5633			if (i == ASSIGN_ID) {
5634				if (!
5635				    (FPT_scsendi
5636				     (p_port,
5637				      &FPT_scamInfo[p_our_id].id_string[0]))) {
5638					i = FPT_scxferc(p_port, 0x00);
5639					if (FPT_scvalq(i)) {
5640						k = FPT_scxferc(p_port, 0x00);
5641
5642						if (FPT_scvalq(k)) {
5643							currCard->ourId =
5644							    ((unsigned char)(i
5645									     <<
5646									     3)
5647							     +
5648							     (k &
5649							      (unsigned char)7))
5650							    & (unsigned char)
5651							    0x3F;
5652							FPT_inisci(p_card,
5653								   p_port,
5654								   p_our_id);
5655							FPT_scamInfo[currCard->
5656								     ourId].
5657							    state = ID_ASSIGNED;
5658							FPT_scamInfo[currCard->
5659								     ourId].
5660							    id_string[0]
5661							    = SLV_TYPE_CODE0;
5662							assigned_id = 1;
5663						}
5664					}
5665				}
5666			}
5667
5668			else if (i == SET_P_FLAG) {
5669				if (!(FPT_scsendi(p_port,
5670						  &FPT_scamInfo[p_our_id].
5671						  id_string[0])))
5672					FPT_scamInfo[p_our_id].id_string[0] |=
5673					    0x80;
5674			}
5675		} while (!assigned_id);
5676
5677		while (FPT_scxferc(p_port, 0x00) != CFG_CMPLT) {
5678		}
5679	}
5680
5681	if (ScamFlg & SCAM_ENABLED) {
5682		FPT_scbusf(p_port);
5683		if (currCard->globalFlags & F_UPDATE_EEPROM) {
5684			FPT_scsavdi(p_card, p_port);
5685			currCard->globalFlags &= ~F_UPDATE_EEPROM;
5686		}
5687	}
5688
5689/*
5690   for (i=0,k=0; i < MAX_SCSI_TAR; i++)
5691      {
5692      if ((FPT_scamInfo[i].state == ID_ASSIGNED) ||
5693         (FPT_scamInfo[i].state == LEGACY))
5694         k++;
5695      }
5696
5697   if (k==2)
5698      currCard->globalFlags |= F_SINGLE_DEVICE;
5699   else
5700      currCard->globalFlags &= ~F_SINGLE_DEVICE;
5701*/
5702}
5703
5704/*---------------------------------------------------------------------
5705 *
5706 * Function: FPT_scarb
5707 *
5708 * Description: Gain control of the bus and wait SCAM select time (250ms)
5709 *
5710 *---------------------------------------------------------------------*/
5711
5712static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type)
5713{
5714	if (p_sel_type == INIT_SELTD) {
5715
5716		while (RD_HARPOON(p_port + hp_scsisig) & (SCSI_SEL | SCSI_BSY)) {
5717		}
5718
5719		if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL)
5720			return 0;
5721
5722		if (RD_HARPOON(p_port + hp_scsidata_0) != 00)
5723			return 0;
5724
5725		WR_HARPOON(p_port + hp_scsisig,
5726			   (RD_HARPOON(p_port + hp_scsisig) | SCSI_BSY));
5727
5728		if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL) {
5729
5730			WR_HARPOON(p_port + hp_scsisig,
5731				   (RD_HARPOON(p_port + hp_scsisig) &
5732				    ~SCSI_BSY));
5733			return 0;
5734		}
5735
5736		WR_HARPOON(p_port + hp_scsisig,
5737			   (RD_HARPOON(p_port + hp_scsisig) | SCSI_SEL));
5738
5739		if (RD_HARPOON(p_port + hp_scsidata_0) != 00) {
5740
5741			WR_HARPOON(p_port + hp_scsisig,
5742				   (RD_HARPOON(p_port + hp_scsisig) &
5743				    ~(SCSI_BSY | SCSI_SEL)));
5744			return 0;
5745		}
5746	}
5747
5748	WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
5749					   & ~ACTdeassert));
5750	WR_HARPOON(p_port + hp_scsireset, SCAM_EN);
5751	WR_HARPOON(p_port + hp_scsidata_0, 0x00);
5752	WR_HARPOON(p_port + hp_scsidata_1, 0x00);
5753	WR_HARPOON(p_port + hp_portctrl_0, SCSI_BUS_EN);
5754
5755	WR_HARPOON(p_port + hp_scsisig,
5756		   (RD_HARPOON(p_port + hp_scsisig) | SCSI_MSG));
5757
5758	WR_HARPOON(p_port + hp_scsisig, (RD_HARPOON(p_port + hp_scsisig)
5759					 & ~SCSI_BSY));
5760
5761	FPT_Wait(p_port, TO_250ms);
5762
5763	return 1;
5764}
5765
5766/*---------------------------------------------------------------------
5767 *
5768 * Function: FPT_scbusf
5769 *
5770 * Description: Release the SCSI bus and disable SCAM selection.
5771 *
5772 *---------------------------------------------------------------------*/
5773
5774static void FPT_scbusf(unsigned long p_port)
5775{
5776	WR_HARPOON(p_port + hp_page_ctrl,
5777		   (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
5778
5779	WR_HARPOON(p_port + hp_scsidata_0, 0x00);
5780
5781	WR_HARPOON(p_port + hp_portctrl_0, (RD_HARPOON(p_port + hp_portctrl_0)
5782					    & ~SCSI_BUS_EN));
5783
5784	WR_HARPOON(p_port + hp_scsisig, 0x00);
5785
5786	WR_HARPOON(p_port + hp_scsireset, (RD_HARPOON(p_port + hp_scsireset)
5787					   & ~SCAM_EN));
5788
5789	WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
5790					   | ACTdeassert));
5791
5792	WRW_HARPOON((p_port + hp_intstat), (BUS_FREE | AUTO_INT | SCAM_SEL));
5793
5794	WR_HARPOON(p_port + hp_page_ctrl,
5795		   (RD_HARPOON(p_port + hp_page_ctrl) & ~G_INT_DISABLE));
5796}
5797
5798/*---------------------------------------------------------------------
5799 *
5800 * Function: FPT_scasid
5801 *
5802 * Description: Assign an ID to all the SCAM devices.
5803 *
5804 *---------------------------------------------------------------------*/
5805
5806static void FPT_scasid(unsigned char p_card, unsigned long p_port)
5807{
5808	unsigned char temp_id_string[ID_STRING_LENGTH];
5809
5810	unsigned char i, k, scam_id;
5811	unsigned char crcBytes[3];
5812	struct nvram_info *pCurrNvRam;
5813	unsigned short *pCrcBytes;
5814
5815	pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
5816
5817	i = 0;
5818
5819	while (!i) {
5820
5821		for (k = 0; k < ID_STRING_LENGTH; k++) {
5822			temp_id_string[k] = (unsigned char)0x00;
5823		}
5824
5825		FPT_scxferc(p_port, SYNC_PTRN);
5826		FPT_scxferc(p_port, ASSIGN_ID);
5827
5828		if (!(FPT_sciso(p_port, &temp_id_string[0]))) {
5829			if (pCurrNvRam) {
5830				pCrcBytes = (unsigned short *)&crcBytes[0];
5831				*pCrcBytes = FPT_CalcCrc16(&temp_id_string[0]);
5832				crcBytes[2] = FPT_CalcLrc(&temp_id_string[0]);
5833				temp_id_string[1] = crcBytes[2];
5834				temp_id_string[2] = crcBytes[0];
5835				temp_id_string[3] = crcBytes[1];
5836				for (k = 4; k < ID_STRING_LENGTH; k++)
5837					temp_id_string[k] = (unsigned char)0x00;
5838			}
5839			i = FPT_scmachid(p_card, temp_id_string);
5840
5841			if (i == CLR_PRIORITY) {
5842				FPT_scxferc(p_port, MISC_CODE);
5843				FPT_scxferc(p_port, CLR_P_FLAG);
5844				i = 0;	/*Not the last ID yet. */
5845			}
5846
5847			else if (i != NO_ID_AVAIL) {
5848				if (i < 8)
5849					FPT_scxferc(p_port, ID_0_7);
5850				else
5851					FPT_scxferc(p_port, ID_8_F);
5852
5853				scam_id = (i & (unsigned char)0x07);
5854
5855				for (k = 1; k < 0x08; k <<= 1)
5856					if (!(k & i))
5857						scam_id += 0x08;	/*Count number of zeros in DB0-3. */
5858
5859				FPT_scxferc(p_port, scam_id);
5860
5861				i = 0;	/*Not the last ID yet. */
5862			}
5863		}
5864
5865		else {
5866			i = 1;
5867		}
5868
5869	}			/*End while */
5870
5871	FPT_scxferc(p_port, SYNC_PTRN);
5872	FPT_scxferc(p_port, CFG_CMPLT);
5873}
5874
5875/*---------------------------------------------------------------------
5876 *
5877 * Function: FPT_scsel
5878 *
5879 * Description: Select all the SCAM devices.
5880 *
5881 *---------------------------------------------------------------------*/
5882
5883static void FPT_scsel(unsigned long p_port)
5884{
5885
5886	WR_HARPOON(p_port + hp_scsisig, SCSI_SEL);
5887	FPT_scwiros(p_port, SCSI_MSG);
5888
5889	WR_HARPOON(p_port + hp_scsisig, (SCSI_SEL | SCSI_BSY));
5890
5891	WR_HARPOON(p_port + hp_scsisig,
5892		   (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5893	WR_HARPOON(p_port + hp_scsidata_0,
5894		   (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) |
5895				   (unsigned char)(BIT(7) + BIT(6))));
5896
5897	WR_HARPOON(p_port + hp_scsisig, (SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5898	FPT_scwiros(p_port, SCSI_SEL);
5899
5900	WR_HARPOON(p_port + hp_scsidata_0,
5901		   (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) &
5902				   ~(unsigned char)BIT(6)));
5903	FPT_scwirod(p_port, BIT(6));
5904
5905	WR_HARPOON(p_port + hp_scsisig,
5906		   (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5907}
5908
5909/*---------------------------------------------------------------------
5910 *
5911 * Function: FPT_scxferc
5912 *
5913 * Description: Handshake the p_data (DB4-0) across the bus.
5914 *
5915 *---------------------------------------------------------------------*/
5916
5917static unsigned char FPT_scxferc(unsigned long p_port, unsigned char p_data)
5918{
5919	unsigned char curr_data, ret_data;
5920
5921	curr_data = p_data | BIT(7) | BIT(5);	/*Start with DB7 & DB5 asserted. */
5922
5923	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5924
5925	curr_data &= ~BIT(7);
5926
5927	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5928
5929	FPT_scwirod(p_port, BIT(7));	/*Wait for DB7 to be released. */
5930	while (!(RD_HARPOON(p_port + hp_scsidata_0) & BIT(5))) ;
5931
5932	ret_data = (RD_HARPOON(p_port + hp_scsidata_0) & (unsigned char)0x1F);
5933
5934	curr_data |= BIT(6);
5935
5936	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5937
5938	curr_data &= ~BIT(5);
5939
5940	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5941
5942	FPT_scwirod(p_port, BIT(5));	/*Wait for DB5 to be released. */
5943
5944	curr_data &= ~(BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));	/*Release data bits */
5945	curr_data |= BIT(7);
5946
5947	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5948
5949	curr_data &= ~BIT(6);
5950
5951	WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5952
5953	FPT_scwirod(p_port, BIT(6));	/*Wait for DB6 to be released. */
5954
5955	return ret_data;
5956}
5957
5958/*---------------------------------------------------------------------
5959 *
5960 * Function: FPT_scsendi
5961 *
5962 * Description: Transfer our Identification string to determine if we
5963 *              will be the dominant master.
5964 *
5965 *---------------------------------------------------------------------*/
5966
5967static unsigned char FPT_scsendi(unsigned long p_port,
5968				 unsigned char p_id_string[])
5969{
5970	unsigned char ret_data, byte_cnt, bit_cnt, defer;
5971
5972	defer = 0;
5973
5974	for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
5975
5976		for (bit_cnt = 0x80; bit_cnt != 0; bit_cnt >>= 1) {
5977
5978			if (defer)
5979				ret_data = FPT_scxferc(p_port, 00);
5980
5981			else if (p_id_string[byte_cnt] & bit_cnt)
5982
5983				ret_data = FPT_scxferc(p_port, 02);
5984
5985			else {
5986
5987				ret_data = FPT_scxferc(p_port, 01);
5988				if (ret_data & 02)
5989					defer = 1;
5990			}
5991
5992			if ((ret_data & 0x1C) == 0x10)
5993				return 0x00;	/*End of isolation stage, we won! */
5994
5995			if (ret_data & 0x1C)
5996				return 0xFF;
5997
5998			if ((defer) && (!(ret_data & 0x1F)))
5999				return 0x01;	/*End of isolation stage, we lost. */
6000
6001		}		/*bit loop */
6002
6003	}			/*byte loop */
6004
6005	if (defer)
6006		return 0x01;	/*We lost */
6007	else
6008		return 0;	/*We WON! Yeeessss! */
6009}
6010
6011/*---------------------------------------------------------------------
6012 *
6013 * Function: FPT_sciso
6014 *
6015 * Description: Transfer the Identification string.
6016 *
6017 *---------------------------------------------------------------------*/
6018
6019static unsigned char FPT_sciso(unsigned long p_port,
6020			       unsigned char p_id_string[])
6021{
6022	unsigned char ret_data, the_data, byte_cnt, bit_cnt;
6023
6024	the_data = 0;
6025
6026	for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
6027
6028		for (bit_cnt = 0; bit_cnt < 8; bit_cnt++) {
6029
6030			ret_data = FPT_scxferc(p_port, 0);
6031
6032			if (ret_data & 0xFC)
6033				return 0xFF;
6034
6035			else {
6036
6037				the_data <<= 1;
6038				if (ret_data & BIT(1)) {
6039					the_data |= 1;
6040				}
6041			}
6042
6043			if ((ret_data & 0x1F) == 0) {
6044/*
6045				if(bit_cnt != 0 || bit_cnt != 8)
6046				{
6047					byte_cnt = 0;
6048					bit_cnt = 0;
6049					FPT_scxferc(p_port, SYNC_PTRN);
6050					FPT_scxferc(p_port, ASSIGN_ID);
6051					continue;
6052				}
6053*/
6054				if (byte_cnt)
6055					return 0x00;
6056				else
6057					return 0xFF;
6058			}
6059
6060		}		/*bit loop */
6061
6062		p_id_string[byte_cnt] = the_data;
6063
6064	}			/*byte loop */
6065
6066	return 0;
6067}
6068
6069/*---------------------------------------------------------------------
6070 *
6071 * Function: FPT_scwirod
6072 *
6073 * Description: Sample the SCSI data bus making sure the signal has been
6074 *              deasserted for the correct number of consecutive samples.
6075 *
6076 *---------------------------------------------------------------------*/
6077
6078static void FPT_scwirod(unsigned long p_port, unsigned char p_data_bit)
6079{
6080	unsigned char i;
6081
6082	i = 0;
6083	while (i < MAX_SCSI_TAR) {
6084
6085		if (RD_HARPOON(p_port + hp_scsidata_0) & p_data_bit)
6086
6087			i = 0;
6088
6089		else
6090
6091			i++;
6092
6093	}
6094}
6095
6096/*---------------------------------------------------------------------
6097 *
6098 * Function: FPT_scwiros
6099 *
6100 * Description: Sample the SCSI Signal lines making sure the signal has been
6101 *              deasserted for the correct number of consecutive samples.
6102 *
6103 *---------------------------------------------------------------------*/
6104
6105static void FPT_scwiros(unsigned long p_port, unsigned char p_data_bit)
6106{
6107	unsigned char i;
6108
6109	i = 0;
6110	while (i < MAX_SCSI_TAR) {
6111
6112		if (RD_HARPOON(p_port + hp_scsisig) & p_data_bit)
6113
6114			i = 0;
6115
6116		else
6117
6118			i++;
6119
6120	}
6121}
6122
6123/*---------------------------------------------------------------------
6124 *
6125 * Function: FPT_scvalq
6126 *
6127 * Description: Make sure we received a valid data byte.
6128 *
6129 *---------------------------------------------------------------------*/
6130
6131static unsigned char FPT_scvalq(unsigned char p_quintet)
6132{
6133	unsigned char count;
6134
6135	for (count = 1; count < 0x08; count <<= 1) {
6136		if (!(p_quintet & count))
6137			p_quintet -= 0x80;
6138	}
6139
6140	if (p_quintet & 0x18)
6141		return 0;
6142
6143	else
6144		return 1;
6145}
6146
6147/*---------------------------------------------------------------------
6148 *
6149 * Function: FPT_scsell
6150 *
6151 * Description: Select the specified device ID using a selection timeout
6152 *              less than 4ms.  If somebody responds then it is a legacy
6153 *              drive and this ID must be marked as such.
6154 *
6155 *---------------------------------------------------------------------*/
6156
6157static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id)
6158{
6159	unsigned long i;
6160
6161	WR_HARPOON(p_port + hp_page_ctrl,
6162		   (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
6163
6164	ARAM_ACCESS(p_port);
6165
6166	WR_HARPOON(p_port + hp_addstat,
6167		   (RD_HARPOON(p_port + hp_addstat) | SCAM_TIMER));
6168	WR_HARPOON(p_port + hp_seltimeout, TO_4ms);
6169
6170	for (i = p_port + CMD_STRT; i < p_port + CMD_STRT + 12; i += 2) {
6171		WRW_HARPOON(i, (MPM_OP + ACOMMAND));
6172	}
6173	WRW_HARPOON(i, (BRH_OP + ALWAYS + NP));
6174
6175	WRW_HARPOON((p_port + hp_intstat),
6176		    (RESET | TIMEOUT | SEL | BUS_FREE | AUTO_INT));
6177
6178	WR_HARPOON(p_port + hp_select_id, targ_id);
6179
6180	WR_HARPOON(p_port + hp_portctrl_0, SCSI_PORT);
6181	WR_HARPOON(p_port + hp_autostart_3, (SELECT | CMD_ONLY_STRT));
6182	WR_HARPOON(p_port + hp_scsictrl_0, (SEL_TAR | ENA_RESEL));
6183
6184	while (!(RDW_HARPOON((p_port + hp_intstat)) &
6185		 (RESET | PROG_HLT | TIMEOUT | AUTO_INT))) {
6186	}
6187
6188	if (RDW_HARPOON((p_port + hp_intstat)) & RESET)
6189		FPT_Wait(p_port, TO_250ms);
6190
6191	DISABLE_AUTO(p_port);
6192
6193	WR_HARPOON(p_port + hp_addstat,
6194		   (RD_HARPOON(p_port + hp_addstat) & ~SCAM_TIMER));
6195	WR_HARPOON(p_port + hp_seltimeout, TO_290ms);
6196
6197	SGRAM_ACCESS(p_port);
6198
6199	if (RDW_HARPOON((p_port + hp_intstat)) & (RESET | TIMEOUT)) {
6200
6201		WRW_HARPOON((p_port + hp_intstat),
6202			    (RESET | TIMEOUT | SEL | BUS_FREE | PHASE));
6203
6204		WR_HARPOON(p_port + hp_page_ctrl,
6205			   (RD_HARPOON(p_port + hp_page_ctrl) &
6206			    ~G_INT_DISABLE));
6207
6208		return 0;	/*No legacy device */
6209	}
6210
6211	else {
6212
6213		while (!(RDW_HARPOON((p_port + hp_intstat)) & BUS_FREE)) {
6214			if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ) {
6215				WR_HARPOON(p_port + hp_scsisig,
6216					   (SCSI_ACK + S_ILL_PH));
6217				ACCEPT_MSG(p_port);
6218			}
6219		}
6220
6221		WRW_HARPOON((p_port + hp_intstat), CLR_ALL_INT_1);
6222
6223		WR_HARPOON(p_port + hp_page_ctrl,
6224			   (RD_HARPOON(p_port + hp_page_ctrl) &
6225			    ~G_INT_DISABLE));
6226
6227		return 1;	/*Found one of them oldies! */
6228	}
6229}
6230
6231/*---------------------------------------------------------------------
6232 *
6233 * Function: FPT_scwtsel
6234 *
6235 * Description: Wait to be selected by another SCAM initiator.
6236 *
6237 *---------------------------------------------------------------------*/
6238
6239static void FPT_scwtsel(unsigned long p_port)
6240{
6241	while (!(RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL)) {
6242	}
6243}
6244
6245/*---------------------------------------------------------------------
6246 *
6247 * Function: FPT_inisci
6248 *
6249 * Description: Setup the data Structure with the info from the EEPROM.
6250 *
6251 *---------------------------------------------------------------------*/
6252
6253static void FPT_inisci(unsigned char p_card, unsigned long p_port,
6254		       unsigned char p_our_id)
6255{
6256	unsigned char i, k, max_id;
6257	unsigned short ee_data;
6258	struct nvram_info *pCurrNvRam;
6259
6260	pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
6261
6262	if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6263		max_id = 0x08;
6264
6265	else
6266		max_id = 0x10;
6267
6268	if (pCurrNvRam) {
6269		for (i = 0; i < max_id; i++) {
6270
6271			for (k = 0; k < 4; k++)
6272				FPT_scamInfo[i].id_string[k] =
6273				    pCurrNvRam->niScamTbl[i][k];
6274			for (k = 4; k < ID_STRING_LENGTH; k++)
6275				FPT_scamInfo[i].id_string[k] =
6276				    (unsigned char)0x00;
6277
6278			if (FPT_scamInfo[i].id_string[0] == 0x00)
6279				FPT_scamInfo[i].state = ID_UNUSED;	/*Default to unused ID. */
6280			else
6281				FPT_scamInfo[i].state = ID_UNASSIGNED;	/*Default to unassigned ID. */
6282
6283		}
6284	} else {
6285		for (i = 0; i < max_id; i++) {
6286			for (k = 0; k < ID_STRING_LENGTH; k += 2) {
6287				ee_data =
6288				    FPT_utilEERead(p_port,
6289						   (unsigned
6290						    short)((EE_SCAMBASE / 2) +
6291							   (unsigned short)(i *
6292									    ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
6293				FPT_scamInfo[i].id_string[k] =
6294				    (unsigned char)ee_data;
6295				ee_data >>= 8;
6296				FPT_scamInfo[i].id_string[k + 1] =
6297				    (unsigned char)ee_data;
6298			}
6299
6300			if ((FPT_scamInfo[i].id_string[0] == 0x00) ||
6301			    (FPT_scamInfo[i].id_string[0] == 0xFF))
6302
6303				FPT_scamInfo[i].state = ID_UNUSED;	/*Default to unused ID. */
6304
6305			else
6306				FPT_scamInfo[i].state = ID_UNASSIGNED;	/*Default to unassigned ID. */
6307
6308		}
6309	}
6310	for (k = 0; k < ID_STRING_LENGTH; k++)
6311		FPT_scamInfo[p_our_id].id_string[k] = FPT_scamHAString[k];
6312
6313}
6314
6315/*---------------------------------------------------------------------
6316 *
6317 * Function: FPT_scmachid
6318 *
6319 * Description: Match the Device ID string with our values stored in
6320 *              the EEPROM.
6321 *
6322 *---------------------------------------------------------------------*/
6323
6324static unsigned char FPT_scmachid(unsigned char p_card,
6325				  unsigned char p_id_string[])
6326{
6327
6328	unsigned char i, k, match;
6329
6330	for (i = 0; i < MAX_SCSI_TAR; i++) {
6331
6332		match = 1;
6333
6334		for (k = 0; k < ID_STRING_LENGTH; k++) {
6335			if (p_id_string[k] != FPT_scamInfo[i].id_string[k])
6336				match = 0;
6337		}
6338
6339		if (match) {
6340			FPT_scamInfo[i].state = ID_ASSIGNED;
6341			return i;
6342		}
6343
6344	}
6345
6346	if (p_id_string[0] & BIT(5))
6347		i = 8;
6348	else
6349		i = MAX_SCSI_TAR;
6350
6351	if (((p_id_string[0] & 0x06) == 0x02)
6352	    || ((p_id_string[0] & 0x06) == 0x04))
6353		match = p_id_string[1] & (unsigned char)0x1F;
6354	else
6355		match = 7;
6356
6357	while (i > 0) {
6358		i--;
6359
6360		if (FPT_scamInfo[match].state == ID_UNUSED) {
6361			for (k = 0; k < ID_STRING_LENGTH; k++) {
6362				FPT_scamInfo[match].id_string[k] =
6363				    p_id_string[k];
6364			}
6365
6366			FPT_scamInfo[match].state = ID_ASSIGNED;
6367
6368			if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
6369				FPT_BL_Card[p_card].globalFlags |=
6370				    F_UPDATE_EEPROM;
6371			return match;
6372
6373		}
6374
6375		match--;
6376
6377		if (match == 0xFF) {
6378			if (p_id_string[0] & BIT(5))
6379				match = 7;
6380			else
6381				match = MAX_SCSI_TAR - 1;
6382		}
6383	}
6384
6385	if (p_id_string[0] & BIT(7)) {
6386		return CLR_PRIORITY;
6387	}
6388
6389	if (p_id_string[0] & BIT(5))
6390		i = 8;
6391	else
6392		i = MAX_SCSI_TAR;
6393
6394	if (((p_id_string[0] & 0x06) == 0x02)
6395	    || ((p_id_string[0] & 0x06) == 0x04))
6396		match = p_id_string[1] & (unsigned char)0x1F;
6397	else
6398		match = 7;
6399
6400	while (i > 0) {
6401
6402		i--;
6403
6404		if (FPT_scamInfo[match].state == ID_UNASSIGNED) {
6405			for (k = 0; k < ID_STRING_LENGTH; k++) {
6406				FPT_scamInfo[match].id_string[k] =
6407				    p_id_string[k];
6408			}
6409
6410			FPT_scamInfo[match].id_string[0] |= BIT(7);
6411			FPT_scamInfo[match].state = ID_ASSIGNED;
6412			if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
6413				FPT_BL_Card[p_card].globalFlags |=
6414				    F_UPDATE_EEPROM;
6415			return match;
6416
6417		}
6418
6419		match--;
6420
6421		if (match == 0xFF) {
6422			if (p_id_string[0] & BIT(5))
6423				match = 7;
6424			else
6425				match = MAX_SCSI_TAR - 1;
6426		}
6427	}
6428
6429	return NO_ID_AVAIL;
6430}
6431
6432/*---------------------------------------------------------------------
6433 *
6434 * Function: FPT_scsavdi
6435 *
6436 * Description: Save off the device SCAM ID strings.
6437 *
6438 *---------------------------------------------------------------------*/
6439
6440static void FPT_scsavdi(unsigned char p_card, unsigned long p_port)
6441{
6442	unsigned char i, k, max_id;
6443	unsigned short ee_data, sum_data;
6444
6445	sum_data = 0x0000;
6446
6447	for (i = 1; i < EE_SCAMBASE / 2; i++) {
6448		sum_data += FPT_utilEERead(p_port, i);
6449	}
6450
6451	FPT_utilEEWriteOnOff(p_port, 1);	/* Enable write access to the EEPROM */
6452
6453	if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6454		max_id = 0x08;
6455
6456	else
6457		max_id = 0x10;
6458
6459	for (i = 0; i < max_id; i++) {
6460
6461		for (k = 0; k < ID_STRING_LENGTH; k += 2) {
6462			ee_data = FPT_scamInfo[i].id_string[k + 1];
6463			ee_data <<= 8;
6464			ee_data |= FPT_scamInfo[i].id_string[k];
6465			sum_data += ee_data;
6466			FPT_utilEEWrite(p_port, ee_data,
6467					(unsigned short)((EE_SCAMBASE / 2) +
6468							 (unsigned short)(i *
6469									  ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
6470		}
6471	}
6472
6473	FPT_utilEEWrite(p_port, sum_data, EEPROM_CHECK_SUM / 2);
6474	FPT_utilEEWriteOnOff(p_port, 0);	/* Turn off write access */
6475}
6476
6477/*---------------------------------------------------------------------
6478 *
6479 * Function: FPT_XbowInit
6480 *
6481 * Description: Setup the Xbow for normal operation.
6482 *
6483 *---------------------------------------------------------------------*/
6484
6485static void FPT_XbowInit(unsigned long port, unsigned char ScamFlg)
6486{
6487	unsigned char i;
6488
6489	i = RD_HARPOON(port + hp_page_ctrl);
6490	WR_HARPOON(port + hp_page_ctrl, (unsigned char)(i | G_INT_DISABLE));
6491
6492	WR_HARPOON(port + hp_scsireset, 0x00);
6493	WR_HARPOON(port + hp_portctrl_1, HOST_MODE8);
6494
6495	WR_HARPOON(port + hp_scsireset, (DMA_RESET | HPSCSI_RESET | PROG_RESET |
6496					 FIFO_CLR));
6497
6498	WR_HARPOON(port + hp_scsireset, SCSI_INI);
6499
6500	WR_HARPOON(port + hp_clkctrl_0, CLKCTRL_DEFAULT);
6501
6502	WR_HARPOON(port + hp_scsisig, 0x00);	/*  Clear any signals we might */
6503	WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
6504
6505	WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
6506
6507	FPT_default_intena = RESET | RSEL | PROG_HLT | TIMEOUT |
6508	    BUS_FREE | XFER_CNT_0 | AUTO_INT;
6509
6510	if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2))
6511		FPT_default_intena |= SCAM_SEL;
6512
6513	WRW_HARPOON((port + hp_intena), FPT_default_intena);
6514
6515	WR_HARPOON(port + hp_seltimeout, TO_290ms);
6516
6517	/* Turn on SCSI_MODE8 for narrow cards to fix the
6518	   strapping issue with the DUAL CHANNEL card */
6519	if (RD_HARPOON(port + hp_page_ctrl) & NARROW_SCSI_CARD)
6520		WR_HARPOON(port + hp_addstat, SCSI_MODE8);
6521
6522	WR_HARPOON(port + hp_page_ctrl, i);
6523
6524}
6525
6526/*---------------------------------------------------------------------
6527 *
6528 * Function: FPT_BusMasterInit
6529 *
6530 * Description: Initialize the BusMaster for normal operations.
6531 *
6532 *---------------------------------------------------------------------*/
6533
6534static void FPT_BusMasterInit(unsigned long p_port)
6535{
6536
6537	WR_HARPOON(p_port + hp_sys_ctrl, DRVR_RST);
6538	WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
6539
6540	WR_HARPOON(p_port + hp_host_blk_cnt, XFER_BLK64);
6541
6542	WR_HARPOON(p_port + hp_bm_ctrl, (BMCTRL_DEFAULT));
6543
6544	WR_HARPOON(p_port + hp_ee_ctrl, (SCSI_TERM_ENA_H));
6545
6546	RD_HARPOON(p_port + hp_int_status);	/*Clear interrupts. */
6547	WR_HARPOON(p_port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
6548	WR_HARPOON(p_port + hp_page_ctrl, (RD_HARPOON(p_port + hp_page_ctrl) &
6549					   ~SCATTER_EN));
6550}
6551
6552/*---------------------------------------------------------------------
6553 *
6554 * Function: FPT_DiagEEPROM
6555 *
6556 * Description: Verfiy checksum and 'Key' and initialize the EEPROM if
6557 *              necessary.
6558 *
6559 *---------------------------------------------------------------------*/
6560
6561static void FPT_DiagEEPROM(unsigned long p_port)
6562{
6563	unsigned short index, temp, max_wd_cnt;
6564
6565	if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6566		max_wd_cnt = EEPROM_WD_CNT;
6567	else
6568		max_wd_cnt = EEPROM_WD_CNT * 2;
6569
6570	temp = FPT_utilEERead(p_port, FW_SIGNATURE / 2);
6571
6572	if (temp == 0x4641) {
6573
6574		for (index = 2; index < max_wd_cnt; index++) {
6575
6576			temp += FPT_utilEERead(p_port, index);
6577
6578		}
6579
6580		if (temp == FPT_utilEERead(p_port, EEPROM_CHECK_SUM / 2)) {
6581
6582			return;	/*EEPROM is Okay so return now! */
6583		}
6584	}
6585
6586	FPT_utilEEWriteOnOff(p_port, (unsigned char)1);
6587
6588	for (index = 0; index < max_wd_cnt; index++) {
6589
6590		FPT_utilEEWrite(p_port, 0x0000, index);
6591	}
6592
6593	temp = 0;
6594
6595	FPT_utilEEWrite(p_port, 0x4641, FW_SIGNATURE / 2);
6596	temp += 0x4641;
6597	FPT_utilEEWrite(p_port, 0x3920, MODEL_NUMB_0 / 2);
6598	temp += 0x3920;
6599	FPT_utilEEWrite(p_port, 0x3033, MODEL_NUMB_2 / 2);
6600	temp += 0x3033;
6601	FPT_utilEEWrite(p_port, 0x2020, MODEL_NUMB_4 / 2);
6602	temp += 0x2020;
6603	FPT_utilEEWrite(p_port, 0x70D3, SYSTEM_CONFIG / 2);
6604	temp += 0x70D3;
6605	FPT_utilEEWrite(p_port, 0x0010, BIOS_CONFIG / 2);
6606	temp += 0x0010;
6607	FPT_utilEEWrite(p_port, 0x0003, SCAM_CONFIG / 2);
6608	temp += 0x0003;
6609	FPT_utilEEWrite(p_port, 0x0007, ADAPTER_SCSI_ID / 2);
6610	temp += 0x0007;
6611
6612	FPT_utilEEWrite(p_port, 0x0000, IGNORE_B_SCAN / 2);
6613	temp += 0x0000;
6614	FPT_utilEEWrite(p_port, 0x0000, SEND_START_ENA / 2);
6615	temp += 0x0000;
6616	FPT_utilEEWrite(p_port, 0x0000, DEVICE_ENABLE / 2);
6617	temp += 0x0000;
6618
6619	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL01 / 2);
6620	temp += 0x4242;
6621	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL23 / 2);
6622	temp += 0x4242;
6623	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL45 / 2);
6624	temp += 0x4242;
6625	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL67 / 2);
6626	temp += 0x4242;
6627	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL89 / 2);
6628	temp += 0x4242;
6629	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLab / 2);
6630	temp += 0x4242;
6631	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLcd / 2);
6632	temp += 0x4242;
6633	FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLef / 2);
6634	temp += 0x4242;
6635
6636	FPT_utilEEWrite(p_port, 0x6C46, 64 / 2);	/*PRODUCT ID */
6637	temp += 0x6C46;
6638	FPT_utilEEWrite(p_port, 0x7361, 66 / 2);	/* FlashPoint LT   */
6639	temp += 0x7361;
6640	FPT_utilEEWrite(p_port, 0x5068, 68 / 2);
6641	temp += 0x5068;
6642	FPT_utilEEWrite(p_port, 0x696F, 70 / 2);
6643	temp += 0x696F;
6644	FPT_utilEEWrite(p_port, 0x746E, 72 / 2);
6645	temp += 0x746E;
6646	FPT_utilEEWrite(p_port, 0x4C20, 74 / 2);
6647	temp += 0x4C20;
6648	FPT_utilEEWrite(p_port, 0x2054, 76 / 2);
6649	temp += 0x2054;
6650	FPT_utilEEWrite(p_port, 0x2020, 78 / 2);
6651	temp += 0x2020;
6652
6653	index = ((EE_SCAMBASE / 2) + (7 * 16));
6654	FPT_utilEEWrite(p_port, (0x0700 + TYPE_CODE0), index);
6655	temp += (0x0700 + TYPE_CODE0);
6656	index++;
6657	FPT_utilEEWrite(p_port, 0x5542, index);	/*Vendor ID code */
6658	temp += 0x5542;		/* BUSLOGIC      */
6659	index++;
6660	FPT_utilEEWrite(p_port, 0x4C53, index);
6661	temp += 0x4C53;
6662	index++;
6663	FPT_utilEEWrite(p_port, 0x474F, index);
6664	temp += 0x474F;
6665	index++;
6666	FPT_utilEEWrite(p_port, 0x4349, index);
6667	temp += 0x4349;
6668	index++;
6669	FPT_utilEEWrite(p_port, 0x5442, index);	/*Vendor unique code */
6670	temp += 0x5442;		/* BT- 930           */
6671	index++;
6672	FPT_utilEEWrite(p_port, 0x202D, index);
6673	temp += 0x202D;
6674	index++;
6675	FPT_utilEEWrite(p_port, 0x3339, index);
6676	temp += 0x3339;
6677	index++;		/*Serial #          */
6678	FPT_utilEEWrite(p_port, 0x2030, index);	/* 01234567         */
6679	temp += 0x2030;
6680	index++;
6681	FPT_utilEEWrite(p_port, 0x5453, index);
6682	temp += 0x5453;
6683	index++;
6684	FPT_utilEEWrite(p_port, 0x5645, index);
6685	temp += 0x5645;
6686	index++;
6687	FPT_utilEEWrite(p_port, 0x2045, index);
6688	temp += 0x2045;
6689	index++;
6690	FPT_utilEEWrite(p_port, 0x202F, index);
6691	temp += 0x202F;
6692	index++;
6693	FPT_utilEEWrite(p_port, 0x4F4A, index);
6694	temp += 0x4F4A;
6695	index++;
6696	FPT_utilEEWrite(p_port, 0x204E, index);
6697	temp += 0x204E;
6698	index++;
6699	FPT_utilEEWrite(p_port, 0x3539, index);
6700	temp += 0x3539;
6701
6702	FPT_utilEEWrite(p_port, temp, EEPROM_CHECK_SUM / 2);
6703
6704	FPT_utilEEWriteOnOff(p_port, (unsigned char)0);
6705
6706}
6707
6708/*---------------------------------------------------------------------
6709 *
6710 * Function: Queue Search Select
6711 *
6712 * Description: Try to find a new command to execute.
6713 *
6714 *---------------------------------------------------------------------*/
6715
6716static void FPT_queueSearchSelect(struct sccb_card *pCurrCard,
6717				  unsigned char p_card)
6718{
6719	unsigned char scan_ptr, lun;
6720	struct sccb_mgr_tar_info *currTar_Info;
6721	struct sccb *pOldSccb;
6722
6723	scan_ptr = pCurrCard->scanIndex;
6724	do {
6725		currTar_Info = &FPT_sccbMgrTbl[p_card][scan_ptr];
6726		if ((pCurrCard->globalFlags & F_CONLUN_IO) &&
6727		    ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
6728		     TAG_Q_TRYING)) {
6729			if (currTar_Info->TarSelQ_Cnt != 0) {
6730
6731				scan_ptr++;
6732				if (scan_ptr == MAX_SCSI_TAR)
6733					scan_ptr = 0;
6734
6735				for (lun = 0; lun < MAX_LUN; lun++) {
6736					if (currTar_Info->TarLUNBusy[lun] == 0) {
6737
6738						pCurrCard->currentSCCB =
6739						    currTar_Info->TarSelQ_Head;
6740						pOldSccb = NULL;
6741
6742						while ((pCurrCard->
6743							currentSCCB != NULL)
6744						       && (lun !=
6745							   pCurrCard->
6746							   currentSCCB->Lun)) {
6747							pOldSccb =
6748							    pCurrCard->
6749							    currentSCCB;
6750							pCurrCard->currentSCCB =
6751							    (struct sccb
6752							     *)(pCurrCard->
6753								currentSCCB)->
6754							    Sccb_forwardlink;
6755						}
6756						if (pCurrCard->currentSCCB ==
6757						    NULL)
6758							continue;
6759						if (pOldSccb != NULL) {
6760							pOldSccb->
6761							    Sccb_forwardlink =
6762							    (struct sccb
6763							     *)(pCurrCard->
6764								currentSCCB)->
6765							    Sccb_forwardlink;
6766							pOldSccb->
6767							    Sccb_backlink =
6768							    (struct sccb
6769							     *)(pCurrCard->
6770								currentSCCB)->
6771							    Sccb_backlink;
6772							currTar_Info->
6773							    TarSelQ_Cnt--;
6774						} else {
6775							currTar_Info->
6776							    TarSelQ_Head =
6777							    (struct sccb
6778							     *)(pCurrCard->
6779								currentSCCB)->
6780							    Sccb_forwardlink;
6781
6782							if (currTar_Info->
6783							    TarSelQ_Head ==
6784							    NULL) {
6785								currTar_Info->
6786								    TarSelQ_Tail
6787								    = NULL;
6788								currTar_Info->
6789								    TarSelQ_Cnt
6790								    = 0;
6791							} else {
6792								currTar_Info->
6793								    TarSelQ_Cnt--;
6794								currTar_Info->
6795								    TarSelQ_Head->
6796								    Sccb_backlink
6797								    =
6798								    (struct sccb
6799								     *)NULL;
6800							}
6801						}
6802						pCurrCard->scanIndex = scan_ptr;
6803
6804						pCurrCard->globalFlags |=
6805						    F_NEW_SCCB_CMD;
6806
6807						break;
6808					}
6809				}
6810			}
6811
6812			else {
6813				scan_ptr++;
6814				if (scan_ptr == MAX_SCSI_TAR) {
6815					scan_ptr = 0;
6816				}
6817			}
6818
6819		} else {
6820			if ((currTar_Info->TarSelQ_Cnt != 0) &&
6821			    (currTar_Info->TarLUNBusy[0] == 0)) {
6822
6823				pCurrCard->currentSCCB =
6824				    currTar_Info->TarSelQ_Head;
6825
6826				currTar_Info->TarSelQ_Head =
6827				    (struct sccb *)(pCurrCard->currentSCCB)->
6828				    Sccb_forwardlink;
6829
6830				if (currTar_Info->TarSelQ_Head == NULL) {
6831					currTar_Info->TarSelQ_Tail = NULL;
6832					currTar_Info->TarSelQ_Cnt = 0;
6833				} else {
6834					currTar_Info->TarSelQ_Cnt--;
6835					currTar_Info->TarSelQ_Head->
6836					    Sccb_backlink = (struct sccb *)NULL;
6837				}
6838
6839				scan_ptr++;
6840				if (scan_ptr == MAX_SCSI_TAR)
6841					scan_ptr = 0;
6842
6843				pCurrCard->scanIndex = scan_ptr;
6844
6845				pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
6846
6847				break;
6848			}
6849
6850			else {
6851				scan_ptr++;
6852				if (scan_ptr == MAX_SCSI_TAR) {
6853					scan_ptr = 0;
6854				}
6855			}
6856		}
6857	} while (scan_ptr != pCurrCard->scanIndex);
6858}
6859
6860/*---------------------------------------------------------------------
6861 *
6862 * Function: Queue Select Fail
6863 *
6864 * Description: Add the current SCCB to the head of the Queue.
6865 *
6866 *---------------------------------------------------------------------*/
6867
6868static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
6869				unsigned char p_card)
6870{
6871	unsigned char thisTarg;
6872	struct sccb_mgr_tar_info *currTar_Info;
6873
6874	if (pCurrCard->currentSCCB != NULL) {
6875		thisTarg =
6876		    (unsigned char)(((struct sccb *)(pCurrCard->currentSCCB))->
6877				    TargID);
6878		currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
6879
6880		pCurrCard->currentSCCB->Sccb_backlink = (struct sccb *)NULL;
6881
6882		pCurrCard->currentSCCB->Sccb_forwardlink =
6883		    currTar_Info->TarSelQ_Head;
6884
6885		if (currTar_Info->TarSelQ_Cnt == 0) {
6886			currTar_Info->TarSelQ_Tail = pCurrCard->currentSCCB;
6887		}
6888
6889		else {
6890			currTar_Info->TarSelQ_Head->Sccb_backlink =
6891			    pCurrCard->currentSCCB;
6892		}
6893
6894		currTar_Info->TarSelQ_Head = pCurrCard->currentSCCB;
6895
6896		pCurrCard->currentSCCB = NULL;
6897		currTar_Info->TarSelQ_Cnt++;
6898	}
6899}
6900
6901/*---------------------------------------------------------------------
6902 *
6903 * Function: Queue Command Complete
6904 *
6905 * Description: Call the callback function with the current SCCB.
6906 *
6907 *---------------------------------------------------------------------*/
6908
6909static void FPT_queueCmdComplete(struct sccb_card *pCurrCard,
6910				 struct sccb *p_sccb, unsigned char p_card)
6911{
6912
6913	unsigned char i, SCSIcmd;
6914	CALL_BK_FN callback;
6915	struct sccb_mgr_tar_info *currTar_Info;
6916
6917	SCSIcmd = p_sccb->Cdb[0];
6918
6919	if (!(p_sccb->Sccb_XferState & F_ALL_XFERRED)) {
6920
6921		if ((p_sccb->
6922		     ControlByte & (SCCB_DATA_XFER_OUT | SCCB_DATA_XFER_IN))
6923		    && (p_sccb->HostStatus == SCCB_COMPLETE)
6924		    && (p_sccb->TargetStatus != SSCHECK))
6925
6926			if ((SCSIcmd == SCSI_READ) ||
6927			    (SCSIcmd == SCSI_WRITE) ||
6928			    (SCSIcmd == SCSI_READ_EXTENDED) ||
6929			    (SCSIcmd == SCSI_WRITE_EXTENDED) ||
6930			    (SCSIcmd == SCSI_WRITE_AND_VERIFY) ||
6931			    (SCSIcmd == SCSI_START_STOP_UNIT) ||
6932			    (pCurrCard->globalFlags & F_NO_FILTER)
6933			    )
6934				p_sccb->HostStatus = SCCB_DATA_UNDER_RUN;
6935	}
6936
6937	if (p_sccb->SccbStatus == SCCB_IN_PROCESS) {
6938		if (p_sccb->HostStatus || p_sccb->TargetStatus)
6939			p_sccb->SccbStatus = SCCB_ERROR;
6940		else
6941			p_sccb->SccbStatus = SCCB_SUCCESS;
6942	}
6943
6944	if (p_sccb->Sccb_XferState & F_AUTO_SENSE) {
6945
6946		p_sccb->CdbLength = p_sccb->Save_CdbLen;
6947		for (i = 0; i < 6; i++) {
6948			p_sccb->Cdb[i] = p_sccb->Save_Cdb[i];
6949		}
6950	}
6951
6952	if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) ||
6953	    (p_sccb->OperationCode == RESIDUAL_COMMAND)) {
6954
6955		FPT_utilUpdateResidual(p_sccb);
6956	}
6957
6958	pCurrCard->cmdCounter--;
6959	if (!pCurrCard->cmdCounter) {
6960
6961		if (pCurrCard->globalFlags & F_GREEN_PC) {
6962			WR_HARPOON(pCurrCard->ioPort + hp_clkctrl_0,
6963				   (PWR_DWN | CLKCTRL_DEFAULT));
6964			WR_HARPOON(pCurrCard->ioPort + hp_sys_ctrl, STOP_CLK);
6965		}
6966
6967		WR_HARPOON(pCurrCard->ioPort + hp_semaphore,
6968			   (RD_HARPOON(pCurrCard->ioPort + hp_semaphore) &
6969			    ~SCCB_MGR_ACTIVE));
6970
6971	}
6972
6973	if (pCurrCard->discQCount != 0) {
6974		currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
6975		if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
6976		     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
6977		      TAG_Q_TRYING))) {
6978			pCurrCard->discQCount--;
6979			pCurrCard->discQ_Tbl[currTar_Info->
6980					     LunDiscQ_Idx[p_sccb->Lun]] = NULL;
6981		} else {
6982			if (p_sccb->Sccb_tag) {
6983				pCurrCard->discQCount--;
6984				pCurrCard->discQ_Tbl[p_sccb->Sccb_tag] = NULL;
6985			} else {
6986				pCurrCard->discQCount--;
6987				pCurrCard->discQ_Tbl[currTar_Info->
6988						     LunDiscQ_Idx[0]] = NULL;
6989			}
6990		}
6991
6992	}
6993
6994	callback = (CALL_BK_FN) p_sccb->SccbCallback;
6995	callback(p_sccb);
6996	pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
6997	pCurrCard->currentSCCB = NULL;
6998}
6999
7000/*---------------------------------------------------------------------
7001 *
7002 * Function: Queue Disconnect
7003 *
7004 * Description: Add SCCB to our disconnect array.
7005 *
7006 *---------------------------------------------------------------------*/
7007static void FPT_queueDisconnect(struct sccb *p_sccb, unsigned char p_card)
7008{
7009	struct sccb_mgr_tar_info *currTar_Info;
7010
7011	currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
7012
7013	if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
7014	     ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
7015		FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
7016					      LunDiscQ_Idx[p_sccb->Lun]] =
7017		    p_sccb;
7018	} else {
7019		if (p_sccb->Sccb_tag) {
7020			FPT_BL_Card[p_card].discQ_Tbl[p_sccb->Sccb_tag] =
7021			    p_sccb;
7022			FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarLUNBusy[0] =
7023			    0;
7024			FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarTagQ_Cnt++;
7025		} else {
7026			FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
7027						      LunDiscQ_Idx[0]] = p_sccb;
7028		}
7029	}
7030	FPT_BL_Card[p_card].currentSCCB = NULL;
7031}
7032
7033/*---------------------------------------------------------------------
7034 *
7035 * Function: Queue Flush SCCB
7036 *
7037 * Description: Flush all SCCB's back to the host driver for this target.
7038 *
7039 *---------------------------------------------------------------------*/
7040
7041static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code)
7042{
7043	unsigned char qtag, thisTarg;
7044	struct sccb *currSCCB;
7045	struct sccb_mgr_tar_info *currTar_Info;
7046
7047	currSCCB = FPT_BL_Card[p_card].currentSCCB;
7048	if (currSCCB != NULL) {
7049		thisTarg = (unsigned char)currSCCB->TargID;
7050		currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
7051
7052		for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
7053
7054			if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
7055			    (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
7056			     thisTarg)) {
7057
7058				FPT_BL_Card[p_card].discQ_Tbl[qtag]->
7059				    HostStatus = (unsigned char)error_code;
7060
7061				FPT_queueCmdComplete(&FPT_BL_Card[p_card],
7062						     FPT_BL_Card[p_card].
7063						     discQ_Tbl[qtag], p_card);
7064
7065				FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
7066				currTar_Info->TarTagQ_Cnt--;
7067
7068			}
7069		}
7070	}
7071
7072}
7073
7074/*---------------------------------------------------------------------
7075 *
7076 * Function: Queue Flush Target SCCB
7077 *
7078 * Description: Flush all SCCB's back to the host driver for this target.
7079 *
7080 *---------------------------------------------------------------------*/
7081
7082static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
7083				   unsigned char error_code)
7084{
7085	unsigned char qtag;
7086	struct sccb_mgr_tar_info *currTar_Info;
7087
7088	currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
7089
7090	for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
7091
7092		if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
7093		    (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg)) {
7094
7095			FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus =
7096			    (unsigned char)error_code;
7097
7098			FPT_queueCmdComplete(&FPT_BL_Card[p_card],
7099					     FPT_BL_Card[p_card].
7100					     discQ_Tbl[qtag], p_card);
7101
7102			FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
7103			currTar_Info->TarTagQ_Cnt--;
7104
7105		}
7106	}
7107
7108}
7109
7110static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char p_card)
7111{
7112	struct sccb_mgr_tar_info *currTar_Info;
7113	currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
7114
7115	p_SCCB->Sccb_forwardlink = NULL;
7116
7117	p_SCCB->Sccb_backlink = currTar_Info->TarSelQ_Tail;
7118
7119	if (currTar_Info->TarSelQ_Cnt == 0) {
7120
7121		currTar_Info->TarSelQ_Head = p_SCCB;
7122	}
7123
7124	else {
7125
7126		currTar_Info->TarSelQ_Tail->Sccb_forwardlink = p_SCCB;
7127	}
7128
7129	currTar_Info->TarSelQ_Tail = p_SCCB;
7130	currTar_Info->TarSelQ_Cnt++;
7131}
7132
7133/*---------------------------------------------------------------------
7134 *
7135 * Function: Queue Find SCCB
7136 *
7137 * Description: Search the target select Queue for this SCCB, and
7138 *              remove it if found.
7139 *
7140 *---------------------------------------------------------------------*/
7141
7142static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB,
7143				       unsigned char p_card)
7144{
7145	struct sccb *q_ptr;
7146	struct sccb_mgr_tar_info *currTar_Info;
7147
7148	currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
7149
7150	q_ptr = currTar_Info->TarSelQ_Head;
7151
7152	while (q_ptr != NULL) {
7153
7154		if (q_ptr == p_SCCB) {
7155
7156			if (currTar_Info->TarSelQ_Head == q_ptr) {
7157
7158				currTar_Info->TarSelQ_Head =
7159				    q_ptr->Sccb_forwardlink;
7160			}
7161
7162			if (currTar_Info->TarSelQ_Tail == q_ptr) {
7163
7164				currTar_Info->TarSelQ_Tail =
7165				    q_ptr->Sccb_backlink;
7166			}
7167
7168			if (q_ptr->Sccb_forwardlink != NULL) {
7169				q_ptr->Sccb_forwardlink->Sccb_backlink =
7170				    q_ptr->Sccb_backlink;
7171			}
7172
7173			if (q_ptr->Sccb_backlink != NULL) {
7174				q_ptr->Sccb_backlink->Sccb_forwardlink =
7175				    q_ptr->Sccb_forwardlink;
7176			}
7177
7178			currTar_Info->TarSelQ_Cnt--;
7179
7180			return 1;
7181		}
7182
7183		else {
7184			q_ptr = q_ptr->Sccb_forwardlink;
7185		}
7186	}
7187
7188	return 0;
7189
7190}
7191
7192/*---------------------------------------------------------------------
7193 *
7194 * Function: Utility Update Residual Count
7195 *
7196 * Description: Update the XferCnt to the remaining byte count.
7197 *              If we transferred all the data then just write zero.
7198 *              If Non-SG transfer then report Total Cnt - Actual Transfer
7199 *              Cnt.  For SG transfers add the count fields of all
7200 *              remaining SG elements, as well as any partial remaining
7201 *              element.
7202 *
7203 *---------------------------------------------------------------------*/
7204
7205static void FPT_utilUpdateResidual(struct sccb *p_SCCB)
7206{
7207	unsigned long partial_cnt;
7208	unsigned int sg_index;
7209	unsigned long *sg_ptr;
7210
7211	if (p_SCCB->Sccb_XferState & F_ALL_XFERRED) {
7212
7213		p_SCCB->DataLength = 0x0000;
7214	}
7215
7216	else if (p_SCCB->Sccb_XferState & F_SG_XFER) {
7217
7218		partial_cnt = 0x0000;
7219
7220		sg_index = p_SCCB->Sccb_sgseg;
7221
7222		sg_ptr = (unsigned long *)p_SCCB->DataPointer;
7223
7224		if (p_SCCB->Sccb_SGoffset) {
7225
7226			partial_cnt = p_SCCB->Sccb_SGoffset;
7227			sg_index++;
7228		}
7229
7230		while (((unsigned long)sg_index *
7231			(unsigned long)SG_ELEMENT_SIZE) < p_SCCB->DataLength) {
7232
7233			partial_cnt += *(sg_ptr + (sg_index * 2));
7234			sg_index++;
7235		}
7236
7237		p_SCCB->DataLength = partial_cnt;
7238	}
7239
7240	else {
7241
7242		p_SCCB->DataLength -= p_SCCB->Sccb_ATC;
7243	}
7244}
7245
7246/*---------------------------------------------------------------------
7247 *
7248 * Function: Wait 1 Second
7249 *
7250 * Description: Wait for 1 second.
7251 *
7252 *---------------------------------------------------------------------*/
7253
7254static void FPT_Wait1Second(unsigned long p_port)
7255{
7256	unsigned char i;
7257
7258	for (i = 0; i < 4; i++) {
7259
7260		FPT_Wait(p_port, TO_250ms);
7261
7262		if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
7263			break;
7264
7265		if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
7266			break;
7267	}
7268}
7269
7270/*---------------------------------------------------------------------
7271 *
7272 * Function: FPT_Wait
7273 *
7274 * Description: Wait the desired delay.
7275 *
7276 *---------------------------------------------------------------------*/
7277
7278static void FPT_Wait(unsigned long p_port, unsigned char p_delay)
7279{
7280	unsigned char old_timer;
7281	unsigned char green_flag;
7282
7283	old_timer = RD_HARPOON(p_port + hp_seltimeout);
7284
7285	green_flag = RD_HARPOON(p_port + hp_clkctrl_0);
7286	WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
7287
7288	WR_HARPOON(p_port + hp_seltimeout, p_delay);
7289	WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
7290	WRW_HARPOON((p_port + hp_intena), (FPT_default_intena & ~TIMEOUT));
7291
7292	WR_HARPOON(p_port + hp_portctrl_0,
7293		   (RD_HARPOON(p_port + hp_portctrl_0) | START_TO));
7294
7295	while (!(RDW_HARPOON((p_port + hp_intstat)) & TIMEOUT)) {
7296
7297		if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
7298			break;
7299
7300		if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
7301			break;
7302	}
7303
7304	WR_HARPOON(p_port + hp_portctrl_0,
7305		   (RD_HARPOON(p_port + hp_portctrl_0) & ~START_TO));
7306
7307	WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
7308	WRW_HARPOON((p_port + hp_intena), FPT_default_intena);
7309
7310	WR_HARPOON(p_port + hp_clkctrl_0, green_flag);
7311
7312	WR_HARPOON(p_port + hp_seltimeout, old_timer);
7313}
7314
7315/*---------------------------------------------------------------------
7316 *
7317 * Function: Enable/Disable Write to EEPROM
7318 *
7319 * Description: The EEPROM must first be enabled for writes
7320 *              A total of 9 clocks are needed.
7321 *
7322 *---------------------------------------------------------------------*/
7323
7324static void FPT_utilEEWriteOnOff(unsigned long p_port, unsigned char p_mode)
7325{
7326	unsigned char ee_value;
7327
7328	ee_value =
7329	    (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
7330			    (EXT_ARB_ACK | SCSI_TERM_ENA_H));
7331
7332	if (p_mode)
7333
7334		FPT_utilEESendCmdAddr(p_port, EWEN, EWEN_ADDR);
7335
7336	else
7337
7338		FPT_utilEESendCmdAddr(p_port, EWDS, EWDS_ADDR);
7339
7340	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));	/*Turn off CS */
7341	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);	/*Turn off Master Select */
7342}
7343
7344/*---------------------------------------------------------------------
7345 *
7346 * Function: Write EEPROM
7347 *
7348 * Description: Write a word to the EEPROM at the specified
7349 *              address.
7350 *
7351 *---------------------------------------------------------------------*/
7352
7353static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data,
7354			    unsigned short ee_addr)
7355{
7356
7357	unsigned char ee_value;
7358	unsigned short i;
7359
7360	ee_value =
7361	    (unsigned
7362	     char)((RD_HARPOON(p_port + hp_ee_ctrl) &
7363		    (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
7364
7365	FPT_utilEESendCmdAddr(p_port, EE_WRITE, ee_addr);
7366
7367	ee_value |= (SEE_MS + SEE_CS);
7368
7369	for (i = 0x8000; i != 0; i >>= 1) {
7370
7371		if (i & ee_data)
7372			ee_value |= SEE_DO;
7373		else
7374			ee_value &= ~SEE_DO;
7375
7376		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7377		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7378		ee_value |= SEE_CLK;	/* Clock  data! */
7379		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7380		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7381		ee_value &= ~SEE_CLK;
7382		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7383		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7384	}
7385	ee_value &= (EXT_ARB_ACK | SCSI_TERM_ENA_H);
7386	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));
7387
7388	FPT_Wait(p_port, TO_10ms);
7389
7390	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS | SEE_CS));	/* Set CS to EEPROM */
7391	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));	/* Turn off CS */
7392	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);	/* Turn off Master Select */
7393}
7394
7395/*---------------------------------------------------------------------
7396 *
7397 * Function: Read EEPROM
7398 *
7399 * Description: Read a word from the EEPROM at the desired
7400 *              address.
7401 *
7402 *---------------------------------------------------------------------*/
7403
7404static unsigned short FPT_utilEERead(unsigned long p_port,
7405				     unsigned short ee_addr)
7406{
7407	unsigned short i, ee_data1, ee_data2;
7408
7409	i = 0;
7410	ee_data1 = FPT_utilEEReadOrg(p_port, ee_addr);
7411	do {
7412		ee_data2 = FPT_utilEEReadOrg(p_port, ee_addr);
7413
7414		if (ee_data1 == ee_data2)
7415			return ee_data1;
7416
7417		ee_data1 = ee_data2;
7418		i++;
7419
7420	} while (i < 4);
7421
7422	return ee_data1;
7423}
7424
7425/*---------------------------------------------------------------------
7426 *
7427 * Function: Read EEPROM Original 
7428 *
7429 * Description: Read a word from the EEPROM at the desired
7430 *              address.
7431 *
7432 *---------------------------------------------------------------------*/
7433
7434static unsigned short FPT_utilEEReadOrg(unsigned long p_port,
7435					unsigned short ee_addr)
7436{
7437
7438	unsigned char ee_value;
7439	unsigned short i, ee_data;
7440
7441	ee_value =
7442	    (unsigned
7443	     char)((RD_HARPOON(p_port + hp_ee_ctrl) &
7444		    (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
7445
7446	FPT_utilEESendCmdAddr(p_port, EE_READ, ee_addr);
7447
7448	ee_value |= (SEE_MS + SEE_CS);
7449	ee_data = 0;
7450
7451	for (i = 1; i <= 16; i++) {
7452
7453		ee_value |= SEE_CLK;	/* Clock  data! */
7454		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7455		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7456		ee_value &= ~SEE_CLK;
7457		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7458		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7459
7460		ee_data <<= 1;
7461
7462		if (RD_HARPOON(p_port + hp_ee_ctrl) & SEE_DI)
7463			ee_data |= 1;
7464	}
7465
7466	ee_value &= ~(SEE_MS + SEE_CS);
7467	WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));	/*Turn off CS */
7468	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);	/*Turn off Master Select */
7469
7470	return ee_data;
7471}
7472
7473/*---------------------------------------------------------------------
7474 *
7475 * Function: Send EE command and Address to the EEPROM
7476 *
7477 * Description: Transfers the correct command and sends the address
7478 *              to the eeprom.
7479 *
7480 *---------------------------------------------------------------------*/
7481
7482static void FPT_utilEESendCmdAddr(unsigned long p_port, unsigned char ee_cmd,
7483				  unsigned short ee_addr)
7484{
7485	unsigned char ee_value;
7486	unsigned char narrow_flg;
7487
7488	unsigned short i;
7489
7490	narrow_flg =
7491	    (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
7492			    NARROW_SCSI_CARD);
7493
7494	ee_value = SEE_MS;
7495	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7496
7497	ee_value |= SEE_CS;	/* Set CS to EEPROM */
7498	WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7499
7500	for (i = 0x04; i != 0; i >>= 1) {
7501
7502		if (i & ee_cmd)
7503			ee_value |= SEE_DO;
7504		else
7505			ee_value &= ~SEE_DO;
7506
7507		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7508		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7509		ee_value |= SEE_CLK;	/* Clock  data! */
7510		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7511		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7512		ee_value &= ~SEE_CLK;
7513		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7514		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7515	}
7516
7517	if (narrow_flg)
7518		i = 0x0080;
7519
7520	else
7521		i = 0x0200;
7522
7523	while (i != 0) {
7524
7525		if (i & ee_addr)
7526			ee_value |= SEE_DO;
7527		else
7528			ee_value &= ~SEE_DO;
7529
7530		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7531		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7532		ee_value |= SEE_CLK;	/* Clock  data! */
7533		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7534		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7535		ee_value &= ~SEE_CLK;
7536		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7537		WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7538
7539		i >>= 1;
7540	}
7541}
7542
7543static unsigned short FPT_CalcCrc16(unsigned char buffer[])
7544{
7545	unsigned short crc = 0;
7546	int i, j;
7547	unsigned short ch;
7548	for (i = 0; i < ID_STRING_LENGTH; i++) {
7549		ch = (unsigned short)buffer[i];
7550		for (j = 0; j < 8; j++) {
7551			if ((crc ^ ch) & 1)
7552				crc = (crc >> 1) ^ CRCMASK;
7553			else
7554				crc >>= 1;
7555			ch >>= 1;
7556		}
7557	}
7558	return crc;
7559}
7560
7561static unsigned char FPT_CalcLrc(unsigned char buffer[])
7562{
7563	int i;
7564	unsigned char lrc;
7565	lrc = 0;
7566	for (i = 0; i < ID_STRING_LENGTH; i++)
7567		lrc ^= buffer[i];
7568	return lrc;
7569}
7570
7571/*
7572  The following inline definitions avoid type conflicts.
7573*/
7574
7575static inline unsigned char
7576FlashPoint__ProbeHostAdapter(struct FlashPoint_Info *FlashPointInfo)
7577{
7578	return FlashPoint_ProbeHostAdapter((struct sccb_mgr_info *)
7579					   FlashPointInfo);
7580}
7581
7582static inline FlashPoint_CardHandle_T
7583FlashPoint__HardwareResetHostAdapter(struct FlashPoint_Info *FlashPointInfo)
7584{
7585	return FlashPoint_HardwareResetHostAdapter((struct sccb_mgr_info *)
7586						   FlashPointInfo);
7587}
7588
7589static inline void
7590FlashPoint__ReleaseHostAdapter(FlashPoint_CardHandle_T CardHandle)
7591{
7592	FlashPoint_ReleaseHostAdapter(CardHandle);
7593}
7594
7595static inline void
7596FlashPoint__StartCCB(FlashPoint_CardHandle_T CardHandle,
7597		     struct BusLogic_CCB *CCB)
7598{
7599	FlashPoint_StartCCB(CardHandle, (struct sccb *)CCB);
7600}
7601
7602static inline void
7603FlashPoint__AbortCCB(FlashPoint_CardHandle_T CardHandle,
7604		     struct BusLogic_CCB *CCB)
7605{
7606	FlashPoint_AbortCCB(CardHandle, (struct sccb *)CCB);
7607}
7608
7609static inline bool
7610FlashPoint__InterruptPending(FlashPoint_CardHandle_T CardHandle)
7611{
7612	return FlashPoint_InterruptPending(CardHandle);
7613}
7614
7615static inline int
7616FlashPoint__HandleInterrupt(FlashPoint_CardHandle_T CardHandle)
7617{
7618	return FlashPoint_HandleInterrupt(CardHandle);
7619}
7620
7621#define FlashPoint_ProbeHostAdapter	    FlashPoint__ProbeHostAdapter
7622#define FlashPoint_HardwareResetHostAdapter FlashPoint__HardwareResetHostAdapter
7623#define FlashPoint_ReleaseHostAdapter	    FlashPoint__ReleaseHostAdapter
7624#define FlashPoint_StartCCB		    FlashPoint__StartCCB
7625#define FlashPoint_AbortCCB		    FlashPoint__AbortCCB
7626#define FlashPoint_InterruptPending	    FlashPoint__InterruptPending
7627#define FlashPoint_HandleInterrupt	    FlashPoint__HandleInterrupt
7628
7629#else				/* !CONFIG_SCSI_FLASHPOINT */
7630
7631/*
7632  Define prototypes for the FlashPoint SCCB Manager Functions.
7633*/
7634
7635extern unsigned char FlashPoint_ProbeHostAdapter(struct FlashPoint_Info *);
7636extern FlashPoint_CardHandle_T
7637FlashPoint_HardwareResetHostAdapter(struct FlashPoint_Info *);
7638extern void FlashPoint_StartCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *);
7639extern int FlashPoint_AbortCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *);
7640extern bool FlashPoint_InterruptPending(FlashPoint_CardHandle_T);
7641extern int FlashPoint_HandleInterrupt(FlashPoint_CardHandle_T);
7642extern void FlashPoint_ReleaseHostAdapter(FlashPoint_CardHandle_T);
7643
7644#endif				/* CONFIG_SCSI_FLASHPOINT */