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 +