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