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