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