brintos

brintos / linux-shallow public Read only

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