11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds 31da177e4SLinus Torvalds FlashPoint.c -- FlashPoint SCCB Manager for Linux 41da177e4SLinus Torvalds 51da177e4SLinus Torvalds This file contains the FlashPoint SCCB Manager from BusLogic's FlashPoint 61da177e4SLinus Torvalds Driver Developer's Kit, with minor modifications by Leonard N. Zubkoff for 71da177e4SLinus Torvalds Linux compatibility. It was provided by BusLogic in the form of 16 separate 81da177e4SLinus Torvalds source files, which would have unnecessarily cluttered the scsi directory, so 91da177e4SLinus Torvalds the individual files have been combined into this single file. 101da177e4SLinus Torvalds 111da177e4SLinus Torvalds Copyright 1995-1996 by Mylex Corporation. All Rights Reserved 121da177e4SLinus Torvalds 131da177e4SLinus Torvalds This file is available under both the GNU General Public License 141da177e4SLinus Torvalds and a BSD-style copyright; see LICENSE.FlashPoint for details. 151da177e4SLinus Torvalds 161da177e4SLinus Torvalds */ 171da177e4SLinus Torvalds 181da177e4SLinus Torvalds 1978b4b05dSMatthew Wilcox #ifdef CONFIG_SCSI_FLASHPOINT 201da177e4SLinus Torvalds 211da177e4SLinus Torvalds #define MAX_CARDS 8 221da177e4SLinus Torvalds #undef BUSTYPE_PCI 231da177e4SLinus Torvalds 241da177e4SLinus Torvalds #define CRCMASK 0xA001 251da177e4SLinus Torvalds 261da177e4SLinus Torvalds #define FAILURE 0xFFFFFFFFL 271da177e4SLinus Torvalds 2869eb2ea4SAlexey Dobriyan struct sccb; 2969eb2ea4SAlexey Dobriyan typedef void (*CALL_BK_FN) (struct sccb *); 301da177e4SLinus Torvalds 317f101662SAlexey Dobriyan struct sccb_mgr_info { 32d63a4cccSAlexey Dobriyan unsigned long si_baseaddr; 33db038cf8SAlexey Dobriyan unsigned char si_present; 34db038cf8SAlexey Dobriyan unsigned char si_intvect; 35db038cf8SAlexey Dobriyan unsigned char si_id; 36db038cf8SAlexey Dobriyan unsigned char si_lun; 37c823feebSAlexey Dobriyan unsigned short si_fw_revision; 38c823feebSAlexey Dobriyan unsigned short si_per_targ_init_sync; 39c823feebSAlexey Dobriyan unsigned short si_per_targ_fast_nego; 40c823feebSAlexey Dobriyan unsigned short si_per_targ_ultra_nego; 41c823feebSAlexey Dobriyan unsigned short si_per_targ_no_disc; 42c823feebSAlexey Dobriyan unsigned short si_per_targ_wide_nego; 43c823feebSAlexey Dobriyan unsigned short si_flags; 44db038cf8SAlexey Dobriyan unsigned char si_card_family; 45db038cf8SAlexey Dobriyan unsigned char si_bustype; 46db038cf8SAlexey Dobriyan unsigned char si_card_model[3]; 47db038cf8SAlexey Dobriyan unsigned char si_relative_cardnum; 48db038cf8SAlexey Dobriyan unsigned char si_reserved[4]; 49d63a4cccSAlexey Dobriyan unsigned long si_OS_reserved; 50db038cf8SAlexey Dobriyan unsigned char si_XlatInfo[4]; 51d63a4cccSAlexey Dobriyan unsigned long si_reserved2[5]; 52d63a4cccSAlexey Dobriyan unsigned long si_secondary_range; 537f101662SAlexey Dobriyan }; 541da177e4SLinus Torvalds 551da177e4SLinus Torvalds #define SCSI_PARITY_ENA 0x0001 561da177e4SLinus Torvalds #define LOW_BYTE_TERM 0x0010 571da177e4SLinus Torvalds #define HIGH_BYTE_TERM 0x0020 581da177e4SLinus Torvalds #define BUSTYPE_PCI 0x3 591da177e4SLinus Torvalds 601da177e4SLinus Torvalds #define SUPPORT_16TAR_32LUN 0x0002 611da177e4SLinus Torvalds #define SOFT_RESET 0x0004 621da177e4SLinus Torvalds #define EXTENDED_TRANSLATION 0x0008 631da177e4SLinus Torvalds #define POST_ALL_UNDERRRUNS 0x0040 641da177e4SLinus Torvalds #define FLAG_SCAM_ENABLED 0x0080 651da177e4SLinus Torvalds #define FLAG_SCAM_LEVEL2 0x0100 661da177e4SLinus Torvalds 671da177e4SLinus Torvalds #define HARPOON_FAMILY 0x02 681da177e4SLinus Torvalds 6932357988SAlexey Dobriyan /* SCCB struct used for both SCCB and UCB manager compiles! 701da177e4SLinus Torvalds * The UCB Manager treats the SCCB as it's 'native hardware structure' 711da177e4SLinus Torvalds */ 721da177e4SLinus Torvalds 731da177e4SLinus Torvalds #pragma pack(1) 7469eb2ea4SAlexey Dobriyan struct sccb { 75db038cf8SAlexey Dobriyan unsigned char OperationCode; 76db038cf8SAlexey Dobriyan unsigned char ControlByte; 77db038cf8SAlexey Dobriyan unsigned char CdbLength; 78db038cf8SAlexey Dobriyan unsigned char RequestSenseLength; 79d63a4cccSAlexey Dobriyan unsigned long DataLength; 80d63a4cccSAlexey Dobriyan unsigned long DataPointer; 81db038cf8SAlexey Dobriyan unsigned char CcbRes[2]; 82db038cf8SAlexey Dobriyan unsigned char HostStatus; 83db038cf8SAlexey Dobriyan unsigned char TargetStatus; 84db038cf8SAlexey Dobriyan unsigned char TargID; 85db038cf8SAlexey Dobriyan unsigned char Lun; 86db038cf8SAlexey Dobriyan unsigned char Cdb[12]; 87db038cf8SAlexey Dobriyan unsigned char CcbRes1; 88db038cf8SAlexey Dobriyan unsigned char Reserved1; 89d63a4cccSAlexey Dobriyan unsigned long Reserved2; 90d63a4cccSAlexey Dobriyan unsigned long SensePointer; 911da177e4SLinus Torvalds 921da177e4SLinus Torvalds CALL_BK_FN SccbCallback; /* VOID (*SccbCallback)(); */ 93d63a4cccSAlexey Dobriyan unsigned long SccbIOPort; /* Identifies board base port */ 94db038cf8SAlexey Dobriyan unsigned char SccbStatus; 95db038cf8SAlexey Dobriyan unsigned char SCCBRes2; 96c823feebSAlexey Dobriyan unsigned short SccbOSFlags; 971da177e4SLinus Torvalds 98d63a4cccSAlexey Dobriyan unsigned long Sccb_XferCnt; /* actual transfer count */ 99d63a4cccSAlexey Dobriyan unsigned long Sccb_ATC; 100d63a4cccSAlexey Dobriyan unsigned long SccbVirtDataPtr; /* virtual addr for OS/2 */ 101d63a4cccSAlexey Dobriyan unsigned long Sccb_res1; 102c823feebSAlexey Dobriyan unsigned short Sccb_MGRFlags; 103c823feebSAlexey Dobriyan unsigned short Sccb_sgseg; 104db038cf8SAlexey Dobriyan unsigned char Sccb_scsimsg; /* identify msg for selection */ 105db038cf8SAlexey Dobriyan unsigned char Sccb_tag; 106db038cf8SAlexey Dobriyan unsigned char Sccb_scsistat; 107db038cf8SAlexey Dobriyan unsigned char Sccb_idmsg; /* image of last msg in */ 10869eb2ea4SAlexey Dobriyan struct sccb *Sccb_forwardlink; 10969eb2ea4SAlexey Dobriyan struct sccb *Sccb_backlink; 110d63a4cccSAlexey Dobriyan unsigned long Sccb_savedATC; 111db038cf8SAlexey Dobriyan unsigned char Save_Cdb[6]; 112db038cf8SAlexey Dobriyan unsigned char Save_CdbLen; 113db038cf8SAlexey Dobriyan unsigned char Sccb_XferState; 114d63a4cccSAlexey Dobriyan unsigned long Sccb_SGoffset; 11569eb2ea4SAlexey Dobriyan }; 1161da177e4SLinus Torvalds 1171da177e4SLinus Torvalds #pragma pack() 1181da177e4SLinus Torvalds 1191da177e4SLinus Torvalds #define SCATTER_GATHER_COMMAND 0x02 1201da177e4SLinus Torvalds #define RESIDUAL_COMMAND 0x03 1211da177e4SLinus Torvalds #define RESIDUAL_SG_COMMAND 0x04 1221da177e4SLinus Torvalds #define RESET_COMMAND 0x81 1231da177e4SLinus Torvalds 1241da177e4SLinus Torvalds #define F_USE_CMD_Q 0x20 /*Inidcates TAGGED command. */ 1251da177e4SLinus Torvalds #define TAG_TYPE_MASK 0xC0 /*Type of tag msg to send. */ 1261da177e4SLinus Torvalds #define SCCB_DATA_XFER_OUT 0x10 /* Write */ 1271da177e4SLinus Torvalds #define SCCB_DATA_XFER_IN 0x08 /* Read */ 1281da177e4SLinus Torvalds 1291da177e4SLinus Torvalds #define NO_AUTO_REQUEST_SENSE 0x01 /* No Request Sense Buffer */ 1301da177e4SLinus Torvalds 1311da177e4SLinus Torvalds #define BUS_FREE_ST 0 1321da177e4SLinus Torvalds #define SELECT_ST 1 1331da177e4SLinus Torvalds #define SELECT_BDR_ST 2 /* Select w\ Bus Device Reset */ 1341da177e4SLinus Torvalds #define SELECT_SN_ST 3 /* Select w\ Sync Nego */ 1351da177e4SLinus Torvalds #define SELECT_WN_ST 4 /* Select w\ Wide Data Nego */ 1361da177e4SLinus Torvalds #define SELECT_Q_ST 5 /* Select w\ Tagged Q'ing */ 1371da177e4SLinus Torvalds #define COMMAND_ST 6 1381da177e4SLinus Torvalds #define DATA_OUT_ST 7 1391da177e4SLinus Torvalds #define DATA_IN_ST 8 1401da177e4SLinus Torvalds #define DISCONNECT_ST 9 1411da177e4SLinus Torvalds #define ABORT_ST 11 1421da177e4SLinus Torvalds 1431da177e4SLinus Torvalds #define F_HOST_XFER_DIR 0x01 1441da177e4SLinus Torvalds #define F_ALL_XFERRED 0x02 1451da177e4SLinus Torvalds #define F_SG_XFER 0x04 1461da177e4SLinus Torvalds #define F_AUTO_SENSE 0x08 1471da177e4SLinus Torvalds #define F_ODD_BALL_CNT 0x10 1481da177e4SLinus Torvalds #define F_NO_DATA_YET 0x80 1491da177e4SLinus Torvalds 1501da177e4SLinus Torvalds #define F_STATUSLOADED 0x01 1511da177e4SLinus Torvalds #define F_DEV_SELECTED 0x04 1521da177e4SLinus Torvalds 1531da177e4SLinus Torvalds #define SCCB_COMPLETE 0x00 /* SCCB completed without error */ 1541da177e4SLinus Torvalds #define SCCB_DATA_UNDER_RUN 0x0C 1551da177e4SLinus Torvalds #define SCCB_SELECTION_TIMEOUT 0x11 /* Set SCSI selection timed out */ 1561da177e4SLinus Torvalds #define SCCB_DATA_OVER_RUN 0x12 1571da177e4SLinus Torvalds #define SCCB_PHASE_SEQUENCE_FAIL 0x14 /* Target bus phase sequence failure */ 1581da177e4SLinus Torvalds 1591da177e4SLinus Torvalds #define SCCB_GROSS_FW_ERR 0x27 /* Major problem! */ 1601da177e4SLinus Torvalds #define SCCB_BM_ERR 0x30 /* BusMaster error. */ 1611da177e4SLinus Torvalds #define SCCB_PARITY_ERR 0x34 /* SCSI parity error */ 1621da177e4SLinus Torvalds 1631da177e4SLinus Torvalds #define SCCB_IN_PROCESS 0x00 1641da177e4SLinus Torvalds #define SCCB_SUCCESS 0x01 1651da177e4SLinus Torvalds #define SCCB_ABORT 0x02 1661da177e4SLinus Torvalds #define SCCB_ERROR 0x04 1671da177e4SLinus Torvalds 1681da177e4SLinus Torvalds #define ORION_FW_REV 3110 1691da177e4SLinus Torvalds 1701da177e4SLinus Torvalds #define QUEUE_DEPTH 254+1 /*1 for Normal disconnect 32 for Q'ing. */ 1711da177e4SLinus Torvalds 1721da177e4SLinus Torvalds #define MAX_MB_CARDS 4 /* Max. no of cards suppoerted on Mother Board */ 1731da177e4SLinus Torvalds 1741da177e4SLinus Torvalds #define MAX_SCSI_TAR 16 1751da177e4SLinus Torvalds #define MAX_LUN 32 1761da177e4SLinus Torvalds #define LUN_MASK 0x1f 1771da177e4SLinus Torvalds 1781da177e4SLinus Torvalds #define SG_BUF_CNT 16 /*Number of prefetched elements. */ 1791da177e4SLinus Torvalds 1801da177e4SLinus Torvalds #define SG_ELEMENT_SIZE 8 /*Eight byte per element. */ 1811da177e4SLinus Torvalds 182ad0e1d9fSAlexey Dobriyan #define RD_HARPOON(ioport) inb((u32)ioport) 183ad0e1d9fSAlexey Dobriyan #define RDW_HARPOON(ioport) inw((u32)ioport) 184ad0e1d9fSAlexey Dobriyan #define RD_HARP32(ioport,offset,data) (data = inl((u32)(ioport + offset))) 185ad0e1d9fSAlexey Dobriyan #define WR_HARPOON(ioport,val) outb((u8) val, (u32)ioport) 186ad0e1d9fSAlexey Dobriyan #define WRW_HARPOON(ioport,val) outw((u16)val, (u32)ioport) 187ad0e1d9fSAlexey Dobriyan #define WR_HARP32(ioport,offset,data) outl(data, (u32)(ioport + offset)) 1881da177e4SLinus Torvalds 1891da177e4SLinus Torvalds #define TAR_SYNC_MASK (BIT(7)+BIT(6)) 1901da177e4SLinus Torvalds #define SYNC_TRYING BIT(6) 1911da177e4SLinus Torvalds #define SYNC_SUPPORTED (BIT(7)+BIT(6)) 1921da177e4SLinus Torvalds 1931da177e4SLinus Torvalds #define TAR_WIDE_MASK (BIT(5)+BIT(4)) 1941da177e4SLinus Torvalds #define WIDE_ENABLED BIT(4) 1951da177e4SLinus Torvalds #define WIDE_NEGOCIATED BIT(5) 1961da177e4SLinus Torvalds 1971da177e4SLinus Torvalds #define TAR_TAG_Q_MASK (BIT(3)+BIT(2)) 1981da177e4SLinus Torvalds #define TAG_Q_TRYING BIT(2) 1991da177e4SLinus Torvalds #define TAG_Q_REJECT BIT(3) 2001da177e4SLinus Torvalds 2011da177e4SLinus Torvalds #define TAR_ALLOW_DISC BIT(0) 2021da177e4SLinus Torvalds 2031da177e4SLinus Torvalds #define EE_SYNC_MASK (BIT(0)+BIT(1)) 2041da177e4SLinus Torvalds #define EE_SYNC_5MB BIT(0) 2051da177e4SLinus Torvalds #define EE_SYNC_10MB BIT(1) 2061da177e4SLinus Torvalds #define EE_SYNC_20MB (BIT(0)+BIT(1)) 2071da177e4SLinus Torvalds 2081da177e4SLinus Torvalds #define EE_WIDE_SCSI BIT(7) 2091da177e4SLinus Torvalds 210f31dc0cdSAlexey Dobriyan struct sccb_mgr_tar_info { 2111da177e4SLinus Torvalds 21269eb2ea4SAlexey Dobriyan struct sccb *TarSelQ_Head; 21369eb2ea4SAlexey Dobriyan struct sccb *TarSelQ_Tail; 214db038cf8SAlexey Dobriyan unsigned char TarLUN_CA; /*Contingent Allgiance */ 215db038cf8SAlexey Dobriyan unsigned char TarTagQ_Cnt; 216db038cf8SAlexey Dobriyan unsigned char TarSelQ_Cnt; 217db038cf8SAlexey Dobriyan unsigned char TarStatus; 218db038cf8SAlexey Dobriyan unsigned char TarEEValue; 219db038cf8SAlexey Dobriyan unsigned char TarSyncCtrl; 220db038cf8SAlexey Dobriyan unsigned char TarReserved[2]; /* for alignment */ 221db038cf8SAlexey Dobriyan unsigned char LunDiscQ_Idx[MAX_LUN]; 222db038cf8SAlexey Dobriyan unsigned char TarLUNBusy[MAX_LUN]; 223f31dc0cdSAlexey Dobriyan }; 2241da177e4SLinus Torvalds 22568d0c1aeSAlexey Dobriyan struct nvram_info { 226db038cf8SAlexey Dobriyan unsigned char niModel; /* Model No. of card */ 227db038cf8SAlexey Dobriyan unsigned char niCardNo; /* Card no. */ 228d63a4cccSAlexey Dobriyan unsigned long niBaseAddr; /* Port Address of card */ 229db038cf8SAlexey Dobriyan unsigned char niSysConf; /* Adapter Configuration byte - Byte 16 of eeprom map */ 230db038cf8SAlexey Dobriyan unsigned char niScsiConf; /* SCSI Configuration byte - Byte 17 of eeprom map */ 231db038cf8SAlexey Dobriyan unsigned char niScamConf; /* SCAM Configuration byte - Byte 20 of eeprom map */ 232db038cf8SAlexey Dobriyan unsigned char niAdapId; /* Host Adapter ID - Byte 24 of eerpom map */ 233db038cf8SAlexey Dobriyan unsigned char niSyncTbl[MAX_SCSI_TAR / 2]; /* Sync/Wide byte of targets */ 234db038cf8SAlexey Dobriyan unsigned char niScamTbl[MAX_SCSI_TAR][4]; /* Compressed Scam name string of Targets */ 23568d0c1aeSAlexey Dobriyan }; 2361da177e4SLinus Torvalds 2371da177e4SLinus Torvalds #define MODEL_LT 1 2381da177e4SLinus Torvalds #define MODEL_DL 2 2391da177e4SLinus Torvalds #define MODEL_LW 3 2401da177e4SLinus Torvalds #define MODEL_DW 4 2411da177e4SLinus Torvalds 24213e6851aSAlexey Dobriyan struct sccb_card { 24369eb2ea4SAlexey Dobriyan struct sccb *currentSCCB; 2447f101662SAlexey Dobriyan struct sccb_mgr_info *cardInfo; 2451da177e4SLinus Torvalds 246d63a4cccSAlexey Dobriyan unsigned long ioPort; 2471da177e4SLinus Torvalds 248c823feebSAlexey Dobriyan unsigned short cmdCounter; 249db038cf8SAlexey Dobriyan unsigned char discQCount; 250db038cf8SAlexey Dobriyan unsigned char tagQ_Lst; 251db038cf8SAlexey Dobriyan unsigned char cardIndex; 252db038cf8SAlexey Dobriyan unsigned char scanIndex; 253db038cf8SAlexey Dobriyan unsigned char globalFlags; 254db038cf8SAlexey Dobriyan unsigned char ourId; 25568d0c1aeSAlexey Dobriyan struct nvram_info *pNvRamInfo; 25669eb2ea4SAlexey Dobriyan struct sccb *discQ_Tbl[QUEUE_DEPTH]; 2571da177e4SLinus Torvalds 25813e6851aSAlexey Dobriyan }; 2591da177e4SLinus Torvalds 2601da177e4SLinus Torvalds #define F_TAG_STARTED 0x01 2611da177e4SLinus Torvalds #define F_CONLUN_IO 0x02 2621da177e4SLinus Torvalds #define F_DO_RENEGO 0x04 2631da177e4SLinus Torvalds #define F_NO_FILTER 0x08 2641da177e4SLinus Torvalds #define F_GREEN_PC 0x10 2651da177e4SLinus Torvalds #define F_HOST_XFER_ACT 0x20 2661da177e4SLinus Torvalds #define F_NEW_SCCB_CMD 0x40 2671da177e4SLinus Torvalds #define F_UPDATE_EEPROM 0x80 2681da177e4SLinus Torvalds 2691da177e4SLinus Torvalds #define ID_STRING_LENGTH 32 2701da177e4SLinus Torvalds #define TYPE_CODE0 0x63 /*Level2 Mstr (bits 7-6), */ 2711da177e4SLinus Torvalds 2721da177e4SLinus Torvalds #define SLV_TYPE_CODE0 0xA3 /*Priority Bit set (bits 7-6), */ 2731da177e4SLinus Torvalds 2741da177e4SLinus Torvalds #define ASSIGN_ID 0x00 2751da177e4SLinus Torvalds #define SET_P_FLAG 0x01 2761da177e4SLinus Torvalds #define CFG_CMPLT 0x03 2771da177e4SLinus Torvalds #define DOM_MSTR 0x0F 2781da177e4SLinus Torvalds #define SYNC_PTRN 0x1F 2791da177e4SLinus Torvalds 2801da177e4SLinus Torvalds #define ID_0_7 0x18 2811da177e4SLinus Torvalds #define ID_8_F 0x11 2821da177e4SLinus Torvalds #define MISC_CODE 0x14 2831da177e4SLinus Torvalds #define CLR_P_FLAG 0x18 2841da177e4SLinus Torvalds 2851da177e4SLinus Torvalds #define INIT_SELTD 0x01 2861da177e4SLinus Torvalds #define LEVEL2_TAR 0x02 2871da177e4SLinus Torvalds 2885c04a7b8SAlexey Dobriyan enum scam_id_st { ID0, ID1, ID2, ID3, ID4, ID5, ID6, ID7, ID8, ID9, ID10, ID11, 2895c04a7b8SAlexey Dobriyan ID12, 2901da177e4SLinus Torvalds ID13, ID14, ID15, ID_UNUSED, ID_UNASSIGNED, ID_ASSIGNED, LEGACY, 2915c04a7b8SAlexey Dobriyan CLR_PRIORITY, NO_ID_AVAIL 2925c04a7b8SAlexey Dobriyan }; 2931da177e4SLinus Torvalds 2941da177e4SLinus Torvalds typedef struct SCCBscam_info { 2951da177e4SLinus Torvalds 296db038cf8SAlexey Dobriyan unsigned char id_string[ID_STRING_LENGTH]; 2971da177e4SLinus Torvalds enum scam_id_st state; 2981da177e4SLinus Torvalds 29985ae97d8SAlexey Dobriyan } SCCBSCAM_INFO; 3001da177e4SLinus Torvalds 3011da177e4SLinus Torvalds #define SCSI_REQUEST_SENSE 0x03 3021da177e4SLinus Torvalds #define SCSI_READ 0x08 3031da177e4SLinus Torvalds #define SCSI_WRITE 0x0A 3041da177e4SLinus Torvalds #define SCSI_START_STOP_UNIT 0x1B 3051da177e4SLinus Torvalds #define SCSI_READ_EXTENDED 0x28 3061da177e4SLinus Torvalds #define SCSI_WRITE_EXTENDED 0x2A 3071da177e4SLinus Torvalds #define SCSI_WRITE_AND_VERIFY 0x2E 3081da177e4SLinus Torvalds 3091da177e4SLinus Torvalds #define SSGOOD 0x00 3101da177e4SLinus Torvalds #define SSCHECK 0x02 3111da177e4SLinus Torvalds #define SSQ_FULL 0x28 3121da177e4SLinus Torvalds 3131da177e4SLinus Torvalds #define SMCMD_COMP 0x00 3141da177e4SLinus Torvalds #define SMEXT 0x01 3151da177e4SLinus Torvalds #define SMSAVE_DATA_PTR 0x02 3161da177e4SLinus Torvalds #define SMREST_DATA_PTR 0x03 3171da177e4SLinus Torvalds #define SMDISC 0x04 3181da177e4SLinus Torvalds #define SMABORT 0x06 3191da177e4SLinus Torvalds #define SMREJECT 0x07 3201da177e4SLinus Torvalds #define SMNO_OP 0x08 3211da177e4SLinus Torvalds #define SMPARITY 0x09 3221da177e4SLinus Torvalds #define SMDEV_RESET 0x0C 3231da177e4SLinus Torvalds #define SMABORT_TAG 0x0D 3241da177e4SLinus Torvalds #define SMINIT_RECOVERY 0x0F 3251da177e4SLinus Torvalds #define SMREL_RECOVERY 0x10 3261da177e4SLinus Torvalds 3271da177e4SLinus Torvalds #define SMIDENT 0x80 3281da177e4SLinus Torvalds #define DISC_PRIV 0x40 3291da177e4SLinus Torvalds 3301da177e4SLinus Torvalds #define SMSYNC 0x01 3311da177e4SLinus Torvalds #define SMWDTR 0x03 3321da177e4SLinus Torvalds #define SM8BIT 0x00 3331da177e4SLinus Torvalds #define SM16BIT 0x01 3341da177e4SLinus Torvalds #define SMIGNORWR 0x23 /* Ignore Wide Residue */ 3351da177e4SLinus Torvalds 3361da177e4SLinus Torvalds #define SIX_BYTE_CMD 0x06 3371da177e4SLinus Torvalds #define TWELVE_BYTE_CMD 0x0C 3381da177e4SLinus Torvalds 3391da177e4SLinus Torvalds #define ASYNC 0x00 3401da177e4SLinus Torvalds #define MAX_OFFSET 0x0F /* Maxbyteoffset for Sync Xfers */ 3411da177e4SLinus Torvalds 3421da177e4SLinus Torvalds #define EEPROM_WD_CNT 256 3431da177e4SLinus Torvalds 3441da177e4SLinus Torvalds #define EEPROM_CHECK_SUM 0 3451da177e4SLinus Torvalds #define FW_SIGNATURE 2 3461da177e4SLinus Torvalds #define MODEL_NUMB_0 4 3471da177e4SLinus Torvalds #define MODEL_NUMB_2 6 3481da177e4SLinus Torvalds #define MODEL_NUMB_4 8 3491da177e4SLinus Torvalds #define SYSTEM_CONFIG 16 3501da177e4SLinus Torvalds #define SCSI_CONFIG 17 3511da177e4SLinus Torvalds #define BIOS_CONFIG 18 3521da177e4SLinus Torvalds #define SCAM_CONFIG 20 3531da177e4SLinus Torvalds #define ADAPTER_SCSI_ID 24 3541da177e4SLinus Torvalds 3551da177e4SLinus Torvalds #define IGNORE_B_SCAN 32 3561da177e4SLinus Torvalds #define SEND_START_ENA 34 3571da177e4SLinus Torvalds #define DEVICE_ENABLE 36 3581da177e4SLinus Torvalds 3591da177e4SLinus Torvalds #define SYNC_RATE_TBL 38 3601da177e4SLinus Torvalds #define SYNC_RATE_TBL01 38 3611da177e4SLinus Torvalds #define SYNC_RATE_TBL23 40 3621da177e4SLinus Torvalds #define SYNC_RATE_TBL45 42 3631da177e4SLinus Torvalds #define SYNC_RATE_TBL67 44 3641da177e4SLinus Torvalds #define SYNC_RATE_TBL89 46 3651da177e4SLinus Torvalds #define SYNC_RATE_TBLab 48 3661da177e4SLinus Torvalds #define SYNC_RATE_TBLcd 50 3671da177e4SLinus Torvalds #define SYNC_RATE_TBLef 52 3681da177e4SLinus Torvalds 3691da177e4SLinus Torvalds #define EE_SCAMBASE 256 3701da177e4SLinus Torvalds 3711da177e4SLinus Torvalds #define SCAM_ENABLED BIT(2) 3721da177e4SLinus Torvalds #define SCAM_LEVEL2 BIT(3) 3731da177e4SLinus Torvalds 3741cafc30fSJiri Slaby #define RENEGO_ENA BIT(10) 3751cafc30fSJiri Slaby #define CONNIO_ENA BIT(11) 3761cafc30fSJiri Slaby #define GREEN_PC_ENA BIT(12) 3771da177e4SLinus Torvalds 3781da177e4SLinus Torvalds #define AUTO_RATE_00 00 3791da177e4SLinus Torvalds #define AUTO_RATE_05 01 3801da177e4SLinus Torvalds #define AUTO_RATE_10 02 3811da177e4SLinus Torvalds #define AUTO_RATE_20 03 3821da177e4SLinus Torvalds 3831da177e4SLinus Torvalds #define WIDE_NEGO_BIT BIT(7) 3841da177e4SLinus Torvalds #define DISC_ENABLE_BIT BIT(6) 3851da177e4SLinus Torvalds 3861da177e4SLinus Torvalds #define hp_vendor_id_0 0x00 /* LSB */ 3871da177e4SLinus Torvalds #define ORION_VEND_0 0x4B 3881da177e4SLinus Torvalds 3891da177e4SLinus Torvalds #define hp_vendor_id_1 0x01 /* MSB */ 3901da177e4SLinus Torvalds #define ORION_VEND_1 0x10 3911da177e4SLinus Torvalds 3921da177e4SLinus Torvalds #define hp_device_id_0 0x02 /* LSB */ 3931da177e4SLinus Torvalds #define ORION_DEV_0 0x30 3941da177e4SLinus Torvalds 3951da177e4SLinus Torvalds #define hp_device_id_1 0x03 /* MSB */ 3961da177e4SLinus Torvalds #define ORION_DEV_1 0x81 3971da177e4SLinus Torvalds 3981da177e4SLinus Torvalds /* Sub Vendor ID and Sub Device ID only available in 3991da177e4SLinus Torvalds Harpoon Version 2 and higher */ 4001da177e4SLinus Torvalds 4011da177e4SLinus Torvalds #define hp_sub_device_id_0 0x06 /* LSB */ 4021da177e4SLinus Torvalds 4031da177e4SLinus Torvalds #define hp_semaphore 0x0C 4041da177e4SLinus Torvalds #define SCCB_MGR_ACTIVE BIT(0) 4051da177e4SLinus Torvalds #define TICKLE_ME BIT(1) 4061da177e4SLinus Torvalds #define SCCB_MGR_PRESENT BIT(3) 4071da177e4SLinus Torvalds #define BIOS_IN_USE BIT(4) 4081da177e4SLinus Torvalds 4091da177e4SLinus Torvalds #define hp_sys_ctrl 0x0F 4101da177e4SLinus Torvalds 4111da177e4SLinus Torvalds #define STOP_CLK BIT(0) /*Turn off BusMaster Clock */ 4121da177e4SLinus Torvalds #define DRVR_RST BIT(1) /*Firmware Reset to 80C15 chip */ 4131da177e4SLinus Torvalds #define HALT_MACH BIT(3) /*Halt State Machine */ 4141da177e4SLinus Torvalds #define HARD_ABORT BIT(4) /*Hard Abort */ 4151da177e4SLinus Torvalds 4161da177e4SLinus Torvalds #define hp_host_blk_cnt 0x13 4171da177e4SLinus Torvalds 4181da177e4SLinus Torvalds #define XFER_BLK64 0x06 /* 1 1 0 64 byte per block */ 4191da177e4SLinus Torvalds 4201da177e4SLinus Torvalds #define BM_THRESHOLD 0x40 /* PCI mode can only xfer 16 bytes */ 4211da177e4SLinus Torvalds 4221da177e4SLinus Torvalds #define hp_int_mask 0x17 4231da177e4SLinus Torvalds 4241da177e4SLinus Torvalds #define INT_CMD_COMPL BIT(0) /* DMA command complete */ 4251da177e4SLinus Torvalds #define INT_EXT_STATUS BIT(1) /* Extended Status Set */ 4261da177e4SLinus Torvalds 4271da177e4SLinus Torvalds #define hp_xfer_cnt_lo 0x18 4281da177e4SLinus Torvalds #define hp_xfer_cnt_hi 0x1A 4291da177e4SLinus Torvalds #define hp_xfer_cmd 0x1B 4301da177e4SLinus Torvalds 4311da177e4SLinus Torvalds #define XFER_HOST_DMA 0x00 /* 0 0 0 Transfer Host -> DMA */ 4321da177e4SLinus Torvalds #define XFER_DMA_HOST 0x01 /* 0 0 1 Transfer DMA -> Host */ 4331da177e4SLinus Torvalds 4341da177e4SLinus Torvalds #define XFER_HOST_AUTO 0x00 /* 0 0 Auto Transfer Size */ 4351da177e4SLinus Torvalds 4361da177e4SLinus Torvalds #define XFER_DMA_8BIT 0x20 /* 0 1 8 BIT Transfer Size */ 4371da177e4SLinus Torvalds 4381da177e4SLinus Torvalds #define DISABLE_INT BIT(7) /*Do not interrupt at end of cmd. */ 4391da177e4SLinus Torvalds 4401da177e4SLinus Torvalds #define HOST_WRT_CMD ((DISABLE_INT + XFER_HOST_DMA + XFER_HOST_AUTO + XFER_DMA_8BIT)) 4411da177e4SLinus Torvalds #define HOST_RD_CMD ((DISABLE_INT + XFER_DMA_HOST + XFER_HOST_AUTO + XFER_DMA_8BIT)) 4421da177e4SLinus Torvalds 4431da177e4SLinus Torvalds #define hp_host_addr_lo 0x1C 4441da177e4SLinus Torvalds #define hp_host_addr_hmi 0x1E 4451da177e4SLinus Torvalds 4461da177e4SLinus Torvalds #define hp_ee_ctrl 0x22 4471da177e4SLinus Torvalds 4481da177e4SLinus Torvalds #define EXT_ARB_ACK BIT(7) 4491da177e4SLinus Torvalds #define SCSI_TERM_ENA_H BIT(6) /* SCSI high byte terminator */ 4501da177e4SLinus Torvalds #define SEE_MS BIT(5) 4511da177e4SLinus Torvalds #define SEE_CS BIT(3) 4521da177e4SLinus Torvalds #define SEE_CLK BIT(2) 4531da177e4SLinus Torvalds #define SEE_DO BIT(1) 4541da177e4SLinus Torvalds #define SEE_DI BIT(0) 4551da177e4SLinus Torvalds 4561da177e4SLinus Torvalds #define EE_READ 0x06 4571da177e4SLinus Torvalds #define EE_WRITE 0x05 4581da177e4SLinus Torvalds #define EWEN 0x04 4591da177e4SLinus Torvalds #define EWEN_ADDR 0x03C0 4601da177e4SLinus Torvalds #define EWDS 0x04 4611da177e4SLinus Torvalds #define EWDS_ADDR 0x0000 4621da177e4SLinus Torvalds 4631da177e4SLinus Torvalds #define hp_bm_ctrl 0x26 4641da177e4SLinus Torvalds 4651da177e4SLinus Torvalds #define SCSI_TERM_ENA_L BIT(0) /*Enable/Disable external terminators */ 4661da177e4SLinus Torvalds #define FLUSH_XFER_CNTR BIT(1) /*Flush transfer counter */ 4671da177e4SLinus Torvalds #define FORCE1_XFER BIT(5) /*Always xfer one byte in byte mode */ 4681da177e4SLinus Torvalds #define FAST_SINGLE BIT(6) /*?? */ 4691da177e4SLinus Torvalds 4701da177e4SLinus Torvalds #define BMCTRL_DEFAULT (FORCE1_XFER|FAST_SINGLE|SCSI_TERM_ENA_L) 4711da177e4SLinus Torvalds 4721da177e4SLinus Torvalds #define hp_sg_addr 0x28 4731da177e4SLinus Torvalds #define hp_page_ctrl 0x29 4741da177e4SLinus Torvalds 4751da177e4SLinus Torvalds #define SCATTER_EN BIT(0) 4761da177e4SLinus Torvalds #define SGRAM_ARAM BIT(1) 4771da177e4SLinus Torvalds #define G_INT_DISABLE BIT(3) /* Enable/Disable all Interrupts */ 4781da177e4SLinus Torvalds #define NARROW_SCSI_CARD BIT(4) /* NARROW/WIDE SCSI config pin */ 4791da177e4SLinus Torvalds 4801da177e4SLinus Torvalds #define hp_pci_stat_cfg 0x2D 4811da177e4SLinus Torvalds 4821da177e4SLinus Torvalds #define REC_MASTER_ABORT BIT(5) /*received Master abort */ 4831da177e4SLinus Torvalds 4841da177e4SLinus Torvalds #define hp_rev_num 0x33 4851da177e4SLinus Torvalds 4861da177e4SLinus Torvalds #define hp_stack_data 0x34 4871da177e4SLinus Torvalds #define hp_stack_addr 0x35 4881da177e4SLinus Torvalds 4891da177e4SLinus Torvalds #define hp_ext_status 0x36 4901da177e4SLinus Torvalds 4911da177e4SLinus Torvalds #define BM_FORCE_OFF BIT(0) /*Bus Master is forced to get off */ 4921da177e4SLinus Torvalds #define PCI_TGT_ABORT BIT(0) /*PCI bus master transaction aborted */ 4931da177e4SLinus Torvalds #define PCI_DEV_TMOUT BIT(1) /*PCI Device Time out */ 4941da177e4SLinus Torvalds #define CMD_ABORTED BIT(4) /*Command aborted */ 4951da177e4SLinus Torvalds #define BM_PARITY_ERR BIT(5) /*parity error on data received */ 4961da177e4SLinus Torvalds #define PIO_OVERRUN BIT(6) /*Slave data overrun */ 4971da177e4SLinus Torvalds #define BM_CMD_BUSY BIT(7) /*Bus master transfer command busy */ 4981da177e4SLinus Torvalds #define BAD_EXT_STATUS (BM_FORCE_OFF | PCI_DEV_TMOUT | CMD_ABORTED | \ 4991da177e4SLinus Torvalds BM_PARITY_ERR | PIO_OVERRUN) 5001da177e4SLinus Torvalds 5011da177e4SLinus Torvalds #define hp_int_status 0x37 5021da177e4SLinus Torvalds 5031da177e4SLinus Torvalds #define EXT_STATUS_ON BIT(1) /*Extended status is valid */ 5041da177e4SLinus Torvalds #define SCSI_INTERRUPT BIT(2) /*Global indication of a SCSI int. */ 5051da177e4SLinus Torvalds #define INT_ASSERTED BIT(5) /* */ 5061da177e4SLinus Torvalds 5071da177e4SLinus Torvalds #define hp_fifo_cnt 0x38 5081da177e4SLinus Torvalds 5091da177e4SLinus Torvalds #define hp_intena 0x40 5101da177e4SLinus Torvalds 5111cafc30fSJiri Slaby #define RESET BIT(7) 5121cafc30fSJiri Slaby #define PROG_HLT BIT(6) 5131cafc30fSJiri Slaby #define PARITY BIT(5) 5141cafc30fSJiri Slaby #define FIFO BIT(4) 5151cafc30fSJiri Slaby #define SEL BIT(3) 5161cafc30fSJiri Slaby #define SCAM_SEL BIT(2) 5171cafc30fSJiri Slaby #define RSEL BIT(1) 5181cafc30fSJiri Slaby #define TIMEOUT BIT(0) 5191cafc30fSJiri Slaby #define BUS_FREE BIT(15) 5201cafc30fSJiri Slaby #define XFER_CNT_0 BIT(14) 5211cafc30fSJiri Slaby #define PHASE BIT(13) 5221cafc30fSJiri Slaby #define IUNKWN BIT(12) 5231cafc30fSJiri Slaby #define ICMD_COMP BIT(11) 5241cafc30fSJiri Slaby #define ITICKLE BIT(10) 5251cafc30fSJiri Slaby #define IDO_STRT BIT(9) 5261cafc30fSJiri Slaby #define ITAR_DISC BIT(8) 5271cafc30fSJiri Slaby #define AUTO_INT (BIT(12)+BIT(11)+BIT(10)+BIT(9)+BIT(8)) 5281da177e4SLinus Torvalds #define CLR_ALL_INT 0xFFFF 5291da177e4SLinus Torvalds #define CLR_ALL_INT_1 0xFF00 5301da177e4SLinus Torvalds 5311da177e4SLinus Torvalds #define hp_intstat 0x42 5321da177e4SLinus Torvalds 5331da177e4SLinus Torvalds #define hp_scsisig 0x44 5341da177e4SLinus Torvalds 5351da177e4SLinus Torvalds #define SCSI_SEL BIT(7) 5361da177e4SLinus Torvalds #define SCSI_BSY BIT(6) 5371da177e4SLinus Torvalds #define SCSI_REQ BIT(5) 5381da177e4SLinus Torvalds #define SCSI_ACK BIT(4) 5391da177e4SLinus Torvalds #define SCSI_ATN BIT(3) 5401da177e4SLinus Torvalds #define SCSI_CD BIT(2) 5411da177e4SLinus Torvalds #define SCSI_MSG BIT(1) 5421da177e4SLinus Torvalds #define SCSI_IOBIT BIT(0) 5431da177e4SLinus Torvalds 5441da177e4SLinus Torvalds #define S_SCSI_PHZ (BIT(2)+BIT(1)+BIT(0)) 5451da177e4SLinus Torvalds #define S_MSGO_PH (BIT(2)+BIT(1) ) 5461da177e4SLinus Torvalds #define S_MSGI_PH (BIT(2)+BIT(1)+BIT(0)) 5471da177e4SLinus Torvalds #define S_DATAI_PH ( BIT(0)) 5481da177e4SLinus Torvalds #define S_DATAO_PH 0x00 5491da177e4SLinus Torvalds #define S_ILL_PH ( BIT(1) ) 5501da177e4SLinus Torvalds 5511da177e4SLinus Torvalds #define hp_scsictrl_0 0x45 5521da177e4SLinus Torvalds 5531da177e4SLinus Torvalds #define SEL_TAR BIT(6) 5541da177e4SLinus Torvalds #define ENA_ATN BIT(4) 5551da177e4SLinus Torvalds #define ENA_RESEL BIT(2) 5561da177e4SLinus Torvalds #define SCSI_RST BIT(1) 5571da177e4SLinus Torvalds #define ENA_SCAM_SEL BIT(0) 5581da177e4SLinus Torvalds 5591da177e4SLinus Torvalds #define hp_portctrl_0 0x46 5601da177e4SLinus Torvalds 5611da177e4SLinus Torvalds #define SCSI_PORT BIT(7) 5621da177e4SLinus Torvalds #define SCSI_INBIT BIT(6) 5631da177e4SLinus Torvalds #define DMA_PORT BIT(5) 5641da177e4SLinus Torvalds #define DMA_RD BIT(4) 5651da177e4SLinus Torvalds #define HOST_PORT BIT(3) 5661da177e4SLinus Torvalds #define HOST_WRT BIT(2) 5671da177e4SLinus Torvalds #define SCSI_BUS_EN BIT(1) 5681da177e4SLinus Torvalds #define START_TO BIT(0) 5691da177e4SLinus Torvalds 5701da177e4SLinus Torvalds #define hp_scsireset 0x47 5711da177e4SLinus Torvalds 5721da177e4SLinus Torvalds #define SCSI_INI BIT(6) 5731da177e4SLinus Torvalds #define SCAM_EN BIT(5) 5741da177e4SLinus Torvalds #define DMA_RESET BIT(3) 5751da177e4SLinus Torvalds #define HPSCSI_RESET BIT(2) 5761da177e4SLinus Torvalds #define PROG_RESET BIT(1) 5771da177e4SLinus Torvalds #define FIFO_CLR BIT(0) 5781da177e4SLinus Torvalds 5791da177e4SLinus Torvalds #define hp_xfercnt_0 0x48 5801da177e4SLinus Torvalds #define hp_xfercnt_2 0x4A 5811da177e4SLinus Torvalds 5821da177e4SLinus Torvalds #define hp_fifodata_0 0x4C 5831da177e4SLinus Torvalds #define hp_addstat 0x4E 5841da177e4SLinus Torvalds 5851da177e4SLinus Torvalds #define SCAM_TIMER BIT(7) 5861da177e4SLinus Torvalds #define SCSI_MODE8 BIT(3) 5871da177e4SLinus Torvalds #define SCSI_PAR_ERR BIT(0) 5881da177e4SLinus Torvalds 5891da177e4SLinus Torvalds #define hp_prgmcnt_0 0x4F 5901da177e4SLinus Torvalds 5911da177e4SLinus Torvalds #define hp_selfid_0 0x50 5921da177e4SLinus Torvalds #define hp_selfid_1 0x51 5931da177e4SLinus Torvalds #define hp_arb_id 0x52 5941da177e4SLinus Torvalds 5951da177e4SLinus Torvalds #define hp_select_id 0x53 5961da177e4SLinus Torvalds 5971da177e4SLinus Torvalds #define hp_synctarg_base 0x54 5981da177e4SLinus Torvalds #define hp_synctarg_12 0x54 5991da177e4SLinus Torvalds #define hp_synctarg_13 0x55 6001da177e4SLinus Torvalds #define hp_synctarg_14 0x56 6011da177e4SLinus Torvalds #define hp_synctarg_15 0x57 6021da177e4SLinus Torvalds 6031da177e4SLinus Torvalds #define hp_synctarg_8 0x58 6041da177e4SLinus Torvalds #define hp_synctarg_9 0x59 6051da177e4SLinus Torvalds #define hp_synctarg_10 0x5A 6061da177e4SLinus Torvalds #define hp_synctarg_11 0x5B 6071da177e4SLinus Torvalds 6081da177e4SLinus Torvalds #define hp_synctarg_4 0x5C 6091da177e4SLinus Torvalds #define hp_synctarg_5 0x5D 6101da177e4SLinus Torvalds #define hp_synctarg_6 0x5E 6111da177e4SLinus Torvalds #define hp_synctarg_7 0x5F 6121da177e4SLinus Torvalds 6131da177e4SLinus Torvalds #define hp_synctarg_0 0x60 6141da177e4SLinus Torvalds #define hp_synctarg_1 0x61 6151da177e4SLinus Torvalds #define hp_synctarg_2 0x62 6161da177e4SLinus Torvalds #define hp_synctarg_3 0x63 6171da177e4SLinus Torvalds 6181da177e4SLinus Torvalds #define NARROW_SCSI BIT(4) 6191da177e4SLinus Torvalds #define DEFAULT_OFFSET 0x0F 6201da177e4SLinus Torvalds 6211da177e4SLinus Torvalds #define hp_autostart_0 0x64 6221da177e4SLinus Torvalds #define hp_autostart_1 0x65 6231da177e4SLinus Torvalds #define hp_autostart_3 0x67 6241da177e4SLinus Torvalds 6251da177e4SLinus Torvalds #define AUTO_IMMED BIT(5) 6261da177e4SLinus Torvalds #define SELECT BIT(6) 6271da177e4SLinus Torvalds #define END_DATA (BIT(7)+BIT(6)) 6281da177e4SLinus Torvalds 6291da177e4SLinus Torvalds #define hp_gp_reg_0 0x68 6301da177e4SLinus Torvalds #define hp_gp_reg_1 0x69 6311da177e4SLinus Torvalds #define hp_gp_reg_3 0x6B 6321da177e4SLinus Torvalds 6331da177e4SLinus Torvalds #define hp_seltimeout 0x6C 6341da177e4SLinus Torvalds 6351da177e4SLinus Torvalds #define TO_4ms 0x67 /* 3.9959ms */ 6361da177e4SLinus Torvalds 6371da177e4SLinus Torvalds #define TO_5ms 0x03 /* 4.9152ms */ 6381da177e4SLinus Torvalds #define TO_10ms 0x07 /* 11.xxxms */ 6391da177e4SLinus Torvalds #define TO_250ms 0x99 /* 250.68ms */ 6401da177e4SLinus Torvalds #define TO_290ms 0xB1 /* 289.99ms */ 6411da177e4SLinus Torvalds 6421da177e4SLinus Torvalds #define hp_clkctrl_0 0x6D 6431da177e4SLinus Torvalds 6441da177e4SLinus Torvalds #define PWR_DWN BIT(6) 6451da177e4SLinus Torvalds #define ACTdeassert BIT(4) 6461da177e4SLinus Torvalds #define CLK_40MHZ (BIT(1) + BIT(0)) 6471da177e4SLinus Torvalds 6481da177e4SLinus Torvalds #define CLKCTRL_DEFAULT (ACTdeassert | CLK_40MHZ) 6491da177e4SLinus Torvalds 6501da177e4SLinus Torvalds #define hp_fiforead 0x6E 6511da177e4SLinus Torvalds #define hp_fifowrite 0x6F 6521da177e4SLinus Torvalds 6531da177e4SLinus Torvalds #define hp_offsetctr 0x70 6541da177e4SLinus Torvalds #define hp_xferstat 0x71 6551da177e4SLinus Torvalds 6561da177e4SLinus Torvalds #define FIFO_EMPTY BIT(6) 6571da177e4SLinus Torvalds 6581da177e4SLinus Torvalds #define hp_portctrl_1 0x72 6591da177e4SLinus Torvalds 6601da177e4SLinus Torvalds #define CHK_SCSI_P BIT(3) 6611da177e4SLinus Torvalds #define HOST_MODE8 BIT(0) 6621da177e4SLinus Torvalds 6631da177e4SLinus Torvalds #define hp_xfer_pad 0x73 6641da177e4SLinus Torvalds 6651da177e4SLinus Torvalds #define ID_UNLOCK BIT(3) 6661da177e4SLinus Torvalds 6671da177e4SLinus Torvalds #define hp_scsidata_0 0x74 6681da177e4SLinus Torvalds #define hp_scsidata_1 0x75 6691da177e4SLinus Torvalds 6701da177e4SLinus Torvalds #define hp_aramBase 0x80 6711da177e4SLinus Torvalds #define BIOS_DATA_OFFSET 0x60 6721da177e4SLinus Torvalds #define BIOS_RELATIVE_CARD 0x64 6731da177e4SLinus Torvalds 6741cafc30fSJiri Slaby #define AR3 (BIT(9) + BIT(8)) 6751cafc30fSJiri Slaby #define SDATA BIT(10) 6761da177e4SLinus Torvalds 6771cafc30fSJiri Slaby #define CRD_OP BIT(11) /* Cmp Reg. w/ Data */ 6781da177e4SLinus Torvalds 6791cafc30fSJiri Slaby #define CRR_OP BIT(12) /* Cmp Reg. w. Reg. */ 6801da177e4SLinus Torvalds 6811cafc30fSJiri Slaby #define CPE_OP (BIT(14)+BIT(11)) /* Cmp SCSI phs & Branch EQ */ 6821da177e4SLinus Torvalds 6831cafc30fSJiri Slaby #define CPN_OP (BIT(14)+BIT(12)) /* Cmp SCSI phs & Branch NOT EQ */ 6841da177e4SLinus Torvalds 6851da177e4SLinus Torvalds #define ADATA_OUT 0x00 6861cafc30fSJiri Slaby #define ADATA_IN BIT(8) 6871cafc30fSJiri Slaby #define ACOMMAND BIT(10) 6881cafc30fSJiri Slaby #define ASTATUS (BIT(10)+BIT(8)) 6891cafc30fSJiri Slaby #define AMSG_OUT (BIT(10)+BIT(9)) 6901cafc30fSJiri Slaby #define AMSG_IN (BIT(10)+BIT(9)+BIT(8)) 6911da177e4SLinus Torvalds 6921cafc30fSJiri Slaby #define BRH_OP BIT(13) /* Branch */ 6931da177e4SLinus Torvalds 6941da177e4SLinus Torvalds #define ALWAYS 0x00 6951cafc30fSJiri Slaby #define EQUAL BIT(8) 6961cafc30fSJiri Slaby #define NOT_EQ BIT(9) 6971da177e4SLinus Torvalds 6981cafc30fSJiri Slaby #define TCB_OP (BIT(13)+BIT(11)) /* Test condition & branch */ 6991da177e4SLinus Torvalds 7001cafc30fSJiri Slaby #define FIFO_0 BIT(10) 7011da177e4SLinus Torvalds 7021cafc30fSJiri Slaby #define MPM_OP BIT(15) /* Match phase and move data */ 7031da177e4SLinus Torvalds 7041cafc30fSJiri Slaby #define MRR_OP BIT(14) /* Move DReg. to Reg. */ 7051da177e4SLinus Torvalds 7061da177e4SLinus Torvalds #define S_IDREG (BIT(2)+BIT(1)+BIT(0)) 7071da177e4SLinus Torvalds 7081da177e4SLinus Torvalds #define D_AR0 0x00 7091da177e4SLinus Torvalds #define D_AR1 BIT(0) 7101da177e4SLinus Torvalds #define D_BUCKET (BIT(2) + BIT(1) + BIT(0)) 7111da177e4SLinus Torvalds 7121cafc30fSJiri Slaby #define RAT_OP (BIT(14)+BIT(13)+BIT(11)) 7131da177e4SLinus Torvalds 7141cafc30fSJiri Slaby #define SSI_OP (BIT(15)+BIT(11)) 7151da177e4SLinus Torvalds 7161da177e4SLinus Torvalds #define SSI_ITAR_DISC (ITAR_DISC >> 8) 7171da177e4SLinus Torvalds #define SSI_IDO_STRT (IDO_STRT >> 8) 7181da177e4SLinus Torvalds 7191da177e4SLinus Torvalds #define SSI_ICMD_COMP (ICMD_COMP >> 8) 7201da177e4SLinus Torvalds #define SSI_ITICKLE (ITICKLE >> 8) 7211da177e4SLinus Torvalds 7221da177e4SLinus Torvalds #define SSI_IUNKWN (IUNKWN >> 8) 7231da177e4SLinus Torvalds #define SSI_INO_CC (IUNKWN >> 8) 7241da177e4SLinus Torvalds #define SSI_IRFAIL (IUNKWN >> 8) 7251da177e4SLinus Torvalds 7261da177e4SLinus Torvalds #define NP 0x10 /*Next Phase */ 7271da177e4SLinus Torvalds #define NTCMD 0x02 /*Non- Tagged Command start */ 7281da177e4SLinus Torvalds #define CMDPZ 0x04 /*Command phase */ 7291da177e4SLinus Torvalds #define DINT 0x12 /*Data Out/In interrupt */ 7301da177e4SLinus Torvalds #define DI 0x13 /*Data Out */ 7311da177e4SLinus Torvalds #define DC 0x19 /*Disconnect Message */ 7321da177e4SLinus Torvalds #define ST 0x1D /*Status Phase */ 7331da177e4SLinus Torvalds #define UNKNWN 0x24 /*Unknown bus action */ 7341da177e4SLinus Torvalds #define CC 0x25 /*Command Completion failure */ 7351da177e4SLinus Torvalds #define TICK 0x26 /*New target reselected us. */ 7361da177e4SLinus Torvalds #define SELCHK 0x28 /*Select & Check SCSI ID latch reg */ 7371da177e4SLinus Torvalds 7381da177e4SLinus Torvalds #define ID_MSG_STRT hp_aramBase + 0x00 7391da177e4SLinus Torvalds #define NON_TAG_ID_MSG hp_aramBase + 0x06 7401da177e4SLinus Torvalds #define CMD_STRT hp_aramBase + 0x08 7411da177e4SLinus Torvalds #define SYNC_MSGS hp_aramBase + 0x08 7421da177e4SLinus Torvalds 7431da177e4SLinus Torvalds #define TAG_STRT 0x00 7441da177e4SLinus Torvalds #define DISCONNECT_START 0x10/2 7451da177e4SLinus Torvalds #define END_DATA_START 0x14/2 7461da177e4SLinus Torvalds #define CMD_ONLY_STRT CMDPZ/2 7471da177e4SLinus Torvalds #define SELCHK_STRT SELCHK/2 7481da177e4SLinus Torvalds 7491da177e4SLinus Torvalds #define GET_XFER_CNT(port, xfercnt) {RD_HARP32(port,hp_xfercnt_0,xfercnt); xfercnt &= 0xFFFFFF;} 7501da177e4SLinus Torvalds /* #define GET_XFER_CNT(port, xfercnt) (xfercnt = RD_HARPOON(port+hp_xfercnt_2), \ 7511da177e4SLinus Torvalds xfercnt <<= 16,\ 752c823feebSAlexey Dobriyan xfercnt |= RDW_HARPOON((unsigned short)(port+hp_xfercnt_0))) 7531da177e4SLinus Torvalds */ 754c823feebSAlexey Dobriyan #define HP_SETUP_ADDR_CNT(port,addr,count) (WRW_HARPOON((port+hp_host_addr_lo), (unsigned short)(addr & 0x0000FFFFL)),\ 7551da177e4SLinus Torvalds addr >>= 16,\ 756c823feebSAlexey Dobriyan WRW_HARPOON((port+hp_host_addr_hmi), (unsigned short)(addr & 0x0000FFFFL)),\ 7571da177e4SLinus Torvalds WR_HARP32(port,hp_xfercnt_0,count),\ 758c823feebSAlexey Dobriyan WRW_HARPOON((port+hp_xfer_cnt_lo), (unsigned short)(count & 0x0000FFFFL)),\ 7591da177e4SLinus Torvalds count >>= 16,\ 7601da177e4SLinus Torvalds WR_HARPOON(port+hp_xfer_cnt_hi, (count & 0xFF))) 7611da177e4SLinus Torvalds 7621da177e4SLinus Torvalds #define ACCEPT_MSG(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\ 7631da177e4SLinus Torvalds WR_HARPOON(port+hp_scsisig, S_ILL_PH);} 7641da177e4SLinus Torvalds 7651da177e4SLinus Torvalds #define ACCEPT_MSG_ATN(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\ 7661da177e4SLinus Torvalds WR_HARPOON(port+hp_scsisig, (S_ILL_PH|SCSI_ATN));} 7671da177e4SLinus Torvalds 7681da177e4SLinus Torvalds #define DISABLE_AUTO(port) (WR_HARPOON(port+hp_scsireset, PROG_RESET),\ 7691da177e4SLinus Torvalds WR_HARPOON(port+hp_scsireset, 0x00)) 7701da177e4SLinus Torvalds 7711da177e4SLinus Torvalds #define ARAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \ 7721da177e4SLinus Torvalds (RD_HARPOON(p_port+hp_page_ctrl) | SGRAM_ARAM))) 7731da177e4SLinus Torvalds 7741da177e4SLinus Torvalds #define SGRAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \ 7751da177e4SLinus Torvalds (RD_HARPOON(p_port+hp_page_ctrl) & ~SGRAM_ARAM))) 7761da177e4SLinus Torvalds 7771da177e4SLinus Torvalds #define MDISABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \ 7781da177e4SLinus Torvalds (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE))) 7791da177e4SLinus Torvalds 7801da177e4SLinus Torvalds #define MENABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \ 7811da177e4SLinus Torvalds (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE))) 7821da177e4SLinus Torvalds 7835c04a7b8SAlexey Dobriyan static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card, 7845c04a7b8SAlexey Dobriyan unsigned char syncFlag); 785d63a4cccSAlexey Dobriyan static void FPT_ssel(unsigned long port, unsigned char p_card); 7865c04a7b8SAlexey Dobriyan static void FPT_sres(unsigned long port, unsigned char p_card, 7875c04a7b8SAlexey Dobriyan struct sccb_card *pCurrCard); 7885c04a7b8SAlexey Dobriyan static void FPT_shandem(unsigned long port, unsigned char p_card, 7895c04a7b8SAlexey Dobriyan struct sccb *pCurrSCCB); 790d63a4cccSAlexey Dobriyan static void FPT_stsyncn(unsigned long port, unsigned char p_card); 7915c04a7b8SAlexey Dobriyan static void FPT_sisyncr(unsigned long port, unsigned char sync_pulse, 7925c04a7b8SAlexey Dobriyan unsigned char offset); 7935c04a7b8SAlexey Dobriyan static void FPT_sssyncv(unsigned long p_port, unsigned char p_id, 7945c04a7b8SAlexey Dobriyan unsigned char p_sync_value, 795f31dc0cdSAlexey Dobriyan struct sccb_mgr_tar_info *currTar_Info); 796d63a4cccSAlexey Dobriyan static void FPT_sresb(unsigned long port, unsigned char p_card); 797d63a4cccSAlexey Dobriyan static void FPT_sxfrp(unsigned long p_port, unsigned char p_card); 798d63a4cccSAlexey Dobriyan static void FPT_schkdd(unsigned long port, unsigned char p_card); 799d63a4cccSAlexey Dobriyan static unsigned char FPT_RdStack(unsigned long port, unsigned char index); 8005c04a7b8SAlexey Dobriyan static void FPT_WrStack(unsigned long portBase, unsigned char index, 8015c04a7b8SAlexey Dobriyan unsigned char data); 802d63a4cccSAlexey Dobriyan static unsigned char FPT_ChkIfChipInitialized(unsigned long ioPort); 8031da177e4SLinus Torvalds 804d63a4cccSAlexey Dobriyan static void FPT_SendMsg(unsigned long port, unsigned char message); 805db038cf8SAlexey Dobriyan static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg, 806db038cf8SAlexey Dobriyan unsigned char error_code); 8071da177e4SLinus Torvalds 80869eb2ea4SAlexey Dobriyan static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card); 80968d0c1aeSAlexey Dobriyan static void FPT_RNVRamData(struct nvram_info *pNvRamInfo); 8101da177e4SLinus Torvalds 811d63a4cccSAlexey Dobriyan static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card); 812d63a4cccSAlexey Dobriyan static void FPT_stwidn(unsigned long port, unsigned char p_card); 813d63a4cccSAlexey Dobriyan static void FPT_siwidr(unsigned long port, unsigned char width); 8141da177e4SLinus Torvalds 8155c04a7b8SAlexey Dobriyan static void FPT_queueSelectFail(struct sccb_card *pCurrCard, 816db038cf8SAlexey Dobriyan unsigned char p_card); 8175c04a7b8SAlexey Dobriyan static void FPT_queueDisconnect(struct sccb *p_SCCB, unsigned char p_card); 8185c04a7b8SAlexey Dobriyan static void FPT_queueCmdComplete(struct sccb_card *pCurrCard, 8195c04a7b8SAlexey Dobriyan struct sccb *p_SCCB, unsigned char p_card); 8205c04a7b8SAlexey Dobriyan static void FPT_queueSearchSelect(struct sccb_card *pCurrCard, 8215c04a7b8SAlexey Dobriyan unsigned char p_card); 822db038cf8SAlexey Dobriyan static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code); 82369eb2ea4SAlexey Dobriyan static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char card); 8245c04a7b8SAlexey Dobriyan static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB, 8255c04a7b8SAlexey Dobriyan unsigned char p_card); 82669eb2ea4SAlexey Dobriyan static void FPT_utilUpdateResidual(struct sccb *p_SCCB); 827c823feebSAlexey Dobriyan static unsigned short FPT_CalcCrc16(unsigned char buffer[]); 828db038cf8SAlexey Dobriyan static unsigned char FPT_CalcLrc(unsigned char buffer[]); 8291da177e4SLinus Torvalds 830d63a4cccSAlexey Dobriyan static void FPT_Wait1Second(unsigned long p_port); 831d63a4cccSAlexey Dobriyan static void FPT_Wait(unsigned long p_port, unsigned char p_delay); 832d63a4cccSAlexey Dobriyan static void FPT_utilEEWriteOnOff(unsigned long p_port, unsigned char p_mode); 8335c04a7b8SAlexey Dobriyan static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data, 8345c04a7b8SAlexey Dobriyan unsigned short ee_addr); 8355c04a7b8SAlexey Dobriyan static unsigned short FPT_utilEERead(unsigned long p_port, 8365c04a7b8SAlexey Dobriyan unsigned short ee_addr); 8375c04a7b8SAlexey Dobriyan static unsigned short FPT_utilEEReadOrg(unsigned long p_port, 8385c04a7b8SAlexey Dobriyan unsigned short ee_addr); 8395c04a7b8SAlexey Dobriyan static void FPT_utilEESendCmdAddr(unsigned long p_port, unsigned char ee_cmd, 8405c04a7b8SAlexey Dobriyan unsigned short ee_addr); 8411da177e4SLinus Torvalds 842d63a4cccSAlexey Dobriyan static void FPT_phaseDataOut(unsigned long port, unsigned char p_card); 843d63a4cccSAlexey Dobriyan static void FPT_phaseDataIn(unsigned long port, unsigned char p_card); 844d63a4cccSAlexey Dobriyan static void FPT_phaseCommand(unsigned long port, unsigned char p_card); 845d63a4cccSAlexey Dobriyan static void FPT_phaseStatus(unsigned long port, unsigned char p_card); 846d63a4cccSAlexey Dobriyan static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card); 847d63a4cccSAlexey Dobriyan static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card); 848d63a4cccSAlexey Dobriyan static void FPT_phaseIllegal(unsigned long port, unsigned char p_card); 8491da177e4SLinus Torvalds 850d63a4cccSAlexey Dobriyan static void FPT_phaseDecode(unsigned long port, unsigned char p_card); 851d63a4cccSAlexey Dobriyan static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card); 852d63a4cccSAlexey Dobriyan static void FPT_phaseBusFree(unsigned long p_port, unsigned char p_card); 8531da177e4SLinus Torvalds 854d63a4cccSAlexey Dobriyan static void FPT_XbowInit(unsigned long port, unsigned char scamFlg); 855d63a4cccSAlexey Dobriyan static void FPT_BusMasterInit(unsigned long p_port); 856d63a4cccSAlexey Dobriyan static void FPT_DiagEEPROM(unsigned long p_port); 8571da177e4SLinus Torvalds 8585c04a7b8SAlexey Dobriyan static void FPT_dataXferProcessor(unsigned long port, 8595c04a7b8SAlexey Dobriyan struct sccb_card *pCurrCard); 8605c04a7b8SAlexey Dobriyan static void FPT_busMstrSGDataXferStart(unsigned long port, 8615c04a7b8SAlexey Dobriyan struct sccb *pCurrSCCB); 8625c04a7b8SAlexey Dobriyan static void FPT_busMstrDataXferStart(unsigned long port, 8635c04a7b8SAlexey Dobriyan struct sccb *pCurrSCCB); 8645c04a7b8SAlexey Dobriyan static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card, 8655c04a7b8SAlexey Dobriyan struct sccb *pCurrSCCB); 86669eb2ea4SAlexey Dobriyan static void FPT_hostDataXferRestart(struct sccb *currSCCB); 8671da177e4SLinus Torvalds 8685c04a7b8SAlexey Dobriyan static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port, 8695c04a7b8SAlexey Dobriyan unsigned char p_card, 8705c04a7b8SAlexey Dobriyan struct sccb_card *pCurrCard, 8715c04a7b8SAlexey Dobriyan unsigned short p_int); 8721da177e4SLinus Torvalds 87347b5d69cSJames Bottomley static void FPT_SccbMgrTableInitAll(void); 8745c04a7b8SAlexey Dobriyan static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard, 8755c04a7b8SAlexey Dobriyan unsigned char p_card); 8765c04a7b8SAlexey Dobriyan static void FPT_SccbMgrTableInitTarget(unsigned char p_card, 8775c04a7b8SAlexey Dobriyan unsigned char target); 8781da177e4SLinus Torvalds 8795c04a7b8SAlexey Dobriyan static void FPT_scini(unsigned char p_card, unsigned char p_our_id, 8805c04a7b8SAlexey Dobriyan unsigned char p_power_up); 8811da177e4SLinus Torvalds 882d63a4cccSAlexey Dobriyan static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type); 883d63a4cccSAlexey Dobriyan static void FPT_scbusf(unsigned long p_port); 884d63a4cccSAlexey Dobriyan static void FPT_scsel(unsigned long p_port); 885d63a4cccSAlexey Dobriyan static void FPT_scasid(unsigned char p_card, unsigned long p_port); 886d63a4cccSAlexey Dobriyan static unsigned char FPT_scxferc(unsigned long p_port, unsigned char p_data); 8875c04a7b8SAlexey Dobriyan static unsigned char FPT_scsendi(unsigned long p_port, 8885c04a7b8SAlexey Dobriyan unsigned char p_id_string[]); 8895c04a7b8SAlexey Dobriyan static unsigned char FPT_sciso(unsigned long p_port, 8905c04a7b8SAlexey Dobriyan unsigned char p_id_string[]); 891d63a4cccSAlexey Dobriyan static void FPT_scwirod(unsigned long p_port, unsigned char p_data_bit); 892d63a4cccSAlexey Dobriyan static void FPT_scwiros(unsigned long p_port, unsigned char p_data_bit); 893db038cf8SAlexey Dobriyan static unsigned char FPT_scvalq(unsigned char p_quintet); 894d63a4cccSAlexey Dobriyan static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id); 895d63a4cccSAlexey Dobriyan static void FPT_scwtsel(unsigned long p_port); 8965c04a7b8SAlexey Dobriyan static void FPT_inisci(unsigned char p_card, unsigned long p_port, 8975c04a7b8SAlexey Dobriyan unsigned char p_our_id); 898d63a4cccSAlexey Dobriyan static void FPT_scsavdi(unsigned char p_card, unsigned long p_port); 8995c04a7b8SAlexey Dobriyan static unsigned char FPT_scmachid(unsigned char p_card, 9005c04a7b8SAlexey Dobriyan unsigned char p_id_string[]); 9011da177e4SLinus Torvalds 902d63a4cccSAlexey Dobriyan static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card); 903d63a4cccSAlexey Dobriyan static void FPT_autoLoadDefaultMap(unsigned long p_port); 9041da177e4SLinus Torvalds 9055c04a7b8SAlexey Dobriyan static struct sccb_mgr_tar_info FPT_sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] = 9065c04a7b8SAlexey Dobriyan { {{0}} }; 90713e6851aSAlexey Dobriyan static struct sccb_card FPT_BL_Card[MAX_CARDS] = { {0} }; 90847b5d69cSJames Bottomley static SCCBSCAM_INFO FPT_scamInfo[MAX_SCSI_TAR] = { {{0}} }; 90968d0c1aeSAlexey Dobriyan static struct nvram_info FPT_nvRamInfo[MAX_MB_CARDS] = { {0} }; 9101da177e4SLinus Torvalds 911db038cf8SAlexey Dobriyan static unsigned char FPT_mbCards = 0; 9125c04a7b8SAlexey Dobriyan static unsigned char FPT_scamHAString[] = 9135c04a7b8SAlexey Dobriyan { 0x63, 0x07, 'B', 'U', 'S', 'L', 'O', 'G', 'I', 'C', 9145c04a7b8SAlexey Dobriyan ' ', 'B', 'T', '-', '9', '3', '0', 9155c04a7b8SAlexey Dobriyan 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 9165c04a7b8SAlexey Dobriyan 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 9175c04a7b8SAlexey Dobriyan }; 9181da177e4SLinus Torvalds 919c823feebSAlexey Dobriyan static unsigned short FPT_default_intena = 0; 9201da177e4SLinus Torvalds 9215c04a7b8SAlexey Dobriyan static void (*FPT_s_PhaseTbl[8]) (unsigned long, unsigned char) = { 9225c04a7b8SAlexey Dobriyan 0}; 9231da177e4SLinus Torvalds 9241da177e4SLinus Torvalds /*--------------------------------------------------------------------- 9251da177e4SLinus Torvalds * 926d8b6b8bdSAlexey Dobriyan * Function: FlashPoint_ProbeHostAdapter 9271da177e4SLinus Torvalds * 9281da177e4SLinus Torvalds * Description: Setup and/or Search for cards and return info to caller. 9291da177e4SLinus Torvalds * 9301da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 9311da177e4SLinus Torvalds 9327f101662SAlexey Dobriyan static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo) 9331da177e4SLinus Torvalds { 934db038cf8SAlexey Dobriyan static unsigned char first_time = 1; 9351da177e4SLinus Torvalds 936db038cf8SAlexey Dobriyan unsigned char i, j, id, ScamFlg; 937c823feebSAlexey Dobriyan unsigned short temp, temp2, temp3, temp4, temp5, temp6; 938d63a4cccSAlexey Dobriyan unsigned long ioport; 93968d0c1aeSAlexey Dobriyan struct nvram_info *pCurrNvRam; 9401da177e4SLinus Torvalds 9411da177e4SLinus Torvalds ioport = pCardInfo->si_baseaddr; 9421da177e4SLinus Torvalds 9431da177e4SLinus Torvalds if (RD_HARPOON(ioport + hp_vendor_id_0) != ORION_VEND_0) 9445c1b85e2SAlexey Dobriyan return (int)FAILURE; 9451da177e4SLinus Torvalds 9461da177e4SLinus Torvalds if ((RD_HARPOON(ioport + hp_vendor_id_1) != ORION_VEND_1)) 9475c1b85e2SAlexey Dobriyan return (int)FAILURE; 9481da177e4SLinus Torvalds 9491da177e4SLinus Torvalds if ((RD_HARPOON(ioport + hp_device_id_0) != ORION_DEV_0)) 9505c1b85e2SAlexey Dobriyan return (int)FAILURE; 9511da177e4SLinus Torvalds 9521da177e4SLinus Torvalds if ((RD_HARPOON(ioport + hp_device_id_1) != ORION_DEV_1)) 9535c1b85e2SAlexey Dobriyan return (int)FAILURE; 9541da177e4SLinus Torvalds 9551da177e4SLinus Torvalds if (RD_HARPOON(ioport + hp_rev_num) != 0x0f) { 9561da177e4SLinus Torvalds 9571da177e4SLinus Torvalds /* For new Harpoon then check for sub_device ID LSB 9581da177e4SLinus Torvalds the bits(0-3) must be all ZERO for compatible with 9591da177e4SLinus Torvalds current version of SCCBMgr, else skip this Harpoon 9601da177e4SLinus Torvalds device. */ 9611da177e4SLinus Torvalds 9621da177e4SLinus Torvalds if (RD_HARPOON(ioport + hp_sub_device_id_0) & 0x0f) 9635c1b85e2SAlexey Dobriyan return (int)FAILURE; 9641da177e4SLinus Torvalds } 9651da177e4SLinus Torvalds 9665c04a7b8SAlexey Dobriyan if (first_time) { 96747b5d69cSJames Bottomley FPT_SccbMgrTableInitAll(); 9681da177e4SLinus Torvalds first_time = 0; 96947b5d69cSJames Bottomley FPT_mbCards = 0; 9701da177e4SLinus Torvalds } 9711da177e4SLinus Torvalds 97247b5d69cSJames Bottomley if (FPT_RdStack(ioport, 0) != 0x00) { 9735c04a7b8SAlexey Dobriyan if (FPT_ChkIfChipInitialized(ioport) == 0) { 9741da177e4SLinus Torvalds pCurrNvRam = NULL; 9751da177e4SLinus Torvalds WR_HARPOON(ioport + hp_semaphore, 0x00); 97647b5d69cSJames Bottomley FPT_XbowInit(ioport, 0); /*Must Init the SCSI before attempting */ 97747b5d69cSJames Bottomley FPT_DiagEEPROM(ioport); 9785c04a7b8SAlexey Dobriyan } else { 97947b5d69cSJames Bottomley if (FPT_mbCards < MAX_MB_CARDS) { 98047b5d69cSJames Bottomley pCurrNvRam = &FPT_nvRamInfo[FPT_mbCards]; 98147b5d69cSJames Bottomley FPT_mbCards++; 9821da177e4SLinus Torvalds pCurrNvRam->niBaseAddr = ioport; 98347b5d69cSJames Bottomley FPT_RNVRamData(pCurrNvRam); 9841da177e4SLinus Torvalds } else 9855c1b85e2SAlexey Dobriyan return (int)FAILURE; 9861da177e4SLinus Torvalds } 9871da177e4SLinus Torvalds } else 9881da177e4SLinus Torvalds pCurrNvRam = NULL; 9891da177e4SLinus Torvalds 9901da177e4SLinus Torvalds WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT); 9911da177e4SLinus Torvalds WR_HARPOON(ioport + hp_sys_ctrl, 0x00); 9921da177e4SLinus Torvalds 9931da177e4SLinus Torvalds if (pCurrNvRam) 9941da177e4SLinus Torvalds pCardInfo->si_id = pCurrNvRam->niAdapId; 9951da177e4SLinus Torvalds else 9965c04a7b8SAlexey Dobriyan pCardInfo->si_id = 9975c04a7b8SAlexey Dobriyan (unsigned 9985c04a7b8SAlexey Dobriyan char)(FPT_utilEERead(ioport, 9995c04a7b8SAlexey Dobriyan (ADAPTER_SCSI_ID / 10005c04a7b8SAlexey Dobriyan 2)) & (unsigned char)0x0FF); 10011da177e4SLinus Torvalds 10021da177e4SLinus Torvalds pCardInfo->si_lun = 0x00; 10031da177e4SLinus Torvalds pCardInfo->si_fw_revision = ORION_FW_REV; 10041da177e4SLinus Torvalds temp2 = 0x0000; 10051da177e4SLinus Torvalds temp3 = 0x0000; 10061da177e4SLinus Torvalds temp4 = 0x0000; 10071da177e4SLinus Torvalds temp5 = 0x0000; 10081da177e4SLinus Torvalds temp6 = 0x0000; 10091da177e4SLinus Torvalds 10101da177e4SLinus Torvalds for (id = 0; id < (16 / 2); id++) { 10111da177e4SLinus Torvalds 10121da177e4SLinus Torvalds if (pCurrNvRam) { 1013c823feebSAlexey Dobriyan temp = (unsigned short)pCurrNvRam->niSyncTbl[id]; 10141da177e4SLinus Torvalds temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) + 10151da177e4SLinus Torvalds (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000)); 10161da177e4SLinus Torvalds } else 10175c04a7b8SAlexey Dobriyan temp = 10185c04a7b8SAlexey Dobriyan FPT_utilEERead(ioport, 10195c04a7b8SAlexey Dobriyan (unsigned short)((SYNC_RATE_TBL / 2) 10205c04a7b8SAlexey Dobriyan + id)); 10211da177e4SLinus Torvalds 10221da177e4SLinus Torvalds for (i = 0; i < 2; temp >>= 8, i++) { 10231da177e4SLinus Torvalds 10241da177e4SLinus Torvalds temp2 >>= 1; 10251da177e4SLinus Torvalds temp3 >>= 1; 10261da177e4SLinus Torvalds temp4 >>= 1; 10271da177e4SLinus Torvalds temp5 >>= 1; 10281da177e4SLinus Torvalds temp6 >>= 1; 10295c04a7b8SAlexey Dobriyan switch (temp & 0x3) { 10301da177e4SLinus Torvalds case AUTO_RATE_20: /* Synchronous, 20 mega-transfers/second */ 10311da177e4SLinus Torvalds temp6 |= 0x8000; /* Fall through */ 10321da177e4SLinus Torvalds case AUTO_RATE_10: /* Synchronous, 10 mega-transfers/second */ 10331da177e4SLinus Torvalds temp5 |= 0x8000; /* Fall through */ 10341da177e4SLinus Torvalds case AUTO_RATE_05: /* Synchronous, 5 mega-transfers/second */ 10351da177e4SLinus Torvalds temp2 |= 0x8000; /* Fall through */ 10361da177e4SLinus Torvalds case AUTO_RATE_00: /* Asynchronous */ 10371da177e4SLinus Torvalds break; 10381da177e4SLinus Torvalds } 10391da177e4SLinus Torvalds 10401da177e4SLinus Torvalds if (temp & DISC_ENABLE_BIT) 10411da177e4SLinus Torvalds temp3 |= 0x8000; 10421da177e4SLinus Torvalds 10431da177e4SLinus Torvalds if (temp & WIDE_NEGO_BIT) 10441da177e4SLinus Torvalds temp4 |= 0x8000; 10451da177e4SLinus Torvalds 10461da177e4SLinus Torvalds } 10471da177e4SLinus Torvalds } 10481da177e4SLinus Torvalds 10491da177e4SLinus Torvalds pCardInfo->si_per_targ_init_sync = temp2; 10501da177e4SLinus Torvalds pCardInfo->si_per_targ_no_disc = temp3; 10511da177e4SLinus Torvalds pCardInfo->si_per_targ_wide_nego = temp4; 10521da177e4SLinus Torvalds pCardInfo->si_per_targ_fast_nego = temp5; 10531da177e4SLinus Torvalds pCardInfo->si_per_targ_ultra_nego = temp6; 10541da177e4SLinus Torvalds 10551da177e4SLinus Torvalds if (pCurrNvRam) 10561da177e4SLinus Torvalds i = pCurrNvRam->niSysConf; 10571da177e4SLinus Torvalds else 10585c04a7b8SAlexey Dobriyan i = (unsigned 10595c04a7b8SAlexey Dobriyan char)(FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2))); 10601da177e4SLinus Torvalds 10611da177e4SLinus Torvalds if (pCurrNvRam) 10621da177e4SLinus Torvalds ScamFlg = pCurrNvRam->niScamConf; 10631da177e4SLinus Torvalds else 10645c04a7b8SAlexey Dobriyan ScamFlg = 10655c04a7b8SAlexey Dobriyan (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2); 10661da177e4SLinus Torvalds 10671da177e4SLinus Torvalds pCardInfo->si_flags = 0x0000; 10681da177e4SLinus Torvalds 10691da177e4SLinus Torvalds if (i & 0x01) 10701da177e4SLinus Torvalds pCardInfo->si_flags |= SCSI_PARITY_ENA; 10711da177e4SLinus Torvalds 10721da177e4SLinus Torvalds if (!(i & 0x02)) 10731da177e4SLinus Torvalds pCardInfo->si_flags |= SOFT_RESET; 10741da177e4SLinus Torvalds 10751da177e4SLinus Torvalds if (i & 0x10) 10761da177e4SLinus Torvalds pCardInfo->si_flags |= EXTENDED_TRANSLATION; 10771da177e4SLinus Torvalds 10781da177e4SLinus Torvalds if (ScamFlg & SCAM_ENABLED) 10791da177e4SLinus Torvalds pCardInfo->si_flags |= FLAG_SCAM_ENABLED; 10801da177e4SLinus Torvalds 10811da177e4SLinus Torvalds if (ScamFlg & SCAM_LEVEL2) 10821da177e4SLinus Torvalds pCardInfo->si_flags |= FLAG_SCAM_LEVEL2; 10831da177e4SLinus Torvalds 10841da177e4SLinus Torvalds j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L); 10851da177e4SLinus Torvalds if (i & 0x04) { 10861da177e4SLinus Torvalds j |= SCSI_TERM_ENA_L; 10871da177e4SLinus Torvalds } 10881da177e4SLinus Torvalds WR_HARPOON(ioport + hp_bm_ctrl, j); 10891da177e4SLinus Torvalds 10901da177e4SLinus Torvalds j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H); 10911da177e4SLinus Torvalds if (i & 0x08) { 10921da177e4SLinus Torvalds j |= SCSI_TERM_ENA_H; 10931da177e4SLinus Torvalds } 10941da177e4SLinus Torvalds WR_HARPOON(ioport + hp_ee_ctrl, j); 10951da177e4SLinus Torvalds 10961da177e4SLinus Torvalds if (!(RD_HARPOON(ioport + hp_page_ctrl) & NARROW_SCSI_CARD)) 10971da177e4SLinus Torvalds 10981da177e4SLinus Torvalds pCardInfo->si_flags |= SUPPORT_16TAR_32LUN; 10991da177e4SLinus Torvalds 11001da177e4SLinus Torvalds pCardInfo->si_card_family = HARPOON_FAMILY; 11011da177e4SLinus Torvalds pCardInfo->si_bustype = BUSTYPE_PCI; 11021da177e4SLinus Torvalds 11031da177e4SLinus Torvalds if (pCurrNvRam) { 11041da177e4SLinus Torvalds pCardInfo->si_card_model[0] = '9'; 11051da177e4SLinus Torvalds switch (pCurrNvRam->niModel & 0x0f) { 11061da177e4SLinus Torvalds case MODEL_LT: 11071da177e4SLinus Torvalds pCardInfo->si_card_model[1] = '3'; 11081da177e4SLinus Torvalds pCardInfo->si_card_model[2] = '0'; 11091da177e4SLinus Torvalds break; 11101da177e4SLinus Torvalds case MODEL_LW: 11111da177e4SLinus Torvalds pCardInfo->si_card_model[1] = '5'; 11121da177e4SLinus Torvalds pCardInfo->si_card_model[2] = '0'; 11131da177e4SLinus Torvalds break; 11141da177e4SLinus Torvalds case MODEL_DL: 11151da177e4SLinus Torvalds pCardInfo->si_card_model[1] = '3'; 11161da177e4SLinus Torvalds pCardInfo->si_card_model[2] = '2'; 11171da177e4SLinus Torvalds break; 11181da177e4SLinus Torvalds case MODEL_DW: 11191da177e4SLinus Torvalds pCardInfo->si_card_model[1] = '5'; 11201da177e4SLinus Torvalds pCardInfo->si_card_model[2] = '2'; 11211da177e4SLinus Torvalds break; 11221da177e4SLinus Torvalds } 11231da177e4SLinus Torvalds } else { 112447b5d69cSJames Bottomley temp = FPT_utilEERead(ioport, (MODEL_NUMB_0 / 2)); 1125db038cf8SAlexey Dobriyan pCardInfo->si_card_model[0] = (unsigned char)(temp >> 8); 112647b5d69cSJames Bottomley temp = FPT_utilEERead(ioport, (MODEL_NUMB_2 / 2)); 11271da177e4SLinus Torvalds 1128db038cf8SAlexey Dobriyan pCardInfo->si_card_model[1] = (unsigned char)(temp & 0x00FF); 1129db038cf8SAlexey Dobriyan pCardInfo->si_card_model[2] = (unsigned char)(temp >> 8); 11301da177e4SLinus Torvalds } 11311da177e4SLinus Torvalds 11325c04a7b8SAlexey Dobriyan if (pCardInfo->si_card_model[1] == '3') { 11331da177e4SLinus Torvalds if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7)) 11341da177e4SLinus Torvalds pCardInfo->si_flags |= LOW_BYTE_TERM; 11355c04a7b8SAlexey Dobriyan } else if (pCardInfo->si_card_model[2] == '0') { 11361da177e4SLinus Torvalds temp = RD_HARPOON(ioport + hp_xfer_pad); 11371da177e4SLinus Torvalds WR_HARPOON(ioport + hp_xfer_pad, (temp & ~BIT(4))); 11381da177e4SLinus Torvalds if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7)) 11391da177e4SLinus Torvalds pCardInfo->si_flags |= LOW_BYTE_TERM; 11401da177e4SLinus Torvalds WR_HARPOON(ioport + hp_xfer_pad, (temp | BIT(4))); 11411da177e4SLinus Torvalds if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7)) 11421da177e4SLinus Torvalds pCardInfo->si_flags |= HIGH_BYTE_TERM; 11431da177e4SLinus Torvalds WR_HARPOON(ioport + hp_xfer_pad, temp); 11445c04a7b8SAlexey Dobriyan } else { 11451da177e4SLinus Torvalds temp = RD_HARPOON(ioport + hp_ee_ctrl); 11461da177e4SLinus Torvalds temp2 = RD_HARPOON(ioport + hp_xfer_pad); 11471da177e4SLinus Torvalds WR_HARPOON(ioport + hp_ee_ctrl, (temp | SEE_CS)); 11481da177e4SLinus Torvalds WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4))); 11491da177e4SLinus Torvalds temp3 = 0; 11505c04a7b8SAlexey Dobriyan for (i = 0; i < 8; i++) { 11511da177e4SLinus Torvalds temp3 <<= 1; 11521da177e4SLinus Torvalds if (!(RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))) 11531da177e4SLinus Torvalds temp3 |= 1; 11541da177e4SLinus Torvalds WR_HARPOON(ioport + hp_xfer_pad, (temp2 & ~BIT(4))); 11551da177e4SLinus Torvalds WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4))); 11561da177e4SLinus Torvalds } 11571da177e4SLinus Torvalds WR_HARPOON(ioport + hp_ee_ctrl, temp); 11581da177e4SLinus Torvalds WR_HARPOON(ioport + hp_xfer_pad, temp2); 11591da177e4SLinus Torvalds if (!(temp3 & BIT(7))) 11601da177e4SLinus Torvalds pCardInfo->si_flags |= LOW_BYTE_TERM; 11611da177e4SLinus Torvalds if (!(temp3 & BIT(6))) 11621da177e4SLinus Torvalds pCardInfo->si_flags |= HIGH_BYTE_TERM; 11631da177e4SLinus Torvalds } 11641da177e4SLinus Torvalds 11651da177e4SLinus Torvalds ARAM_ACCESS(ioport); 11661da177e4SLinus Torvalds 11671da177e4SLinus Torvalds for (i = 0; i < 4; i++) { 11681da177e4SLinus Torvalds 11691da177e4SLinus Torvalds pCardInfo->si_XlatInfo[i] = 11701da177e4SLinus Torvalds RD_HARPOON(ioport + hp_aramBase + BIOS_DATA_OFFSET + i); 11711da177e4SLinus Torvalds } 11721da177e4SLinus Torvalds 11731da177e4SLinus Torvalds /* return with -1 if no sort, else return with 11741da177e4SLinus Torvalds logical card number sorted by BIOS (zero-based) */ 11751da177e4SLinus Torvalds 11761da177e4SLinus Torvalds pCardInfo->si_relative_cardnum = 11775c04a7b8SAlexey Dobriyan (unsigned 11785c04a7b8SAlexey Dobriyan char)(RD_HARPOON(ioport + hp_aramBase + BIOS_RELATIVE_CARD) - 1); 11791da177e4SLinus Torvalds 11801da177e4SLinus Torvalds SGRAM_ACCESS(ioport); 11811da177e4SLinus Torvalds 118247b5d69cSJames Bottomley FPT_s_PhaseTbl[0] = FPT_phaseDataOut; 118347b5d69cSJames Bottomley FPT_s_PhaseTbl[1] = FPT_phaseDataIn; 118447b5d69cSJames Bottomley FPT_s_PhaseTbl[2] = FPT_phaseIllegal; 118547b5d69cSJames Bottomley FPT_s_PhaseTbl[3] = FPT_phaseIllegal; 118647b5d69cSJames Bottomley FPT_s_PhaseTbl[4] = FPT_phaseCommand; 118747b5d69cSJames Bottomley FPT_s_PhaseTbl[5] = FPT_phaseStatus; 118847b5d69cSJames Bottomley FPT_s_PhaseTbl[6] = FPT_phaseMsgOut; 118947b5d69cSJames Bottomley FPT_s_PhaseTbl[7] = FPT_phaseMsgIn; 11901da177e4SLinus Torvalds 11911da177e4SLinus Torvalds pCardInfo->si_present = 0x01; 11921da177e4SLinus Torvalds 11935c1b85e2SAlexey Dobriyan return 0; 11941da177e4SLinus Torvalds } 11951da177e4SLinus Torvalds 11961da177e4SLinus Torvalds /*--------------------------------------------------------------------- 11971da177e4SLinus Torvalds * 1198d8b6b8bdSAlexey Dobriyan * Function: FlashPoint_HardwareResetHostAdapter 11991da177e4SLinus Torvalds * 12001da177e4SLinus Torvalds * Description: Setup adapter for normal operation (hard reset). 12011da177e4SLinus Torvalds * 12021da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 12031da177e4SLinus Torvalds 12045c04a7b8SAlexey Dobriyan static unsigned long FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info 12055c04a7b8SAlexey Dobriyan *pCardInfo) 12061da177e4SLinus Torvalds { 120713e6851aSAlexey Dobriyan struct sccb_card *CurrCard = NULL; 120868d0c1aeSAlexey Dobriyan struct nvram_info *pCurrNvRam; 1209db038cf8SAlexey Dobriyan unsigned char i, j, thisCard, ScamFlg; 1210c823feebSAlexey Dobriyan unsigned short temp, sync_bit_map, id; 1211d63a4cccSAlexey Dobriyan unsigned long ioport; 12121da177e4SLinus Torvalds 12131da177e4SLinus Torvalds ioport = pCardInfo->si_baseaddr; 12141da177e4SLinus Torvalds 12151da177e4SLinus Torvalds for (thisCard = 0; thisCard <= MAX_CARDS; thisCard++) { 12161da177e4SLinus Torvalds 12171da177e4SLinus Torvalds if (thisCard == MAX_CARDS) { 12181da177e4SLinus Torvalds 12195c1b85e2SAlexey Dobriyan return FAILURE; 12201da177e4SLinus Torvalds } 12211da177e4SLinus Torvalds 122247b5d69cSJames Bottomley if (FPT_BL_Card[thisCard].ioPort == ioport) { 12231da177e4SLinus Torvalds 122447b5d69cSJames Bottomley CurrCard = &FPT_BL_Card[thisCard]; 122547b5d69cSJames Bottomley FPT_SccbMgrTableInitCard(CurrCard, thisCard); 12261da177e4SLinus Torvalds break; 12271da177e4SLinus Torvalds } 12281da177e4SLinus Torvalds 122947b5d69cSJames Bottomley else if (FPT_BL_Card[thisCard].ioPort == 0x00) { 12301da177e4SLinus Torvalds 123147b5d69cSJames Bottomley FPT_BL_Card[thisCard].ioPort = ioport; 123247b5d69cSJames Bottomley CurrCard = &FPT_BL_Card[thisCard]; 12331da177e4SLinus Torvalds 123447b5d69cSJames Bottomley if (FPT_mbCards) 123547b5d69cSJames Bottomley for (i = 0; i < FPT_mbCards; i++) { 12365c04a7b8SAlexey Dobriyan if (CurrCard->ioPort == 12375c04a7b8SAlexey Dobriyan FPT_nvRamInfo[i].niBaseAddr) 12385c04a7b8SAlexey Dobriyan CurrCard->pNvRamInfo = 12395c04a7b8SAlexey Dobriyan &FPT_nvRamInfo[i]; 12401da177e4SLinus Torvalds } 124147b5d69cSJames Bottomley FPT_SccbMgrTableInitCard(CurrCard, thisCard); 12421da177e4SLinus Torvalds CurrCard->cardIndex = thisCard; 12431da177e4SLinus Torvalds CurrCard->cardInfo = pCardInfo; 12441da177e4SLinus Torvalds 12451da177e4SLinus Torvalds break; 12461da177e4SLinus Torvalds } 12471da177e4SLinus Torvalds } 12481da177e4SLinus Torvalds 12491da177e4SLinus Torvalds pCurrNvRam = CurrCard->pNvRamInfo; 12501da177e4SLinus Torvalds 12511da177e4SLinus Torvalds if (pCurrNvRam) { 12521da177e4SLinus Torvalds ScamFlg = pCurrNvRam->niScamConf; 12535c04a7b8SAlexey Dobriyan } else { 12545c04a7b8SAlexey Dobriyan ScamFlg = 12555c04a7b8SAlexey Dobriyan (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2); 12561da177e4SLinus Torvalds } 12571da177e4SLinus Torvalds 125847b5d69cSJames Bottomley FPT_BusMasterInit(ioport); 125947b5d69cSJames Bottomley FPT_XbowInit(ioport, ScamFlg); 12601da177e4SLinus Torvalds 126147b5d69cSJames Bottomley FPT_autoLoadDefaultMap(ioport); 12621da177e4SLinus Torvalds 12635c04a7b8SAlexey Dobriyan for (i = 0, id = 0x01; i != pCardInfo->si_id; i++, id <<= 1) { 12645c04a7b8SAlexey Dobriyan } 12651da177e4SLinus Torvalds 12661da177e4SLinus Torvalds WR_HARPOON(ioport + hp_selfid_0, id); 12671da177e4SLinus Torvalds WR_HARPOON(ioport + hp_selfid_1, 0x00); 12681da177e4SLinus Torvalds WR_HARPOON(ioport + hp_arb_id, pCardInfo->si_id); 12691da177e4SLinus Torvalds CurrCard->ourId = pCardInfo->si_id; 12701da177e4SLinus Torvalds 1271db038cf8SAlexey Dobriyan i = (unsigned char)pCardInfo->si_flags; 12721da177e4SLinus Torvalds if (i & SCSI_PARITY_ENA) 12731da177e4SLinus Torvalds WR_HARPOON(ioport + hp_portctrl_1, (HOST_MODE8 | CHK_SCSI_P)); 12741da177e4SLinus Torvalds 12751da177e4SLinus Torvalds j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L); 12761da177e4SLinus Torvalds if (i & LOW_BYTE_TERM) 12771da177e4SLinus Torvalds j |= SCSI_TERM_ENA_L; 12781da177e4SLinus Torvalds WR_HARPOON(ioport + hp_bm_ctrl, j); 12791da177e4SLinus Torvalds 12801da177e4SLinus Torvalds j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H); 12811da177e4SLinus Torvalds if (i & HIGH_BYTE_TERM) 12821da177e4SLinus Torvalds j |= SCSI_TERM_ENA_H; 12831da177e4SLinus Torvalds WR_HARPOON(ioport + hp_ee_ctrl, j); 12841da177e4SLinus Torvalds 12851da177e4SLinus Torvalds if (!(pCardInfo->si_flags & SOFT_RESET)) { 12861da177e4SLinus Torvalds 128747b5d69cSJames Bottomley FPT_sresb(ioport, thisCard); 12881da177e4SLinus Torvalds 128947b5d69cSJames Bottomley FPT_scini(thisCard, pCardInfo->si_id, 0); 12901da177e4SLinus Torvalds } 12911da177e4SLinus Torvalds 12921da177e4SLinus Torvalds if (pCardInfo->si_flags & POST_ALL_UNDERRRUNS) 12931da177e4SLinus Torvalds CurrCard->globalFlags |= F_NO_FILTER; 12941da177e4SLinus Torvalds 12951da177e4SLinus Torvalds if (pCurrNvRam) { 12961da177e4SLinus Torvalds if (pCurrNvRam->niSysConf & 0x10) 12971da177e4SLinus Torvalds CurrCard->globalFlags |= F_GREEN_PC; 12985c04a7b8SAlexey Dobriyan } else { 129947b5d69cSJames Bottomley if (FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)) & GREEN_PC_ENA) 13001da177e4SLinus Torvalds CurrCard->globalFlags |= F_GREEN_PC; 13011da177e4SLinus Torvalds } 13021da177e4SLinus Torvalds 13031da177e4SLinus Torvalds /* Set global flag to indicate Re-Negotiation to be done on all 13041da177e4SLinus Torvalds ckeck condition */ 13051da177e4SLinus Torvalds if (pCurrNvRam) { 13061da177e4SLinus Torvalds if (pCurrNvRam->niScsiConf & 0x04) 13071da177e4SLinus Torvalds CurrCard->globalFlags |= F_DO_RENEGO; 13085c04a7b8SAlexey Dobriyan } else { 130947b5d69cSJames Bottomley if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & RENEGO_ENA) 13101da177e4SLinus Torvalds CurrCard->globalFlags |= F_DO_RENEGO; 13111da177e4SLinus Torvalds } 13121da177e4SLinus Torvalds 13131da177e4SLinus Torvalds if (pCurrNvRam) { 13141da177e4SLinus Torvalds if (pCurrNvRam->niScsiConf & 0x08) 13151da177e4SLinus Torvalds CurrCard->globalFlags |= F_CONLUN_IO; 13165c04a7b8SAlexey Dobriyan } else { 131747b5d69cSJames Bottomley if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & CONNIO_ENA) 13181da177e4SLinus Torvalds CurrCard->globalFlags |= F_CONLUN_IO; 13191da177e4SLinus Torvalds } 13201da177e4SLinus Torvalds 13211da177e4SLinus Torvalds temp = pCardInfo->si_per_targ_no_disc; 13221da177e4SLinus Torvalds 13231da177e4SLinus Torvalds for (i = 0, id = 1; i < MAX_SCSI_TAR; i++, id <<= 1) { 13241da177e4SLinus Torvalds 13251da177e4SLinus Torvalds if (temp & id) 132647b5d69cSJames Bottomley FPT_sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC; 13271da177e4SLinus Torvalds } 13281da177e4SLinus Torvalds 13291da177e4SLinus Torvalds sync_bit_map = 0x0001; 13301da177e4SLinus Torvalds 13311da177e4SLinus Torvalds for (id = 0; id < (MAX_SCSI_TAR / 2); id++) { 13321da177e4SLinus Torvalds 13331da177e4SLinus Torvalds if (pCurrNvRam) { 1334c823feebSAlexey Dobriyan temp = (unsigned short)pCurrNvRam->niSyncTbl[id]; 13351da177e4SLinus Torvalds temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) + 13361da177e4SLinus Torvalds (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000)); 13371da177e4SLinus Torvalds } else 13385c04a7b8SAlexey Dobriyan temp = 13395c04a7b8SAlexey Dobriyan FPT_utilEERead(ioport, 13405c04a7b8SAlexey Dobriyan (unsigned short)((SYNC_RATE_TBL / 2) 13415c04a7b8SAlexey Dobriyan + id)); 13421da177e4SLinus Torvalds 13431da177e4SLinus Torvalds for (i = 0; i < 2; temp >>= 8, i++) { 13441da177e4SLinus Torvalds 13451da177e4SLinus Torvalds if (pCardInfo->si_per_targ_init_sync & sync_bit_map) { 13461da177e4SLinus Torvalds 13475c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[thisCard][id * 2 + 13485c04a7b8SAlexey Dobriyan i].TarEEValue = 13495c04a7b8SAlexey Dobriyan (unsigned char)temp; 13501da177e4SLinus Torvalds } 13511da177e4SLinus Torvalds 13521da177e4SLinus Torvalds else { 13535c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[thisCard][id * 2 + 13545c04a7b8SAlexey Dobriyan i].TarStatus |= 13555c04a7b8SAlexey Dobriyan SYNC_SUPPORTED; 13565c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[thisCard][id * 2 + 13575c04a7b8SAlexey Dobriyan i].TarEEValue = 1358db038cf8SAlexey Dobriyan (unsigned char)(temp & ~EE_SYNC_MASK); 13591da177e4SLinus Torvalds } 13601da177e4SLinus Torvalds 13611da177e4SLinus Torvalds /* if ((pCardInfo->si_per_targ_wide_nego & sync_bit_map) || 13621da177e4SLinus Torvalds (id*2+i >= 8)){ 13631da177e4SLinus Torvalds */ 13641da177e4SLinus Torvalds if (pCardInfo->si_per_targ_wide_nego & sync_bit_map) { 13651da177e4SLinus Torvalds 13665c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[thisCard][id * 2 + 13675c04a7b8SAlexey Dobriyan i].TarEEValue |= 13685c04a7b8SAlexey Dobriyan EE_WIDE_SCSI; 13691da177e4SLinus Torvalds 13701da177e4SLinus Torvalds } 13711da177e4SLinus Torvalds 13721da177e4SLinus Torvalds else { /* NARROW SCSI */ 13735c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[thisCard][id * 2 + 13745c04a7b8SAlexey Dobriyan i].TarStatus |= 13755c04a7b8SAlexey Dobriyan WIDE_NEGOCIATED; 13761da177e4SLinus Torvalds } 13771da177e4SLinus Torvalds 13781da177e4SLinus Torvalds sync_bit_map <<= 1; 13791da177e4SLinus Torvalds 13801da177e4SLinus Torvalds } 13811da177e4SLinus Torvalds } 13821da177e4SLinus Torvalds 13831da177e4SLinus Torvalds WR_HARPOON((ioport + hp_semaphore), 13845c04a7b8SAlexey Dobriyan (unsigned char)(RD_HARPOON((ioport + hp_semaphore)) | 13855c04a7b8SAlexey Dobriyan SCCB_MGR_PRESENT)); 13861da177e4SLinus Torvalds 13875c1b85e2SAlexey Dobriyan return (unsigned long)CurrCard; 13881da177e4SLinus Torvalds } 13891da177e4SLinus Torvalds 1390d63a4cccSAlexey Dobriyan static void FlashPoint_ReleaseHostAdapter(unsigned long pCurrCard) 13911da177e4SLinus Torvalds { 1392db038cf8SAlexey Dobriyan unsigned char i; 1393d63a4cccSAlexey Dobriyan unsigned long portBase; 1394d63a4cccSAlexey Dobriyan unsigned long regOffset; 1395d63a4cccSAlexey Dobriyan unsigned long scamData; 1396d63a4cccSAlexey Dobriyan unsigned long *pScamTbl; 139768d0c1aeSAlexey Dobriyan struct nvram_info *pCurrNvRam; 13981da177e4SLinus Torvalds 139913e6851aSAlexey Dobriyan pCurrNvRam = ((struct sccb_card *)pCurrCard)->pNvRamInfo; 14001da177e4SLinus Torvalds 14011da177e4SLinus Torvalds if (pCurrNvRam) { 140247b5d69cSJames Bottomley FPT_WrStack(pCurrNvRam->niBaseAddr, 0, pCurrNvRam->niModel); 140347b5d69cSJames Bottomley FPT_WrStack(pCurrNvRam->niBaseAddr, 1, pCurrNvRam->niSysConf); 140447b5d69cSJames Bottomley FPT_WrStack(pCurrNvRam->niBaseAddr, 2, pCurrNvRam->niScsiConf); 140547b5d69cSJames Bottomley FPT_WrStack(pCurrNvRam->niBaseAddr, 3, pCurrNvRam->niScamConf); 140647b5d69cSJames Bottomley FPT_WrStack(pCurrNvRam->niBaseAddr, 4, pCurrNvRam->niAdapId); 14071da177e4SLinus Torvalds 14081da177e4SLinus Torvalds for (i = 0; i < MAX_SCSI_TAR / 2; i++) 14095c04a7b8SAlexey Dobriyan FPT_WrStack(pCurrNvRam->niBaseAddr, 14105c04a7b8SAlexey Dobriyan (unsigned char)(i + 5), 14115c04a7b8SAlexey Dobriyan pCurrNvRam->niSyncTbl[i]); 14121da177e4SLinus Torvalds 14131da177e4SLinus Torvalds portBase = pCurrNvRam->niBaseAddr; 14141da177e4SLinus Torvalds 14151da177e4SLinus Torvalds for (i = 0; i < MAX_SCSI_TAR; i++) { 14161da177e4SLinus Torvalds regOffset = hp_aramBase + 64 + i * 4; 1417d63a4cccSAlexey Dobriyan pScamTbl = (unsigned long *)&pCurrNvRam->niScamTbl[i]; 14181da177e4SLinus Torvalds scamData = *pScamTbl; 14191da177e4SLinus Torvalds WR_HARP32(portBase, regOffset, scamData); 14201da177e4SLinus Torvalds } 14211da177e4SLinus Torvalds 14221da177e4SLinus Torvalds } else { 142313e6851aSAlexey Dobriyan FPT_WrStack(((struct sccb_card *)pCurrCard)->ioPort, 0, 0); 14241da177e4SLinus Torvalds } 14251da177e4SLinus Torvalds } 14261da177e4SLinus Torvalds 142768d0c1aeSAlexey Dobriyan static void FPT_RNVRamData(struct nvram_info *pNvRamInfo) 14281da177e4SLinus Torvalds { 1429db038cf8SAlexey Dobriyan unsigned char i; 1430d63a4cccSAlexey Dobriyan unsigned long portBase; 1431d63a4cccSAlexey Dobriyan unsigned long regOffset; 1432d63a4cccSAlexey Dobriyan unsigned long scamData; 1433d63a4cccSAlexey Dobriyan unsigned long *pScamTbl; 14341da177e4SLinus Torvalds 143547b5d69cSJames Bottomley pNvRamInfo->niModel = FPT_RdStack(pNvRamInfo->niBaseAddr, 0); 143647b5d69cSJames Bottomley pNvRamInfo->niSysConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 1); 143747b5d69cSJames Bottomley pNvRamInfo->niScsiConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 2); 143847b5d69cSJames Bottomley pNvRamInfo->niScamConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 3); 143947b5d69cSJames Bottomley pNvRamInfo->niAdapId = FPT_RdStack(pNvRamInfo->niBaseAddr, 4); 14401da177e4SLinus Torvalds 14411da177e4SLinus Torvalds for (i = 0; i < MAX_SCSI_TAR / 2; i++) 14425c04a7b8SAlexey Dobriyan pNvRamInfo->niSyncTbl[i] = 14435c04a7b8SAlexey Dobriyan FPT_RdStack(pNvRamInfo->niBaseAddr, (unsigned char)(i + 5)); 14441da177e4SLinus Torvalds 14451da177e4SLinus Torvalds portBase = pNvRamInfo->niBaseAddr; 14461da177e4SLinus Torvalds 14471da177e4SLinus Torvalds for (i = 0; i < MAX_SCSI_TAR; i++) { 14481da177e4SLinus Torvalds regOffset = hp_aramBase + 64 + i * 4; 14491da177e4SLinus Torvalds RD_HARP32(portBase, regOffset, scamData); 1450d63a4cccSAlexey Dobriyan pScamTbl = (unsigned long *)&pNvRamInfo->niScamTbl[i]; 14511da177e4SLinus Torvalds *pScamTbl = scamData; 14521da177e4SLinus Torvalds } 14531da177e4SLinus Torvalds 14541da177e4SLinus Torvalds } 14551da177e4SLinus Torvalds 1456d63a4cccSAlexey Dobriyan static unsigned char FPT_RdStack(unsigned long portBase, unsigned char index) 14571da177e4SLinus Torvalds { 14581da177e4SLinus Torvalds WR_HARPOON(portBase + hp_stack_addr, index); 14595c1b85e2SAlexey Dobriyan return RD_HARPOON(portBase + hp_stack_data); 14601da177e4SLinus Torvalds } 14611da177e4SLinus Torvalds 14625c04a7b8SAlexey Dobriyan static void FPT_WrStack(unsigned long portBase, unsigned char index, 14635c04a7b8SAlexey Dobriyan unsigned char data) 14641da177e4SLinus Torvalds { 14651da177e4SLinus Torvalds WR_HARPOON(portBase + hp_stack_addr, index); 14661da177e4SLinus Torvalds WR_HARPOON(portBase + hp_stack_data, data); 14671da177e4SLinus Torvalds } 14681da177e4SLinus Torvalds 1469d63a4cccSAlexey Dobriyan static unsigned char FPT_ChkIfChipInitialized(unsigned long ioPort) 14701da177e4SLinus Torvalds { 147147b5d69cSJames Bottomley if ((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != FPT_RdStack(ioPort, 4)) 14725c1b85e2SAlexey Dobriyan return 0; 14731da177e4SLinus Torvalds if ((RD_HARPOON(ioPort + hp_clkctrl_0) & CLKCTRL_DEFAULT) 14741da177e4SLinus Torvalds != CLKCTRL_DEFAULT) 14755c1b85e2SAlexey Dobriyan return 0; 14761da177e4SLinus Torvalds if ((RD_HARPOON(ioPort + hp_seltimeout) == TO_250ms) || 14771da177e4SLinus Torvalds (RD_HARPOON(ioPort + hp_seltimeout) == TO_290ms)) 14785c1b85e2SAlexey Dobriyan return 1; 14795c1b85e2SAlexey Dobriyan return 0; 14801da177e4SLinus Torvalds 14811da177e4SLinus Torvalds } 14825c04a7b8SAlexey Dobriyan 14831da177e4SLinus Torvalds /*--------------------------------------------------------------------- 14841da177e4SLinus Torvalds * 1485d8b6b8bdSAlexey Dobriyan * Function: FlashPoint_StartCCB 14861da177e4SLinus Torvalds * 14871da177e4SLinus Torvalds * Description: Start a command pointed to by p_Sccb. When the 14881da177e4SLinus Torvalds * command is completed it will be returned via the 14891da177e4SLinus Torvalds * callback function. 14901da177e4SLinus Torvalds * 14911da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 149269eb2ea4SAlexey Dobriyan static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb *p_Sccb) 14931da177e4SLinus Torvalds { 1494d63a4cccSAlexey Dobriyan unsigned long ioport; 1495db038cf8SAlexey Dobriyan unsigned char thisCard, lun; 149669eb2ea4SAlexey Dobriyan struct sccb *pSaveSccb; 14971da177e4SLinus Torvalds CALL_BK_FN callback; 14981da177e4SLinus Torvalds 149913e6851aSAlexey Dobriyan thisCard = ((struct sccb_card *)pCurrCard)->cardIndex; 150013e6851aSAlexey Dobriyan ioport = ((struct sccb_card *)pCurrCard)->ioPort; 15011da177e4SLinus Torvalds 15021377d8ddSAdrian Bunk if ((p_Sccb->TargID >= MAX_SCSI_TAR) || (p_Sccb->Lun >= MAX_LUN)) { 15031da177e4SLinus Torvalds 15041da177e4SLinus Torvalds p_Sccb->HostStatus = SCCB_COMPLETE; 15051da177e4SLinus Torvalds p_Sccb->SccbStatus = SCCB_ERROR; 15061da177e4SLinus Torvalds callback = (CALL_BK_FN) p_Sccb->SccbCallback; 15071da177e4SLinus Torvalds if (callback) 15081da177e4SLinus Torvalds callback(p_Sccb); 15091da177e4SLinus Torvalds 15101da177e4SLinus Torvalds return; 15111da177e4SLinus Torvalds } 15121da177e4SLinus Torvalds 151347b5d69cSJames Bottomley FPT_sinits(p_Sccb, thisCard); 15141da177e4SLinus Torvalds 15155c04a7b8SAlexey Dobriyan if (!((struct sccb_card *)pCurrCard)->cmdCounter) { 15165c04a7b8SAlexey Dobriyan WR_HARPOON(ioport + hp_semaphore, 15175c04a7b8SAlexey Dobriyan (RD_HARPOON(ioport + hp_semaphore) 15181da177e4SLinus Torvalds | SCCB_MGR_ACTIVE)); 15191da177e4SLinus Torvalds 15205c04a7b8SAlexey Dobriyan if (((struct sccb_card *)pCurrCard)->globalFlags & F_GREEN_PC) { 15211da177e4SLinus Torvalds WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT); 15221da177e4SLinus Torvalds WR_HARPOON(ioport + hp_sys_ctrl, 0x00); 15231da177e4SLinus Torvalds } 15241da177e4SLinus Torvalds } 15251da177e4SLinus Torvalds 152613e6851aSAlexey Dobriyan ((struct sccb_card *)pCurrCard)->cmdCounter++; 15271da177e4SLinus Torvalds 15281da177e4SLinus Torvalds if (RD_HARPOON(ioport + hp_semaphore) & BIOS_IN_USE) { 15291da177e4SLinus Torvalds 15305c04a7b8SAlexey Dobriyan WR_HARPOON(ioport + hp_semaphore, 15315c04a7b8SAlexey Dobriyan (RD_HARPOON(ioport + hp_semaphore) 15321da177e4SLinus Torvalds | TICKLE_ME)); 15335c04a7b8SAlexey Dobriyan if (p_Sccb->OperationCode == RESET_COMMAND) { 15345c04a7b8SAlexey Dobriyan pSaveSccb = 15355c04a7b8SAlexey Dobriyan ((struct sccb_card *)pCurrCard)->currentSCCB; 153613e6851aSAlexey Dobriyan ((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb; 153747b5d69cSJames Bottomley FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard); 15385c04a7b8SAlexey Dobriyan ((struct sccb_card *)pCurrCard)->currentSCCB = 15395c04a7b8SAlexey Dobriyan pSaveSccb; 15405c04a7b8SAlexey Dobriyan } else { 154147b5d69cSJames Bottomley FPT_queueAddSccb(p_Sccb, thisCard); 15421da177e4SLinus Torvalds } 15431da177e4SLinus Torvalds } 15441da177e4SLinus Torvalds 15451da177e4SLinus Torvalds else if ((RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) { 15461da177e4SLinus Torvalds 15475c04a7b8SAlexey Dobriyan if (p_Sccb->OperationCode == RESET_COMMAND) { 15485c04a7b8SAlexey Dobriyan pSaveSccb = 15495c04a7b8SAlexey Dobriyan ((struct sccb_card *)pCurrCard)->currentSCCB; 155013e6851aSAlexey Dobriyan ((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb; 155147b5d69cSJames Bottomley FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard); 15525c04a7b8SAlexey Dobriyan ((struct sccb_card *)pCurrCard)->currentSCCB = 15535c04a7b8SAlexey Dobriyan pSaveSccb; 15545c04a7b8SAlexey Dobriyan } else { 155547b5d69cSJames Bottomley FPT_queueAddSccb(p_Sccb, thisCard); 15561da177e4SLinus Torvalds } 15571da177e4SLinus Torvalds } 15581da177e4SLinus Torvalds 15591da177e4SLinus Torvalds else { 15601da177e4SLinus Torvalds 15611da177e4SLinus Torvalds MDISABLE_INT(ioport); 15621da177e4SLinus Torvalds 15635c04a7b8SAlexey Dobriyan if ((((struct sccb_card *)pCurrCard)->globalFlags & F_CONLUN_IO) 15645c04a7b8SAlexey Dobriyan && 15655c04a7b8SAlexey Dobriyan ((FPT_sccbMgrTbl[thisCard][p_Sccb->TargID]. 15665c04a7b8SAlexey Dobriyan TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) 15671da177e4SLinus Torvalds lun = p_Sccb->Lun; 15681da177e4SLinus Torvalds else 15691da177e4SLinus Torvalds lun = 0; 157013e6851aSAlexey Dobriyan if ((((struct sccb_card *)pCurrCard)->currentSCCB == NULL) && 15715c04a7b8SAlexey Dobriyan (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarSelQ_Cnt == 0) 15725c04a7b8SAlexey Dobriyan && (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarLUNBusy[lun] 157347b5d69cSJames Bottomley == 0)) { 15741da177e4SLinus Torvalds 157513e6851aSAlexey Dobriyan ((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb; 157647b5d69cSJames Bottomley FPT_ssel(p_Sccb->SccbIOPort, thisCard); 15771da177e4SLinus Torvalds } 15781da177e4SLinus Torvalds 15791da177e4SLinus Torvalds else { 15801da177e4SLinus Torvalds 15815c04a7b8SAlexey Dobriyan if (p_Sccb->OperationCode == RESET_COMMAND) { 15825c04a7b8SAlexey Dobriyan pSaveSccb = 15835c04a7b8SAlexey Dobriyan ((struct sccb_card *)pCurrCard)-> 15845c04a7b8SAlexey Dobriyan currentSCCB; 15855c04a7b8SAlexey Dobriyan ((struct sccb_card *)pCurrCard)->currentSCCB = 15865c04a7b8SAlexey Dobriyan p_Sccb; 15875c04a7b8SAlexey Dobriyan FPT_queueSelectFail(&FPT_BL_Card[thisCard], 15885c04a7b8SAlexey Dobriyan thisCard); 15895c04a7b8SAlexey Dobriyan ((struct sccb_card *)pCurrCard)->currentSCCB = 15905c04a7b8SAlexey Dobriyan pSaveSccb; 15915c04a7b8SAlexey Dobriyan } else { 159247b5d69cSJames Bottomley FPT_queueAddSccb(p_Sccb, thisCard); 15931da177e4SLinus Torvalds } 15941da177e4SLinus Torvalds } 15951da177e4SLinus Torvalds 15961da177e4SLinus Torvalds MENABLE_INT(ioport); 15971da177e4SLinus Torvalds } 15981da177e4SLinus Torvalds 15991da177e4SLinus Torvalds } 16001da177e4SLinus Torvalds 16011da177e4SLinus Torvalds /*--------------------------------------------------------------------- 16021da177e4SLinus Torvalds * 1603d8b6b8bdSAlexey Dobriyan * Function: FlashPoint_AbortCCB 16041da177e4SLinus Torvalds * 16051da177e4SLinus Torvalds * Description: Abort the command pointed to by p_Sccb. When the 16061da177e4SLinus Torvalds * command is completed it will be returned via the 16071da177e4SLinus Torvalds * callback function. 16081da177e4SLinus Torvalds * 16091da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 161069eb2ea4SAlexey Dobriyan static int FlashPoint_AbortCCB(unsigned long pCurrCard, struct sccb *p_Sccb) 16111da177e4SLinus Torvalds { 1612d63a4cccSAlexey Dobriyan unsigned long ioport; 16131da177e4SLinus Torvalds 1614db038cf8SAlexey Dobriyan unsigned char thisCard; 16151da177e4SLinus Torvalds CALL_BK_FN callback; 1616db038cf8SAlexey Dobriyan unsigned char TID; 161769eb2ea4SAlexey Dobriyan struct sccb *pSaveSCCB; 1618f31dc0cdSAlexey Dobriyan struct sccb_mgr_tar_info *currTar_Info; 16191da177e4SLinus Torvalds 162013e6851aSAlexey Dobriyan ioport = ((struct sccb_card *)pCurrCard)->ioPort; 16211da177e4SLinus Torvalds 162213e6851aSAlexey Dobriyan thisCard = ((struct sccb_card *)pCurrCard)->cardIndex; 16231da177e4SLinus Torvalds 16245c04a7b8SAlexey Dobriyan if (!(RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) { 16251da177e4SLinus Torvalds 16265c04a7b8SAlexey Dobriyan if (FPT_queueFindSccb(p_Sccb, thisCard)) { 16271da177e4SLinus Torvalds 162813e6851aSAlexey Dobriyan ((struct sccb_card *)pCurrCard)->cmdCounter--; 16291da177e4SLinus Torvalds 163013e6851aSAlexey Dobriyan if (!((struct sccb_card *)pCurrCard)->cmdCounter) 16315c04a7b8SAlexey Dobriyan WR_HARPOON(ioport + hp_semaphore, 16325c04a7b8SAlexey Dobriyan (RD_HARPOON(ioport + hp_semaphore) 16335c04a7b8SAlexey Dobriyan & (unsigned 16345c04a7b8SAlexey Dobriyan char)(~(SCCB_MGR_ACTIVE | 16355c04a7b8SAlexey Dobriyan TICKLE_ME)))); 16361da177e4SLinus Torvalds 16371da177e4SLinus Torvalds p_Sccb->SccbStatus = SCCB_ABORT; 16381da177e4SLinus Torvalds callback = p_Sccb->SccbCallback; 16391da177e4SLinus Torvalds callback(p_Sccb); 16401da177e4SLinus Torvalds 16415c1b85e2SAlexey Dobriyan return 0; 16421da177e4SLinus Torvalds } 16431da177e4SLinus Torvalds 16445c04a7b8SAlexey Dobriyan else { 16455c04a7b8SAlexey Dobriyan if (((struct sccb_card *)pCurrCard)->currentSCCB == 16465c04a7b8SAlexey Dobriyan p_Sccb) { 16471da177e4SLinus Torvalds p_Sccb->SccbStatus = SCCB_ABORT; 16485c1b85e2SAlexey Dobriyan return 0; 16491da177e4SLinus Torvalds 16501da177e4SLinus Torvalds } 16511da177e4SLinus Torvalds 16525c04a7b8SAlexey Dobriyan else { 16531da177e4SLinus Torvalds 16541da177e4SLinus Torvalds TID = p_Sccb->TargID; 16551da177e4SLinus Torvalds 16565c04a7b8SAlexey Dobriyan if (p_Sccb->Sccb_tag) { 16571da177e4SLinus Torvalds MDISABLE_INT(ioport); 16585c04a7b8SAlexey Dobriyan if (((struct sccb_card *)pCurrCard)-> 16595c04a7b8SAlexey Dobriyan discQ_Tbl[p_Sccb->Sccb_tag] == 16605c04a7b8SAlexey Dobriyan p_Sccb) { 16611da177e4SLinus Torvalds p_Sccb->SccbStatus = SCCB_ABORT; 16625c04a7b8SAlexey Dobriyan p_Sccb->Sccb_scsistat = 16635c04a7b8SAlexey Dobriyan ABORT_ST; 16645c04a7b8SAlexey Dobriyan p_Sccb->Sccb_scsimsg = 16655c04a7b8SAlexey Dobriyan SMABORT_TAG; 16661da177e4SLinus Torvalds 16675c04a7b8SAlexey Dobriyan if (((struct sccb_card *) 16685c04a7b8SAlexey Dobriyan pCurrCard)->currentSCCB == 16695c04a7b8SAlexey Dobriyan NULL) { 16705c04a7b8SAlexey Dobriyan ((struct sccb_card *) 16715c04a7b8SAlexey Dobriyan pCurrCard)-> 16725c04a7b8SAlexey Dobriyan currentSCCB = p_Sccb; 16735c04a7b8SAlexey Dobriyan FPT_ssel(ioport, 16745c04a7b8SAlexey Dobriyan thisCard); 16755c04a7b8SAlexey Dobriyan } else { 16765c04a7b8SAlexey Dobriyan pSaveSCCB = 16775c04a7b8SAlexey Dobriyan ((struct sccb_card 16785c04a7b8SAlexey Dobriyan *)pCurrCard)-> 16795c04a7b8SAlexey Dobriyan currentSCCB; 16805c04a7b8SAlexey Dobriyan ((struct sccb_card *) 16815c04a7b8SAlexey Dobriyan pCurrCard)-> 16825c04a7b8SAlexey Dobriyan currentSCCB = p_Sccb; 168313e6851aSAlexey Dobriyan FPT_queueSelectFail((struct sccb_card *)pCurrCard, thisCard); 16845c04a7b8SAlexey Dobriyan ((struct sccb_card *) 16855c04a7b8SAlexey Dobriyan pCurrCard)-> 16865c04a7b8SAlexey Dobriyan currentSCCB = pSaveSCCB; 16871da177e4SLinus Torvalds } 16881da177e4SLinus Torvalds } 16891da177e4SLinus Torvalds MENABLE_INT(ioport); 16905c1b85e2SAlexey Dobriyan return 0; 16915c04a7b8SAlexey Dobriyan } else { 16925c04a7b8SAlexey Dobriyan currTar_Info = 16935c04a7b8SAlexey Dobriyan &FPT_sccbMgrTbl[thisCard][p_Sccb-> 16945c04a7b8SAlexey Dobriyan TargID]; 16951da177e4SLinus Torvalds 16965c04a7b8SAlexey Dobriyan if (FPT_BL_Card[thisCard]. 16975c04a7b8SAlexey Dobriyan discQ_Tbl[currTar_Info-> 16985c04a7b8SAlexey Dobriyan LunDiscQ_Idx[p_Sccb->Lun]] 16995c04a7b8SAlexey Dobriyan == p_Sccb) { 17001da177e4SLinus Torvalds p_Sccb->SccbStatus = SCCB_ABORT; 17015c1b85e2SAlexey Dobriyan return 0; 17021da177e4SLinus Torvalds } 17031da177e4SLinus Torvalds } 17041da177e4SLinus Torvalds } 17051da177e4SLinus Torvalds } 17061da177e4SLinus Torvalds } 17075c1b85e2SAlexey Dobriyan return -1; 17081da177e4SLinus Torvalds } 17091da177e4SLinus Torvalds 17101da177e4SLinus Torvalds /*--------------------------------------------------------------------- 17111da177e4SLinus Torvalds * 1712d8b6b8bdSAlexey Dobriyan * Function: FlashPoint_InterruptPending 17131da177e4SLinus Torvalds * 17141da177e4SLinus Torvalds * Description: Do a quick check to determine if there is a pending 17151da177e4SLinus Torvalds * interrupt for this card and disable the IRQ Pin if so. 17161da177e4SLinus Torvalds * 17171da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 1718d63a4cccSAlexey Dobriyan static unsigned char FlashPoint_InterruptPending(unsigned long pCurrCard) 17191da177e4SLinus Torvalds { 1720d63a4cccSAlexey Dobriyan unsigned long ioport; 17211da177e4SLinus Torvalds 172213e6851aSAlexey Dobriyan ioport = ((struct sccb_card *)pCurrCard)->ioPort; 17231da177e4SLinus Torvalds 17245c04a7b8SAlexey Dobriyan if (RD_HARPOON(ioport + hp_int_status) & INT_ASSERTED) { 17255c1b85e2SAlexey Dobriyan return 1; 17261da177e4SLinus Torvalds } 17271da177e4SLinus Torvalds 17281da177e4SLinus Torvalds else 17291da177e4SLinus Torvalds 17305c1b85e2SAlexey Dobriyan return 0; 17311da177e4SLinus Torvalds } 17321da177e4SLinus Torvalds 17331da177e4SLinus Torvalds /*--------------------------------------------------------------------- 17341da177e4SLinus Torvalds * 1735d8b6b8bdSAlexey Dobriyan * Function: FlashPoint_HandleInterrupt 17361da177e4SLinus Torvalds * 17371da177e4SLinus Torvalds * Description: This is our entry point when an interrupt is generated 17381da177e4SLinus Torvalds * by the card and the upper level driver passes it on to 17391da177e4SLinus Torvalds * us. 17401da177e4SLinus Torvalds * 17411da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 1742d63a4cccSAlexey Dobriyan static int FlashPoint_HandleInterrupt(unsigned long pCurrCard) 17431da177e4SLinus Torvalds { 174469eb2ea4SAlexey Dobriyan struct sccb *currSCCB; 1745db038cf8SAlexey Dobriyan unsigned char thisCard, result, bm_status, bm_int_st; 1746c823feebSAlexey Dobriyan unsigned short hp_int; 1747db038cf8SAlexey Dobriyan unsigned char i, target; 1748d63a4cccSAlexey Dobriyan unsigned long ioport; 17491da177e4SLinus Torvalds 175013e6851aSAlexey Dobriyan thisCard = ((struct sccb_card *)pCurrCard)->cardIndex; 175113e6851aSAlexey Dobriyan ioport = ((struct sccb_card *)pCurrCard)->ioPort; 17521da177e4SLinus Torvalds 17531da177e4SLinus Torvalds MDISABLE_INT(ioport); 17541da177e4SLinus Torvalds 17551da177e4SLinus Torvalds if ((bm_int_st = RD_HARPOON(ioport + hp_int_status)) & EXT_STATUS_ON) 17565c04a7b8SAlexey Dobriyan bm_status = 17575c04a7b8SAlexey Dobriyan RD_HARPOON(ioport + 17585c04a7b8SAlexey Dobriyan hp_ext_status) & (unsigned char)BAD_EXT_STATUS; 17591da177e4SLinus Torvalds else 17601da177e4SLinus Torvalds bm_status = 0; 17611da177e4SLinus Torvalds 17621da177e4SLinus Torvalds WR_HARPOON(ioport + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT)); 17631da177e4SLinus Torvalds 17645c04a7b8SAlexey Dobriyan while ((hp_int = 17655c04a7b8SAlexey Dobriyan RDW_HARPOON((ioport + 17665c04a7b8SAlexey Dobriyan hp_intstat)) & FPT_default_intena) | bm_status) { 17671da177e4SLinus Torvalds 176813e6851aSAlexey Dobriyan currSCCB = ((struct sccb_card *)pCurrCard)->currentSCCB; 17691da177e4SLinus Torvalds 17701da177e4SLinus Torvalds if (hp_int & (FIFO | TIMEOUT | RESET | SCAM_SEL) || bm_status) { 17715c04a7b8SAlexey Dobriyan result = 17725c04a7b8SAlexey Dobriyan FPT_SccbMgr_bad_isr(ioport, thisCard, 17735c04a7b8SAlexey Dobriyan ((struct sccb_card *)pCurrCard), 17745c04a7b8SAlexey Dobriyan hp_int); 17755c04a7b8SAlexey Dobriyan WRW_HARPOON((ioport + hp_intstat), 17765c04a7b8SAlexey Dobriyan (FIFO | TIMEOUT | RESET | SCAM_SEL)); 17771da177e4SLinus Torvalds bm_status = 0; 17781da177e4SLinus Torvalds 17791da177e4SLinus Torvalds if (result) { 17801da177e4SLinus Torvalds 17811da177e4SLinus Torvalds MENABLE_INT(ioport); 17825c1b85e2SAlexey Dobriyan return result; 17831da177e4SLinus Torvalds } 17841da177e4SLinus Torvalds } 17851da177e4SLinus Torvalds 17861da177e4SLinus Torvalds else if (hp_int & ICMD_COMP) { 17871da177e4SLinus Torvalds 17881da177e4SLinus Torvalds if (!(hp_int & BUS_FREE)) { 17891da177e4SLinus Torvalds /* Wait for the BusFree before starting a new command. We 17901da177e4SLinus Torvalds must also check for being reselected since the BusFree 17911da177e4SLinus Torvalds may not show up if another device reselects us in 1.5us or 17921da177e4SLinus Torvalds less. SRR Wednesday, 3/8/1995. 17931da177e4SLinus Torvalds */ 17945c04a7b8SAlexey Dobriyan while (! 17955c04a7b8SAlexey Dobriyan (RDW_HARPOON((ioport + hp_intstat)) & 17965c04a7b8SAlexey Dobriyan (BUS_FREE | RSEL))) ; 17971da177e4SLinus Torvalds } 17981da177e4SLinus Torvalds 17995c04a7b8SAlexey Dobriyan if (((struct sccb_card *)pCurrCard)-> 18005c04a7b8SAlexey Dobriyan globalFlags & F_HOST_XFER_ACT) 18011da177e4SLinus Torvalds 180247b5d69cSJames Bottomley FPT_phaseChkFifo(ioport, thisCard); 18031da177e4SLinus Torvalds 18041da177e4SLinus Torvalds /* WRW_HARPOON((ioport+hp_intstat), 18051da177e4SLinus Torvalds (BUS_FREE | ICMD_COMP | ITAR_DISC | XFER_CNT_0)); 18061da177e4SLinus Torvalds */ 18071da177e4SLinus Torvalds 18081da177e4SLinus Torvalds WRW_HARPOON((ioport + hp_intstat), CLR_ALL_INT_1); 18091da177e4SLinus Torvalds 181047b5d69cSJames Bottomley FPT_autoCmdCmplt(ioport, thisCard); 18111da177e4SLinus Torvalds 18121da177e4SLinus Torvalds } 18131da177e4SLinus Torvalds 18145c04a7b8SAlexey Dobriyan else if (hp_int & ITAR_DISC) { 18151da177e4SLinus Torvalds 18165c04a7b8SAlexey Dobriyan if (((struct sccb_card *)pCurrCard)-> 18175c04a7b8SAlexey Dobriyan globalFlags & F_HOST_XFER_ACT) { 18181da177e4SLinus Torvalds 181947b5d69cSJames Bottomley FPT_phaseChkFifo(ioport, thisCard); 18201da177e4SLinus Torvalds 18211da177e4SLinus Torvalds } 18221da177e4SLinus Torvalds 18231da177e4SLinus Torvalds if (RD_HARPOON(ioport + hp_gp_reg_1) == SMSAVE_DATA_PTR) { 18241da177e4SLinus Torvalds 18251da177e4SLinus Torvalds WR_HARPOON(ioport + hp_gp_reg_1, 0x00); 18261da177e4SLinus Torvalds currSCCB->Sccb_XferState |= F_NO_DATA_YET; 18271da177e4SLinus Torvalds 18281da177e4SLinus Torvalds currSCCB->Sccb_savedATC = currSCCB->Sccb_ATC; 18291da177e4SLinus Torvalds } 18301da177e4SLinus Torvalds 18311da177e4SLinus Torvalds currSCCB->Sccb_scsistat = DISCONNECT_ST; 183247b5d69cSJames Bottomley FPT_queueDisconnect(currSCCB, thisCard); 18331da177e4SLinus Torvalds 18341da177e4SLinus Torvalds /* Wait for the BusFree before starting a new command. We 18351da177e4SLinus Torvalds must also check for being reselected since the BusFree 18361da177e4SLinus Torvalds may not show up if another device reselects us in 1.5us or 18371da177e4SLinus Torvalds less. SRR Wednesday, 3/8/1995. 18381da177e4SLinus Torvalds */ 18395c04a7b8SAlexey Dobriyan while (! 18405c04a7b8SAlexey Dobriyan (RDW_HARPOON((ioport + hp_intstat)) & 18415c04a7b8SAlexey Dobriyan (BUS_FREE | RSEL)) 18425c04a7b8SAlexey Dobriyan && !((RDW_HARPOON((ioport + hp_intstat)) & PHASE) 18435c04a7b8SAlexey Dobriyan && RD_HARPOON((ioport + hp_scsisig)) == 18445c04a7b8SAlexey Dobriyan (SCSI_BSY | SCSI_REQ | SCSI_CD | SCSI_MSG | 18455c04a7b8SAlexey Dobriyan SCSI_IOBIT))) ; 18461da177e4SLinus Torvalds 18471da177e4SLinus Torvalds /* 18481da177e4SLinus Torvalds The additional loop exit condition above detects a timing problem 18491da177e4SLinus Torvalds with the revision D/E harpoon chips. The caller should reset the 18501da177e4SLinus Torvalds host adapter to recover when 0xFE is returned. 18511da177e4SLinus Torvalds */ 18525c04a7b8SAlexey Dobriyan if (! 18535c04a7b8SAlexey Dobriyan (RDW_HARPOON((ioport + hp_intstat)) & 18545c04a7b8SAlexey Dobriyan (BUS_FREE | RSEL))) { 18551da177e4SLinus Torvalds MENABLE_INT(ioport); 18561da177e4SLinus Torvalds return 0xFE; 18571da177e4SLinus Torvalds } 18581da177e4SLinus Torvalds 18595c04a7b8SAlexey Dobriyan WRW_HARPOON((ioport + hp_intstat), 18605c04a7b8SAlexey Dobriyan (BUS_FREE | ITAR_DISC)); 18611da177e4SLinus Torvalds 18625c04a7b8SAlexey Dobriyan ((struct sccb_card *)pCurrCard)->globalFlags |= 18635c04a7b8SAlexey Dobriyan F_NEW_SCCB_CMD; 18641da177e4SLinus Torvalds 18651da177e4SLinus Torvalds } 18661da177e4SLinus Torvalds 18671da177e4SLinus Torvalds else if (hp_int & RSEL) { 18681da177e4SLinus Torvalds 18695c04a7b8SAlexey Dobriyan WRW_HARPOON((ioport + hp_intstat), 18705c04a7b8SAlexey Dobriyan (PROG_HLT | RSEL | PHASE | BUS_FREE)); 18711da177e4SLinus Torvalds 18725c04a7b8SAlexey Dobriyan if (RDW_HARPOON((ioport + hp_intstat)) & ITAR_DISC) { 18735c04a7b8SAlexey Dobriyan if (((struct sccb_card *)pCurrCard)-> 18745c04a7b8SAlexey Dobriyan globalFlags & F_HOST_XFER_ACT) { 187547b5d69cSJames Bottomley FPT_phaseChkFifo(ioport, thisCard); 18761da177e4SLinus Torvalds } 18771da177e4SLinus Torvalds 18785c04a7b8SAlexey Dobriyan if (RD_HARPOON(ioport + hp_gp_reg_1) == 18795c04a7b8SAlexey Dobriyan SMSAVE_DATA_PTR) { 18801da177e4SLinus Torvalds WR_HARPOON(ioport + hp_gp_reg_1, 0x00); 18815c04a7b8SAlexey Dobriyan currSCCB->Sccb_XferState |= 18825c04a7b8SAlexey Dobriyan F_NO_DATA_YET; 18835c04a7b8SAlexey Dobriyan currSCCB->Sccb_savedATC = 18845c04a7b8SAlexey Dobriyan currSCCB->Sccb_ATC; 18851da177e4SLinus Torvalds } 18861da177e4SLinus Torvalds 18875c04a7b8SAlexey Dobriyan WRW_HARPOON((ioport + hp_intstat), 18885c04a7b8SAlexey Dobriyan (BUS_FREE | ITAR_DISC)); 18891da177e4SLinus Torvalds currSCCB->Sccb_scsistat = DISCONNECT_ST; 189047b5d69cSJames Bottomley FPT_queueDisconnect(currSCCB, thisCard); 18911da177e4SLinus Torvalds } 18921da177e4SLinus Torvalds 18935c04a7b8SAlexey Dobriyan FPT_sres(ioport, thisCard, 18945c04a7b8SAlexey Dobriyan ((struct sccb_card *)pCurrCard)); 189547b5d69cSJames Bottomley FPT_phaseDecode(ioport, thisCard); 18961da177e4SLinus Torvalds 18971da177e4SLinus Torvalds } 18981da177e4SLinus Torvalds 18995c04a7b8SAlexey Dobriyan else if ((hp_int & IDO_STRT) && (!(hp_int & BUS_FREE))) { 19001da177e4SLinus Torvalds 19015c04a7b8SAlexey Dobriyan WRW_HARPOON((ioport + hp_intstat), 19025c04a7b8SAlexey Dobriyan (IDO_STRT | XFER_CNT_0)); 190347b5d69cSJames Bottomley FPT_phaseDecode(ioport, thisCard); 19041da177e4SLinus Torvalds 19051da177e4SLinus Torvalds } 19061da177e4SLinus Torvalds 19075c04a7b8SAlexey Dobriyan else if ((hp_int & IUNKWN) || (hp_int & PROG_HLT)) { 19085c04a7b8SAlexey Dobriyan WRW_HARPOON((ioport + hp_intstat), 19095c04a7b8SAlexey Dobriyan (PHASE | IUNKWN | PROG_HLT)); 19105c04a7b8SAlexey Dobriyan if ((RD_HARPOON(ioport + hp_prgmcnt_0) & (unsigned char) 19115c04a7b8SAlexey Dobriyan 0x3f) < (unsigned char)SELCHK) { 191247b5d69cSJames Bottomley FPT_phaseDecode(ioport, thisCard); 19135c04a7b8SAlexey Dobriyan } else { 19141da177e4SLinus Torvalds /* Harpoon problem some SCSI target device respond to selection 19151da177e4SLinus Torvalds with short BUSY pulse (<400ns) this will make the Harpoon is not able 19161da177e4SLinus Torvalds to latch the correct Target ID into reg. x53. 19171da177e4SLinus Torvalds The work around require to correct this reg. But when write to this 19181da177e4SLinus Torvalds reg. (0x53) also increment the FIFO write addr reg (0x6f), thus we 19191da177e4SLinus Torvalds need to read this reg first then restore it later. After update to 0x53 */ 19201da177e4SLinus Torvalds 19215c04a7b8SAlexey Dobriyan i = (unsigned 19225c04a7b8SAlexey Dobriyan char)(RD_HARPOON(ioport + hp_fifowrite)); 19235c04a7b8SAlexey Dobriyan target = 19245c04a7b8SAlexey Dobriyan (unsigned 19255c04a7b8SAlexey Dobriyan char)(RD_HARPOON(ioport + hp_gp_reg_3)); 19265c04a7b8SAlexey Dobriyan WR_HARPOON(ioport + hp_xfer_pad, 19275c04a7b8SAlexey Dobriyan (unsigned char)ID_UNLOCK); 19285c04a7b8SAlexey Dobriyan WR_HARPOON(ioport + hp_select_id, 19295c04a7b8SAlexey Dobriyan (unsigned char)(target | target << 19305c04a7b8SAlexey Dobriyan 4)); 19315c04a7b8SAlexey Dobriyan WR_HARPOON(ioport + hp_xfer_pad, 19325c04a7b8SAlexey Dobriyan (unsigned char)0x00); 19331da177e4SLinus Torvalds WR_HARPOON(ioport + hp_fifowrite, i); 19345c04a7b8SAlexey Dobriyan WR_HARPOON(ioport + hp_autostart_3, 19355c04a7b8SAlexey Dobriyan (AUTO_IMMED + TAG_STRT)); 19361da177e4SLinus Torvalds } 19371da177e4SLinus Torvalds } 19381da177e4SLinus Torvalds 19391da177e4SLinus Torvalds else if (hp_int & XFER_CNT_0) { 19401da177e4SLinus Torvalds 19411da177e4SLinus Torvalds WRW_HARPOON((ioport + hp_intstat), XFER_CNT_0); 19421da177e4SLinus Torvalds 194347b5d69cSJames Bottomley FPT_schkdd(ioport, thisCard); 19441da177e4SLinus Torvalds 19451da177e4SLinus Torvalds } 19461da177e4SLinus Torvalds 19471da177e4SLinus Torvalds else if (hp_int & BUS_FREE) { 19481da177e4SLinus Torvalds 19491da177e4SLinus Torvalds WRW_HARPOON((ioport + hp_intstat), BUS_FREE); 19501da177e4SLinus Torvalds 19515c04a7b8SAlexey Dobriyan if (((struct sccb_card *)pCurrCard)-> 19525c04a7b8SAlexey Dobriyan globalFlags & F_HOST_XFER_ACT) { 19531da177e4SLinus Torvalds 19545c04a7b8SAlexey Dobriyan FPT_hostDataXferAbort(ioport, thisCard, 19555c04a7b8SAlexey Dobriyan currSCCB); 19561da177e4SLinus Torvalds } 19571da177e4SLinus Torvalds 195847b5d69cSJames Bottomley FPT_phaseBusFree(ioport, thisCard); 19591da177e4SLinus Torvalds } 19601da177e4SLinus Torvalds 19611da177e4SLinus Torvalds else if (hp_int & ITICKLE) { 19621da177e4SLinus Torvalds 19631da177e4SLinus Torvalds WRW_HARPOON((ioport + hp_intstat), ITICKLE); 19645c04a7b8SAlexey Dobriyan ((struct sccb_card *)pCurrCard)->globalFlags |= 19655c04a7b8SAlexey Dobriyan F_NEW_SCCB_CMD; 19661da177e4SLinus Torvalds } 19671da177e4SLinus Torvalds 19685c04a7b8SAlexey Dobriyan if (((struct sccb_card *)pCurrCard)-> 19695c04a7b8SAlexey Dobriyan globalFlags & F_NEW_SCCB_CMD) { 19701da177e4SLinus Torvalds 19715c04a7b8SAlexey Dobriyan ((struct sccb_card *)pCurrCard)->globalFlags &= 19725c04a7b8SAlexey Dobriyan ~F_NEW_SCCB_CMD; 19731da177e4SLinus Torvalds 19745c04a7b8SAlexey Dobriyan if (((struct sccb_card *)pCurrCard)->currentSCCB == 19755c04a7b8SAlexey Dobriyan NULL) { 19761da177e4SLinus Torvalds 19775c04a7b8SAlexey Dobriyan FPT_queueSearchSelect(((struct sccb_card *) 19785c04a7b8SAlexey Dobriyan pCurrCard), thisCard); 19791da177e4SLinus Torvalds } 19801da177e4SLinus Torvalds 19815c04a7b8SAlexey Dobriyan if (((struct sccb_card *)pCurrCard)->currentSCCB != 19825c04a7b8SAlexey Dobriyan NULL) { 19835c04a7b8SAlexey Dobriyan ((struct sccb_card *)pCurrCard)->globalFlags &= 19845c04a7b8SAlexey Dobriyan ~F_NEW_SCCB_CMD; 198547b5d69cSJames Bottomley FPT_ssel(ioport, thisCard); 19861da177e4SLinus Torvalds } 19871da177e4SLinus Torvalds 19881da177e4SLinus Torvalds break; 19891da177e4SLinus Torvalds 19901da177e4SLinus Torvalds } 19911da177e4SLinus Torvalds 19921da177e4SLinus Torvalds } /*end while */ 19931da177e4SLinus Torvalds 19941da177e4SLinus Torvalds MENABLE_INT(ioport); 19951da177e4SLinus Torvalds 19965c1b85e2SAlexey Dobriyan return 0; 19971da177e4SLinus Torvalds } 19981da177e4SLinus Torvalds 19991da177e4SLinus Torvalds /*--------------------------------------------------------------------- 20001da177e4SLinus Torvalds * 20011da177e4SLinus Torvalds * Function: Sccb_bad_isr 20021da177e4SLinus Torvalds * 20031da177e4SLinus Torvalds * Description: Some type of interrupt has occurred which is slightly 20041da177e4SLinus Torvalds * out of the ordinary. We will now decode it fully, in 20051da177e4SLinus Torvalds * this routine. This is broken up in an attempt to save 20061da177e4SLinus Torvalds * processing time. 20071da177e4SLinus Torvalds * 20081da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 20095c04a7b8SAlexey Dobriyan static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port, 20105c04a7b8SAlexey Dobriyan unsigned char p_card, 20115c04a7b8SAlexey Dobriyan struct sccb_card *pCurrCard, 20125c04a7b8SAlexey Dobriyan unsigned short p_int) 20131da177e4SLinus Torvalds { 2014db038cf8SAlexey Dobriyan unsigned char temp, ScamFlg; 2015f31dc0cdSAlexey Dobriyan struct sccb_mgr_tar_info *currTar_Info; 201668d0c1aeSAlexey Dobriyan struct nvram_info *pCurrNvRam; 20171da177e4SLinus Torvalds 20181da177e4SLinus Torvalds if (RD_HARPOON(p_port + hp_ext_status) & 20195c04a7b8SAlexey Dobriyan (BM_FORCE_OFF | PCI_DEV_TMOUT | BM_PARITY_ERR | PIO_OVERRUN)) { 20201da177e4SLinus Torvalds 20215c04a7b8SAlexey Dobriyan if (pCurrCard->globalFlags & F_HOST_XFER_ACT) { 20221da177e4SLinus Torvalds 20235c04a7b8SAlexey Dobriyan FPT_hostDataXferAbort(p_port, p_card, 20245c04a7b8SAlexey Dobriyan pCurrCard->currentSCCB); 20251da177e4SLinus Torvalds } 20261da177e4SLinus Torvalds 20271da177e4SLinus Torvalds if (RD_HARPOON(p_port + hp_pci_stat_cfg) & REC_MASTER_ABORT) 20281da177e4SLinus Torvalds { 20291da177e4SLinus Torvalds WR_HARPOON(p_port + hp_pci_stat_cfg, 20305c04a7b8SAlexey Dobriyan (RD_HARPOON(p_port + hp_pci_stat_cfg) & 20315c04a7b8SAlexey Dobriyan ~REC_MASTER_ABORT)); 20321da177e4SLinus Torvalds 20331da177e4SLinus Torvalds WR_HARPOON(p_port + hp_host_blk_cnt, 0x00); 20341da177e4SLinus Torvalds 20351da177e4SLinus Torvalds } 20361da177e4SLinus Torvalds 20375c04a7b8SAlexey Dobriyan if (pCurrCard->currentSCCB != NULL) { 20381da177e4SLinus Torvalds 20391da177e4SLinus Torvalds if (!pCurrCard->currentSCCB->HostStatus) 20405c04a7b8SAlexey Dobriyan pCurrCard->currentSCCB->HostStatus = 20415c04a7b8SAlexey Dobriyan SCCB_BM_ERR; 20421da177e4SLinus Torvalds 204347b5d69cSJames Bottomley FPT_sxfrp(p_port, p_card); 20441da177e4SLinus Torvalds 2045db038cf8SAlexey Dobriyan temp = (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) & 20461da177e4SLinus Torvalds (EXT_ARB_ACK | SCSI_TERM_ENA_H)); 20475c04a7b8SAlexey Dobriyan WR_HARPOON(p_port + hp_ee_ctrl, 20485c04a7b8SAlexey Dobriyan ((unsigned char)temp | SEE_MS | SEE_CS)); 20491da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, temp); 20501da177e4SLinus Torvalds 20515c04a7b8SAlexey Dobriyan if (! 20525c04a7b8SAlexey Dobriyan (RDW_HARPOON((p_port + hp_intstat)) & 20535c04a7b8SAlexey Dobriyan (BUS_FREE | RESET))) { 205447b5d69cSJames Bottomley FPT_phaseDecode(p_port, p_card); 20551da177e4SLinus Torvalds } 20561da177e4SLinus Torvalds } 20571da177e4SLinus Torvalds } 20581da177e4SLinus Torvalds 20595c04a7b8SAlexey Dobriyan else if (p_int & RESET) { 20601da177e4SLinus Torvalds 20611da177e4SLinus Torvalds WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT); 20621da177e4SLinus Torvalds WR_HARPOON(p_port + hp_sys_ctrl, 0x00); 20631da177e4SLinus Torvalds if (pCurrCard->currentSCCB != NULL) { 20641da177e4SLinus Torvalds 20651da177e4SLinus Torvalds if (pCurrCard->globalFlags & F_HOST_XFER_ACT) 20661da177e4SLinus Torvalds 20675c04a7b8SAlexey Dobriyan FPT_hostDataXferAbort(p_port, p_card, 20685c04a7b8SAlexey Dobriyan pCurrCard->currentSCCB); 20691da177e4SLinus Torvalds } 20701da177e4SLinus Torvalds 20711da177e4SLinus Torvalds DISABLE_AUTO(p_port); 20721da177e4SLinus Torvalds 207347b5d69cSJames Bottomley FPT_sresb(p_port, p_card); 20741da177e4SLinus Torvalds 20755c04a7b8SAlexey Dobriyan while (RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST) { 20765c04a7b8SAlexey Dobriyan } 20771da177e4SLinus Torvalds 20781da177e4SLinus Torvalds pCurrNvRam = pCurrCard->pNvRamInfo; 20791da177e4SLinus Torvalds if (pCurrNvRam) { 20801da177e4SLinus Torvalds ScamFlg = pCurrNvRam->niScamConf; 20815c04a7b8SAlexey Dobriyan } else { 20825c04a7b8SAlexey Dobriyan ScamFlg = 20835c04a7b8SAlexey Dobriyan (unsigned char)FPT_utilEERead(p_port, 20845c04a7b8SAlexey Dobriyan SCAM_CONFIG / 2); 20851da177e4SLinus Torvalds } 20861da177e4SLinus Torvalds 208747b5d69cSJames Bottomley FPT_XbowInit(p_port, ScamFlg); 20881da177e4SLinus Torvalds 208947b5d69cSJames Bottomley FPT_scini(p_card, pCurrCard->ourId, 0); 20901da177e4SLinus Torvalds 20915c1b85e2SAlexey Dobriyan return 0xFF; 20921da177e4SLinus Torvalds } 20931da177e4SLinus Torvalds 20941da177e4SLinus Torvalds else if (p_int & FIFO) { 20951da177e4SLinus Torvalds 20961da177e4SLinus Torvalds WRW_HARPOON((p_port + hp_intstat), FIFO); 20971da177e4SLinus Torvalds 20981da177e4SLinus Torvalds if (pCurrCard->currentSCCB != NULL) 209947b5d69cSJames Bottomley FPT_sxfrp(p_port, p_card); 21001da177e4SLinus Torvalds } 21011da177e4SLinus Torvalds 21025c04a7b8SAlexey Dobriyan else if (p_int & TIMEOUT) { 21031da177e4SLinus Torvalds 21041da177e4SLinus Torvalds DISABLE_AUTO(p_port); 21051da177e4SLinus Torvalds 21061da177e4SLinus Torvalds WRW_HARPOON((p_port + hp_intstat), 21075c04a7b8SAlexey Dobriyan (PROG_HLT | TIMEOUT | SEL | BUS_FREE | PHASE | 21085c04a7b8SAlexey Dobriyan IUNKWN)); 21091da177e4SLinus Torvalds 21101da177e4SLinus Torvalds pCurrCard->currentSCCB->HostStatus = SCCB_SELECTION_TIMEOUT; 21111da177e4SLinus Torvalds 21125c04a7b8SAlexey Dobriyan currTar_Info = 21135c04a7b8SAlexey Dobriyan &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID]; 21145c04a7b8SAlexey Dobriyan if ((pCurrCard->globalFlags & F_CONLUN_IO) 21155c04a7b8SAlexey Dobriyan && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != 21165c04a7b8SAlexey Dobriyan TAG_Q_TRYING)) 21175c04a7b8SAlexey Dobriyan currTar_Info->TarLUNBusy[pCurrCard->currentSCCB->Lun] = 21185c04a7b8SAlexey Dobriyan 0; 21191da177e4SLinus Torvalds else 212047b5d69cSJames Bottomley currTar_Info->TarLUNBusy[0] = 0; 21211da177e4SLinus Torvalds 21225c04a7b8SAlexey Dobriyan if (currTar_Info->TarEEValue & EE_SYNC_MASK) { 21231da177e4SLinus Torvalds currTar_Info->TarSyncCtrl = 0; 21241da177e4SLinus Torvalds currTar_Info->TarStatus &= ~TAR_SYNC_MASK; 21251da177e4SLinus Torvalds } 21261da177e4SLinus Torvalds 21275c04a7b8SAlexey Dobriyan if (currTar_Info->TarEEValue & EE_WIDE_SCSI) { 21281da177e4SLinus Torvalds currTar_Info->TarStatus &= ~TAR_WIDE_MASK; 21291da177e4SLinus Torvalds } 21301da177e4SLinus Torvalds 21315c04a7b8SAlexey Dobriyan FPT_sssyncv(p_port, pCurrCard->currentSCCB->TargID, NARROW_SCSI, 21325c04a7b8SAlexey Dobriyan currTar_Info); 21331da177e4SLinus Torvalds 213447b5d69cSJames Bottomley FPT_queueCmdComplete(pCurrCard, pCurrCard->currentSCCB, p_card); 21351da177e4SLinus Torvalds 21361da177e4SLinus Torvalds } 21371da177e4SLinus Torvalds 21385c04a7b8SAlexey Dobriyan else if (p_int & SCAM_SEL) { 21391da177e4SLinus Torvalds 214047b5d69cSJames Bottomley FPT_scarb(p_port, LEVEL2_TAR); 214147b5d69cSJames Bottomley FPT_scsel(p_port); 214247b5d69cSJames Bottomley FPT_scasid(p_card, p_port); 21431da177e4SLinus Torvalds 214447b5d69cSJames Bottomley FPT_scbusf(p_port); 21451da177e4SLinus Torvalds 21461da177e4SLinus Torvalds WRW_HARPOON((p_port + hp_intstat), SCAM_SEL); 21471da177e4SLinus Torvalds } 21481da177e4SLinus Torvalds 21495c1b85e2SAlexey Dobriyan return 0x00; 21501da177e4SLinus Torvalds } 21511da177e4SLinus Torvalds 21521da177e4SLinus Torvalds /*--------------------------------------------------------------------- 21531da177e4SLinus Torvalds * 21541da177e4SLinus Torvalds * Function: SccbMgrTableInit 21551da177e4SLinus Torvalds * 21561da177e4SLinus Torvalds * Description: Initialize all Sccb manager data structures. 21571da177e4SLinus Torvalds * 21581da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 21591da177e4SLinus Torvalds 216047b5d69cSJames Bottomley static void FPT_SccbMgrTableInitAll() 21611da177e4SLinus Torvalds { 2162db038cf8SAlexey Dobriyan unsigned char thisCard; 21631da177e4SLinus Torvalds 21645c04a7b8SAlexey Dobriyan for (thisCard = 0; thisCard < MAX_CARDS; thisCard++) { 216547b5d69cSJames Bottomley FPT_SccbMgrTableInitCard(&FPT_BL_Card[thisCard], thisCard); 21661da177e4SLinus Torvalds 216747b5d69cSJames Bottomley FPT_BL_Card[thisCard].ioPort = 0x00; 216847b5d69cSJames Bottomley FPT_BL_Card[thisCard].cardInfo = NULL; 216947b5d69cSJames Bottomley FPT_BL_Card[thisCard].cardIndex = 0xFF; 217047b5d69cSJames Bottomley FPT_BL_Card[thisCard].ourId = 0x00; 217147b5d69cSJames Bottomley FPT_BL_Card[thisCard].pNvRamInfo = NULL; 21721da177e4SLinus Torvalds } 21731da177e4SLinus Torvalds } 21741da177e4SLinus Torvalds 21751da177e4SLinus Torvalds /*--------------------------------------------------------------------- 21761da177e4SLinus Torvalds * 21771da177e4SLinus Torvalds * Function: SccbMgrTableInit 21781da177e4SLinus Torvalds * 21791da177e4SLinus Torvalds * Description: Initialize all Sccb manager data structures. 21801da177e4SLinus Torvalds * 21811da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 21821da177e4SLinus Torvalds 21835c04a7b8SAlexey Dobriyan static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard, 21845c04a7b8SAlexey Dobriyan unsigned char p_card) 21851da177e4SLinus Torvalds { 2186db038cf8SAlexey Dobriyan unsigned char scsiID, qtag; 21871da177e4SLinus Torvalds 21885c04a7b8SAlexey Dobriyan for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) { 218947b5d69cSJames Bottomley FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL; 21901da177e4SLinus Torvalds } 21911da177e4SLinus Torvalds 21925c04a7b8SAlexey Dobriyan for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) { 219347b5d69cSJames Bottomley FPT_sccbMgrTbl[p_card][scsiID].TarStatus = 0; 219447b5d69cSJames Bottomley FPT_sccbMgrTbl[p_card][scsiID].TarEEValue = 0; 219547b5d69cSJames Bottomley FPT_SccbMgrTableInitTarget(p_card, scsiID); 21961da177e4SLinus Torvalds } 21971da177e4SLinus Torvalds 21981da177e4SLinus Torvalds pCurrCard->scanIndex = 0x00; 21991da177e4SLinus Torvalds pCurrCard->currentSCCB = NULL; 22001da177e4SLinus Torvalds pCurrCard->globalFlags = 0x00; 22011da177e4SLinus Torvalds pCurrCard->cmdCounter = 0x00; 22021da177e4SLinus Torvalds pCurrCard->tagQ_Lst = 0x01; 22031da177e4SLinus Torvalds pCurrCard->discQCount = 0; 22041da177e4SLinus Torvalds 22051da177e4SLinus Torvalds } 22061da177e4SLinus Torvalds 22071da177e4SLinus Torvalds /*--------------------------------------------------------------------- 22081da177e4SLinus Torvalds * 22091da177e4SLinus Torvalds * Function: SccbMgrTableInit 22101da177e4SLinus Torvalds * 22111da177e4SLinus Torvalds * Description: Initialize all Sccb manager data structures. 22121da177e4SLinus Torvalds * 22131da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 22141da177e4SLinus Torvalds 22155c04a7b8SAlexey Dobriyan static void FPT_SccbMgrTableInitTarget(unsigned char p_card, 22165c04a7b8SAlexey Dobriyan unsigned char target) 22171da177e4SLinus Torvalds { 22181da177e4SLinus Torvalds 2219db038cf8SAlexey Dobriyan unsigned char lun, qtag; 2220f31dc0cdSAlexey Dobriyan struct sccb_mgr_tar_info *currTar_Info; 22211da177e4SLinus Torvalds 222247b5d69cSJames Bottomley currTar_Info = &FPT_sccbMgrTbl[p_card][target]; 22231da177e4SLinus Torvalds 22241da177e4SLinus Torvalds currTar_Info->TarSelQ_Cnt = 0; 22251da177e4SLinus Torvalds currTar_Info->TarSyncCtrl = 0; 22261da177e4SLinus Torvalds 22271da177e4SLinus Torvalds currTar_Info->TarSelQ_Head = NULL; 22281da177e4SLinus Torvalds currTar_Info->TarSelQ_Tail = NULL; 22291da177e4SLinus Torvalds currTar_Info->TarTagQ_Cnt = 0; 223047b5d69cSJames Bottomley currTar_Info->TarLUN_CA = 0; 22311da177e4SLinus Torvalds 22325c04a7b8SAlexey Dobriyan for (lun = 0; lun < MAX_LUN; lun++) { 223347b5d69cSJames Bottomley currTar_Info->TarLUNBusy[lun] = 0; 22341da177e4SLinus Torvalds currTar_Info->LunDiscQ_Idx[lun] = 0; 22351da177e4SLinus Torvalds } 22361da177e4SLinus Torvalds 22375c04a7b8SAlexey Dobriyan for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) { 22385c04a7b8SAlexey Dobriyan if (FPT_BL_Card[p_card].discQ_Tbl[qtag] != NULL) { 22395c04a7b8SAlexey Dobriyan if (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == 22405c04a7b8SAlexey Dobriyan target) { 224147b5d69cSJames Bottomley FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL; 224247b5d69cSJames Bottomley FPT_BL_Card[p_card].discQCount--; 22431da177e4SLinus Torvalds } 22441da177e4SLinus Torvalds } 22451da177e4SLinus Torvalds } 22461da177e4SLinus Torvalds } 22471da177e4SLinus Torvalds 22481da177e4SLinus Torvalds /*--------------------------------------------------------------------- 22491da177e4SLinus Torvalds * 22501da177e4SLinus Torvalds * Function: sfetm 22511da177e4SLinus Torvalds * 22521da177e4SLinus Torvalds * Description: Read in a message byte from the SCSI bus, and check 22531da177e4SLinus Torvalds * for a parity error. 22541da177e4SLinus Torvalds * 22551da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 22561da177e4SLinus Torvalds 225769eb2ea4SAlexey Dobriyan static unsigned char FPT_sfm(unsigned long port, struct sccb *pCurrSCCB) 22581da177e4SLinus Torvalds { 2259db038cf8SAlexey Dobriyan unsigned char message; 2260c823feebSAlexey Dobriyan unsigned short TimeOutLoop; 22611da177e4SLinus Torvalds 22621da177e4SLinus Torvalds TimeOutLoop = 0; 22631da177e4SLinus Torvalds while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) && 22645c04a7b8SAlexey Dobriyan (TimeOutLoop++ < 20000)) { 22655c04a7b8SAlexey Dobriyan } 22661da177e4SLinus Torvalds 22671da177e4SLinus Torvalds WR_HARPOON(port + hp_portctrl_0, SCSI_PORT); 22681da177e4SLinus Torvalds 22691da177e4SLinus Torvalds message = RD_HARPOON(port + hp_scsidata_0); 22701da177e4SLinus Torvalds 22711da177e4SLinus Torvalds WR_HARPOON(port + hp_scsisig, SCSI_ACK + S_MSGI_PH); 22721da177e4SLinus Torvalds 22731da177e4SLinus Torvalds if (TimeOutLoop > 20000) 22741da177e4SLinus Torvalds message = 0x00; /* force message byte = 0 if Time Out on Req */ 22751da177e4SLinus Torvalds 22761da177e4SLinus Torvalds if ((RDW_HARPOON((port + hp_intstat)) & PARITY) && 22775c04a7b8SAlexey Dobriyan (RD_HARPOON(port + hp_addstat) & SCSI_PAR_ERR)) { 22781da177e4SLinus Torvalds WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH)); 22791da177e4SLinus Torvalds WR_HARPOON(port + hp_xferstat, 0); 22801da177e4SLinus Torvalds WR_HARPOON(port + hp_fiforead, 0); 22811da177e4SLinus Torvalds WR_HARPOON(port + hp_fifowrite, 0); 22825c04a7b8SAlexey Dobriyan if (pCurrSCCB != NULL) { 22831da177e4SLinus Torvalds pCurrSCCB->Sccb_scsimsg = SMPARITY; 22841da177e4SLinus Torvalds } 22851da177e4SLinus Torvalds message = 0x00; 22865c04a7b8SAlexey Dobriyan do { 22871da177e4SLinus Torvalds ACCEPT_MSG_ATN(port); 22881da177e4SLinus Torvalds TimeOutLoop = 0; 22891da177e4SLinus Torvalds while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) && 22905c04a7b8SAlexey Dobriyan (TimeOutLoop++ < 20000)) { 22915c04a7b8SAlexey Dobriyan } 22925c04a7b8SAlexey Dobriyan if (TimeOutLoop > 20000) { 22931da177e4SLinus Torvalds WRW_HARPOON((port + hp_intstat), PARITY); 22945c1b85e2SAlexey Dobriyan return message; 22951da177e4SLinus Torvalds } 22965c04a7b8SAlexey Dobriyan if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) != 22975c04a7b8SAlexey Dobriyan S_MSGI_PH) { 22981da177e4SLinus Torvalds WRW_HARPOON((port + hp_intstat), PARITY); 22995c1b85e2SAlexey Dobriyan return message; 23001da177e4SLinus Torvalds } 23011da177e4SLinus Torvalds WR_HARPOON(port + hp_portctrl_0, SCSI_PORT); 23021da177e4SLinus Torvalds 23031da177e4SLinus Torvalds RD_HARPOON(port + hp_scsidata_0); 23041da177e4SLinus Torvalds 23051da177e4SLinus Torvalds WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH)); 23061da177e4SLinus Torvalds 23071da177e4SLinus Torvalds } while (1); 23081da177e4SLinus Torvalds 23091da177e4SLinus Torvalds } 23101da177e4SLinus Torvalds WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH)); 23111da177e4SLinus Torvalds WR_HARPOON(port + hp_xferstat, 0); 23121da177e4SLinus Torvalds WR_HARPOON(port + hp_fiforead, 0); 23131da177e4SLinus Torvalds WR_HARPOON(port + hp_fifowrite, 0); 23145c1b85e2SAlexey Dobriyan return message; 23151da177e4SLinus Torvalds } 23161da177e4SLinus Torvalds 23171da177e4SLinus Torvalds /*--------------------------------------------------------------------- 23181da177e4SLinus Torvalds * 231947b5d69cSJames Bottomley * Function: FPT_ssel 23201da177e4SLinus Torvalds * 23211da177e4SLinus Torvalds * Description: Load up automation and select target device. 23221da177e4SLinus Torvalds * 23231da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 23241da177e4SLinus Torvalds 2325d63a4cccSAlexey Dobriyan static void FPT_ssel(unsigned long port, unsigned char p_card) 23261da177e4SLinus Torvalds { 23271da177e4SLinus Torvalds 2328db038cf8SAlexey Dobriyan unsigned char auto_loaded, i, target, *theCCB; 23291da177e4SLinus Torvalds 2330d63a4cccSAlexey Dobriyan unsigned long cdb_reg; 233113e6851aSAlexey Dobriyan struct sccb_card *CurrCard; 233269eb2ea4SAlexey Dobriyan struct sccb *currSCCB; 2333f31dc0cdSAlexey Dobriyan struct sccb_mgr_tar_info *currTar_Info; 2334db038cf8SAlexey Dobriyan unsigned char lastTag, lun; 23351da177e4SLinus Torvalds 233647b5d69cSJames Bottomley CurrCard = &FPT_BL_Card[p_card]; 23371da177e4SLinus Torvalds currSCCB = CurrCard->currentSCCB; 23381da177e4SLinus Torvalds target = currSCCB->TargID; 233947b5d69cSJames Bottomley currTar_Info = &FPT_sccbMgrTbl[p_card][target]; 23401da177e4SLinus Torvalds lastTag = CurrCard->tagQ_Lst; 23411da177e4SLinus Torvalds 23421da177e4SLinus Torvalds ARAM_ACCESS(port); 23431da177e4SLinus Torvalds 23441da177e4SLinus Torvalds if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT) 23451da177e4SLinus Torvalds currSCCB->ControlByte &= ~F_USE_CMD_Q; 23461da177e4SLinus Torvalds 23471da177e4SLinus Torvalds if (((CurrCard->globalFlags & F_CONLUN_IO) && 23481da177e4SLinus Torvalds ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) 23491da177e4SLinus Torvalds 23501da177e4SLinus Torvalds lun = currSCCB->Lun; 23511da177e4SLinus Torvalds else 23521da177e4SLinus Torvalds lun = 0; 23531da177e4SLinus Torvalds 23545c04a7b8SAlexey Dobriyan if (CurrCard->globalFlags & F_TAG_STARTED) { 23555c04a7b8SAlexey Dobriyan if (!(currSCCB->ControlByte & F_USE_CMD_Q)) { 235647b5d69cSJames Bottomley if ((currTar_Info->TarLUN_CA == 0) 23571da177e4SLinus Torvalds && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) 23585c04a7b8SAlexey Dobriyan == TAG_Q_TRYING)) { 23591da177e4SLinus Torvalds 23605c04a7b8SAlexey Dobriyan if (currTar_Info->TarTagQ_Cnt != 0) { 236147b5d69cSJames Bottomley currTar_Info->TarLUNBusy[lun] = 1; 236247b5d69cSJames Bottomley FPT_queueSelectFail(CurrCard, p_card); 23631da177e4SLinus Torvalds SGRAM_ACCESS(port); 23641da177e4SLinus Torvalds return; 23651da177e4SLinus Torvalds } 23661da177e4SLinus Torvalds 23671da177e4SLinus Torvalds else { 236847b5d69cSJames Bottomley currTar_Info->TarLUNBusy[lun] = 1; 23691da177e4SLinus Torvalds } 23701da177e4SLinus Torvalds 23715c04a7b8SAlexey Dobriyan } 23725c04a7b8SAlexey Dobriyan /*End non-tagged */ 23731da177e4SLinus Torvalds else { 237447b5d69cSJames Bottomley currTar_Info->TarLUNBusy[lun] = 1; 23751da177e4SLinus Torvalds } 23761da177e4SLinus Torvalds 23775c04a7b8SAlexey Dobriyan } 23785c04a7b8SAlexey Dobriyan /*!Use cmd Q Tagged */ 23791da177e4SLinus Torvalds else { 23805c04a7b8SAlexey Dobriyan if (currTar_Info->TarLUN_CA == 1) { 238147b5d69cSJames Bottomley FPT_queueSelectFail(CurrCard, p_card); 23821da177e4SLinus Torvalds SGRAM_ACCESS(port); 23831da177e4SLinus Torvalds return; 23841da177e4SLinus Torvalds } 23851da177e4SLinus Torvalds 238647b5d69cSJames Bottomley currTar_Info->TarLUNBusy[lun] = 1; 23871da177e4SLinus Torvalds 23881da177e4SLinus Torvalds } /*else use cmd Q tagged */ 23891da177e4SLinus Torvalds 23905c04a7b8SAlexey Dobriyan } 23915c04a7b8SAlexey Dobriyan /*if glob tagged started */ 23921da177e4SLinus Torvalds else { 239347b5d69cSJames Bottomley currTar_Info->TarLUNBusy[lun] = 1; 23941da177e4SLinus Torvalds } 23951da177e4SLinus Torvalds 23961da177e4SLinus Torvalds if ((((CurrCard->globalFlags & F_CONLUN_IO) && 23971da177e4SLinus Torvalds ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) 23985c04a7b8SAlexey Dobriyan || (!(currSCCB->ControlByte & F_USE_CMD_Q)))) { 23995c04a7b8SAlexey Dobriyan if (CurrCard->discQCount >= QUEUE_DEPTH) { 240047b5d69cSJames Bottomley currTar_Info->TarLUNBusy[lun] = 1; 240147b5d69cSJames Bottomley FPT_queueSelectFail(CurrCard, p_card); 24021da177e4SLinus Torvalds SGRAM_ACCESS(port); 24031da177e4SLinus Torvalds return; 24041da177e4SLinus Torvalds } 24055c04a7b8SAlexey Dobriyan for (i = 1; i < QUEUE_DEPTH; i++) { 24065c04a7b8SAlexey Dobriyan if (++lastTag >= QUEUE_DEPTH) 24075c04a7b8SAlexey Dobriyan lastTag = 1; 24085c04a7b8SAlexey Dobriyan if (CurrCard->discQ_Tbl[lastTag] == NULL) { 24091da177e4SLinus Torvalds CurrCard->tagQ_Lst = lastTag; 24101da177e4SLinus Torvalds currTar_Info->LunDiscQ_Idx[lun] = lastTag; 24111da177e4SLinus Torvalds CurrCard->discQ_Tbl[lastTag] = currSCCB; 24121da177e4SLinus Torvalds CurrCard->discQCount++; 24131da177e4SLinus Torvalds break; 24141da177e4SLinus Torvalds } 24151da177e4SLinus Torvalds } 24165c04a7b8SAlexey Dobriyan if (i == QUEUE_DEPTH) { 241747b5d69cSJames Bottomley currTar_Info->TarLUNBusy[lun] = 1; 241847b5d69cSJames Bottomley FPT_queueSelectFail(CurrCard, p_card); 24191da177e4SLinus Torvalds SGRAM_ACCESS(port); 24201da177e4SLinus Torvalds return; 24211da177e4SLinus Torvalds } 24221da177e4SLinus Torvalds } 24231da177e4SLinus Torvalds 242447b5d69cSJames Bottomley auto_loaded = 0; 24251da177e4SLinus Torvalds 24261da177e4SLinus Torvalds WR_HARPOON(port + hp_select_id, target); 24271da177e4SLinus Torvalds WR_HARPOON(port + hp_gp_reg_3, target); /* Use by new automation logic */ 24281da177e4SLinus Torvalds 24291da177e4SLinus Torvalds if (currSCCB->OperationCode == RESET_COMMAND) { 24301da177e4SLinus Torvalds WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT + 24315c04a7b8SAlexey Dobriyan (currSCCB-> 24325c04a7b8SAlexey Dobriyan Sccb_idmsg & ~DISC_PRIV))); 24331da177e4SLinus Torvalds 24341da177e4SLinus Torvalds WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + NP); 24351da177e4SLinus Torvalds 24361da177e4SLinus Torvalds currSCCB->Sccb_scsimsg = SMDEV_RESET; 24371da177e4SLinus Torvalds 24381da177e4SLinus Torvalds WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT)); 243947b5d69cSJames Bottomley auto_loaded = 1; 24401da177e4SLinus Torvalds currSCCB->Sccb_scsistat = SELECT_BDR_ST; 24411da177e4SLinus Torvalds 24425c04a7b8SAlexey Dobriyan if (currTar_Info->TarEEValue & EE_SYNC_MASK) { 24431da177e4SLinus Torvalds currTar_Info->TarSyncCtrl = 0; 24441da177e4SLinus Torvalds currTar_Info->TarStatus &= ~TAR_SYNC_MASK; 24451da177e4SLinus Torvalds } 24461da177e4SLinus Torvalds 24475c04a7b8SAlexey Dobriyan if (currTar_Info->TarEEValue & EE_WIDE_SCSI) { 24481da177e4SLinus Torvalds currTar_Info->TarStatus &= ~TAR_WIDE_MASK; 24491da177e4SLinus Torvalds } 24501da177e4SLinus Torvalds 245147b5d69cSJames Bottomley FPT_sssyncv(port, target, NARROW_SCSI, currTar_Info); 245247b5d69cSJames Bottomley FPT_SccbMgrTableInitTarget(p_card, target); 24531da177e4SLinus Torvalds 24541da177e4SLinus Torvalds } 24551da177e4SLinus Torvalds 24565c04a7b8SAlexey Dobriyan else if (currSCCB->Sccb_scsistat == ABORT_ST) { 24571da177e4SLinus Torvalds WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT + 24585c04a7b8SAlexey Dobriyan (currSCCB-> 24595c04a7b8SAlexey Dobriyan Sccb_idmsg & ~DISC_PRIV))); 24601da177e4SLinus Torvalds 24611da177e4SLinus Torvalds WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ); 24621da177e4SLinus Torvalds 24631da177e4SLinus Torvalds WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + 24645c04a7b8SAlexey Dobriyan (((unsigned 24655c04a7b8SAlexey Dobriyan char)(currSCCB-> 24665c04a7b8SAlexey Dobriyan ControlByte & 24675c04a7b8SAlexey Dobriyan TAG_TYPE_MASK) 24685c04a7b8SAlexey Dobriyan >> 6) | (unsigned char) 24695c04a7b8SAlexey Dobriyan 0x20))); 24701da177e4SLinus Torvalds WRW_HARPOON((port + SYNC_MSGS + 2), 24711da177e4SLinus Torvalds (MPM_OP + AMSG_OUT + currSCCB->Sccb_tag)); 24721da177e4SLinus Torvalds WRW_HARPOON((port + SYNC_MSGS + 4), (BRH_OP + ALWAYS + NP)); 24731da177e4SLinus Torvalds 24741da177e4SLinus Torvalds WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT)); 247547b5d69cSJames Bottomley auto_loaded = 1; 24761da177e4SLinus Torvalds 24771da177e4SLinus Torvalds } 24781da177e4SLinus Torvalds 24791da177e4SLinus Torvalds else if (!(currTar_Info->TarStatus & WIDE_NEGOCIATED)) { 248047b5d69cSJames Bottomley auto_loaded = FPT_siwidn(port, p_card); 24811da177e4SLinus Torvalds currSCCB->Sccb_scsistat = SELECT_WN_ST; 24821da177e4SLinus Torvalds } 24831da177e4SLinus Torvalds 24841da177e4SLinus Torvalds else if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) 24851da177e4SLinus Torvalds == SYNC_SUPPORTED)) { 248647b5d69cSJames Bottomley auto_loaded = FPT_sisyncn(port, p_card, 0); 24871da177e4SLinus Torvalds currSCCB->Sccb_scsistat = SELECT_SN_ST; 24881da177e4SLinus Torvalds } 24891da177e4SLinus Torvalds 24905c04a7b8SAlexey Dobriyan if (!auto_loaded) { 24911da177e4SLinus Torvalds 24925c04a7b8SAlexey Dobriyan if (currSCCB->ControlByte & F_USE_CMD_Q) { 24931da177e4SLinus Torvalds 24941da177e4SLinus Torvalds CurrCard->globalFlags |= F_TAG_STARTED; 24951da177e4SLinus Torvalds 24961da177e4SLinus Torvalds if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) 24975c04a7b8SAlexey Dobriyan == TAG_Q_REJECT) { 24981da177e4SLinus Torvalds currSCCB->ControlByte &= ~F_USE_CMD_Q; 24991da177e4SLinus Torvalds 25001da177e4SLinus Torvalds /* Fix up the start instruction with a jump to 25011da177e4SLinus Torvalds Non-Tag-CMD handling */ 25025c04a7b8SAlexey Dobriyan WRW_HARPOON((port + ID_MSG_STRT), 25035c04a7b8SAlexey Dobriyan BRH_OP + ALWAYS + NTCMD); 25041da177e4SLinus Torvalds 25051da177e4SLinus Torvalds WRW_HARPOON((port + NON_TAG_ID_MSG), 25065c04a7b8SAlexey Dobriyan (MPM_OP + AMSG_OUT + 25075c04a7b8SAlexey Dobriyan currSCCB->Sccb_idmsg)); 25081da177e4SLinus Torvalds 25095c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_autostart_3, 25105c04a7b8SAlexey Dobriyan (SELECT + SELCHK_STRT)); 25111da177e4SLinus Torvalds 2512*25985edcSLucas De Marchi /* Setup our STATE so we know what happened when 25131da177e4SLinus Torvalds the wheels fall off. */ 25141da177e4SLinus Torvalds currSCCB->Sccb_scsistat = SELECT_ST; 25151da177e4SLinus Torvalds 251647b5d69cSJames Bottomley currTar_Info->TarLUNBusy[lun] = 1; 25171da177e4SLinus Torvalds } 25181da177e4SLinus Torvalds 25195c04a7b8SAlexey Dobriyan else { 25205c04a7b8SAlexey Dobriyan WRW_HARPOON((port + ID_MSG_STRT), 25215c04a7b8SAlexey Dobriyan (MPM_OP + AMSG_OUT + 25225c04a7b8SAlexey Dobriyan currSCCB->Sccb_idmsg)); 25231da177e4SLinus Torvalds 25245c04a7b8SAlexey Dobriyan WRW_HARPOON((port + ID_MSG_STRT + 2), 25255c04a7b8SAlexey Dobriyan (MPM_OP + AMSG_OUT + 25265c04a7b8SAlexey Dobriyan (((unsigned char)(currSCCB-> 25275c04a7b8SAlexey Dobriyan ControlByte & 25285c04a7b8SAlexey Dobriyan TAG_TYPE_MASK) 2529db038cf8SAlexey Dobriyan >> 6) | (unsigned char)0x20))); 25301da177e4SLinus Torvalds 25315c04a7b8SAlexey Dobriyan for (i = 1; i < QUEUE_DEPTH; i++) { 25325c04a7b8SAlexey Dobriyan if (++lastTag >= QUEUE_DEPTH) 25335c04a7b8SAlexey Dobriyan lastTag = 1; 25345c04a7b8SAlexey Dobriyan if (CurrCard->discQ_Tbl[lastTag] == 25355c04a7b8SAlexey Dobriyan NULL) { 25365c04a7b8SAlexey Dobriyan WRW_HARPOON((port + 25375c04a7b8SAlexey Dobriyan ID_MSG_STRT + 6), 25385c04a7b8SAlexey Dobriyan (MPM_OP + AMSG_OUT + 25395c04a7b8SAlexey Dobriyan lastTag)); 25401da177e4SLinus Torvalds CurrCard->tagQ_Lst = lastTag; 25411da177e4SLinus Torvalds currSCCB->Sccb_tag = lastTag; 25425c04a7b8SAlexey Dobriyan CurrCard->discQ_Tbl[lastTag] = 25435c04a7b8SAlexey Dobriyan currSCCB; 25441da177e4SLinus Torvalds CurrCard->discQCount++; 25451da177e4SLinus Torvalds break; 25461da177e4SLinus Torvalds } 25471da177e4SLinus Torvalds } 25481da177e4SLinus Torvalds 25495c04a7b8SAlexey Dobriyan if (i == QUEUE_DEPTH) { 255047b5d69cSJames Bottomley currTar_Info->TarLUNBusy[lun] = 1; 255147b5d69cSJames Bottomley FPT_queueSelectFail(CurrCard, p_card); 25521da177e4SLinus Torvalds SGRAM_ACCESS(port); 25531da177e4SLinus Torvalds return; 25541da177e4SLinus Torvalds } 25551da177e4SLinus Torvalds 25561da177e4SLinus Torvalds currSCCB->Sccb_scsistat = SELECT_Q_ST; 25571da177e4SLinus Torvalds 25585c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_autostart_3, 25595c04a7b8SAlexey Dobriyan (SELECT + SELCHK_STRT)); 25601da177e4SLinus Torvalds } 25611da177e4SLinus Torvalds } 25621da177e4SLinus Torvalds 25635c04a7b8SAlexey Dobriyan else { 25641da177e4SLinus Torvalds 25655c04a7b8SAlexey Dobriyan WRW_HARPOON((port + ID_MSG_STRT), 25665c04a7b8SAlexey Dobriyan BRH_OP + ALWAYS + NTCMD); 25671da177e4SLinus Torvalds 25681da177e4SLinus Torvalds WRW_HARPOON((port + NON_TAG_ID_MSG), 25691da177e4SLinus Torvalds (MPM_OP + AMSG_OUT + currSCCB->Sccb_idmsg)); 25701da177e4SLinus Torvalds 25711da177e4SLinus Torvalds currSCCB->Sccb_scsistat = SELECT_ST; 25721da177e4SLinus Torvalds 25735c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_autostart_3, 25745c04a7b8SAlexey Dobriyan (SELECT + SELCHK_STRT)); 25751da177e4SLinus Torvalds } 25761da177e4SLinus Torvalds 2577db038cf8SAlexey Dobriyan theCCB = (unsigned char *)&currSCCB->Cdb[0]; 25781da177e4SLinus Torvalds 25791da177e4SLinus Torvalds cdb_reg = port + CMD_STRT; 25801da177e4SLinus Torvalds 25815c04a7b8SAlexey Dobriyan for (i = 0; i < currSCCB->CdbLength; i++) { 25821da177e4SLinus Torvalds WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + *theCCB)); 25831da177e4SLinus Torvalds cdb_reg += 2; 25841da177e4SLinus Torvalds theCCB++; 25851da177e4SLinus Torvalds } 25861da177e4SLinus Torvalds 25871da177e4SLinus Torvalds if (currSCCB->CdbLength != TWELVE_BYTE_CMD) 25881da177e4SLinus Torvalds WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP)); 25891da177e4SLinus Torvalds 25905c04a7b8SAlexey Dobriyan } 25915c04a7b8SAlexey Dobriyan /* auto_loaded */ 2592c823feebSAlexey Dobriyan WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00); 25931da177e4SLinus Torvalds WR_HARPOON(port + hp_xferstat, 0x00); 25941da177e4SLinus Torvalds 25951da177e4SLinus Torvalds WRW_HARPOON((port + hp_intstat), (PROG_HLT | TIMEOUT | SEL | BUS_FREE)); 25961da177e4SLinus Torvalds 25971da177e4SLinus Torvalds WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT)); 25981da177e4SLinus Torvalds 25995c04a7b8SAlexey Dobriyan if (!(currSCCB->Sccb_MGRFlags & F_DEV_SELECTED)) { 26005c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_scsictrl_0, 26015c04a7b8SAlexey Dobriyan (SEL_TAR | ENA_ATN | ENA_RESEL | ENA_SCAM_SEL)); 26025c04a7b8SAlexey Dobriyan } else { 26031da177e4SLinus Torvalds 2604db038cf8SAlexey Dobriyan /* auto_loaded = (RD_HARPOON(port+hp_autostart_3) & (unsigned char)0x1F); 26051da177e4SLinus Torvalds auto_loaded |= AUTO_IMMED; */ 26061da177e4SLinus Torvalds auto_loaded = AUTO_IMMED; 26071da177e4SLinus Torvalds 26081da177e4SLinus Torvalds DISABLE_AUTO(port); 26091da177e4SLinus Torvalds 26101da177e4SLinus Torvalds WR_HARPOON(port + hp_autostart_3, auto_loaded); 26111da177e4SLinus Torvalds } 26121da177e4SLinus Torvalds 26131da177e4SLinus Torvalds SGRAM_ACCESS(port); 26141da177e4SLinus Torvalds } 26151da177e4SLinus Torvalds 26161da177e4SLinus Torvalds /*--------------------------------------------------------------------- 26171da177e4SLinus Torvalds * 261847b5d69cSJames Bottomley * Function: FPT_sres 26191da177e4SLinus Torvalds * 26201da177e4SLinus Torvalds * Description: Hookup the correct CCB and handle the incoming messages. 26211da177e4SLinus Torvalds * 26221da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 26231da177e4SLinus Torvalds 26245c04a7b8SAlexey Dobriyan static void FPT_sres(unsigned long port, unsigned char p_card, 26255c04a7b8SAlexey Dobriyan struct sccb_card *pCurrCard) 26261da177e4SLinus Torvalds { 26271da177e4SLinus Torvalds 2628db038cf8SAlexey Dobriyan unsigned char our_target, message, lun = 0, tag, msgRetryCount; 26291da177e4SLinus Torvalds 2630f31dc0cdSAlexey Dobriyan struct sccb_mgr_tar_info *currTar_Info; 263169eb2ea4SAlexey Dobriyan struct sccb *currSCCB; 26321da177e4SLinus Torvalds 26335c04a7b8SAlexey Dobriyan if (pCurrCard->currentSCCB != NULL) { 26345c04a7b8SAlexey Dobriyan currTar_Info = 26355c04a7b8SAlexey Dobriyan &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID]; 26361da177e4SLinus Torvalds DISABLE_AUTO(port); 26371da177e4SLinus Torvalds 26381da177e4SLinus Torvalds WR_HARPOON((port + hp_scsictrl_0), (ENA_RESEL | ENA_SCAM_SEL)); 26391da177e4SLinus Torvalds 26401da177e4SLinus Torvalds currSCCB = pCurrCard->currentSCCB; 26415c04a7b8SAlexey Dobriyan if (currSCCB->Sccb_scsistat == SELECT_WN_ST) { 26421da177e4SLinus Torvalds currTar_Info->TarStatus &= ~TAR_WIDE_MASK; 26431da177e4SLinus Torvalds currSCCB->Sccb_scsistat = BUS_FREE_ST; 26441da177e4SLinus Torvalds } 26455c04a7b8SAlexey Dobriyan if (currSCCB->Sccb_scsistat == SELECT_SN_ST) { 26461da177e4SLinus Torvalds currTar_Info->TarStatus &= ~TAR_SYNC_MASK; 26471da177e4SLinus Torvalds currSCCB->Sccb_scsistat = BUS_FREE_ST; 26481da177e4SLinus Torvalds } 26491da177e4SLinus Torvalds if (((pCurrCard->globalFlags & F_CONLUN_IO) && 26505c04a7b8SAlexey Dobriyan ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != 26515c04a7b8SAlexey Dobriyan TAG_Q_TRYING))) { 265247b5d69cSJames Bottomley currTar_Info->TarLUNBusy[currSCCB->Lun] = 0; 26535c04a7b8SAlexey Dobriyan if (currSCCB->Sccb_scsistat != ABORT_ST) { 26541da177e4SLinus Torvalds pCurrCard->discQCount--; 26555c04a7b8SAlexey Dobriyan pCurrCard->discQ_Tbl[currTar_Info-> 26565c04a7b8SAlexey Dobriyan LunDiscQ_Idx[currSCCB-> 26575c04a7b8SAlexey Dobriyan Lun]] 26581da177e4SLinus Torvalds = NULL; 26591da177e4SLinus Torvalds } 26605c04a7b8SAlexey Dobriyan } else { 266147b5d69cSJames Bottomley currTar_Info->TarLUNBusy[0] = 0; 26625c04a7b8SAlexey Dobriyan if (currSCCB->Sccb_tag) { 26635c04a7b8SAlexey Dobriyan if (currSCCB->Sccb_scsistat != ABORT_ST) { 26641da177e4SLinus Torvalds pCurrCard->discQCount--; 26655c04a7b8SAlexey Dobriyan pCurrCard->discQ_Tbl[currSCCB-> 26665c04a7b8SAlexey Dobriyan Sccb_tag] = NULL; 26671da177e4SLinus Torvalds } 26685c04a7b8SAlexey Dobriyan } else { 26695c04a7b8SAlexey Dobriyan if (currSCCB->Sccb_scsistat != ABORT_ST) { 26701da177e4SLinus Torvalds pCurrCard->discQCount--; 26715c04a7b8SAlexey Dobriyan pCurrCard->discQ_Tbl[currTar_Info-> 26725c04a7b8SAlexey Dobriyan LunDiscQ_Idx[0]] = 26735c04a7b8SAlexey Dobriyan NULL; 26741da177e4SLinus Torvalds } 26751da177e4SLinus Torvalds } 26761da177e4SLinus Torvalds } 26771da177e4SLinus Torvalds 267847b5d69cSJames Bottomley FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card); 26791da177e4SLinus Torvalds } 26801da177e4SLinus Torvalds 2681c823feebSAlexey Dobriyan WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00); 26821da177e4SLinus Torvalds 2683db038cf8SAlexey Dobriyan our_target = (unsigned char)(RD_HARPOON(port + hp_select_id) >> 4); 268447b5d69cSJames Bottomley currTar_Info = &FPT_sccbMgrTbl[p_card][our_target]; 26851da177e4SLinus Torvalds 26861da177e4SLinus Torvalds msgRetryCount = 0; 26875c04a7b8SAlexey Dobriyan do { 26881da177e4SLinus Torvalds 268947b5d69cSJames Bottomley currTar_Info = &FPT_sccbMgrTbl[p_card][our_target]; 26901da177e4SLinus Torvalds tag = 0; 26911da177e4SLinus Torvalds 26925c04a7b8SAlexey Dobriyan while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) { 26935c04a7b8SAlexey Dobriyan if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) { 26941da177e4SLinus Torvalds 26951da177e4SLinus Torvalds WRW_HARPOON((port + hp_intstat), PHASE); 26961da177e4SLinus Torvalds return; 26971da177e4SLinus Torvalds } 26981da177e4SLinus Torvalds } 26991da177e4SLinus Torvalds 27001da177e4SLinus Torvalds WRW_HARPOON((port + hp_intstat), PHASE); 27015c04a7b8SAlexey Dobriyan if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH) { 27021da177e4SLinus Torvalds 270347b5d69cSJames Bottomley message = FPT_sfm(port, pCurrCard->currentSCCB); 27045c04a7b8SAlexey Dobriyan if (message) { 27051da177e4SLinus Torvalds 27065c04a7b8SAlexey Dobriyan if (message <= (0x80 | LUN_MASK)) { 2707db038cf8SAlexey Dobriyan lun = message & (unsigned char)LUN_MASK; 27081da177e4SLinus Torvalds 27095c04a7b8SAlexey Dobriyan if ((currTar_Info-> 27105c04a7b8SAlexey Dobriyan TarStatus & TAR_TAG_Q_MASK) == 27115c04a7b8SAlexey Dobriyan TAG_Q_TRYING) { 27125c04a7b8SAlexey Dobriyan if (currTar_Info->TarTagQ_Cnt != 27135c04a7b8SAlexey Dobriyan 0) { 27141da177e4SLinus Torvalds 27155c04a7b8SAlexey Dobriyan if (! 27165c04a7b8SAlexey Dobriyan (currTar_Info-> 27175c04a7b8SAlexey Dobriyan TarLUN_CA)) { 27181da177e4SLinus Torvalds ACCEPT_MSG(port); /*Release the ACK for ID msg. */ 27191da177e4SLinus Torvalds 27205c04a7b8SAlexey Dobriyan message = 27215c04a7b8SAlexey Dobriyan FPT_sfm 27225c04a7b8SAlexey Dobriyan (port, 27235c04a7b8SAlexey Dobriyan pCurrCard-> 27245c04a7b8SAlexey Dobriyan currentSCCB); 27255c04a7b8SAlexey Dobriyan if (message) { 27265c04a7b8SAlexey Dobriyan ACCEPT_MSG 27275c04a7b8SAlexey Dobriyan (port); 27281da177e4SLinus Torvalds } 27291da177e4SLinus Torvalds 27301da177e4SLinus Torvalds else 27315c04a7b8SAlexey Dobriyan message 27325c04a7b8SAlexey Dobriyan = 0; 27331da177e4SLinus Torvalds 27345c04a7b8SAlexey Dobriyan if (message != 27355c04a7b8SAlexey Dobriyan 0) { 27365c04a7b8SAlexey Dobriyan tag = 27375c04a7b8SAlexey Dobriyan FPT_sfm 27385c04a7b8SAlexey Dobriyan (port, 27395c04a7b8SAlexey Dobriyan pCurrCard-> 27405c04a7b8SAlexey Dobriyan currentSCCB); 27411da177e4SLinus Torvalds 27425c04a7b8SAlexey Dobriyan if (! 27435c04a7b8SAlexey Dobriyan (tag)) 27445c04a7b8SAlexey Dobriyan message 27455c04a7b8SAlexey Dobriyan = 27465c04a7b8SAlexey Dobriyan 0; 27471da177e4SLinus Torvalds } 27481da177e4SLinus Torvalds 27495c04a7b8SAlexey Dobriyan } 27505c04a7b8SAlexey Dobriyan /*C.A. exists! */ 27515c04a7b8SAlexey Dobriyan } 27525c04a7b8SAlexey Dobriyan /*End Q cnt != 0 */ 27535c04a7b8SAlexey Dobriyan } 27545c04a7b8SAlexey Dobriyan /*End Tag cmds supported! */ 27555c04a7b8SAlexey Dobriyan } 27565c04a7b8SAlexey Dobriyan /*End valid ID message. */ 27575c04a7b8SAlexey Dobriyan else { 27581da177e4SLinus Torvalds 27591da177e4SLinus Torvalds ACCEPT_MSG_ATN(port); 27601da177e4SLinus Torvalds } 27611da177e4SLinus Torvalds 27625c04a7b8SAlexey Dobriyan } 27635c04a7b8SAlexey Dobriyan /* End good id message. */ 27645c04a7b8SAlexey Dobriyan else { 27651da177e4SLinus Torvalds 276647b5d69cSJames Bottomley message = 0; 27671da177e4SLinus Torvalds } 27685c04a7b8SAlexey Dobriyan } else { 27691da177e4SLinus Torvalds ACCEPT_MSG_ATN(port); 27701da177e4SLinus Torvalds 27715c04a7b8SAlexey Dobriyan while (! 27725c04a7b8SAlexey Dobriyan (RDW_HARPOON((port + hp_intstat)) & 27735c04a7b8SAlexey Dobriyan (PHASE | RESET)) 27745c04a7b8SAlexey Dobriyan && !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ) 27755c04a7b8SAlexey Dobriyan && (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ; 27761da177e4SLinus Torvalds 27771da177e4SLinus Torvalds return; 27781da177e4SLinus Torvalds } 27791da177e4SLinus Torvalds 27805c04a7b8SAlexey Dobriyan if (message == 0) { 27811da177e4SLinus Torvalds msgRetryCount++; 27825c04a7b8SAlexey Dobriyan if (msgRetryCount == 1) { 278347b5d69cSJames Bottomley FPT_SendMsg(port, SMPARITY); 27845c04a7b8SAlexey Dobriyan } else { 278547b5d69cSJames Bottomley FPT_SendMsg(port, SMDEV_RESET); 27861da177e4SLinus Torvalds 27875c04a7b8SAlexey Dobriyan FPT_sssyncv(port, our_target, NARROW_SCSI, 27885c04a7b8SAlexey Dobriyan currTar_Info); 27891da177e4SLinus Torvalds 27905c04a7b8SAlexey Dobriyan if (FPT_sccbMgrTbl[p_card][our_target]. 27915c04a7b8SAlexey Dobriyan TarEEValue & EE_SYNC_MASK) { 27921da177e4SLinus Torvalds 27935c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][our_target]. 27945c04a7b8SAlexey Dobriyan TarStatus &= ~TAR_SYNC_MASK; 27951da177e4SLinus Torvalds 27961da177e4SLinus Torvalds } 27971da177e4SLinus Torvalds 27985c04a7b8SAlexey Dobriyan if (FPT_sccbMgrTbl[p_card][our_target]. 27995c04a7b8SAlexey Dobriyan TarEEValue & EE_WIDE_SCSI) { 28001da177e4SLinus Torvalds 28015c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][our_target]. 28025c04a7b8SAlexey Dobriyan TarStatus &= ~TAR_WIDE_MASK; 28031da177e4SLinus Torvalds } 28041da177e4SLinus Torvalds 28055c04a7b8SAlexey Dobriyan FPT_queueFlushTargSccb(p_card, our_target, 28065c04a7b8SAlexey Dobriyan SCCB_COMPLETE); 280747b5d69cSJames Bottomley FPT_SccbMgrTableInitTarget(p_card, our_target); 28081da177e4SLinus Torvalds return; 28091da177e4SLinus Torvalds } 28101da177e4SLinus Torvalds } 281147b5d69cSJames Bottomley } while (message == 0); 28121da177e4SLinus Torvalds 28131da177e4SLinus Torvalds if (((pCurrCard->globalFlags & F_CONLUN_IO) && 28145c04a7b8SAlexey Dobriyan ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) { 281547b5d69cSJames Bottomley currTar_Info->TarLUNBusy[lun] = 1; 28165c04a7b8SAlexey Dobriyan pCurrCard->currentSCCB = 28175c04a7b8SAlexey Dobriyan pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[lun]]; 28185c04a7b8SAlexey Dobriyan if (pCurrCard->currentSCCB != NULL) { 28191da177e4SLinus Torvalds ACCEPT_MSG(port); 28205c04a7b8SAlexey Dobriyan } else { 28211da177e4SLinus Torvalds ACCEPT_MSG_ATN(port); 28221da177e4SLinus Torvalds } 28235c04a7b8SAlexey Dobriyan } else { 282447b5d69cSJames Bottomley currTar_Info->TarLUNBusy[0] = 1; 28251da177e4SLinus Torvalds 28265c04a7b8SAlexey Dobriyan if (tag) { 28275c04a7b8SAlexey Dobriyan if (pCurrCard->discQ_Tbl[tag] != NULL) { 28285c04a7b8SAlexey Dobriyan pCurrCard->currentSCCB = 28295c04a7b8SAlexey Dobriyan pCurrCard->discQ_Tbl[tag]; 28301da177e4SLinus Torvalds currTar_Info->TarTagQ_Cnt--; 28311da177e4SLinus Torvalds ACCEPT_MSG(port); 28325c04a7b8SAlexey Dobriyan } else { 28331da177e4SLinus Torvalds ACCEPT_MSG_ATN(port); 28341da177e4SLinus Torvalds } 28355c04a7b8SAlexey Dobriyan } else { 28365c04a7b8SAlexey Dobriyan pCurrCard->currentSCCB = 28375c04a7b8SAlexey Dobriyan pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]]; 28385c04a7b8SAlexey Dobriyan if (pCurrCard->currentSCCB != NULL) { 28391da177e4SLinus Torvalds ACCEPT_MSG(port); 28405c04a7b8SAlexey Dobriyan } else { 28411da177e4SLinus Torvalds ACCEPT_MSG_ATN(port); 28421da177e4SLinus Torvalds } 28431da177e4SLinus Torvalds } 28441da177e4SLinus Torvalds } 28451da177e4SLinus Torvalds 28465c04a7b8SAlexey Dobriyan if (pCurrCard->currentSCCB != NULL) { 28475c04a7b8SAlexey Dobriyan if (pCurrCard->currentSCCB->Sccb_scsistat == ABORT_ST) { 28481da177e4SLinus Torvalds /* During Abort Tag command, the target could have got re-selected 28491da177e4SLinus Torvalds and completed the command. Check the select Q and remove the CCB 28501da177e4SLinus Torvalds if it is in the Select Q */ 285147b5d69cSJames Bottomley FPT_queueFindSccb(pCurrCard->currentSCCB, p_card); 28521da177e4SLinus Torvalds } 28531da177e4SLinus Torvalds } 28541da177e4SLinus Torvalds 28551da177e4SLinus Torvalds while (!(RDW_HARPOON((port + hp_intstat)) & (PHASE | RESET)) && 28561da177e4SLinus Torvalds !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ) && 28571da177e4SLinus Torvalds (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ; 28581da177e4SLinus Torvalds } 28591da177e4SLinus Torvalds 2860d63a4cccSAlexey Dobriyan static void FPT_SendMsg(unsigned long port, unsigned char message) 28611da177e4SLinus Torvalds { 28625c04a7b8SAlexey Dobriyan while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) { 28635c04a7b8SAlexey Dobriyan if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) { 28641da177e4SLinus Torvalds 28651da177e4SLinus Torvalds WRW_HARPOON((port + hp_intstat), PHASE); 28661da177e4SLinus Torvalds return; 28671da177e4SLinus Torvalds } 28681da177e4SLinus Torvalds } 28691da177e4SLinus Torvalds 28701da177e4SLinus Torvalds WRW_HARPOON((port + hp_intstat), PHASE); 28715c04a7b8SAlexey Dobriyan if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGO_PH) { 28725c04a7b8SAlexey Dobriyan WRW_HARPOON((port + hp_intstat), 28735c04a7b8SAlexey Dobriyan (BUS_FREE | PHASE | XFER_CNT_0)); 28741da177e4SLinus Torvalds 28751da177e4SLinus Torvalds WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN); 28761da177e4SLinus Torvalds 28771da177e4SLinus Torvalds WR_HARPOON(port + hp_scsidata_0, message); 28781da177e4SLinus Torvalds 28791da177e4SLinus Torvalds WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH)); 28801da177e4SLinus Torvalds 28811da177e4SLinus Torvalds ACCEPT_MSG(port); 28821da177e4SLinus Torvalds 28831da177e4SLinus Torvalds WR_HARPOON(port + hp_portctrl_0, 0x00); 28841da177e4SLinus Torvalds 28851da177e4SLinus Torvalds if ((message == SMABORT) || (message == SMDEV_RESET) || 28865c04a7b8SAlexey Dobriyan (message == SMABORT_TAG)) { 28875c04a7b8SAlexey Dobriyan while (! 28885c04a7b8SAlexey Dobriyan (RDW_HARPOON((port + hp_intstat)) & 28895c04a7b8SAlexey Dobriyan (BUS_FREE | PHASE))) { 28905c04a7b8SAlexey Dobriyan } 28911da177e4SLinus Torvalds 28925c04a7b8SAlexey Dobriyan if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) { 28931da177e4SLinus Torvalds WRW_HARPOON((port + hp_intstat), BUS_FREE); 28941da177e4SLinus Torvalds } 28951da177e4SLinus Torvalds } 28961da177e4SLinus Torvalds } 28971da177e4SLinus Torvalds } 28981da177e4SLinus Torvalds 28991da177e4SLinus Torvalds /*--------------------------------------------------------------------- 29001da177e4SLinus Torvalds * 290147b5d69cSJames Bottomley * Function: FPT_sdecm 29021da177e4SLinus Torvalds * 2903*25985edcSLucas De Marchi * Description: Determine the proper response to the message from the 29041da177e4SLinus Torvalds * target device. 29051da177e4SLinus Torvalds * 29061da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 29075c04a7b8SAlexey Dobriyan static void FPT_sdecm(unsigned char message, unsigned long port, 29085c04a7b8SAlexey Dobriyan unsigned char p_card) 29091da177e4SLinus Torvalds { 291069eb2ea4SAlexey Dobriyan struct sccb *currSCCB; 291113e6851aSAlexey Dobriyan struct sccb_card *CurrCard; 2912f31dc0cdSAlexey Dobriyan struct sccb_mgr_tar_info *currTar_Info; 29131da177e4SLinus Torvalds 291447b5d69cSJames Bottomley CurrCard = &FPT_BL_Card[p_card]; 29151da177e4SLinus Torvalds currSCCB = CurrCard->currentSCCB; 29161da177e4SLinus Torvalds 291747b5d69cSJames Bottomley currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID]; 29181da177e4SLinus Torvalds 29195c04a7b8SAlexey Dobriyan if (message == SMREST_DATA_PTR) { 29205c04a7b8SAlexey Dobriyan if (!(currSCCB->Sccb_XferState & F_NO_DATA_YET)) { 29211da177e4SLinus Torvalds currSCCB->Sccb_ATC = currSCCB->Sccb_savedATC; 29221da177e4SLinus Torvalds 292347b5d69cSJames Bottomley FPT_hostDataXferRestart(currSCCB); 29241da177e4SLinus Torvalds } 29251da177e4SLinus Torvalds 29261da177e4SLinus Torvalds ACCEPT_MSG(port); 29275c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_autostart_1, 29285c04a7b8SAlexey Dobriyan (AUTO_IMMED + DISCONNECT_START)); 29291da177e4SLinus Torvalds } 29301da177e4SLinus Torvalds 29315c04a7b8SAlexey Dobriyan else if (message == SMCMD_COMP) { 29321da177e4SLinus Torvalds 29335c04a7b8SAlexey Dobriyan if (currSCCB->Sccb_scsistat == SELECT_Q_ST) { 29345c04a7b8SAlexey Dobriyan currTar_Info->TarStatus &= 29355c04a7b8SAlexey Dobriyan ~(unsigned char)TAR_TAG_Q_MASK; 2936db038cf8SAlexey Dobriyan currTar_Info->TarStatus |= (unsigned char)TAG_Q_REJECT; 29371da177e4SLinus Torvalds } 29381da177e4SLinus Torvalds 29391da177e4SLinus Torvalds ACCEPT_MSG(port); 29401da177e4SLinus Torvalds 29411da177e4SLinus Torvalds } 29421da177e4SLinus Torvalds 29431da177e4SLinus Torvalds else if ((message == SMNO_OP) || (message >= SMIDENT) 29445c04a7b8SAlexey Dobriyan || (message == SMINIT_RECOVERY) || (message == SMREL_RECOVERY)) { 29451da177e4SLinus Torvalds 29461da177e4SLinus Torvalds ACCEPT_MSG(port); 29475c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_autostart_1, 29485c04a7b8SAlexey Dobriyan (AUTO_IMMED + DISCONNECT_START)); 29491da177e4SLinus Torvalds } 29501da177e4SLinus Torvalds 29515c04a7b8SAlexey Dobriyan else if (message == SMREJECT) { 29521da177e4SLinus Torvalds 29531da177e4SLinus Torvalds if ((currSCCB->Sccb_scsistat == SELECT_SN_ST) || 29541da177e4SLinus Torvalds (currSCCB->Sccb_scsistat == SELECT_WN_ST) || 29555c04a7b8SAlexey Dobriyan ((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING) 29565c04a7b8SAlexey Dobriyan || ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == 29575c04a7b8SAlexey Dobriyan TAG_Q_TRYING)) 29581da177e4SLinus Torvalds { 29591da177e4SLinus Torvalds WRW_HARPOON((port + hp_intstat), BUS_FREE); 29601da177e4SLinus Torvalds 29611da177e4SLinus Torvalds ACCEPT_MSG(port); 29621da177e4SLinus Torvalds 29631da177e4SLinus Torvalds while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) && 29645c04a7b8SAlexey Dobriyan (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE))) 29651da177e4SLinus Torvalds { 29661da177e4SLinus Torvalds } 29671da177e4SLinus Torvalds 29685c04a7b8SAlexey Dobriyan if (currSCCB->Lun == 0x00) { 29695c04a7b8SAlexey Dobriyan if ((currSCCB->Sccb_scsistat == SELECT_SN_ST)) { 29701da177e4SLinus Torvalds 29715c04a7b8SAlexey Dobriyan currTar_Info->TarStatus |= 29725c04a7b8SAlexey Dobriyan (unsigned char)SYNC_SUPPORTED; 29731da177e4SLinus Torvalds 29745c04a7b8SAlexey Dobriyan currTar_Info->TarEEValue &= 29755c04a7b8SAlexey Dobriyan ~EE_SYNC_MASK; 29765c04a7b8SAlexey Dobriyan } 29771da177e4SLinus Torvalds 29785c04a7b8SAlexey Dobriyan else if ((currSCCB->Sccb_scsistat == 29795c04a7b8SAlexey Dobriyan SELECT_WN_ST)) { 29805c04a7b8SAlexey Dobriyan 29815c04a7b8SAlexey Dobriyan currTar_Info->TarStatus = 29825c04a7b8SAlexey Dobriyan (currTar_Info-> 29835c04a7b8SAlexey Dobriyan TarStatus & ~WIDE_ENABLED) | 29845c04a7b8SAlexey Dobriyan WIDE_NEGOCIATED; 29855c04a7b8SAlexey Dobriyan 29865c04a7b8SAlexey Dobriyan currTar_Info->TarEEValue &= 29875c04a7b8SAlexey Dobriyan ~EE_WIDE_SCSI; 29881da177e4SLinus Torvalds 29891da177e4SLinus Torvalds } 29901da177e4SLinus Torvalds 29915c04a7b8SAlexey Dobriyan else if ((currTar_Info-> 29925c04a7b8SAlexey Dobriyan TarStatus & TAR_TAG_Q_MASK) == 29935c04a7b8SAlexey Dobriyan TAG_Q_TRYING) { 29945c04a7b8SAlexey Dobriyan currTar_Info->TarStatus = 29955c04a7b8SAlexey Dobriyan (currTar_Info-> 29965c04a7b8SAlexey Dobriyan TarStatus & ~(unsigned char) 29975c04a7b8SAlexey Dobriyan TAR_TAG_Q_MASK) | TAG_Q_REJECT; 29981da177e4SLinus Torvalds 29991da177e4SLinus Torvalds currSCCB->ControlByte &= ~F_USE_CMD_Q; 30001da177e4SLinus Torvalds CurrCard->discQCount--; 30015c04a7b8SAlexey Dobriyan CurrCard->discQ_Tbl[currSCCB-> 30025c04a7b8SAlexey Dobriyan Sccb_tag] = NULL; 30031da177e4SLinus Torvalds currSCCB->Sccb_tag = 0x00; 30041da177e4SLinus Torvalds 30051da177e4SLinus Torvalds } 30061da177e4SLinus Torvalds } 30071da177e4SLinus Torvalds 30085c04a7b8SAlexey Dobriyan if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) { 30091da177e4SLinus Torvalds 30105c04a7b8SAlexey Dobriyan if (currSCCB->Lun == 0x00) { 30115c04a7b8SAlexey Dobriyan WRW_HARPOON((port + hp_intstat), 30125c04a7b8SAlexey Dobriyan BUS_FREE); 30131da177e4SLinus Torvalds CurrCard->globalFlags |= F_NEW_SCCB_CMD; 30141da177e4SLinus Torvalds } 30151da177e4SLinus Torvalds } 30161da177e4SLinus Torvalds 30175c04a7b8SAlexey Dobriyan else { 30181da177e4SLinus Torvalds 30191da177e4SLinus Torvalds if ((CurrCard->globalFlags & F_CONLUN_IO) && 30205c04a7b8SAlexey Dobriyan ((currTar_Info-> 30215c04a7b8SAlexey Dobriyan TarStatus & TAR_TAG_Q_MASK) != 30225c04a7b8SAlexey Dobriyan TAG_Q_TRYING)) 30235c04a7b8SAlexey Dobriyan currTar_Info->TarLUNBusy[currSCCB-> 30245c04a7b8SAlexey Dobriyan Lun] = 1; 30251da177e4SLinus Torvalds else 302647b5d69cSJames Bottomley currTar_Info->TarLUNBusy[0] = 1; 30271da177e4SLinus Torvalds 30285c04a7b8SAlexey Dobriyan currSCCB->ControlByte &= 30295c04a7b8SAlexey Dobriyan ~(unsigned char)F_USE_CMD_Q; 30301da177e4SLinus Torvalds 30315c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_autostart_1, 30325c04a7b8SAlexey Dobriyan (AUTO_IMMED + DISCONNECT_START)); 30331da177e4SLinus Torvalds 30341da177e4SLinus Torvalds } 30351da177e4SLinus Torvalds } 30361da177e4SLinus Torvalds 30375c04a7b8SAlexey Dobriyan else { 30381da177e4SLinus Torvalds ACCEPT_MSG(port); 30391da177e4SLinus Torvalds 30401da177e4SLinus Torvalds while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) && 30415c04a7b8SAlexey Dobriyan (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE))) 30421da177e4SLinus Torvalds { 30435c04a7b8SAlexey Dobriyan } 30445c04a7b8SAlexey Dobriyan 30455c04a7b8SAlexey Dobriyan if (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)) { 30465c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_autostart_1, 30475c04a7b8SAlexey Dobriyan (AUTO_IMMED + DISCONNECT_START)); 30481da177e4SLinus Torvalds } 30491da177e4SLinus Torvalds } 30501da177e4SLinus Torvalds } 30511da177e4SLinus Torvalds 30525c04a7b8SAlexey Dobriyan else if (message == SMEXT) { 30531da177e4SLinus Torvalds 30541da177e4SLinus Torvalds ACCEPT_MSG(port); 305547b5d69cSJames Bottomley FPT_shandem(port, p_card, currSCCB); 30561da177e4SLinus Torvalds } 30571da177e4SLinus Torvalds 30585c04a7b8SAlexey Dobriyan else if (message == SMIGNORWR) { 30591da177e4SLinus Torvalds 30601da177e4SLinus Torvalds ACCEPT_MSG(port); /* ACK the RESIDUE MSG */ 30611da177e4SLinus Torvalds 306247b5d69cSJames Bottomley message = FPT_sfm(port, currSCCB); 30631da177e4SLinus Torvalds 30641da177e4SLinus Torvalds if (currSCCB->Sccb_scsimsg != SMPARITY) 30651da177e4SLinus Torvalds ACCEPT_MSG(port); 30665c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_autostart_1, 30675c04a7b8SAlexey Dobriyan (AUTO_IMMED + DISCONNECT_START)); 30681da177e4SLinus Torvalds } 30691da177e4SLinus Torvalds 30705c04a7b8SAlexey Dobriyan else { 30711da177e4SLinus Torvalds 30721da177e4SLinus Torvalds currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL; 30731da177e4SLinus Torvalds currSCCB->Sccb_scsimsg = SMREJECT; 30741da177e4SLinus Torvalds 30751da177e4SLinus Torvalds ACCEPT_MSG_ATN(port); 30765c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_autostart_1, 30775c04a7b8SAlexey Dobriyan (AUTO_IMMED + DISCONNECT_START)); 30781da177e4SLinus Torvalds } 30791da177e4SLinus Torvalds } 30801da177e4SLinus Torvalds 30811da177e4SLinus Torvalds /*--------------------------------------------------------------------- 30821da177e4SLinus Torvalds * 308347b5d69cSJames Bottomley * Function: FPT_shandem 30841da177e4SLinus Torvalds * 30851da177e4SLinus Torvalds * Description: Decide what to do with the extended message. 30861da177e4SLinus Torvalds * 30871da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 30885c04a7b8SAlexey Dobriyan static void FPT_shandem(unsigned long port, unsigned char p_card, 30895c04a7b8SAlexey Dobriyan struct sccb *pCurrSCCB) 30901da177e4SLinus Torvalds { 3091db038cf8SAlexey Dobriyan unsigned char length, message; 30921da177e4SLinus Torvalds 309347b5d69cSJames Bottomley length = FPT_sfm(port, pCurrSCCB); 30945c04a7b8SAlexey Dobriyan if (length) { 30951da177e4SLinus Torvalds 30961da177e4SLinus Torvalds ACCEPT_MSG(port); 309747b5d69cSJames Bottomley message = FPT_sfm(port, pCurrSCCB); 30985c04a7b8SAlexey Dobriyan if (message) { 30991da177e4SLinus Torvalds 31005c04a7b8SAlexey Dobriyan if (message == SMSYNC) { 31011da177e4SLinus Torvalds 31025c04a7b8SAlexey Dobriyan if (length == 0x03) { 31031da177e4SLinus Torvalds 31041da177e4SLinus Torvalds ACCEPT_MSG(port); 310547b5d69cSJames Bottomley FPT_stsyncn(port, p_card); 31065c04a7b8SAlexey Dobriyan } else { 31071da177e4SLinus Torvalds 31081da177e4SLinus Torvalds pCurrSCCB->Sccb_scsimsg = SMREJECT; 31091da177e4SLinus Torvalds ACCEPT_MSG_ATN(port); 31101da177e4SLinus Torvalds } 31115c04a7b8SAlexey Dobriyan } else if (message == SMWDTR) { 31121da177e4SLinus Torvalds 31135c04a7b8SAlexey Dobriyan if (length == 0x02) { 31141da177e4SLinus Torvalds 31151da177e4SLinus Torvalds ACCEPT_MSG(port); 311647b5d69cSJames Bottomley FPT_stwidn(port, p_card); 31175c04a7b8SAlexey Dobriyan } else { 31181da177e4SLinus Torvalds 31191da177e4SLinus Torvalds pCurrSCCB->Sccb_scsimsg = SMREJECT; 31201da177e4SLinus Torvalds ACCEPT_MSG_ATN(port); 31211da177e4SLinus Torvalds 31225c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_autostart_1, 31235c04a7b8SAlexey Dobriyan (AUTO_IMMED + 31245c04a7b8SAlexey Dobriyan DISCONNECT_START)); 31251da177e4SLinus Torvalds } 31265c04a7b8SAlexey Dobriyan } else { 31271da177e4SLinus Torvalds 31281da177e4SLinus Torvalds pCurrSCCB->Sccb_scsimsg = SMREJECT; 31291da177e4SLinus Torvalds ACCEPT_MSG_ATN(port); 31301da177e4SLinus Torvalds 31315c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_autostart_1, 31325c04a7b8SAlexey Dobriyan (AUTO_IMMED + DISCONNECT_START)); 31331da177e4SLinus Torvalds } 31345c04a7b8SAlexey Dobriyan } else { 31351da177e4SLinus Torvalds if (pCurrSCCB->Sccb_scsimsg != SMPARITY) 31361da177e4SLinus Torvalds ACCEPT_MSG(port); 31375c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_autostart_1, 31385c04a7b8SAlexey Dobriyan (AUTO_IMMED + DISCONNECT_START)); 31391da177e4SLinus Torvalds } 31405c04a7b8SAlexey Dobriyan } else { 31411da177e4SLinus Torvalds if (pCurrSCCB->Sccb_scsimsg == SMPARITY) 31425c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_autostart_1, 31435c04a7b8SAlexey Dobriyan (AUTO_IMMED + DISCONNECT_START)); 31441da177e4SLinus Torvalds } 31451da177e4SLinus Torvalds } 31461da177e4SLinus Torvalds 31471da177e4SLinus Torvalds /*--------------------------------------------------------------------- 31481da177e4SLinus Torvalds * 314947b5d69cSJames Bottomley * Function: FPT_sisyncn 31501da177e4SLinus Torvalds * 31511da177e4SLinus Torvalds * Description: Read in a message byte from the SCSI bus, and check 31521da177e4SLinus Torvalds * for a parity error. 31531da177e4SLinus Torvalds * 31541da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 31551da177e4SLinus Torvalds 31565c04a7b8SAlexey Dobriyan static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card, 31575c04a7b8SAlexey Dobriyan unsigned char syncFlag) 31581da177e4SLinus Torvalds { 315969eb2ea4SAlexey Dobriyan struct sccb *currSCCB; 3160f31dc0cdSAlexey Dobriyan struct sccb_mgr_tar_info *currTar_Info; 31611da177e4SLinus Torvalds 316247b5d69cSJames Bottomley currSCCB = FPT_BL_Card[p_card].currentSCCB; 316347b5d69cSJames Bottomley currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID]; 31641da177e4SLinus Torvalds 31651da177e4SLinus Torvalds if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)) { 31661da177e4SLinus Torvalds 31671da177e4SLinus Torvalds WRW_HARPOON((port + ID_MSG_STRT), 31685c04a7b8SAlexey Dobriyan (MPM_OP + AMSG_OUT + 31695c04a7b8SAlexey Dobriyan (currSCCB-> 31705c04a7b8SAlexey Dobriyan Sccb_idmsg & ~(unsigned char)DISC_PRIV))); 31711da177e4SLinus Torvalds 31721da177e4SLinus Torvalds WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ); 31731da177e4SLinus Torvalds 31745c04a7b8SAlexey Dobriyan WRW_HARPOON((port + SYNC_MSGS + 0), 31755c04a7b8SAlexey Dobriyan (MPM_OP + AMSG_OUT + SMEXT)); 31761da177e4SLinus Torvalds WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03)); 31775c04a7b8SAlexey Dobriyan WRW_HARPOON((port + SYNC_MSGS + 4), 31785c04a7b8SAlexey Dobriyan (MPM_OP + AMSG_OUT + SMSYNC)); 31791da177e4SLinus Torvalds 31801da177e4SLinus Torvalds if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB) 31811da177e4SLinus Torvalds 31825c04a7b8SAlexey Dobriyan WRW_HARPOON((port + SYNC_MSGS + 6), 31835c04a7b8SAlexey Dobriyan (MPM_OP + AMSG_OUT + 12)); 31841da177e4SLinus Torvalds 31855c04a7b8SAlexey Dobriyan else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == 31865c04a7b8SAlexey Dobriyan EE_SYNC_10MB) 31871da177e4SLinus Torvalds 31885c04a7b8SAlexey Dobriyan WRW_HARPOON((port + SYNC_MSGS + 6), 31895c04a7b8SAlexey Dobriyan (MPM_OP + AMSG_OUT + 25)); 31901da177e4SLinus Torvalds 31915c04a7b8SAlexey Dobriyan else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == 31925c04a7b8SAlexey Dobriyan EE_SYNC_5MB) 31931da177e4SLinus Torvalds 31945c04a7b8SAlexey Dobriyan WRW_HARPOON((port + SYNC_MSGS + 6), 31955c04a7b8SAlexey Dobriyan (MPM_OP + AMSG_OUT + 50)); 31961da177e4SLinus Torvalds 31971da177e4SLinus Torvalds else 31985c04a7b8SAlexey Dobriyan WRW_HARPOON((port + SYNC_MSGS + 6), 31995c04a7b8SAlexey Dobriyan (MPM_OP + AMSG_OUT + 00)); 32001da177e4SLinus Torvalds 32011da177e4SLinus Torvalds WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP)); 32025c04a7b8SAlexey Dobriyan WRW_HARPOON((port + SYNC_MSGS + 10), 32035c04a7b8SAlexey Dobriyan (MPM_OP + AMSG_OUT + DEFAULT_OFFSET)); 32041da177e4SLinus Torvalds WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP)); 32051da177e4SLinus Torvalds 32065c04a7b8SAlexey Dobriyan if (syncFlag == 0) { 32075c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_autostart_3, 32085c04a7b8SAlexey Dobriyan (SELECT + SELCHK_STRT)); 32095c04a7b8SAlexey Dobriyan currTar_Info->TarStatus = 32105c04a7b8SAlexey Dobriyan ((currTar_Info-> 32115c04a7b8SAlexey Dobriyan TarStatus & ~(unsigned char)TAR_SYNC_MASK) | 32125c04a7b8SAlexey Dobriyan (unsigned char)SYNC_TRYING); 32135c04a7b8SAlexey Dobriyan } else { 32145c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_autostart_3, 32155c04a7b8SAlexey Dobriyan (AUTO_IMMED + CMD_ONLY_STRT)); 32161da177e4SLinus Torvalds } 32171da177e4SLinus Torvalds 32185c1b85e2SAlexey Dobriyan return 1; 32191da177e4SLinus Torvalds } 32201da177e4SLinus Torvalds 32211da177e4SLinus Torvalds else { 32221da177e4SLinus Torvalds 3223db038cf8SAlexey Dobriyan currTar_Info->TarStatus |= (unsigned char)SYNC_SUPPORTED; 32241da177e4SLinus Torvalds currTar_Info->TarEEValue &= ~EE_SYNC_MASK; 32255c1b85e2SAlexey Dobriyan return 0; 32261da177e4SLinus Torvalds } 32271da177e4SLinus Torvalds } 32281da177e4SLinus Torvalds 32291da177e4SLinus Torvalds /*--------------------------------------------------------------------- 32301da177e4SLinus Torvalds * 323147b5d69cSJames Bottomley * Function: FPT_stsyncn 32321da177e4SLinus Torvalds * 32331da177e4SLinus Torvalds * Description: The has sent us a Sync Nego message so handle it as 32341da177e4SLinus Torvalds * necessary. 32351da177e4SLinus Torvalds * 32361da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 3237d63a4cccSAlexey Dobriyan static void FPT_stsyncn(unsigned long port, unsigned char p_card) 32381da177e4SLinus Torvalds { 3239db038cf8SAlexey Dobriyan unsigned char sync_msg, offset, sync_reg, our_sync_msg; 324069eb2ea4SAlexey Dobriyan struct sccb *currSCCB; 3241f31dc0cdSAlexey Dobriyan struct sccb_mgr_tar_info *currTar_Info; 32421da177e4SLinus Torvalds 324347b5d69cSJames Bottomley currSCCB = FPT_BL_Card[p_card].currentSCCB; 324447b5d69cSJames Bottomley currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID]; 32451da177e4SLinus Torvalds 324647b5d69cSJames Bottomley sync_msg = FPT_sfm(port, currSCCB); 32471da177e4SLinus Torvalds 32485c04a7b8SAlexey Dobriyan if ((sync_msg == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) { 32495c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_autostart_1, 32505c04a7b8SAlexey Dobriyan (AUTO_IMMED + DISCONNECT_START)); 32511da177e4SLinus Torvalds return; 32521da177e4SLinus Torvalds } 32531da177e4SLinus Torvalds 32541da177e4SLinus Torvalds ACCEPT_MSG(port); 32551da177e4SLinus Torvalds 325647b5d69cSJames Bottomley offset = FPT_sfm(port, currSCCB); 32571da177e4SLinus Torvalds 32585c04a7b8SAlexey Dobriyan if ((offset == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) { 32595c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_autostart_1, 32605c04a7b8SAlexey Dobriyan (AUTO_IMMED + DISCONNECT_START)); 32611da177e4SLinus Torvalds return; 32621da177e4SLinus Torvalds } 32631da177e4SLinus Torvalds 32641da177e4SLinus Torvalds if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB) 32651da177e4SLinus Torvalds 32661da177e4SLinus Torvalds our_sync_msg = 12; /* Setup our Message to 20mb/s */ 32671da177e4SLinus Torvalds 32681da177e4SLinus Torvalds else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_10MB) 32691da177e4SLinus Torvalds 32701da177e4SLinus Torvalds our_sync_msg = 25; /* Setup our Message to 10mb/s */ 32711da177e4SLinus Torvalds 32721da177e4SLinus Torvalds else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_5MB) 32731da177e4SLinus Torvalds 32741da177e4SLinus Torvalds our_sync_msg = 50; /* Setup our Message to 5mb/s */ 32751da177e4SLinus Torvalds else 32761da177e4SLinus Torvalds 32771da177e4SLinus Torvalds our_sync_msg = 0; /* Message = Async */ 32781da177e4SLinus Torvalds 32791da177e4SLinus Torvalds if (sync_msg < our_sync_msg) { 32801da177e4SLinus Torvalds sync_msg = our_sync_msg; /*if faster, then set to max. */ 32811da177e4SLinus Torvalds } 32821da177e4SLinus Torvalds 32831da177e4SLinus Torvalds if (offset == ASYNC) 32841da177e4SLinus Torvalds sync_msg = ASYNC; 32851da177e4SLinus Torvalds 32861da177e4SLinus Torvalds if (offset > MAX_OFFSET) 32871da177e4SLinus Torvalds offset = MAX_OFFSET; 32881da177e4SLinus Torvalds 32891da177e4SLinus Torvalds sync_reg = 0x00; 32901da177e4SLinus Torvalds 32911da177e4SLinus Torvalds if (sync_msg > 12) 32921da177e4SLinus Torvalds 32931da177e4SLinus Torvalds sync_reg = 0x20; /* Use 10MB/s */ 32941da177e4SLinus Torvalds 32951da177e4SLinus Torvalds if (sync_msg > 25) 32961da177e4SLinus Torvalds 32971da177e4SLinus Torvalds sync_reg = 0x40; /* Use 6.6MB/s */ 32981da177e4SLinus Torvalds 32991da177e4SLinus Torvalds if (sync_msg > 38) 33001da177e4SLinus Torvalds 33011da177e4SLinus Torvalds sync_reg = 0x60; /* Use 5MB/s */ 33021da177e4SLinus Torvalds 33031da177e4SLinus Torvalds if (sync_msg > 50) 33041da177e4SLinus Torvalds 33051da177e4SLinus Torvalds sync_reg = 0x80; /* Use 4MB/s */ 33061da177e4SLinus Torvalds 33071da177e4SLinus Torvalds if (sync_msg > 62) 33081da177e4SLinus Torvalds 33091da177e4SLinus Torvalds sync_reg = 0xA0; /* Use 3.33MB/s */ 33101da177e4SLinus Torvalds 33111da177e4SLinus Torvalds if (sync_msg > 75) 33121da177e4SLinus Torvalds 33131da177e4SLinus Torvalds sync_reg = 0xC0; /* Use 2.85MB/s */ 33141da177e4SLinus Torvalds 33151da177e4SLinus Torvalds if (sync_msg > 87) 33161da177e4SLinus Torvalds 33171da177e4SLinus Torvalds sync_reg = 0xE0; /* Use 2.5MB/s */ 33181da177e4SLinus Torvalds 33191da177e4SLinus Torvalds if (sync_msg > 100) { 33201da177e4SLinus Torvalds 33211da177e4SLinus Torvalds sync_reg = 0x00; /* Use ASYNC */ 33221da177e4SLinus Torvalds offset = 0x00; 33231da177e4SLinus Torvalds } 33241da177e4SLinus Torvalds 33251da177e4SLinus Torvalds if (currTar_Info->TarStatus & WIDE_ENABLED) 33261da177e4SLinus Torvalds 33271da177e4SLinus Torvalds sync_reg |= offset; 33281da177e4SLinus Torvalds 33291da177e4SLinus Torvalds else 33301da177e4SLinus Torvalds 33311da177e4SLinus Torvalds sync_reg |= (offset | NARROW_SCSI); 33321da177e4SLinus Torvalds 333347b5d69cSJames Bottomley FPT_sssyncv(port, currSCCB->TargID, sync_reg, currTar_Info); 33341da177e4SLinus Torvalds 33351da177e4SLinus Torvalds if (currSCCB->Sccb_scsistat == SELECT_SN_ST) { 33361da177e4SLinus Torvalds 33371da177e4SLinus Torvalds ACCEPT_MSG(port); 33381da177e4SLinus Torvalds 33391da177e4SLinus Torvalds currTar_Info->TarStatus = ((currTar_Info->TarStatus & 33405c04a7b8SAlexey Dobriyan ~(unsigned char)TAR_SYNC_MASK) | 33415c04a7b8SAlexey Dobriyan (unsigned char)SYNC_SUPPORTED); 33421da177e4SLinus Torvalds 33435c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_autostart_1, 33445c04a7b8SAlexey Dobriyan (AUTO_IMMED + DISCONNECT_START)); 33451da177e4SLinus Torvalds } 33461da177e4SLinus Torvalds 33471da177e4SLinus Torvalds else { 33481da177e4SLinus Torvalds 33491da177e4SLinus Torvalds ACCEPT_MSG_ATN(port); 33501da177e4SLinus Torvalds 335147b5d69cSJames Bottomley FPT_sisyncr(port, sync_msg, offset); 33521da177e4SLinus Torvalds 33531da177e4SLinus Torvalds currTar_Info->TarStatus = ((currTar_Info->TarStatus & 33545c04a7b8SAlexey Dobriyan ~(unsigned char)TAR_SYNC_MASK) | 33555c04a7b8SAlexey Dobriyan (unsigned char)SYNC_SUPPORTED); 33561da177e4SLinus Torvalds } 33571da177e4SLinus Torvalds } 33581da177e4SLinus Torvalds 33591da177e4SLinus Torvalds /*--------------------------------------------------------------------- 33601da177e4SLinus Torvalds * 336147b5d69cSJames Bottomley * Function: FPT_sisyncr 33621da177e4SLinus Torvalds * 33631da177e4SLinus Torvalds * Description: Answer the targets sync message. 33641da177e4SLinus Torvalds * 33651da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 33665c04a7b8SAlexey Dobriyan static void FPT_sisyncr(unsigned long port, unsigned char sync_pulse, 33675c04a7b8SAlexey Dobriyan unsigned char offset) 33681da177e4SLinus Torvalds { 33691da177e4SLinus Torvalds ARAM_ACCESS(port); 33701da177e4SLinus Torvalds WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT)); 33711da177e4SLinus Torvalds WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03)); 33721da177e4SLinus Torvalds WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMSYNC)); 33731da177e4SLinus Torvalds WRW_HARPOON((port + SYNC_MSGS + 6), (MPM_OP + AMSG_OUT + sync_pulse)); 33741da177e4SLinus Torvalds WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP)); 33751da177e4SLinus Torvalds WRW_HARPOON((port + SYNC_MSGS + 10), (MPM_OP + AMSG_OUT + offset)); 33761da177e4SLinus Torvalds WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP)); 33771da177e4SLinus Torvalds SGRAM_ACCESS(port); 33781da177e4SLinus Torvalds 33791da177e4SLinus Torvalds WR_HARPOON(port + hp_portctrl_0, SCSI_PORT); 33801da177e4SLinus Torvalds WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1); 33811da177e4SLinus Torvalds 33821da177e4SLinus Torvalds WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT)); 33831da177e4SLinus Torvalds 33845c04a7b8SAlexey Dobriyan while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) { 33851da177e4SLinus Torvalds } 33865c04a7b8SAlexey Dobriyan } 33871da177e4SLinus Torvalds 33881da177e4SLinus Torvalds /*--------------------------------------------------------------------- 33891da177e4SLinus Torvalds * 339047b5d69cSJames Bottomley * Function: FPT_siwidn 33911da177e4SLinus Torvalds * 33921da177e4SLinus Torvalds * Description: Read in a message byte from the SCSI bus, and check 33931da177e4SLinus Torvalds * for a parity error. 33941da177e4SLinus Torvalds * 33951da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 33961da177e4SLinus Torvalds 3397d63a4cccSAlexey Dobriyan static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card) 33981da177e4SLinus Torvalds { 339969eb2ea4SAlexey Dobriyan struct sccb *currSCCB; 3400f31dc0cdSAlexey Dobriyan struct sccb_mgr_tar_info *currTar_Info; 34011da177e4SLinus Torvalds 340247b5d69cSJames Bottomley currSCCB = FPT_BL_Card[p_card].currentSCCB; 340347b5d69cSJames Bottomley currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID]; 34041da177e4SLinus Torvalds 34051da177e4SLinus Torvalds if (!((currTar_Info->TarStatus & TAR_WIDE_MASK) == WIDE_NEGOCIATED)) { 34061da177e4SLinus Torvalds 34071da177e4SLinus Torvalds WRW_HARPOON((port + ID_MSG_STRT), 34085c04a7b8SAlexey Dobriyan (MPM_OP + AMSG_OUT + 34095c04a7b8SAlexey Dobriyan (currSCCB-> 34105c04a7b8SAlexey Dobriyan Sccb_idmsg & ~(unsigned char)DISC_PRIV))); 34111da177e4SLinus Torvalds 34121da177e4SLinus Torvalds WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ); 34131da177e4SLinus Torvalds 34145c04a7b8SAlexey Dobriyan WRW_HARPOON((port + SYNC_MSGS + 0), 34155c04a7b8SAlexey Dobriyan (MPM_OP + AMSG_OUT + SMEXT)); 34161da177e4SLinus Torvalds WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02)); 34175c04a7b8SAlexey Dobriyan WRW_HARPOON((port + SYNC_MSGS + 4), 34185c04a7b8SAlexey Dobriyan (MPM_OP + AMSG_OUT + SMWDTR)); 34191da177e4SLinus Torvalds WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP)); 34205c04a7b8SAlexey Dobriyan WRW_HARPOON((port + SYNC_MSGS + 8), 34215c04a7b8SAlexey Dobriyan (MPM_OP + AMSG_OUT + SM16BIT)); 34221da177e4SLinus Torvalds WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP)); 34231da177e4SLinus Torvalds 34241da177e4SLinus Torvalds WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT)); 34251da177e4SLinus Torvalds 34261da177e4SLinus Torvalds currTar_Info->TarStatus = ((currTar_Info->TarStatus & 34275c04a7b8SAlexey Dobriyan ~(unsigned char)TAR_WIDE_MASK) | 34285c04a7b8SAlexey Dobriyan (unsigned char)WIDE_ENABLED); 34291da177e4SLinus Torvalds 34305c1b85e2SAlexey Dobriyan return 1; 34311da177e4SLinus Torvalds } 34321da177e4SLinus Torvalds 34331da177e4SLinus Torvalds else { 34341da177e4SLinus Torvalds 34351da177e4SLinus Torvalds currTar_Info->TarStatus = ((currTar_Info->TarStatus & 34365c04a7b8SAlexey Dobriyan ~(unsigned char)TAR_WIDE_MASK) | 34375c04a7b8SAlexey Dobriyan WIDE_NEGOCIATED); 34381da177e4SLinus Torvalds 34391da177e4SLinus Torvalds currTar_Info->TarEEValue &= ~EE_WIDE_SCSI; 34405c1b85e2SAlexey Dobriyan return 0; 34411da177e4SLinus Torvalds } 34421da177e4SLinus Torvalds } 34431da177e4SLinus Torvalds 34441da177e4SLinus Torvalds /*--------------------------------------------------------------------- 34451da177e4SLinus Torvalds * 344647b5d69cSJames Bottomley * Function: FPT_stwidn 34471da177e4SLinus Torvalds * 34481da177e4SLinus Torvalds * Description: The has sent us a Wide Nego message so handle it as 34491da177e4SLinus Torvalds * necessary. 34501da177e4SLinus Torvalds * 34511da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 3452d63a4cccSAlexey Dobriyan static void FPT_stwidn(unsigned long port, unsigned char p_card) 34531da177e4SLinus Torvalds { 3454db038cf8SAlexey Dobriyan unsigned char width; 345569eb2ea4SAlexey Dobriyan struct sccb *currSCCB; 3456f31dc0cdSAlexey Dobriyan struct sccb_mgr_tar_info *currTar_Info; 34571da177e4SLinus Torvalds 345847b5d69cSJames Bottomley currSCCB = FPT_BL_Card[p_card].currentSCCB; 345947b5d69cSJames Bottomley currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID]; 34601da177e4SLinus Torvalds 346147b5d69cSJames Bottomley width = FPT_sfm(port, currSCCB); 34621da177e4SLinus Torvalds 34635c04a7b8SAlexey Dobriyan if ((width == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) { 34645c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_autostart_1, 34655c04a7b8SAlexey Dobriyan (AUTO_IMMED + DISCONNECT_START)); 34661da177e4SLinus Torvalds return; 34671da177e4SLinus Torvalds } 34681da177e4SLinus Torvalds 34691da177e4SLinus Torvalds if (!(currTar_Info->TarEEValue & EE_WIDE_SCSI)) 34701da177e4SLinus Torvalds width = 0; 34711da177e4SLinus Torvalds 34721da177e4SLinus Torvalds if (width) { 34731da177e4SLinus Torvalds currTar_Info->TarStatus |= WIDE_ENABLED; 34741da177e4SLinus Torvalds width = 0; 34755c04a7b8SAlexey Dobriyan } else { 34761da177e4SLinus Torvalds width = NARROW_SCSI; 34771da177e4SLinus Torvalds currTar_Info->TarStatus &= ~WIDE_ENABLED; 34781da177e4SLinus Torvalds } 34791da177e4SLinus Torvalds 348047b5d69cSJames Bottomley FPT_sssyncv(port, currSCCB->TargID, width, currTar_Info); 34811da177e4SLinus Torvalds 34825c04a7b8SAlexey Dobriyan if (currSCCB->Sccb_scsistat == SELECT_WN_ST) { 34831da177e4SLinus Torvalds 34841da177e4SLinus Torvalds currTar_Info->TarStatus |= WIDE_NEGOCIATED; 34851da177e4SLinus Torvalds 34865c04a7b8SAlexey Dobriyan if (! 34875c04a7b8SAlexey Dobriyan ((currTar_Info->TarStatus & TAR_SYNC_MASK) == 34885c04a7b8SAlexey Dobriyan SYNC_SUPPORTED)) { 34891da177e4SLinus Torvalds ACCEPT_MSG_ATN(port); 34901da177e4SLinus Torvalds ARAM_ACCESS(port); 349147b5d69cSJames Bottomley FPT_sisyncn(port, p_card, 1); 34921da177e4SLinus Torvalds currSCCB->Sccb_scsistat = SELECT_SN_ST; 34931da177e4SLinus Torvalds SGRAM_ACCESS(port); 34945c04a7b8SAlexey Dobriyan } else { 34951da177e4SLinus Torvalds ACCEPT_MSG(port); 34965c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_autostart_1, 34975c04a7b8SAlexey Dobriyan (AUTO_IMMED + DISCONNECT_START)); 34981da177e4SLinus Torvalds } 34991da177e4SLinus Torvalds } 35001da177e4SLinus Torvalds 35011da177e4SLinus Torvalds else { 35021da177e4SLinus Torvalds 35031da177e4SLinus Torvalds ACCEPT_MSG_ATN(port); 35041da177e4SLinus Torvalds 35051da177e4SLinus Torvalds if (currTar_Info->TarEEValue & EE_WIDE_SCSI) 35061da177e4SLinus Torvalds width = SM16BIT; 35071da177e4SLinus Torvalds else 35081da177e4SLinus Torvalds width = SM8BIT; 35091da177e4SLinus Torvalds 351047b5d69cSJames Bottomley FPT_siwidr(port, width); 35111da177e4SLinus Torvalds 35121da177e4SLinus Torvalds currTar_Info->TarStatus |= (WIDE_NEGOCIATED | WIDE_ENABLED); 35131da177e4SLinus Torvalds } 35141da177e4SLinus Torvalds } 35151da177e4SLinus Torvalds 35161da177e4SLinus Torvalds /*--------------------------------------------------------------------- 35171da177e4SLinus Torvalds * 351847b5d69cSJames Bottomley * Function: FPT_siwidr 35191da177e4SLinus Torvalds * 35201da177e4SLinus Torvalds * Description: Answer the targets Wide nego message. 35211da177e4SLinus Torvalds * 35221da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 3523d63a4cccSAlexey Dobriyan static void FPT_siwidr(unsigned long port, unsigned char width) 35241da177e4SLinus Torvalds { 35251da177e4SLinus Torvalds ARAM_ACCESS(port); 35261da177e4SLinus Torvalds WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT)); 35271da177e4SLinus Torvalds WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02)); 35281da177e4SLinus Torvalds WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMWDTR)); 35291da177e4SLinus Torvalds WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP)); 35301da177e4SLinus Torvalds WRW_HARPOON((port + SYNC_MSGS + 8), (MPM_OP + AMSG_OUT + width)); 35311da177e4SLinus Torvalds WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP)); 35321da177e4SLinus Torvalds SGRAM_ACCESS(port); 35331da177e4SLinus Torvalds 35341da177e4SLinus Torvalds WR_HARPOON(port + hp_portctrl_0, SCSI_PORT); 35351da177e4SLinus Torvalds WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1); 35361da177e4SLinus Torvalds 35371da177e4SLinus Torvalds WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT)); 35381da177e4SLinus Torvalds 35395c04a7b8SAlexey Dobriyan while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) { 35401da177e4SLinus Torvalds } 35415c04a7b8SAlexey Dobriyan } 35421da177e4SLinus Torvalds 35431da177e4SLinus Torvalds /*--------------------------------------------------------------------- 35441da177e4SLinus Torvalds * 354547b5d69cSJames Bottomley * Function: FPT_sssyncv 35461da177e4SLinus Torvalds * 35471da177e4SLinus Torvalds * Description: Write the desired value to the Sync Register for the 35481da177e4SLinus Torvalds * ID specified. 35491da177e4SLinus Torvalds * 35501da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 35515c04a7b8SAlexey Dobriyan static void FPT_sssyncv(unsigned long p_port, unsigned char p_id, 35525c04a7b8SAlexey Dobriyan unsigned char p_sync_value, 3553f31dc0cdSAlexey Dobriyan struct sccb_mgr_tar_info *currTar_Info) 35541da177e4SLinus Torvalds { 3555db038cf8SAlexey Dobriyan unsigned char index; 35561da177e4SLinus Torvalds 35571da177e4SLinus Torvalds index = p_id; 35581da177e4SLinus Torvalds 35591da177e4SLinus Torvalds switch (index) { 35601da177e4SLinus Torvalds 35611da177e4SLinus Torvalds case 0: 35621da177e4SLinus Torvalds index = 12; /* hp_synctarg_0 */ 35631da177e4SLinus Torvalds break; 35641da177e4SLinus Torvalds case 1: 35651da177e4SLinus Torvalds index = 13; /* hp_synctarg_1 */ 35661da177e4SLinus Torvalds break; 35671da177e4SLinus Torvalds case 2: 35681da177e4SLinus Torvalds index = 14; /* hp_synctarg_2 */ 35691da177e4SLinus Torvalds break; 35701da177e4SLinus Torvalds case 3: 35711da177e4SLinus Torvalds index = 15; /* hp_synctarg_3 */ 35721da177e4SLinus Torvalds break; 35731da177e4SLinus Torvalds case 4: 35741da177e4SLinus Torvalds index = 8; /* hp_synctarg_4 */ 35751da177e4SLinus Torvalds break; 35761da177e4SLinus Torvalds case 5: 35771da177e4SLinus Torvalds index = 9; /* hp_synctarg_5 */ 35781da177e4SLinus Torvalds break; 35791da177e4SLinus Torvalds case 6: 35801da177e4SLinus Torvalds index = 10; /* hp_synctarg_6 */ 35811da177e4SLinus Torvalds break; 35821da177e4SLinus Torvalds case 7: 35831da177e4SLinus Torvalds index = 11; /* hp_synctarg_7 */ 35841da177e4SLinus Torvalds break; 35851da177e4SLinus Torvalds case 8: 35861da177e4SLinus Torvalds index = 4; /* hp_synctarg_8 */ 35871da177e4SLinus Torvalds break; 35881da177e4SLinus Torvalds case 9: 35891da177e4SLinus Torvalds index = 5; /* hp_synctarg_9 */ 35901da177e4SLinus Torvalds break; 35911da177e4SLinus Torvalds case 10: 35921da177e4SLinus Torvalds index = 6; /* hp_synctarg_10 */ 35931da177e4SLinus Torvalds break; 35941da177e4SLinus Torvalds case 11: 35951da177e4SLinus Torvalds index = 7; /* hp_synctarg_11 */ 35961da177e4SLinus Torvalds break; 35971da177e4SLinus Torvalds case 12: 35981da177e4SLinus Torvalds index = 0; /* hp_synctarg_12 */ 35991da177e4SLinus Torvalds break; 36001da177e4SLinus Torvalds case 13: 36011da177e4SLinus Torvalds index = 1; /* hp_synctarg_13 */ 36021da177e4SLinus Torvalds break; 36031da177e4SLinus Torvalds case 14: 36041da177e4SLinus Torvalds index = 2; /* hp_synctarg_14 */ 36051da177e4SLinus Torvalds break; 36061da177e4SLinus Torvalds case 15: 36071da177e4SLinus Torvalds index = 3; /* hp_synctarg_15 */ 36081da177e4SLinus Torvalds 36091da177e4SLinus Torvalds } 36101da177e4SLinus Torvalds 36111da177e4SLinus Torvalds WR_HARPOON(p_port + hp_synctarg_base + index, p_sync_value); 36121da177e4SLinus Torvalds 36131da177e4SLinus Torvalds currTar_Info->TarSyncCtrl = p_sync_value; 36141da177e4SLinus Torvalds } 36151da177e4SLinus Torvalds 36161da177e4SLinus Torvalds /*--------------------------------------------------------------------- 36171da177e4SLinus Torvalds * 361847b5d69cSJames Bottomley * Function: FPT_sresb 36191da177e4SLinus Torvalds * 36201da177e4SLinus Torvalds * Description: Reset the desired card's SCSI bus. 36211da177e4SLinus Torvalds * 36221da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 3623d63a4cccSAlexey Dobriyan static void FPT_sresb(unsigned long port, unsigned char p_card) 36241da177e4SLinus Torvalds { 3625db038cf8SAlexey Dobriyan unsigned char scsiID, i; 36261da177e4SLinus Torvalds 3627f31dc0cdSAlexey Dobriyan struct sccb_mgr_tar_info *currTar_Info; 36281da177e4SLinus Torvalds 36291da177e4SLinus Torvalds WR_HARPOON(port + hp_page_ctrl, 36301da177e4SLinus Torvalds (RD_HARPOON(port + hp_page_ctrl) | G_INT_DISABLE)); 36311da177e4SLinus Torvalds WRW_HARPOON((port + hp_intstat), CLR_ALL_INT); 36321da177e4SLinus Torvalds 36331da177e4SLinus Torvalds WR_HARPOON(port + hp_scsictrl_0, SCSI_RST); 36341da177e4SLinus Torvalds 36351da177e4SLinus Torvalds scsiID = RD_HARPOON(port + hp_seltimeout); 36361da177e4SLinus Torvalds WR_HARPOON(port + hp_seltimeout, TO_5ms); 36371da177e4SLinus Torvalds WRW_HARPOON((port + hp_intstat), TIMEOUT); 36381da177e4SLinus Torvalds 36391da177e4SLinus Torvalds WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT | START_TO)); 36401da177e4SLinus Torvalds 36415c04a7b8SAlexey Dobriyan while (!(RDW_HARPOON((port + hp_intstat)) & TIMEOUT)) { 36425c04a7b8SAlexey Dobriyan } 36431da177e4SLinus Torvalds 36441da177e4SLinus Torvalds WR_HARPOON(port + hp_seltimeout, scsiID); 36451da177e4SLinus Torvalds 36461da177e4SLinus Torvalds WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL); 36471da177e4SLinus Torvalds 364847b5d69cSJames Bottomley FPT_Wait(port, TO_5ms); 36491da177e4SLinus Torvalds 36501da177e4SLinus Torvalds WRW_HARPOON((port + hp_intstat), CLR_ALL_INT); 36511da177e4SLinus Torvalds 36521da177e4SLinus Torvalds WR_HARPOON(port + hp_int_mask, (RD_HARPOON(port + hp_int_mask) | 0x00)); 36531da177e4SLinus Torvalds 36545c04a7b8SAlexey Dobriyan for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) { 365547b5d69cSJames Bottomley currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID]; 36561da177e4SLinus Torvalds 36575c04a7b8SAlexey Dobriyan if (currTar_Info->TarEEValue & EE_SYNC_MASK) { 36581da177e4SLinus Torvalds currTar_Info->TarSyncCtrl = 0; 36591da177e4SLinus Torvalds currTar_Info->TarStatus &= ~TAR_SYNC_MASK; 36601da177e4SLinus Torvalds } 36611da177e4SLinus Torvalds 36625c04a7b8SAlexey Dobriyan if (currTar_Info->TarEEValue & EE_WIDE_SCSI) { 36631da177e4SLinus Torvalds currTar_Info->TarStatus &= ~TAR_WIDE_MASK; 36641da177e4SLinus Torvalds } 36651da177e4SLinus Torvalds 366647b5d69cSJames Bottomley FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info); 36671da177e4SLinus Torvalds 366847b5d69cSJames Bottomley FPT_SccbMgrTableInitTarget(p_card, scsiID); 36691da177e4SLinus Torvalds } 36701da177e4SLinus Torvalds 367147b5d69cSJames Bottomley FPT_BL_Card[p_card].scanIndex = 0x00; 367247b5d69cSJames Bottomley FPT_BL_Card[p_card].currentSCCB = NULL; 367347b5d69cSJames Bottomley FPT_BL_Card[p_card].globalFlags &= ~(F_TAG_STARTED | F_HOST_XFER_ACT 36741da177e4SLinus Torvalds | F_NEW_SCCB_CMD); 367547b5d69cSJames Bottomley FPT_BL_Card[p_card].cmdCounter = 0x00; 367647b5d69cSJames Bottomley FPT_BL_Card[p_card].discQCount = 0x00; 367747b5d69cSJames Bottomley FPT_BL_Card[p_card].tagQ_Lst = 0x01; 36781da177e4SLinus Torvalds 36791da177e4SLinus Torvalds for (i = 0; i < QUEUE_DEPTH; i++) 368047b5d69cSJames Bottomley FPT_BL_Card[p_card].discQ_Tbl[i] = NULL; 36811da177e4SLinus Torvalds 36821da177e4SLinus Torvalds WR_HARPOON(port + hp_page_ctrl, 36831da177e4SLinus Torvalds (RD_HARPOON(port + hp_page_ctrl) & ~G_INT_DISABLE)); 36841da177e4SLinus Torvalds 36851da177e4SLinus Torvalds } 36861da177e4SLinus Torvalds 36871da177e4SLinus Torvalds /*--------------------------------------------------------------------- 36881da177e4SLinus Torvalds * 368947b5d69cSJames Bottomley * Function: FPT_ssenss 36901da177e4SLinus Torvalds * 36911da177e4SLinus Torvalds * Description: Setup for the Auto Sense command. 36921da177e4SLinus Torvalds * 36931da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 369413e6851aSAlexey Dobriyan static void FPT_ssenss(struct sccb_card *pCurrCard) 36951da177e4SLinus Torvalds { 3696db038cf8SAlexey Dobriyan unsigned char i; 369769eb2ea4SAlexey Dobriyan struct sccb *currSCCB; 36981da177e4SLinus Torvalds 36991da177e4SLinus Torvalds currSCCB = pCurrCard->currentSCCB; 37001da177e4SLinus Torvalds 37011da177e4SLinus Torvalds currSCCB->Save_CdbLen = currSCCB->CdbLength; 37021da177e4SLinus Torvalds 37031da177e4SLinus Torvalds for (i = 0; i < 6; i++) { 37041da177e4SLinus Torvalds 37051da177e4SLinus Torvalds currSCCB->Save_Cdb[i] = currSCCB->Cdb[i]; 37061da177e4SLinus Torvalds } 37071da177e4SLinus Torvalds 37081da177e4SLinus Torvalds currSCCB->CdbLength = SIX_BYTE_CMD; 37091da177e4SLinus Torvalds currSCCB->Cdb[0] = SCSI_REQUEST_SENSE; 3710db038cf8SAlexey Dobriyan currSCCB->Cdb[1] = currSCCB->Cdb[1] & (unsigned char)0xE0; /*Keep LUN. */ 37111da177e4SLinus Torvalds currSCCB->Cdb[2] = 0x00; 37121da177e4SLinus Torvalds currSCCB->Cdb[3] = 0x00; 37131da177e4SLinus Torvalds currSCCB->Cdb[4] = currSCCB->RequestSenseLength; 37141da177e4SLinus Torvalds currSCCB->Cdb[5] = 0x00; 37151da177e4SLinus Torvalds 37161da177e4SLinus Torvalds currSCCB->Sccb_XferCnt = (unsigned long)currSCCB->RequestSenseLength; 37171da177e4SLinus Torvalds 37181da177e4SLinus Torvalds currSCCB->Sccb_ATC = 0x00; 37191da177e4SLinus Torvalds 37201da177e4SLinus Torvalds currSCCB->Sccb_XferState |= F_AUTO_SENSE; 37211da177e4SLinus Torvalds 37221da177e4SLinus Torvalds currSCCB->Sccb_XferState &= ~F_SG_XFER; 37231da177e4SLinus Torvalds 3724db038cf8SAlexey Dobriyan currSCCB->Sccb_idmsg = currSCCB->Sccb_idmsg & ~(unsigned char)DISC_PRIV; 37251da177e4SLinus Torvalds 37261da177e4SLinus Torvalds currSCCB->ControlByte = 0x00; 37271da177e4SLinus Torvalds 37281da177e4SLinus Torvalds currSCCB->Sccb_MGRFlags &= F_STATUSLOADED; 37291da177e4SLinus Torvalds } 37301da177e4SLinus Torvalds 37311da177e4SLinus Torvalds /*--------------------------------------------------------------------- 37321da177e4SLinus Torvalds * 373347b5d69cSJames Bottomley * Function: FPT_sxfrp 37341da177e4SLinus Torvalds * 37351da177e4SLinus Torvalds * Description: Transfer data into the bit bucket until the device 37361da177e4SLinus Torvalds * decides to switch phase. 37371da177e4SLinus Torvalds * 37381da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 37391da177e4SLinus Torvalds 3740d63a4cccSAlexey Dobriyan static void FPT_sxfrp(unsigned long p_port, unsigned char p_card) 37411da177e4SLinus Torvalds { 3742db038cf8SAlexey Dobriyan unsigned char curr_phz; 37431da177e4SLinus Torvalds 37441da177e4SLinus Torvalds DISABLE_AUTO(p_port); 37451da177e4SLinus Torvalds 374647b5d69cSJames Bottomley if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) { 37471da177e4SLinus Torvalds 37485c04a7b8SAlexey Dobriyan FPT_hostDataXferAbort(p_port, p_card, 37495c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card].currentSCCB); 37501da177e4SLinus Torvalds 37511da177e4SLinus Torvalds } 37521da177e4SLinus Torvalds 37531da177e4SLinus Torvalds /* If the Automation handled the end of the transfer then do not 37541da177e4SLinus Torvalds match the phase or we will get out of sync with the ISR. */ 37551da177e4SLinus Torvalds 37565c04a7b8SAlexey Dobriyan if (RDW_HARPOON((p_port + hp_intstat)) & 37575c04a7b8SAlexey Dobriyan (BUS_FREE | XFER_CNT_0 | AUTO_INT)) 37581da177e4SLinus Torvalds return; 37591da177e4SLinus Torvalds 37601da177e4SLinus Torvalds WR_HARPOON(p_port + hp_xfercnt_0, 0x00); 37611da177e4SLinus Torvalds 3762db038cf8SAlexey Dobriyan curr_phz = RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ; 37631da177e4SLinus Torvalds 37641da177e4SLinus Torvalds WRW_HARPOON((p_port + hp_intstat), XFER_CNT_0); 37651da177e4SLinus Torvalds 37661da177e4SLinus Torvalds WR_HARPOON(p_port + hp_scsisig, curr_phz); 37671da177e4SLinus Torvalds 37681da177e4SLinus Torvalds while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET)) && 37695c04a7b8SAlexey Dobriyan (curr_phz == 37705c04a7b8SAlexey Dobriyan (RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ))) 37711da177e4SLinus Torvalds { 37725c04a7b8SAlexey Dobriyan if (curr_phz & (unsigned char)SCSI_IOBIT) { 37735c04a7b8SAlexey Dobriyan WR_HARPOON(p_port + hp_portctrl_0, 37745c04a7b8SAlexey Dobriyan (SCSI_PORT | HOST_PORT | SCSI_INBIT)); 37751da177e4SLinus Torvalds 37765c04a7b8SAlexey Dobriyan if (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) { 37771da177e4SLinus Torvalds RD_HARPOON(p_port + hp_fifodata_0); 37781da177e4SLinus Torvalds } 37795c04a7b8SAlexey Dobriyan } else { 37805c04a7b8SAlexey Dobriyan WR_HARPOON(p_port + hp_portctrl_0, 37815c04a7b8SAlexey Dobriyan (SCSI_PORT | HOST_PORT | HOST_WRT)); 37825c04a7b8SAlexey Dobriyan if (RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY) { 37831da177e4SLinus Torvalds WR_HARPOON(p_port + hp_fifodata_0, 0xFA); 37841da177e4SLinus Torvalds } 37851da177e4SLinus Torvalds } 37861da177e4SLinus Torvalds } /* End of While loop for padding data I/O phase */ 37871da177e4SLinus Torvalds 37885c04a7b8SAlexey Dobriyan while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) { 37891da177e4SLinus Torvalds if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ) 37901da177e4SLinus Torvalds break; 37911da177e4SLinus Torvalds } 37921da177e4SLinus Torvalds 37935c04a7b8SAlexey Dobriyan WR_HARPOON(p_port + hp_portctrl_0, 37945c04a7b8SAlexey Dobriyan (SCSI_PORT | HOST_PORT | SCSI_INBIT)); 37955c04a7b8SAlexey Dobriyan while (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) { 37961da177e4SLinus Torvalds RD_HARPOON(p_port + hp_fifodata_0); 37971da177e4SLinus Torvalds } 37981da177e4SLinus Torvalds 37995c04a7b8SAlexey Dobriyan if (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) { 38005c04a7b8SAlexey Dobriyan WR_HARPOON(p_port + hp_autostart_0, 38015c04a7b8SAlexey Dobriyan (AUTO_IMMED + DISCONNECT_START)); 38025c04a7b8SAlexey Dobriyan while (!(RDW_HARPOON((p_port + hp_intstat)) & AUTO_INT)) { 38031da177e4SLinus Torvalds } 38041da177e4SLinus Torvalds 38055c04a7b8SAlexey Dobriyan if (RDW_HARPOON((p_port + hp_intstat)) & 38065c04a7b8SAlexey Dobriyan (ICMD_COMP | ITAR_DISC)) 38075c04a7b8SAlexey Dobriyan while (! 38085c04a7b8SAlexey Dobriyan (RDW_HARPOON((p_port + hp_intstat)) & 38095c04a7b8SAlexey Dobriyan (BUS_FREE | RSEL))) ; 38105c04a7b8SAlexey Dobriyan } 38115c04a7b8SAlexey Dobriyan } 38121da177e4SLinus Torvalds 38131da177e4SLinus Torvalds /*--------------------------------------------------------------------- 38141da177e4SLinus Torvalds * 381547b5d69cSJames Bottomley * Function: FPT_schkdd 38161da177e4SLinus Torvalds * 38171da177e4SLinus Torvalds * Description: Make sure data has been flushed from both FIFOs and abort 38181da177e4SLinus Torvalds * the operations if necessary. 38191da177e4SLinus Torvalds * 38201da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 38211da177e4SLinus Torvalds 3822d63a4cccSAlexey Dobriyan static void FPT_schkdd(unsigned long port, unsigned char p_card) 38231da177e4SLinus Torvalds { 3824c823feebSAlexey Dobriyan unsigned short TimeOutLoop; 3825db038cf8SAlexey Dobriyan unsigned char sPhase; 38261da177e4SLinus Torvalds 382769eb2ea4SAlexey Dobriyan struct sccb *currSCCB; 38281da177e4SLinus Torvalds 382947b5d69cSJames Bottomley currSCCB = FPT_BL_Card[p_card].currentSCCB; 38301da177e4SLinus Torvalds 38311da177e4SLinus Torvalds if ((currSCCB->Sccb_scsistat != DATA_OUT_ST) && 38321da177e4SLinus Torvalds (currSCCB->Sccb_scsistat != DATA_IN_ST)) { 38331da177e4SLinus Torvalds return; 38341da177e4SLinus Torvalds } 38351da177e4SLinus Torvalds 38365c04a7b8SAlexey Dobriyan if (currSCCB->Sccb_XferState & F_ODD_BALL_CNT) { 38371da177e4SLinus Torvalds 38381da177e4SLinus Torvalds currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - 1); 38391da177e4SLinus Torvalds 38401da177e4SLinus Torvalds currSCCB->Sccb_XferCnt = 1; 38411da177e4SLinus Torvalds 38421da177e4SLinus Torvalds currSCCB->Sccb_XferState &= ~F_ODD_BALL_CNT; 3843c823feebSAlexey Dobriyan WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00); 38441da177e4SLinus Torvalds WR_HARPOON(port + hp_xferstat, 0x00); 38451da177e4SLinus Torvalds } 38461da177e4SLinus Torvalds 38475c04a7b8SAlexey Dobriyan else { 38481da177e4SLinus Torvalds 38491da177e4SLinus Torvalds currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt; 38501da177e4SLinus Torvalds 38511da177e4SLinus Torvalds currSCCB->Sccb_XferCnt = 0; 38521da177e4SLinus Torvalds } 38531da177e4SLinus Torvalds 38541da177e4SLinus Torvalds if ((RDW_HARPOON((port + hp_intstat)) & PARITY) && 38551da177e4SLinus Torvalds (currSCCB->HostStatus == SCCB_COMPLETE)) { 38561da177e4SLinus Torvalds 38571da177e4SLinus Torvalds currSCCB->HostStatus = SCCB_PARITY_ERR; 38581da177e4SLinus Torvalds WRW_HARPOON((port + hp_intstat), PARITY); 38591da177e4SLinus Torvalds } 38601da177e4SLinus Torvalds 386147b5d69cSJames Bottomley FPT_hostDataXferAbort(port, p_card, currSCCB); 38621da177e4SLinus Torvalds 38635c04a7b8SAlexey Dobriyan while (RD_HARPOON(port + hp_scsisig) & SCSI_ACK) { 38645c04a7b8SAlexey Dobriyan } 38651da177e4SLinus Torvalds 38661da177e4SLinus Torvalds TimeOutLoop = 0; 38671da177e4SLinus Torvalds 38685c04a7b8SAlexey Dobriyan while (RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY) { 38691da177e4SLinus Torvalds if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) { 38701da177e4SLinus Torvalds return; 38711da177e4SLinus Torvalds } 3872db038cf8SAlexey Dobriyan if (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) { 38731da177e4SLinus Torvalds break; 38741da177e4SLinus Torvalds } 38751da177e4SLinus Torvalds if (RDW_HARPOON((port + hp_intstat)) & RESET) { 38761da177e4SLinus Torvalds return; 38771da177e4SLinus Torvalds } 38785c04a7b8SAlexey Dobriyan if ((RD_HARPOON(port + hp_scsisig) & SCSI_REQ) 38795c04a7b8SAlexey Dobriyan || (TimeOutLoop++ > 0x3000)) 38801da177e4SLinus Torvalds break; 38811da177e4SLinus Torvalds } 38821da177e4SLinus Torvalds 38831da177e4SLinus Torvalds sPhase = RD_HARPOON(port + hp_scsisig) & (SCSI_BSY | S_SCSI_PHZ); 38841da177e4SLinus Torvalds if ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) || 3885db038cf8SAlexey Dobriyan (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) || 38861da177e4SLinus Torvalds (sPhase == (SCSI_BSY | S_DATAO_PH)) || 38875c04a7b8SAlexey Dobriyan (sPhase == (SCSI_BSY | S_DATAI_PH))) { 38881da177e4SLinus Torvalds 38891da177e4SLinus Torvalds WR_HARPOON(port + hp_portctrl_0, SCSI_PORT); 38901da177e4SLinus Torvalds 38915c04a7b8SAlexey Dobriyan if (!(currSCCB->Sccb_XferState & F_ALL_XFERRED)) { 38921da177e4SLinus Torvalds if (currSCCB->Sccb_XferState & F_HOST_XFER_DIR) { 389347b5d69cSJames Bottomley FPT_phaseDataIn(port, p_card); 38941da177e4SLinus Torvalds } 38951da177e4SLinus Torvalds 38961da177e4SLinus Torvalds else { 389747b5d69cSJames Bottomley FPT_phaseDataOut(port, p_card); 38981da177e4SLinus Torvalds } 38995c04a7b8SAlexey Dobriyan } else { 390047b5d69cSJames Bottomley FPT_sxfrp(port, p_card); 39011da177e4SLinus Torvalds if (!(RDW_HARPOON((port + hp_intstat)) & 39025c04a7b8SAlexey Dobriyan (BUS_FREE | ICMD_COMP | ITAR_DISC | RESET))) { 39031da177e4SLinus Torvalds WRW_HARPOON((port + hp_intstat), AUTO_INT); 390447b5d69cSJames Bottomley FPT_phaseDecode(port, p_card); 39051da177e4SLinus Torvalds } 39061da177e4SLinus Torvalds } 39071da177e4SLinus Torvalds 39081da177e4SLinus Torvalds } 39091da177e4SLinus Torvalds 39101da177e4SLinus Torvalds else { 39111da177e4SLinus Torvalds WR_HARPOON(port + hp_portctrl_0, 0x00); 39121da177e4SLinus Torvalds } 39131da177e4SLinus Torvalds } 39141da177e4SLinus Torvalds 39151da177e4SLinus Torvalds /*--------------------------------------------------------------------- 39161da177e4SLinus Torvalds * 391747b5d69cSJames Bottomley * Function: FPT_sinits 39181da177e4SLinus Torvalds * 39191da177e4SLinus Torvalds * Description: Setup SCCB manager fields in this SCCB. 39201da177e4SLinus Torvalds * 39211da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 39221da177e4SLinus Torvalds 392369eb2ea4SAlexey Dobriyan static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card) 39241da177e4SLinus Torvalds { 3925f31dc0cdSAlexey Dobriyan struct sccb_mgr_tar_info *currTar_Info; 39261da177e4SLinus Torvalds 39275d7ebb9cSDan Carpenter if ((p_sccb->TargID >= MAX_SCSI_TAR) || (p_sccb->Lun >= MAX_LUN)) { 39281da177e4SLinus Torvalds return; 39291da177e4SLinus Torvalds } 393047b5d69cSJames Bottomley currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID]; 39311da177e4SLinus Torvalds 39321da177e4SLinus Torvalds p_sccb->Sccb_XferState = 0x00; 39331da177e4SLinus Torvalds p_sccb->Sccb_XferCnt = p_sccb->DataLength; 39341da177e4SLinus Torvalds 39351da177e4SLinus Torvalds if ((p_sccb->OperationCode == SCATTER_GATHER_COMMAND) || 39361da177e4SLinus Torvalds (p_sccb->OperationCode == RESIDUAL_SG_COMMAND)) { 39371da177e4SLinus Torvalds 39381da177e4SLinus Torvalds p_sccb->Sccb_SGoffset = 0; 39391da177e4SLinus Torvalds p_sccb->Sccb_XferState = F_SG_XFER; 39401da177e4SLinus Torvalds p_sccb->Sccb_XferCnt = 0x00; 39411da177e4SLinus Torvalds } 39421da177e4SLinus Torvalds 39431da177e4SLinus Torvalds if (p_sccb->DataLength == 0x00) 39441da177e4SLinus Torvalds 39451da177e4SLinus Torvalds p_sccb->Sccb_XferState |= F_ALL_XFERRED; 39461da177e4SLinus Torvalds 39475c04a7b8SAlexey Dobriyan if (p_sccb->ControlByte & F_USE_CMD_Q) { 39481da177e4SLinus Torvalds if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT) 39491da177e4SLinus Torvalds p_sccb->ControlByte &= ~F_USE_CMD_Q; 39501da177e4SLinus Torvalds 39511da177e4SLinus Torvalds else 39521da177e4SLinus Torvalds currTar_Info->TarStatus |= TAG_Q_TRYING; 39531da177e4SLinus Torvalds } 39541da177e4SLinus Torvalds 39551da177e4SLinus Torvalds /* For !single SCSI device in system & device allow Disconnect 39561da177e4SLinus Torvalds or command is tag_q type then send Cmd with Disconnect Enable 39571da177e4SLinus Torvalds else send Cmd with Disconnect Disable */ 39581da177e4SLinus Torvalds 39591da177e4SLinus Torvalds /* 396047b5d69cSJames Bottomley if (((!(FPT_BL_Card[p_card].globalFlags & F_SINGLE_DEVICE)) && 39611da177e4SLinus Torvalds (currTar_Info->TarStatus & TAR_ALLOW_DISC)) || 39621da177e4SLinus Torvalds (currTar_Info->TarStatus & TAG_Q_TRYING)) { 39631da177e4SLinus Torvalds */ 39641da177e4SLinus Torvalds if ((currTar_Info->TarStatus & TAR_ALLOW_DISC) || 39651da177e4SLinus Torvalds (currTar_Info->TarStatus & TAG_Q_TRYING)) { 39665c04a7b8SAlexey Dobriyan p_sccb->Sccb_idmsg = 39675c04a7b8SAlexey Dobriyan (unsigned char)(SMIDENT | DISC_PRIV) | p_sccb->Lun; 39681da177e4SLinus Torvalds } 39691da177e4SLinus Torvalds 39701da177e4SLinus Torvalds else { 39711da177e4SLinus Torvalds 3972db038cf8SAlexey Dobriyan p_sccb->Sccb_idmsg = (unsigned char)SMIDENT | p_sccb->Lun; 39731da177e4SLinus Torvalds } 39741da177e4SLinus Torvalds 39751da177e4SLinus Torvalds p_sccb->HostStatus = 0x00; 39761da177e4SLinus Torvalds p_sccb->TargetStatus = 0x00; 39771da177e4SLinus Torvalds p_sccb->Sccb_tag = 0x00; 39781da177e4SLinus Torvalds p_sccb->Sccb_MGRFlags = 0x00; 39791da177e4SLinus Torvalds p_sccb->Sccb_sgseg = 0x00; 39801da177e4SLinus Torvalds p_sccb->Sccb_ATC = 0x00; 39811da177e4SLinus Torvalds p_sccb->Sccb_savedATC = 0x00; 39821da177e4SLinus Torvalds /* 39831da177e4SLinus Torvalds p_sccb->SccbVirtDataPtr = 0x00; 39841da177e4SLinus Torvalds p_sccb->Sccb_forwardlink = NULL; 39851da177e4SLinus Torvalds p_sccb->Sccb_backlink = NULL; 39861da177e4SLinus Torvalds */ 39871da177e4SLinus Torvalds p_sccb->Sccb_scsistat = BUS_FREE_ST; 39881da177e4SLinus Torvalds p_sccb->SccbStatus = SCCB_IN_PROCESS; 39891da177e4SLinus Torvalds p_sccb->Sccb_scsimsg = SMNO_OP; 39901da177e4SLinus Torvalds 39911da177e4SLinus Torvalds } 39921da177e4SLinus Torvalds 39931da177e4SLinus Torvalds /*--------------------------------------------------------------------- 39941da177e4SLinus Torvalds * 39951da177e4SLinus Torvalds * Function: Phase Decode 39961da177e4SLinus Torvalds * 39971da177e4SLinus Torvalds * Description: Determine the phase and call the appropriate function. 39981da177e4SLinus Torvalds * 39991da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 40001da177e4SLinus Torvalds 4001d63a4cccSAlexey Dobriyan static void FPT_phaseDecode(unsigned long p_port, unsigned char p_card) 40021da177e4SLinus Torvalds { 40031da177e4SLinus Torvalds unsigned char phase_ref; 4004d63a4cccSAlexey Dobriyan void (*phase) (unsigned long, unsigned char); 40051da177e4SLinus Torvalds 40061da177e4SLinus Torvalds DISABLE_AUTO(p_port); 40071da177e4SLinus Torvalds 40085c04a7b8SAlexey Dobriyan phase_ref = 40095c04a7b8SAlexey Dobriyan (unsigned char)(RD_HARPOON(p_port + hp_scsisig) & S_SCSI_PHZ); 40101da177e4SLinus Torvalds 401147b5d69cSJames Bottomley phase = FPT_s_PhaseTbl[phase_ref]; 40121da177e4SLinus Torvalds 40131da177e4SLinus Torvalds (*phase) (p_port, p_card); /* Call the correct phase func */ 40141da177e4SLinus Torvalds } 40151da177e4SLinus Torvalds 40161da177e4SLinus Torvalds /*--------------------------------------------------------------------- 40171da177e4SLinus Torvalds * 40181da177e4SLinus Torvalds * Function: Data Out Phase 40191da177e4SLinus Torvalds * 40201da177e4SLinus Torvalds * Description: Start up both the BusMaster and Xbow. 40211da177e4SLinus Torvalds * 40221da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 40231da177e4SLinus Torvalds 4024d63a4cccSAlexey Dobriyan static void FPT_phaseDataOut(unsigned long port, unsigned char p_card) 40251da177e4SLinus Torvalds { 40261da177e4SLinus Torvalds 402769eb2ea4SAlexey Dobriyan struct sccb *currSCCB; 40281da177e4SLinus Torvalds 402947b5d69cSJames Bottomley currSCCB = FPT_BL_Card[p_card].currentSCCB; 40305c04a7b8SAlexey Dobriyan if (currSCCB == NULL) { 40311da177e4SLinus Torvalds return; /* Exit if No SCCB record */ 40321da177e4SLinus Torvalds } 40331da177e4SLinus Torvalds 40341da177e4SLinus Torvalds currSCCB->Sccb_scsistat = DATA_OUT_ST; 40351da177e4SLinus Torvalds currSCCB->Sccb_XferState &= ~(F_HOST_XFER_DIR | F_NO_DATA_YET); 40361da177e4SLinus Torvalds 40371da177e4SLinus Torvalds WR_HARPOON(port + hp_portctrl_0, SCSI_PORT); 40381da177e4SLinus Torvalds 40391da177e4SLinus Torvalds WRW_HARPOON((port + hp_intstat), XFER_CNT_0); 40401da177e4SLinus Torvalds 40411da177e4SLinus Torvalds WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START)); 40421da177e4SLinus Torvalds 404347b5d69cSJames Bottomley FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]); 40441da177e4SLinus Torvalds 40451da177e4SLinus Torvalds if (currSCCB->Sccb_XferCnt == 0) { 40461da177e4SLinus Torvalds 40471da177e4SLinus Torvalds if ((currSCCB->ControlByte & SCCB_DATA_XFER_OUT) && 40481da177e4SLinus Torvalds (currSCCB->HostStatus == SCCB_COMPLETE)) 40491da177e4SLinus Torvalds currSCCB->HostStatus = SCCB_DATA_OVER_RUN; 40501da177e4SLinus Torvalds 405147b5d69cSJames Bottomley FPT_sxfrp(port, p_card); 40521da177e4SLinus Torvalds if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET))) 405347b5d69cSJames Bottomley FPT_phaseDecode(port, p_card); 40541da177e4SLinus Torvalds } 40551da177e4SLinus Torvalds } 40561da177e4SLinus Torvalds 40571da177e4SLinus Torvalds /*--------------------------------------------------------------------- 40581da177e4SLinus Torvalds * 40591da177e4SLinus Torvalds * Function: Data In Phase 40601da177e4SLinus Torvalds * 40611da177e4SLinus Torvalds * Description: Startup the BusMaster and the XBOW. 40621da177e4SLinus Torvalds * 40631da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 40641da177e4SLinus Torvalds 4065d63a4cccSAlexey Dobriyan static void FPT_phaseDataIn(unsigned long port, unsigned char p_card) 40661da177e4SLinus Torvalds { 40671da177e4SLinus Torvalds 406869eb2ea4SAlexey Dobriyan struct sccb *currSCCB; 40691da177e4SLinus Torvalds 407047b5d69cSJames Bottomley currSCCB = FPT_BL_Card[p_card].currentSCCB; 40711da177e4SLinus Torvalds 40725c04a7b8SAlexey Dobriyan if (currSCCB == NULL) { 40731da177e4SLinus Torvalds return; /* Exit if No SCCB record */ 40741da177e4SLinus Torvalds } 40751da177e4SLinus Torvalds 40761da177e4SLinus Torvalds currSCCB->Sccb_scsistat = DATA_IN_ST; 40771da177e4SLinus Torvalds currSCCB->Sccb_XferState |= F_HOST_XFER_DIR; 40781da177e4SLinus Torvalds currSCCB->Sccb_XferState &= ~F_NO_DATA_YET; 40791da177e4SLinus Torvalds 40801da177e4SLinus Torvalds WR_HARPOON(port + hp_portctrl_0, SCSI_PORT); 40811da177e4SLinus Torvalds 40821da177e4SLinus Torvalds WRW_HARPOON((port + hp_intstat), XFER_CNT_0); 40831da177e4SLinus Torvalds 40841da177e4SLinus Torvalds WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START)); 40851da177e4SLinus Torvalds 408647b5d69cSJames Bottomley FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]); 40871da177e4SLinus Torvalds 40881da177e4SLinus Torvalds if (currSCCB->Sccb_XferCnt == 0) { 40891da177e4SLinus Torvalds 40901da177e4SLinus Torvalds if ((currSCCB->ControlByte & SCCB_DATA_XFER_IN) && 40911da177e4SLinus Torvalds (currSCCB->HostStatus == SCCB_COMPLETE)) 40921da177e4SLinus Torvalds currSCCB->HostStatus = SCCB_DATA_OVER_RUN; 40931da177e4SLinus Torvalds 409447b5d69cSJames Bottomley FPT_sxfrp(port, p_card); 40951da177e4SLinus Torvalds if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET))) 409647b5d69cSJames Bottomley FPT_phaseDecode(port, p_card); 40971da177e4SLinus Torvalds 40981da177e4SLinus Torvalds } 40991da177e4SLinus Torvalds } 41001da177e4SLinus Torvalds 41011da177e4SLinus Torvalds /*--------------------------------------------------------------------- 41021da177e4SLinus Torvalds * 41031da177e4SLinus Torvalds * Function: Command Phase 41041da177e4SLinus Torvalds * 41051da177e4SLinus Torvalds * Description: Load the CDB into the automation and start it up. 41061da177e4SLinus Torvalds * 41071da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 41081da177e4SLinus Torvalds 4109d63a4cccSAlexey Dobriyan static void FPT_phaseCommand(unsigned long p_port, unsigned char p_card) 41101da177e4SLinus Torvalds { 411169eb2ea4SAlexey Dobriyan struct sccb *currSCCB; 4112d63a4cccSAlexey Dobriyan unsigned long cdb_reg; 4113db038cf8SAlexey Dobriyan unsigned char i; 41141da177e4SLinus Torvalds 411547b5d69cSJames Bottomley currSCCB = FPT_BL_Card[p_card].currentSCCB; 41161da177e4SLinus Torvalds 41171da177e4SLinus Torvalds if (currSCCB->OperationCode == RESET_COMMAND) { 41181da177e4SLinus Torvalds 41191da177e4SLinus Torvalds currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL; 41201da177e4SLinus Torvalds currSCCB->CdbLength = SIX_BYTE_CMD; 41211da177e4SLinus Torvalds } 41221da177e4SLinus Torvalds 41231da177e4SLinus Torvalds WR_HARPOON(p_port + hp_scsisig, 0x00); 41241da177e4SLinus Torvalds 41251da177e4SLinus Torvalds ARAM_ACCESS(p_port); 41261da177e4SLinus Torvalds 41271da177e4SLinus Torvalds cdb_reg = p_port + CMD_STRT; 41281da177e4SLinus Torvalds 41291da177e4SLinus Torvalds for (i = 0; i < currSCCB->CdbLength; i++) { 41301da177e4SLinus Torvalds 41311da177e4SLinus Torvalds if (currSCCB->OperationCode == RESET_COMMAND) 41321da177e4SLinus Torvalds 41331da177e4SLinus Torvalds WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + 0x00)); 41341da177e4SLinus Torvalds 41351da177e4SLinus Torvalds else 41365c04a7b8SAlexey Dobriyan WRW_HARPOON(cdb_reg, 41375c04a7b8SAlexey Dobriyan (MPM_OP + ACOMMAND + currSCCB->Cdb[i])); 41381da177e4SLinus Torvalds cdb_reg += 2; 41391da177e4SLinus Torvalds } 41401da177e4SLinus Torvalds 41411da177e4SLinus Torvalds if (currSCCB->CdbLength != TWELVE_BYTE_CMD) 41421da177e4SLinus Torvalds WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP)); 41431da177e4SLinus Torvalds 41441da177e4SLinus Torvalds WR_HARPOON(p_port + hp_portctrl_0, (SCSI_PORT)); 41451da177e4SLinus Torvalds 41461da177e4SLinus Torvalds currSCCB->Sccb_scsistat = COMMAND_ST; 41471da177e4SLinus Torvalds 41481da177e4SLinus Torvalds WR_HARPOON(p_port + hp_autostart_3, (AUTO_IMMED | CMD_ONLY_STRT)); 41491da177e4SLinus Torvalds SGRAM_ACCESS(p_port); 41501da177e4SLinus Torvalds } 41511da177e4SLinus Torvalds 41521da177e4SLinus Torvalds /*--------------------------------------------------------------------- 41531da177e4SLinus Torvalds * 41541da177e4SLinus Torvalds * Function: Status phase 41551da177e4SLinus Torvalds * 41561da177e4SLinus Torvalds * Description: Bring in the status and command complete message bytes 41571da177e4SLinus Torvalds * 41581da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 41591da177e4SLinus Torvalds 4160d63a4cccSAlexey Dobriyan static void FPT_phaseStatus(unsigned long port, unsigned char p_card) 41611da177e4SLinus Torvalds { 41621da177e4SLinus Torvalds /* Start-up the automation to finish off this command and let the 41631da177e4SLinus Torvalds isr handle the interrupt for command complete when it comes in. 41641da177e4SLinus Torvalds We could wait here for the interrupt to be generated? 41651da177e4SLinus Torvalds */ 41661da177e4SLinus Torvalds 41671da177e4SLinus Torvalds WR_HARPOON(port + hp_scsisig, 0x00); 41681da177e4SLinus Torvalds 41691da177e4SLinus Torvalds WR_HARPOON(port + hp_autostart_0, (AUTO_IMMED + END_DATA_START)); 41701da177e4SLinus Torvalds } 41711da177e4SLinus Torvalds 41721da177e4SLinus Torvalds /*--------------------------------------------------------------------- 41731da177e4SLinus Torvalds * 41741da177e4SLinus Torvalds * Function: Phase Message Out 41751da177e4SLinus Torvalds * 41761da177e4SLinus Torvalds * Description: Send out our message (if we have one) and handle whatever 41771da177e4SLinus Torvalds * else is involed. 41781da177e4SLinus Torvalds * 41791da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 41801da177e4SLinus Torvalds 4181d63a4cccSAlexey Dobriyan static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card) 41821da177e4SLinus Torvalds { 4183db038cf8SAlexey Dobriyan unsigned char message, scsiID; 418469eb2ea4SAlexey Dobriyan struct sccb *currSCCB; 4185f31dc0cdSAlexey Dobriyan struct sccb_mgr_tar_info *currTar_Info; 41861da177e4SLinus Torvalds 418747b5d69cSJames Bottomley currSCCB = FPT_BL_Card[p_card].currentSCCB; 41881da177e4SLinus Torvalds 41891da177e4SLinus Torvalds if (currSCCB != NULL) { 41901da177e4SLinus Torvalds 41911da177e4SLinus Torvalds message = currSCCB->Sccb_scsimsg; 41921da177e4SLinus Torvalds scsiID = currSCCB->TargID; 41931da177e4SLinus Torvalds 41945c04a7b8SAlexey Dobriyan if (message == SMDEV_RESET) { 41951da177e4SLinus Torvalds 419647b5d69cSJames Bottomley currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID]; 41971da177e4SLinus Torvalds currTar_Info->TarSyncCtrl = 0; 419847b5d69cSJames Bottomley FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info); 41991da177e4SLinus Torvalds 42005c04a7b8SAlexey Dobriyan if (FPT_sccbMgrTbl[p_card][scsiID]. 42015c04a7b8SAlexey Dobriyan TarEEValue & EE_SYNC_MASK) { 42021da177e4SLinus Torvalds 42035c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][scsiID].TarStatus &= 42045c04a7b8SAlexey Dobriyan ~TAR_SYNC_MASK; 42051da177e4SLinus Torvalds 42061da177e4SLinus Torvalds } 42071da177e4SLinus Torvalds 42085c04a7b8SAlexey Dobriyan if (FPT_sccbMgrTbl[p_card][scsiID]. 42095c04a7b8SAlexey Dobriyan TarEEValue & EE_WIDE_SCSI) { 42101da177e4SLinus Torvalds 42115c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][scsiID].TarStatus &= 42125c04a7b8SAlexey Dobriyan ~TAR_WIDE_MASK; 42131da177e4SLinus Torvalds } 42141da177e4SLinus Torvalds 421547b5d69cSJames Bottomley FPT_queueFlushSccb(p_card, SCCB_COMPLETE); 421647b5d69cSJames Bottomley FPT_SccbMgrTableInitTarget(p_card, scsiID); 42175c04a7b8SAlexey Dobriyan } else if (currSCCB->Sccb_scsistat == ABORT_ST) { 42181da177e4SLinus Torvalds currSCCB->HostStatus = SCCB_COMPLETE; 42195c04a7b8SAlexey Dobriyan if (FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] != 42205c04a7b8SAlexey Dobriyan NULL) { 42215c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card].discQ_Tbl[currSCCB-> 42225c04a7b8SAlexey Dobriyan Sccb_tag] = NULL; 422347b5d69cSJames Bottomley FPT_sccbMgrTbl[p_card][scsiID].TarTagQ_Cnt--; 42241da177e4SLinus Torvalds } 42251da177e4SLinus Torvalds 42261da177e4SLinus Torvalds } 42271da177e4SLinus Torvalds 42285c04a7b8SAlexey Dobriyan else if (currSCCB->Sccb_scsistat < COMMAND_ST) { 42291da177e4SLinus Torvalds 42305c04a7b8SAlexey Dobriyan if (message == SMNO_OP) { 42311da177e4SLinus Torvalds currSCCB->Sccb_MGRFlags |= F_DEV_SELECTED; 42321da177e4SLinus Torvalds 423347b5d69cSJames Bottomley FPT_ssel(port, p_card); 42341da177e4SLinus Torvalds return; 42351da177e4SLinus Torvalds } 42365c04a7b8SAlexey Dobriyan } else { 42371da177e4SLinus Torvalds 42381da177e4SLinus Torvalds if (message == SMABORT) 42391da177e4SLinus Torvalds 424047b5d69cSJames Bottomley FPT_queueFlushSccb(p_card, SCCB_COMPLETE); 42411da177e4SLinus Torvalds } 42421da177e4SLinus Torvalds 42435c04a7b8SAlexey Dobriyan } else { 42441da177e4SLinus Torvalds message = SMABORT; 42451da177e4SLinus Torvalds } 42461da177e4SLinus Torvalds 42471da177e4SLinus Torvalds WRW_HARPOON((port + hp_intstat), (BUS_FREE | PHASE | XFER_CNT_0)); 42481da177e4SLinus Torvalds 42491da177e4SLinus Torvalds WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN); 42501da177e4SLinus Torvalds 42511da177e4SLinus Torvalds WR_HARPOON(port + hp_scsidata_0, message); 42521da177e4SLinus Torvalds 42531da177e4SLinus Torvalds WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH)); 42541da177e4SLinus Torvalds 42551da177e4SLinus Torvalds ACCEPT_MSG(port); 42561da177e4SLinus Torvalds 42571da177e4SLinus Torvalds WR_HARPOON(port + hp_portctrl_0, 0x00); 42581da177e4SLinus Torvalds 42591da177e4SLinus Torvalds if ((message == SMABORT) || (message == SMDEV_RESET) || 42605c04a7b8SAlexey Dobriyan (message == SMABORT_TAG)) { 42611da177e4SLinus Torvalds 42625c04a7b8SAlexey Dobriyan while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | PHASE))) { 42635c04a7b8SAlexey Dobriyan } 42641da177e4SLinus Torvalds 42655c04a7b8SAlexey Dobriyan if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) { 42661da177e4SLinus Torvalds WRW_HARPOON((port + hp_intstat), BUS_FREE); 42671da177e4SLinus Torvalds 42685c04a7b8SAlexey Dobriyan if (currSCCB != NULL) { 42691da177e4SLinus Torvalds 42705c04a7b8SAlexey Dobriyan if ((FPT_BL_Card[p_card]. 42715c04a7b8SAlexey Dobriyan globalFlags & F_CONLUN_IO) 42725c04a7b8SAlexey Dobriyan && 42735c04a7b8SAlexey Dobriyan ((FPT_sccbMgrTbl[p_card][currSCCB->TargID]. 42745c04a7b8SAlexey Dobriyan TarStatus & TAR_TAG_Q_MASK) != 42755c04a7b8SAlexey Dobriyan TAG_Q_TRYING)) 42765c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][currSCCB-> 42775c04a7b8SAlexey Dobriyan TargID]. 42785c04a7b8SAlexey Dobriyan TarLUNBusy[currSCCB->Lun] = 0; 42791da177e4SLinus Torvalds else 42805c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][currSCCB-> 42815c04a7b8SAlexey Dobriyan TargID]. 42825c04a7b8SAlexey Dobriyan TarLUNBusy[0] = 0; 42831da177e4SLinus Torvalds 42845c04a7b8SAlexey Dobriyan FPT_queueCmdComplete(&FPT_BL_Card[p_card], 42855c04a7b8SAlexey Dobriyan currSCCB, p_card); 42861da177e4SLinus Torvalds } 42871da177e4SLinus Torvalds 42885c04a7b8SAlexey Dobriyan else { 42895c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card].globalFlags |= 42905c04a7b8SAlexey Dobriyan F_NEW_SCCB_CMD; 42911da177e4SLinus Torvalds } 42921da177e4SLinus Torvalds } 42931da177e4SLinus Torvalds 42945c04a7b8SAlexey Dobriyan else { 42951da177e4SLinus Torvalds 429647b5d69cSJames Bottomley FPT_sxfrp(port, p_card); 42971da177e4SLinus Torvalds } 42981da177e4SLinus Torvalds } 42991da177e4SLinus Torvalds 43005c04a7b8SAlexey Dobriyan else { 43011da177e4SLinus Torvalds 43025c04a7b8SAlexey Dobriyan if (message == SMPARITY) { 43031da177e4SLinus Torvalds currSCCB->Sccb_scsimsg = SMNO_OP; 43045c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_autostart_1, 43055c04a7b8SAlexey Dobriyan (AUTO_IMMED + DISCONNECT_START)); 43065c04a7b8SAlexey Dobriyan } else { 430747b5d69cSJames Bottomley FPT_sxfrp(port, p_card); 43081da177e4SLinus Torvalds } 43091da177e4SLinus Torvalds } 43101da177e4SLinus Torvalds } 43111da177e4SLinus Torvalds 43121da177e4SLinus Torvalds /*--------------------------------------------------------------------- 43131da177e4SLinus Torvalds * 43141da177e4SLinus Torvalds * Function: Message In phase 43151da177e4SLinus Torvalds * 43161da177e4SLinus Torvalds * Description: Bring in the message and determine what to do with it. 43171da177e4SLinus Torvalds * 43181da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 43191da177e4SLinus Torvalds 4320d63a4cccSAlexey Dobriyan static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card) 43211da177e4SLinus Torvalds { 4322db038cf8SAlexey Dobriyan unsigned char message; 432369eb2ea4SAlexey Dobriyan struct sccb *currSCCB; 43241da177e4SLinus Torvalds 432547b5d69cSJames Bottomley currSCCB = FPT_BL_Card[p_card].currentSCCB; 43261da177e4SLinus Torvalds 43275c04a7b8SAlexey Dobriyan if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) { 43281da177e4SLinus Torvalds 432947b5d69cSJames Bottomley FPT_phaseChkFifo(port, p_card); 43301da177e4SLinus Torvalds } 43311da177e4SLinus Torvalds 43321da177e4SLinus Torvalds message = RD_HARPOON(port + hp_scsidata_0); 43335c04a7b8SAlexey Dobriyan if ((message == SMDISC) || (message == SMSAVE_DATA_PTR)) { 43341da177e4SLinus Torvalds 43355c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_autostart_1, 43365c04a7b8SAlexey Dobriyan (AUTO_IMMED + END_DATA_START)); 43371da177e4SLinus Torvalds 43381da177e4SLinus Torvalds } 43391da177e4SLinus Torvalds 43405c04a7b8SAlexey Dobriyan else { 43411da177e4SLinus Torvalds 434247b5d69cSJames Bottomley message = FPT_sfm(port, currSCCB); 43435c04a7b8SAlexey Dobriyan if (message) { 43441da177e4SLinus Torvalds 434547b5d69cSJames Bottomley FPT_sdecm(message, port, p_card); 43461da177e4SLinus Torvalds 43475c04a7b8SAlexey Dobriyan } else { 43481da177e4SLinus Torvalds if (currSCCB->Sccb_scsimsg != SMPARITY) 43491da177e4SLinus Torvalds ACCEPT_MSG(port); 43505c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_autostart_1, 43515c04a7b8SAlexey Dobriyan (AUTO_IMMED + DISCONNECT_START)); 43521da177e4SLinus Torvalds } 43531da177e4SLinus Torvalds } 43541da177e4SLinus Torvalds 43551da177e4SLinus Torvalds } 43561da177e4SLinus Torvalds 43571da177e4SLinus Torvalds /*--------------------------------------------------------------------- 43581da177e4SLinus Torvalds * 43591da177e4SLinus Torvalds * Function: Illegal phase 43601da177e4SLinus Torvalds * 43611da177e4SLinus Torvalds * Description: Target switched to some illegal phase, so all we can do 43621da177e4SLinus Torvalds * is report an error back to the host (if that is possible) 43631da177e4SLinus Torvalds * and send an ABORT message to the misbehaving target. 43641da177e4SLinus Torvalds * 43651da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 43661da177e4SLinus Torvalds 4367d63a4cccSAlexey Dobriyan static void FPT_phaseIllegal(unsigned long port, unsigned char p_card) 43681da177e4SLinus Torvalds { 436969eb2ea4SAlexey Dobriyan struct sccb *currSCCB; 43701da177e4SLinus Torvalds 437147b5d69cSJames Bottomley currSCCB = FPT_BL_Card[p_card].currentSCCB; 43721da177e4SLinus Torvalds 43731da177e4SLinus Torvalds WR_HARPOON(port + hp_scsisig, RD_HARPOON(port + hp_scsisig)); 43741da177e4SLinus Torvalds if (currSCCB != NULL) { 43751da177e4SLinus Torvalds 43761da177e4SLinus Torvalds currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL; 43771da177e4SLinus Torvalds currSCCB->Sccb_scsistat = ABORT_ST; 43781da177e4SLinus Torvalds currSCCB->Sccb_scsimsg = SMABORT; 43791da177e4SLinus Torvalds } 43801da177e4SLinus Torvalds 43811da177e4SLinus Torvalds ACCEPT_MSG_ATN(port); 43821da177e4SLinus Torvalds } 43831da177e4SLinus Torvalds 43841da177e4SLinus Torvalds /*--------------------------------------------------------------------- 43851da177e4SLinus Torvalds * 43861da177e4SLinus Torvalds * Function: Phase Check FIFO 43871da177e4SLinus Torvalds * 43881da177e4SLinus Torvalds * Description: Make sure data has been flushed from both FIFOs and abort 43891da177e4SLinus Torvalds * the operations if necessary. 43901da177e4SLinus Torvalds * 43911da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 43921da177e4SLinus Torvalds 4393d63a4cccSAlexey Dobriyan static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card) 43941da177e4SLinus Torvalds { 4395d63a4cccSAlexey Dobriyan unsigned long xfercnt; 439669eb2ea4SAlexey Dobriyan struct sccb *currSCCB; 43971da177e4SLinus Torvalds 439847b5d69cSJames Bottomley currSCCB = FPT_BL_Card[p_card].currentSCCB; 43991da177e4SLinus Torvalds 44005c04a7b8SAlexey Dobriyan if (currSCCB->Sccb_scsistat == DATA_IN_ST) { 44011da177e4SLinus Torvalds 44021da177e4SLinus Torvalds while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) && 44035c04a7b8SAlexey Dobriyan (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)) { 44045c04a7b8SAlexey Dobriyan } 44051da177e4SLinus Torvalds 44065c04a7b8SAlexey Dobriyan if (!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) { 44071da177e4SLinus Torvalds currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt; 44081da177e4SLinus Torvalds 44091da177e4SLinus Torvalds currSCCB->Sccb_XferCnt = 0; 44101da177e4SLinus Torvalds 44111da177e4SLinus Torvalds if ((RDW_HARPOON((port + hp_intstat)) & PARITY) && 44125c04a7b8SAlexey Dobriyan (currSCCB->HostStatus == SCCB_COMPLETE)) { 44131da177e4SLinus Torvalds currSCCB->HostStatus = SCCB_PARITY_ERR; 44141da177e4SLinus Torvalds WRW_HARPOON((port + hp_intstat), PARITY); 44151da177e4SLinus Torvalds } 44161da177e4SLinus Torvalds 441747b5d69cSJames Bottomley FPT_hostDataXferAbort(port, p_card, currSCCB); 44181da177e4SLinus Torvalds 441947b5d69cSJames Bottomley FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]); 44201da177e4SLinus Torvalds 44215c04a7b8SAlexey Dobriyan while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) 44225c04a7b8SAlexey Dobriyan && (RD_HARPOON(port + hp_ext_status) & 44235c04a7b8SAlexey Dobriyan BM_CMD_BUSY)) { 44245c04a7b8SAlexey Dobriyan } 44251da177e4SLinus Torvalds 44261da177e4SLinus Torvalds } 44275c04a7b8SAlexey Dobriyan } 44281da177e4SLinus Torvalds 44295c04a7b8SAlexey Dobriyan /*End Data In specific code. */ 44301da177e4SLinus Torvalds GET_XFER_CNT(port, xfercnt); 44311da177e4SLinus Torvalds 44321da177e4SLinus Torvalds WR_HARPOON(port + hp_xfercnt_0, 0x00); 44331da177e4SLinus Torvalds 44341da177e4SLinus Torvalds WR_HARPOON(port + hp_portctrl_0, 0x00); 44351da177e4SLinus Torvalds 44361da177e4SLinus Torvalds currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - xfercnt); 44371da177e4SLinus Torvalds 44381da177e4SLinus Torvalds currSCCB->Sccb_XferCnt = xfercnt; 44391da177e4SLinus Torvalds 44401da177e4SLinus Torvalds if ((RDW_HARPOON((port + hp_intstat)) & PARITY) && 44411da177e4SLinus Torvalds (currSCCB->HostStatus == SCCB_COMPLETE)) { 44421da177e4SLinus Torvalds 44431da177e4SLinus Torvalds currSCCB->HostStatus = SCCB_PARITY_ERR; 44441da177e4SLinus Torvalds WRW_HARPOON((port + hp_intstat), PARITY); 44451da177e4SLinus Torvalds } 44461da177e4SLinus Torvalds 444747b5d69cSJames Bottomley FPT_hostDataXferAbort(port, p_card, currSCCB); 44481da177e4SLinus Torvalds 44491da177e4SLinus Torvalds WR_HARPOON(port + hp_fifowrite, 0x00); 44501da177e4SLinus Torvalds WR_HARPOON(port + hp_fiforead, 0x00); 44511da177e4SLinus Torvalds WR_HARPOON(port + hp_xferstat, 0x00); 44521da177e4SLinus Torvalds 44531da177e4SLinus Torvalds WRW_HARPOON((port + hp_intstat), XFER_CNT_0); 44541da177e4SLinus Torvalds } 44551da177e4SLinus Torvalds 44561da177e4SLinus Torvalds /*--------------------------------------------------------------------- 44571da177e4SLinus Torvalds * 44581da177e4SLinus Torvalds * Function: Phase Bus Free 44591da177e4SLinus Torvalds * 44601da177e4SLinus Torvalds * Description: We just went bus free so figure out if it was 44611da177e4SLinus Torvalds * because of command complete or from a disconnect. 44621da177e4SLinus Torvalds * 44631da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 4464d63a4cccSAlexey Dobriyan static void FPT_phaseBusFree(unsigned long port, unsigned char p_card) 44651da177e4SLinus Torvalds { 446669eb2ea4SAlexey Dobriyan struct sccb *currSCCB; 44671da177e4SLinus Torvalds 446847b5d69cSJames Bottomley currSCCB = FPT_BL_Card[p_card].currentSCCB; 44691da177e4SLinus Torvalds 44705c04a7b8SAlexey Dobriyan if (currSCCB != NULL) { 44711da177e4SLinus Torvalds 44721da177e4SLinus Torvalds DISABLE_AUTO(port); 44731da177e4SLinus Torvalds 44745c04a7b8SAlexey Dobriyan if (currSCCB->OperationCode == RESET_COMMAND) { 44751da177e4SLinus Torvalds 447647b5d69cSJames Bottomley if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) && 44775c04a7b8SAlexey Dobriyan ((FPT_sccbMgrTbl[p_card][currSCCB->TargID]. 44785c04a7b8SAlexey Dobriyan TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) 44795c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][currSCCB->TargID]. 44805c04a7b8SAlexey Dobriyan TarLUNBusy[currSCCB->Lun] = 0; 44811da177e4SLinus Torvalds else 44825c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][currSCCB->TargID]. 44835c04a7b8SAlexey Dobriyan TarLUNBusy[0] = 0; 44841da177e4SLinus Torvalds 44855c04a7b8SAlexey Dobriyan FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, 44865c04a7b8SAlexey Dobriyan p_card); 44871da177e4SLinus Torvalds 448847b5d69cSJames Bottomley FPT_queueSearchSelect(&FPT_BL_Card[p_card], p_card); 44891da177e4SLinus Torvalds 44901da177e4SLinus Torvalds } 44911da177e4SLinus Torvalds 44925c04a7b8SAlexey Dobriyan else if (currSCCB->Sccb_scsistat == SELECT_SN_ST) { 449347b5d69cSJames Bottomley FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |= 4494db038cf8SAlexey Dobriyan (unsigned char)SYNC_SUPPORTED; 44955c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= 44965c04a7b8SAlexey Dobriyan ~EE_SYNC_MASK; 44971da177e4SLinus Torvalds } 44981da177e4SLinus Torvalds 44995c04a7b8SAlexey Dobriyan else if (currSCCB->Sccb_scsistat == SELECT_WN_ST) { 450047b5d69cSJames Bottomley FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus = 450147b5d69cSJames Bottomley (FPT_sccbMgrTbl[p_card][currSCCB->TargID]. 45021da177e4SLinus Torvalds TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED; 45031da177e4SLinus Torvalds 45045c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= 45055c04a7b8SAlexey Dobriyan ~EE_WIDE_SCSI; 45061da177e4SLinus Torvalds } 45071da177e4SLinus Torvalds 45085c04a7b8SAlexey Dobriyan else if (currSCCB->Sccb_scsistat == SELECT_Q_ST) { 45091da177e4SLinus Torvalds /* Make sure this is not a phony BUS_FREE. If we were 45101da177e4SLinus Torvalds reselected or if BUSY is NOT on then this is a 45111da177e4SLinus Torvalds valid BUS FREE. SRR Wednesday, 5/10/1995. */ 45121da177e4SLinus Torvalds 45131da177e4SLinus Torvalds if ((!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) || 45145c04a7b8SAlexey Dobriyan (RDW_HARPOON((port + hp_intstat)) & RSEL)) { 45155c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][currSCCB->TargID]. 45165c04a7b8SAlexey Dobriyan TarStatus &= ~TAR_TAG_Q_MASK; 45175c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][currSCCB->TargID]. 45185c04a7b8SAlexey Dobriyan TarStatus |= TAG_Q_REJECT; 45191da177e4SLinus Torvalds } 45201da177e4SLinus Torvalds 45215c04a7b8SAlexey Dobriyan else { 45221da177e4SLinus Torvalds return; 45231da177e4SLinus Torvalds } 45241da177e4SLinus Torvalds } 45251da177e4SLinus Torvalds 45265c04a7b8SAlexey Dobriyan else { 45271da177e4SLinus Torvalds 45281da177e4SLinus Torvalds currSCCB->Sccb_scsistat = BUS_FREE_ST; 45291da177e4SLinus Torvalds 45305c04a7b8SAlexey Dobriyan if (!currSCCB->HostStatus) { 45311da177e4SLinus Torvalds currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL; 45321da177e4SLinus Torvalds } 45331da177e4SLinus Torvalds 453447b5d69cSJames Bottomley if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) && 45355c04a7b8SAlexey Dobriyan ((FPT_sccbMgrTbl[p_card][currSCCB->TargID]. 45365c04a7b8SAlexey Dobriyan TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) 45375c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][currSCCB->TargID]. 45385c04a7b8SAlexey Dobriyan TarLUNBusy[currSCCB->Lun] = 0; 45391da177e4SLinus Torvalds else 45405c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][currSCCB->TargID]. 45415c04a7b8SAlexey Dobriyan TarLUNBusy[0] = 0; 45421da177e4SLinus Torvalds 45435c04a7b8SAlexey Dobriyan FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, 45445c04a7b8SAlexey Dobriyan p_card); 45451da177e4SLinus Torvalds return; 45461da177e4SLinus Torvalds } 45471da177e4SLinus Torvalds 454847b5d69cSJames Bottomley FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD; 45491da177e4SLinus Torvalds 45501da177e4SLinus Torvalds } /*end if !=null */ 45511da177e4SLinus Torvalds } 45521da177e4SLinus Torvalds 45531da177e4SLinus Torvalds /*--------------------------------------------------------------------- 45541da177e4SLinus Torvalds * 45551da177e4SLinus Torvalds * Function: Auto Load Default Map 45561da177e4SLinus Torvalds * 45571da177e4SLinus Torvalds * Description: Load the Automation RAM with the defualt map values. 45581da177e4SLinus Torvalds * 45591da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 4560d63a4cccSAlexey Dobriyan static void FPT_autoLoadDefaultMap(unsigned long p_port) 45611da177e4SLinus Torvalds { 4562d63a4cccSAlexey Dobriyan unsigned long map_addr; 45631da177e4SLinus Torvalds 45641da177e4SLinus Torvalds ARAM_ACCESS(p_port); 45651da177e4SLinus Torvalds map_addr = p_port + hp_aramBase; 45661da177e4SLinus Torvalds 45671da177e4SLinus Torvalds WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0xC0)); /*ID MESSAGE */ 45681da177e4SLinus Torvalds map_addr += 2; 45691da177e4SLinus Torvalds WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x20)); /*SIMPLE TAG QUEUEING MSG */ 45701da177e4SLinus Torvalds map_addr += 2; 45711da177e4SLinus Torvalds WRW_HARPOON(map_addr, RAT_OP); /*RESET ATTENTION */ 45721da177e4SLinus Torvalds map_addr += 2; 45731da177e4SLinus Torvalds WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x00)); /*TAG ID MSG */ 45741da177e4SLinus Torvalds map_addr += 2; 45751da177e4SLinus Torvalds WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 0 */ 45761da177e4SLinus Torvalds map_addr += 2; 45771da177e4SLinus Torvalds WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 1 */ 45781da177e4SLinus Torvalds map_addr += 2; 45791da177e4SLinus Torvalds WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 2 */ 45801da177e4SLinus Torvalds map_addr += 2; 45811da177e4SLinus Torvalds WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 3 */ 45821da177e4SLinus Torvalds map_addr += 2; 45831da177e4SLinus Torvalds WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 4 */ 45841da177e4SLinus Torvalds map_addr += 2; 45851da177e4SLinus Torvalds WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 5 */ 45861da177e4SLinus Torvalds map_addr += 2; 45871da177e4SLinus Torvalds WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 6 */ 45881da177e4SLinus Torvalds map_addr += 2; 45891da177e4SLinus Torvalds WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 7 */ 45901da177e4SLinus Torvalds map_addr += 2; 45911da177e4SLinus Torvalds WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 8 */ 45921da177e4SLinus Torvalds map_addr += 2; 45931da177e4SLinus Torvalds WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 9 */ 45941da177e4SLinus Torvalds map_addr += 2; 45951da177e4SLinus Torvalds WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 10 */ 45961da177e4SLinus Torvalds map_addr += 2; 45971da177e4SLinus Torvalds WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 11 */ 45981da177e4SLinus Torvalds map_addr += 2; 45991da177e4SLinus Torvalds WRW_HARPOON(map_addr, (CPE_OP + ADATA_OUT + DINT)); /*JUMP IF DATA OUT */ 46001da177e4SLinus Torvalds map_addr += 2; 46011da177e4SLinus Torvalds WRW_HARPOON(map_addr, (TCB_OP + FIFO_0 + DI)); /*JUMP IF NO DATA IN FIFO */ 46021da177e4SLinus Torvalds map_addr += 2; /*This means AYNC DATA IN */ 46031da177e4SLinus Torvalds WRW_HARPOON(map_addr, (SSI_OP + SSI_IDO_STRT)); /*STOP AND INTERRUPT */ 46041da177e4SLinus Torvalds map_addr += 2; 46051da177e4SLinus Torvalds WRW_HARPOON(map_addr, (CPE_OP + ADATA_IN + DINT)); /*JUMP IF NOT DATA IN PHZ */ 46061da177e4SLinus Torvalds map_addr += 2; 46071da177e4SLinus Torvalds WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST)); /*IF NOT MSG IN CHECK 4 DATA IN */ 46081da177e4SLinus Torvalds map_addr += 2; 46091da177e4SLinus Torvalds WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x02)); /*SAVE DATA PTR MSG? */ 46101da177e4SLinus Torvalds map_addr += 2; 46111da177e4SLinus Torvalds WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + DC)); /*GO CHECK FOR DISCONNECT MSG */ 46121da177e4SLinus Torvalds map_addr += 2; 46131da177e4SLinus Torvalds WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR1)); /*SAVE DATA PTRS MSG */ 46141da177e4SLinus Torvalds map_addr += 2; 46151da177e4SLinus Torvalds WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST)); /*IF NOT MSG IN CHECK DATA IN */ 46161da177e4SLinus Torvalds map_addr += 2; 46171da177e4SLinus Torvalds WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x04)); /*DISCONNECT MSG? */ 46181da177e4SLinus Torvalds map_addr += 2; 46191da177e4SLinus Torvalds WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + UNKNWN)); /*UKNKNOWN MSG */ 46201da177e4SLinus Torvalds map_addr += 2; 46211da177e4SLinus Torvalds WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET)); /*XFER DISCONNECT MSG */ 46221da177e4SLinus Torvalds map_addr += 2; 46231da177e4SLinus Torvalds WRW_HARPOON(map_addr, (SSI_OP + SSI_ITAR_DISC)); /*STOP AND INTERRUPT */ 46241da177e4SLinus Torvalds map_addr += 2; 46251da177e4SLinus Torvalds WRW_HARPOON(map_addr, (CPN_OP + ASTATUS + UNKNWN)); /*JUMP IF NOT STATUS PHZ. */ 46261da177e4SLinus Torvalds map_addr += 2; 46271da177e4SLinus Torvalds WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR0)); /*GET STATUS BYTE */ 46281da177e4SLinus Torvalds map_addr += 2; 46291da177e4SLinus Torvalds WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + CC)); /*ERROR IF NOT MSG IN PHZ */ 46301da177e4SLinus Torvalds map_addr += 2; 46311da177e4SLinus Torvalds WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x00)); /*CHECK FOR CMD COMPLETE MSG. */ 46321da177e4SLinus Torvalds map_addr += 2; 46331da177e4SLinus Torvalds WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + CC)); /*ERROR IF NOT CMD COMPLETE MSG. */ 46341da177e4SLinus Torvalds map_addr += 2; 46351da177e4SLinus Torvalds WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET)); /*GET CMD COMPLETE MSG */ 46361da177e4SLinus Torvalds map_addr += 2; 46371da177e4SLinus Torvalds WRW_HARPOON(map_addr, (SSI_OP + SSI_ICMD_COMP)); /*END OF COMMAND */ 46381da177e4SLinus Torvalds map_addr += 2; 46391da177e4SLinus Torvalds 46401da177e4SLinus Torvalds WRW_HARPOON(map_addr, (SSI_OP + SSI_IUNKWN)); /*RECEIVED UNKNOWN MSG BYTE */ 46411da177e4SLinus Torvalds map_addr += 2; 46421da177e4SLinus Torvalds WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */ 46431da177e4SLinus Torvalds map_addr += 2; 46441da177e4SLinus Torvalds WRW_HARPOON(map_addr, (SSI_OP + SSI_ITICKLE)); /*BIOS Tickled the Mgr */ 46451da177e4SLinus Torvalds map_addr += 2; 46461da177e4SLinus Torvalds WRW_HARPOON(map_addr, (SSI_OP + SSI_IRFAIL)); /*EXPECTED ID/TAG MESSAGES AND */ 46471da177e4SLinus Torvalds map_addr += 2; /* DIDN'T GET ONE */ 46481da177e4SLinus Torvalds WRW_HARPOON(map_addr, (CRR_OP + AR3 + S_IDREG)); /* comp SCSI SEL ID & AR3 */ 46491da177e4SLinus Torvalds map_addr += 2; 46501da177e4SLinus Torvalds WRW_HARPOON(map_addr, (BRH_OP + EQUAL + 0x00)); /*SEL ID OK then Conti. */ 46511da177e4SLinus Torvalds map_addr += 2; 46521da177e4SLinus Torvalds WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */ 46531da177e4SLinus Torvalds 46541da177e4SLinus Torvalds SGRAM_ACCESS(p_port); 46551da177e4SLinus Torvalds } 46561da177e4SLinus Torvalds 46571da177e4SLinus Torvalds /*--------------------------------------------------------------------- 46581da177e4SLinus Torvalds * 46591da177e4SLinus Torvalds * Function: Auto Command Complete 46601da177e4SLinus Torvalds * 46611da177e4SLinus Torvalds * Description: Post command back to host and find another command 46621da177e4SLinus Torvalds * to execute. 46631da177e4SLinus Torvalds * 46641da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 46651da177e4SLinus Torvalds 4666d63a4cccSAlexey Dobriyan static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card) 46671da177e4SLinus Torvalds { 466869eb2ea4SAlexey Dobriyan struct sccb *currSCCB; 4669db038cf8SAlexey Dobriyan unsigned char status_byte; 46701da177e4SLinus Torvalds 467147b5d69cSJames Bottomley currSCCB = FPT_BL_Card[p_card].currentSCCB; 46721da177e4SLinus Torvalds 46731da177e4SLinus Torvalds status_byte = RD_HARPOON(p_port + hp_gp_reg_0); 46741da177e4SLinus Torvalds 467547b5d69cSJames Bottomley FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA = 0; 46761da177e4SLinus Torvalds 46771da177e4SLinus Torvalds if (status_byte != SSGOOD) { 46781da177e4SLinus Torvalds 46791da177e4SLinus Torvalds if (status_byte == SSQ_FULL) { 46801da177e4SLinus Torvalds 468147b5d69cSJames Bottomley if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) && 46825c04a7b8SAlexey Dobriyan ((FPT_sccbMgrTbl[p_card][currSCCB->TargID]. 46835c04a7b8SAlexey Dobriyan TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) { 46845c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][currSCCB->TargID]. 46855c04a7b8SAlexey Dobriyan TarLUNBusy[currSCCB->Lun] = 1; 468647b5d69cSJames Bottomley if (FPT_BL_Card[p_card].discQCount != 0) 468747b5d69cSJames Bottomley FPT_BL_Card[p_card].discQCount--; 46885c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card]. 46895c04a7b8SAlexey Dobriyan discQ_Tbl[FPT_sccbMgrTbl[p_card] 46905c04a7b8SAlexey Dobriyan [currSCCB->TargID]. 46915c04a7b8SAlexey Dobriyan LunDiscQ_Idx[currSCCB->Lun]] = 46925c04a7b8SAlexey Dobriyan NULL; 46935c04a7b8SAlexey Dobriyan } else { 46945c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][currSCCB->TargID]. 46955c04a7b8SAlexey Dobriyan TarLUNBusy[0] = 1; 46965c04a7b8SAlexey Dobriyan if (currSCCB->Sccb_tag) { 469747b5d69cSJames Bottomley if (FPT_BL_Card[p_card].discQCount != 0) 46985c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card]. 46995c04a7b8SAlexey Dobriyan discQCount--; 47005c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card].discQ_Tbl[currSCCB-> 47015c04a7b8SAlexey Dobriyan Sccb_tag] 47025c04a7b8SAlexey Dobriyan = NULL; 47035c04a7b8SAlexey Dobriyan } else { 470447b5d69cSJames Bottomley if (FPT_BL_Card[p_card].discQCount != 0) 47055c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card]. 47065c04a7b8SAlexey Dobriyan discQCount--; 47075c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card]. 47085c04a7b8SAlexey Dobriyan discQ_Tbl[FPT_sccbMgrTbl[p_card] 47095c04a7b8SAlexey Dobriyan [currSCCB->TargID]. 47105c04a7b8SAlexey Dobriyan LunDiscQ_Idx[0]] = NULL; 47111da177e4SLinus Torvalds } 47121da177e4SLinus Torvalds } 47131da177e4SLinus Torvalds 47141da177e4SLinus Torvalds currSCCB->Sccb_MGRFlags |= F_STATUSLOADED; 47151da177e4SLinus Torvalds 471647b5d69cSJames Bottomley FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card); 47171da177e4SLinus Torvalds 47181da177e4SLinus Torvalds return; 47191da177e4SLinus Torvalds } 47201da177e4SLinus Torvalds 47215c04a7b8SAlexey Dobriyan if (currSCCB->Sccb_scsistat == SELECT_SN_ST) { 472247b5d69cSJames Bottomley FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |= 4723db038cf8SAlexey Dobriyan (unsigned char)SYNC_SUPPORTED; 47241da177e4SLinus Torvalds 47255c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= 47265c04a7b8SAlexey Dobriyan ~EE_SYNC_MASK; 472747b5d69cSJames Bottomley FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD; 47281da177e4SLinus Torvalds 472947b5d69cSJames Bottomley if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) && 47305c04a7b8SAlexey Dobriyan ((FPT_sccbMgrTbl[p_card][currSCCB->TargID]. 47315c04a7b8SAlexey Dobriyan TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) { 47325c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][currSCCB->TargID]. 47335c04a7b8SAlexey Dobriyan TarLUNBusy[currSCCB->Lun] = 1; 473447b5d69cSJames Bottomley if (FPT_BL_Card[p_card].discQCount != 0) 473547b5d69cSJames Bottomley FPT_BL_Card[p_card].discQCount--; 47365c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card]. 47375c04a7b8SAlexey Dobriyan discQ_Tbl[FPT_sccbMgrTbl[p_card] 47385c04a7b8SAlexey Dobriyan [currSCCB->TargID]. 47395c04a7b8SAlexey Dobriyan LunDiscQ_Idx[currSCCB->Lun]] = 47405c04a7b8SAlexey Dobriyan NULL; 47415c04a7b8SAlexey Dobriyan } else { 47425c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][currSCCB->TargID]. 47435c04a7b8SAlexey Dobriyan TarLUNBusy[0] = 1; 47445c04a7b8SAlexey Dobriyan if (currSCCB->Sccb_tag) { 474547b5d69cSJames Bottomley if (FPT_BL_Card[p_card].discQCount != 0) 47465c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card]. 47475c04a7b8SAlexey Dobriyan discQCount--; 47485c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card].discQ_Tbl[currSCCB-> 47495c04a7b8SAlexey Dobriyan Sccb_tag] 47505c04a7b8SAlexey Dobriyan = NULL; 47515c04a7b8SAlexey Dobriyan } else { 475247b5d69cSJames Bottomley if (FPT_BL_Card[p_card].discQCount != 0) 47535c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card]. 47545c04a7b8SAlexey Dobriyan discQCount--; 47555c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card]. 47565c04a7b8SAlexey Dobriyan discQ_Tbl[FPT_sccbMgrTbl[p_card] 47575c04a7b8SAlexey Dobriyan [currSCCB->TargID]. 47585c04a7b8SAlexey Dobriyan LunDiscQ_Idx[0]] = NULL; 47591da177e4SLinus Torvalds } 47601da177e4SLinus Torvalds } 47611da177e4SLinus Torvalds return; 47621da177e4SLinus Torvalds 47631da177e4SLinus Torvalds } 47641da177e4SLinus Torvalds 47655c04a7b8SAlexey Dobriyan if (currSCCB->Sccb_scsistat == SELECT_WN_ST) { 47661da177e4SLinus Torvalds 476747b5d69cSJames Bottomley FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus = 476847b5d69cSJames Bottomley (FPT_sccbMgrTbl[p_card][currSCCB->TargID]. 47691da177e4SLinus Torvalds TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED; 47701da177e4SLinus Torvalds 47715c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &= 47725c04a7b8SAlexey Dobriyan ~EE_WIDE_SCSI; 477347b5d69cSJames Bottomley FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD; 47741da177e4SLinus Torvalds 477547b5d69cSJames Bottomley if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) && 47765c04a7b8SAlexey Dobriyan ((FPT_sccbMgrTbl[p_card][currSCCB->TargID]. 47775c04a7b8SAlexey Dobriyan TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) { 47785c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][currSCCB->TargID]. 47795c04a7b8SAlexey Dobriyan TarLUNBusy[currSCCB->Lun] = 1; 478047b5d69cSJames Bottomley if (FPT_BL_Card[p_card].discQCount != 0) 478147b5d69cSJames Bottomley FPT_BL_Card[p_card].discQCount--; 47825c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card]. 47835c04a7b8SAlexey Dobriyan discQ_Tbl[FPT_sccbMgrTbl[p_card] 47845c04a7b8SAlexey Dobriyan [currSCCB->TargID]. 47855c04a7b8SAlexey Dobriyan LunDiscQ_Idx[currSCCB->Lun]] = 47865c04a7b8SAlexey Dobriyan NULL; 47875c04a7b8SAlexey Dobriyan } else { 47885c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][currSCCB->TargID]. 47895c04a7b8SAlexey Dobriyan TarLUNBusy[0] = 1; 47905c04a7b8SAlexey Dobriyan if (currSCCB->Sccb_tag) { 479147b5d69cSJames Bottomley if (FPT_BL_Card[p_card].discQCount != 0) 47925c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card]. 47935c04a7b8SAlexey Dobriyan discQCount--; 47945c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card].discQ_Tbl[currSCCB-> 47955c04a7b8SAlexey Dobriyan Sccb_tag] 47965c04a7b8SAlexey Dobriyan = NULL; 47975c04a7b8SAlexey Dobriyan } else { 479847b5d69cSJames Bottomley if (FPT_BL_Card[p_card].discQCount != 0) 47995c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card]. 48005c04a7b8SAlexey Dobriyan discQCount--; 48015c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card]. 48025c04a7b8SAlexey Dobriyan discQ_Tbl[FPT_sccbMgrTbl[p_card] 48035c04a7b8SAlexey Dobriyan [currSCCB->TargID]. 48045c04a7b8SAlexey Dobriyan LunDiscQ_Idx[0]] = NULL; 48051da177e4SLinus Torvalds } 48061da177e4SLinus Torvalds } 48071da177e4SLinus Torvalds return; 48081da177e4SLinus Torvalds 48091da177e4SLinus Torvalds } 48101da177e4SLinus Torvalds 48115c04a7b8SAlexey Dobriyan if (status_byte == SSCHECK) { 48125c04a7b8SAlexey Dobriyan if (FPT_BL_Card[p_card].globalFlags & F_DO_RENEGO) { 48135c04a7b8SAlexey Dobriyan if (FPT_sccbMgrTbl[p_card][currSCCB->TargID]. 48145c04a7b8SAlexey Dobriyan TarEEValue & EE_SYNC_MASK) { 48155c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][currSCCB-> 48165c04a7b8SAlexey Dobriyan TargID]. 48175c04a7b8SAlexey Dobriyan TarStatus &= ~TAR_SYNC_MASK; 48181da177e4SLinus Torvalds } 48195c04a7b8SAlexey Dobriyan if (FPT_sccbMgrTbl[p_card][currSCCB->TargID]. 48205c04a7b8SAlexey Dobriyan TarEEValue & EE_WIDE_SCSI) { 48215c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][currSCCB-> 48225c04a7b8SAlexey Dobriyan TargID]. 48235c04a7b8SAlexey Dobriyan TarStatus &= ~TAR_WIDE_MASK; 48241da177e4SLinus Torvalds } 48251da177e4SLinus Torvalds } 48261da177e4SLinus Torvalds } 48271da177e4SLinus Torvalds 48281da177e4SLinus Torvalds if (!(currSCCB->Sccb_XferState & F_AUTO_SENSE)) { 48291da177e4SLinus Torvalds 48301da177e4SLinus Torvalds currSCCB->SccbStatus = SCCB_ERROR; 48311da177e4SLinus Torvalds currSCCB->TargetStatus = status_byte; 48321da177e4SLinus Torvalds 48331da177e4SLinus Torvalds if (status_byte == SSCHECK) { 48341da177e4SLinus Torvalds 48355c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][currSCCB->TargID]. 48365c04a7b8SAlexey Dobriyan TarLUN_CA = 1; 48371da177e4SLinus Torvalds 48385c04a7b8SAlexey Dobriyan if (currSCCB->RequestSenseLength != 48395c04a7b8SAlexey Dobriyan NO_AUTO_REQUEST_SENSE) { 48401da177e4SLinus Torvalds 48411da177e4SLinus Torvalds if (currSCCB->RequestSenseLength == 0) 48425c04a7b8SAlexey Dobriyan currSCCB->RequestSenseLength = 48435c04a7b8SAlexey Dobriyan 14; 48441da177e4SLinus Torvalds 484547b5d69cSJames Bottomley FPT_ssenss(&FPT_BL_Card[p_card]); 48465c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card].globalFlags |= 48475c04a7b8SAlexey Dobriyan F_NEW_SCCB_CMD; 48481da177e4SLinus Torvalds 48495c04a7b8SAlexey Dobriyan if (((FPT_BL_Card[p_card]. 48505c04a7b8SAlexey Dobriyan globalFlags & F_CONLUN_IO) 48515c04a7b8SAlexey Dobriyan && 48525c04a7b8SAlexey Dobriyan ((FPT_sccbMgrTbl[p_card] 48535c04a7b8SAlexey Dobriyan [currSCCB->TargID]. 48545c04a7b8SAlexey Dobriyan TarStatus & TAR_TAG_Q_MASK) != 48555c04a7b8SAlexey Dobriyan TAG_Q_TRYING))) { 48565c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card] 48575c04a7b8SAlexey Dobriyan [currSCCB->TargID]. 48585c04a7b8SAlexey Dobriyan TarLUNBusy[currSCCB->Lun] = 48595c04a7b8SAlexey Dobriyan 1; 48605c04a7b8SAlexey Dobriyan if (FPT_BL_Card[p_card]. 48615c04a7b8SAlexey Dobriyan discQCount != 0) 48625c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card]. 48635c04a7b8SAlexey Dobriyan discQCount--; 48645c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card]. 48655c04a7b8SAlexey Dobriyan discQ_Tbl[FPT_sccbMgrTbl 48665c04a7b8SAlexey Dobriyan [p_card] 48675c04a7b8SAlexey Dobriyan [currSCCB-> 48685c04a7b8SAlexey Dobriyan TargID]. 48695c04a7b8SAlexey Dobriyan LunDiscQ_Idx 48705c04a7b8SAlexey Dobriyan [currSCCB->Lun]] = 48715c04a7b8SAlexey Dobriyan NULL; 48725c04a7b8SAlexey Dobriyan } else { 48735c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card] 48745c04a7b8SAlexey Dobriyan [currSCCB->TargID]. 48755c04a7b8SAlexey Dobriyan TarLUNBusy[0] = 1; 48765c04a7b8SAlexey Dobriyan if (currSCCB->Sccb_tag) { 48775c04a7b8SAlexey Dobriyan if (FPT_BL_Card[p_card]. 48785c04a7b8SAlexey Dobriyan discQCount != 0) 48795c04a7b8SAlexey Dobriyan FPT_BL_Card 48805c04a7b8SAlexey Dobriyan [p_card]. 48815c04a7b8SAlexey Dobriyan discQCount--; 48825c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card]. 48835c04a7b8SAlexey Dobriyan discQ_Tbl[currSCCB-> 48845c04a7b8SAlexey Dobriyan Sccb_tag] 48855c04a7b8SAlexey Dobriyan = NULL; 48865c04a7b8SAlexey Dobriyan } else { 48875c04a7b8SAlexey Dobriyan if (FPT_BL_Card[p_card]. 48885c04a7b8SAlexey Dobriyan discQCount != 0) 48895c04a7b8SAlexey Dobriyan FPT_BL_Card 48905c04a7b8SAlexey Dobriyan [p_card]. 48915c04a7b8SAlexey Dobriyan discQCount--; 48925c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card]. 48935c04a7b8SAlexey Dobriyan discQ_Tbl 48945c04a7b8SAlexey Dobriyan [FPT_sccbMgrTbl 48955c04a7b8SAlexey Dobriyan [p_card][currSCCB-> 48965c04a7b8SAlexey Dobriyan TargID]. 48975c04a7b8SAlexey Dobriyan LunDiscQ_Idx[0]] = 48985c04a7b8SAlexey Dobriyan NULL; 48991da177e4SLinus Torvalds } 49001da177e4SLinus Torvalds } 49011da177e4SLinus Torvalds return; 49021da177e4SLinus Torvalds } 49031da177e4SLinus Torvalds } 490447b5d69cSJames Bottomley } 490547b5d69cSJames Bottomley } 490647b5d69cSJames Bottomley 490747b5d69cSJames Bottomley if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) && 49085c04a7b8SAlexey Dobriyan ((FPT_sccbMgrTbl[p_card][currSCCB->TargID]. 49095c04a7b8SAlexey Dobriyan TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)) 49105c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB-> 49115c04a7b8SAlexey Dobriyan Lun] = 0; 49121da177e4SLinus Torvalds else 491347b5d69cSJames Bottomley FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0; 491447b5d69cSJames Bottomley 491547b5d69cSJames Bottomley FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, p_card); 49161da177e4SLinus Torvalds } 49171da177e4SLinus Torvalds 49181da177e4SLinus Torvalds #define SHORT_WAIT 0x0000000F 49191da177e4SLinus Torvalds #define LONG_WAIT 0x0000FFFFL 49201da177e4SLinus Torvalds 49211da177e4SLinus Torvalds /*--------------------------------------------------------------------- 49221da177e4SLinus Torvalds * 49231da177e4SLinus Torvalds * Function: Data Transfer Processor 49241da177e4SLinus Torvalds * 49251da177e4SLinus Torvalds * Description: This routine performs two tasks. 49261da177e4SLinus Torvalds * (1) Start data transfer by calling HOST_DATA_XFER_START 49271da177e4SLinus Torvalds * function. Once data transfer is started, (2) Depends 49281da177e4SLinus Torvalds * on the type of data transfer mode Scatter/Gather mode 49291da177e4SLinus Torvalds * or NON Scatter/Gather mode. In NON Scatter/Gather mode, 49301da177e4SLinus Torvalds * this routine checks Sccb_MGRFlag (F_HOST_XFER_ACT bit) for 49311da177e4SLinus Torvalds * data transfer done. In Scatter/Gather mode, this routine 49321da177e4SLinus Torvalds * checks bus master command complete and dual rank busy 49331da177e4SLinus Torvalds * bit to keep chaining SC transfer command. Similarly, 49341da177e4SLinus Torvalds * in Scatter/Gather mode, it checks Sccb_MGRFlag 49351da177e4SLinus Torvalds * (F_HOST_XFER_ACT bit) for data transfer done. 49361da177e4SLinus Torvalds * 49371da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 49381da177e4SLinus Torvalds 49395c04a7b8SAlexey Dobriyan static void FPT_dataXferProcessor(unsigned long port, 49405c04a7b8SAlexey Dobriyan struct sccb_card *pCurrCard) 49411da177e4SLinus Torvalds { 494269eb2ea4SAlexey Dobriyan struct sccb *currSCCB; 49431da177e4SLinus Torvalds 49441da177e4SLinus Torvalds currSCCB = pCurrCard->currentSCCB; 49451da177e4SLinus Torvalds 49465c04a7b8SAlexey Dobriyan if (currSCCB->Sccb_XferState & F_SG_XFER) { 49471da177e4SLinus Torvalds if (pCurrCard->globalFlags & F_HOST_XFER_ACT) 49481da177e4SLinus Torvalds { 4949db038cf8SAlexey Dobriyan currSCCB->Sccb_sgseg += (unsigned char)SG_BUF_CNT; 49501da177e4SLinus Torvalds currSCCB->Sccb_SGoffset = 0x00; 49511da177e4SLinus Torvalds } 49521da177e4SLinus Torvalds pCurrCard->globalFlags |= F_HOST_XFER_ACT; 49531da177e4SLinus Torvalds 495447b5d69cSJames Bottomley FPT_busMstrSGDataXferStart(port, currSCCB); 49551da177e4SLinus Torvalds } 49561da177e4SLinus Torvalds 49575c04a7b8SAlexey Dobriyan else { 49585c04a7b8SAlexey Dobriyan if (!(pCurrCard->globalFlags & F_HOST_XFER_ACT)) { 49591da177e4SLinus Torvalds pCurrCard->globalFlags |= F_HOST_XFER_ACT; 49601da177e4SLinus Torvalds 496147b5d69cSJames Bottomley FPT_busMstrDataXferStart(port, currSCCB); 49621da177e4SLinus Torvalds } 49631da177e4SLinus Torvalds } 49641da177e4SLinus Torvalds } 49651da177e4SLinus Torvalds 49661da177e4SLinus Torvalds /*--------------------------------------------------------------------- 49671da177e4SLinus Torvalds * 49681da177e4SLinus Torvalds * Function: BusMaster Scatter Gather Data Transfer Start 49691da177e4SLinus Torvalds * 49701da177e4SLinus Torvalds * Description: 49711da177e4SLinus Torvalds * 49721da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 49735c04a7b8SAlexey Dobriyan static void FPT_busMstrSGDataXferStart(unsigned long p_port, 49745c04a7b8SAlexey Dobriyan struct sccb *pcurrSCCB) 49751da177e4SLinus Torvalds { 4976d63a4cccSAlexey Dobriyan unsigned long count, addr, tmpSGCnt; 4977ce793215SAlexey Dobriyan unsigned int sg_index; 4978db038cf8SAlexey Dobriyan unsigned char sg_count, i; 4979d63a4cccSAlexey Dobriyan unsigned long reg_offset; 49801da177e4SLinus Torvalds 49811da177e4SLinus Torvalds if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) { 49821da177e4SLinus Torvalds 4983d63a4cccSAlexey Dobriyan count = ((unsigned long)HOST_RD_CMD) << 24; 49841da177e4SLinus Torvalds } 49851da177e4SLinus Torvalds 49861da177e4SLinus Torvalds else { 4987d63a4cccSAlexey Dobriyan count = ((unsigned long)HOST_WRT_CMD) << 24; 49881da177e4SLinus Torvalds } 49891da177e4SLinus Torvalds 49901da177e4SLinus Torvalds sg_count = 0; 49911da177e4SLinus Torvalds tmpSGCnt = 0; 49921da177e4SLinus Torvalds sg_index = pcurrSCCB->Sccb_sgseg; 49931da177e4SLinus Torvalds reg_offset = hp_aramBase; 49941da177e4SLinus Torvalds 49955c04a7b8SAlexey Dobriyan i = (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) & 49965c04a7b8SAlexey Dobriyan ~(SGRAM_ARAM | SCATTER_EN)); 49971da177e4SLinus Torvalds 49981da177e4SLinus Torvalds WR_HARPOON(p_port + hp_page_ctrl, i); 49991da177e4SLinus Torvalds 5000db038cf8SAlexey Dobriyan while ((sg_count < (unsigned char)SG_BUF_CNT) && 50015c04a7b8SAlexey Dobriyan ((unsigned long)(sg_index * (unsigned int)SG_ELEMENT_SIZE) < 50025c04a7b8SAlexey Dobriyan pcurrSCCB->DataLength)) { 50031da177e4SLinus Torvalds 5004d63a4cccSAlexey Dobriyan tmpSGCnt += *(((unsigned long *)pcurrSCCB->DataPointer) + 50051da177e4SLinus Torvalds (sg_index * 2)); 50061da177e4SLinus Torvalds 5007d63a4cccSAlexey Dobriyan count |= *(((unsigned long *)pcurrSCCB->DataPointer) + 50081da177e4SLinus Torvalds (sg_index * 2)); 50091da177e4SLinus Torvalds 5010d63a4cccSAlexey Dobriyan addr = *(((unsigned long *)pcurrSCCB->DataPointer) + 50111da177e4SLinus Torvalds ((sg_index * 2) + 1)); 50121da177e4SLinus Torvalds 50131da177e4SLinus Torvalds if ((!sg_count) && (pcurrSCCB->Sccb_SGoffset)) { 50141da177e4SLinus Torvalds 50155c04a7b8SAlexey Dobriyan addr += 50165c04a7b8SAlexey Dobriyan ((count & 0x00FFFFFFL) - pcurrSCCB->Sccb_SGoffset); 50175c04a7b8SAlexey Dobriyan count = 50185c04a7b8SAlexey Dobriyan (count & 0xFF000000L) | pcurrSCCB->Sccb_SGoffset; 50191da177e4SLinus Torvalds 50201da177e4SLinus Torvalds tmpSGCnt = count & 0x00FFFFFFL; 50211da177e4SLinus Torvalds } 50221da177e4SLinus Torvalds 50231da177e4SLinus Torvalds WR_HARP32(p_port, reg_offset, addr); 50241da177e4SLinus Torvalds reg_offset += 4; 50251da177e4SLinus Torvalds 50261da177e4SLinus Torvalds WR_HARP32(p_port, reg_offset, count); 50271da177e4SLinus Torvalds reg_offset += 4; 50281da177e4SLinus Torvalds 50291da177e4SLinus Torvalds count &= 0xFF000000L; 50301da177e4SLinus Torvalds sg_index++; 50311da177e4SLinus Torvalds sg_count++; 50321da177e4SLinus Torvalds 50331da177e4SLinus Torvalds } /*End While */ 50341da177e4SLinus Torvalds 50351da177e4SLinus Torvalds pcurrSCCB->Sccb_XferCnt = tmpSGCnt; 50361da177e4SLinus Torvalds 50371da177e4SLinus Torvalds WR_HARPOON(p_port + hp_sg_addr, (sg_count << 4)); 50381da177e4SLinus Torvalds 50391da177e4SLinus Torvalds if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) { 50401da177e4SLinus Torvalds 50411da177e4SLinus Torvalds WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt); 50421da177e4SLinus Torvalds 50435c04a7b8SAlexey Dobriyan WR_HARPOON(p_port + hp_portctrl_0, 50445c04a7b8SAlexey Dobriyan (DMA_PORT | SCSI_PORT | SCSI_INBIT)); 50451da177e4SLinus Torvalds WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH); 50461da177e4SLinus Torvalds } 50471da177e4SLinus Torvalds 50481da177e4SLinus Torvalds else { 50491da177e4SLinus Torvalds 50501da177e4SLinus Torvalds if ((!(RD_HARPOON(p_port + hp_synctarg_0) & NARROW_SCSI)) && 50515c04a7b8SAlexey Dobriyan (tmpSGCnt & 0x000000001)) { 50521da177e4SLinus Torvalds 50531da177e4SLinus Torvalds pcurrSCCB->Sccb_XferState |= F_ODD_BALL_CNT; 50541da177e4SLinus Torvalds tmpSGCnt--; 50551da177e4SLinus Torvalds } 50561da177e4SLinus Torvalds 50571da177e4SLinus Torvalds WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt); 50581da177e4SLinus Torvalds 50595c04a7b8SAlexey Dobriyan WR_HARPOON(p_port + hp_portctrl_0, 50605c04a7b8SAlexey Dobriyan (SCSI_PORT | DMA_PORT | DMA_RD)); 50611da177e4SLinus Torvalds WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH); 50621da177e4SLinus Torvalds } 50631da177e4SLinus Torvalds 5064db038cf8SAlexey Dobriyan WR_HARPOON(p_port + hp_page_ctrl, (unsigned char)(i | SCATTER_EN)); 50651da177e4SLinus Torvalds 50661da177e4SLinus Torvalds } 50671da177e4SLinus Torvalds 50681da177e4SLinus Torvalds /*--------------------------------------------------------------------- 50691da177e4SLinus Torvalds * 50701da177e4SLinus Torvalds * Function: BusMaster Data Transfer Start 50711da177e4SLinus Torvalds * 50721da177e4SLinus Torvalds * Description: 50731da177e4SLinus Torvalds * 50741da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 50755c04a7b8SAlexey Dobriyan static void FPT_busMstrDataXferStart(unsigned long p_port, 50765c04a7b8SAlexey Dobriyan struct sccb *pcurrSCCB) 50771da177e4SLinus Torvalds { 5078d63a4cccSAlexey Dobriyan unsigned long addr, count; 50791da177e4SLinus Torvalds 50801da177e4SLinus Torvalds if (!(pcurrSCCB->Sccb_XferState & F_AUTO_SENSE)) { 50811da177e4SLinus Torvalds 50821da177e4SLinus Torvalds count = pcurrSCCB->Sccb_XferCnt; 50831da177e4SLinus Torvalds 50845c04a7b8SAlexey Dobriyan addr = 50855c04a7b8SAlexey Dobriyan (unsigned long)pcurrSCCB->DataPointer + pcurrSCCB->Sccb_ATC; 50861da177e4SLinus Torvalds } 50871da177e4SLinus Torvalds 50881da177e4SLinus Torvalds else { 50891da177e4SLinus Torvalds addr = pcurrSCCB->SensePointer; 50901da177e4SLinus Torvalds count = pcurrSCCB->RequestSenseLength; 50911da177e4SLinus Torvalds 50921da177e4SLinus Torvalds } 50931da177e4SLinus Torvalds 50941da177e4SLinus Torvalds HP_SETUP_ADDR_CNT(p_port, addr, count); 50951da177e4SLinus Torvalds 50961da177e4SLinus Torvalds if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) { 50971da177e4SLinus Torvalds 50985c04a7b8SAlexey Dobriyan WR_HARPOON(p_port + hp_portctrl_0, 50995c04a7b8SAlexey Dobriyan (DMA_PORT | SCSI_PORT | SCSI_INBIT)); 51001da177e4SLinus Torvalds WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH); 51011da177e4SLinus Torvalds 51021da177e4SLinus Torvalds WR_HARPOON(p_port + hp_xfer_cmd, 51031da177e4SLinus Torvalds (XFER_DMA_HOST | XFER_HOST_AUTO | XFER_DMA_8BIT)); 51041da177e4SLinus Torvalds } 51051da177e4SLinus Torvalds 51061da177e4SLinus Torvalds else { 51071da177e4SLinus Torvalds 51085c04a7b8SAlexey Dobriyan WR_HARPOON(p_port + hp_portctrl_0, 51095c04a7b8SAlexey Dobriyan (SCSI_PORT | DMA_PORT | DMA_RD)); 51101da177e4SLinus Torvalds WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH); 51111da177e4SLinus Torvalds 51121da177e4SLinus Torvalds WR_HARPOON(p_port + hp_xfer_cmd, 51131da177e4SLinus Torvalds (XFER_HOST_DMA | XFER_HOST_AUTO | XFER_DMA_8BIT)); 51141da177e4SLinus Torvalds 51151da177e4SLinus Torvalds } 51161da177e4SLinus Torvalds } 51171da177e4SLinus Torvalds 51181da177e4SLinus Torvalds /*--------------------------------------------------------------------- 51191da177e4SLinus Torvalds * 51201da177e4SLinus Torvalds * Function: BusMaster Timeout Handler 51211da177e4SLinus Torvalds * 51221da177e4SLinus Torvalds * Description: This function is called after a bus master command busy time 51231da177e4SLinus Torvalds * out is detected. This routines issue halt state machine 51241da177e4SLinus Torvalds * with a software time out for command busy. If command busy 51251da177e4SLinus Torvalds * is still asserted at the end of the time out, it issues 51261da177e4SLinus Torvalds * hard abort with another software time out. It hard abort 51271da177e4SLinus Torvalds * command busy is also time out, it'll just give up. 51281da177e4SLinus Torvalds * 51291da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 5130d63a4cccSAlexey Dobriyan static unsigned char FPT_busMstrTimeOut(unsigned long p_port) 51311da177e4SLinus Torvalds { 5132d63a4cccSAlexey Dobriyan unsigned long timeout; 51331da177e4SLinus Torvalds 51341da177e4SLinus Torvalds timeout = LONG_WAIT; 51351da177e4SLinus Torvalds 51361da177e4SLinus Torvalds WR_HARPOON(p_port + hp_sys_ctrl, HALT_MACH); 51371da177e4SLinus Torvalds 51385c04a7b8SAlexey Dobriyan while ((!(RD_HARPOON(p_port + hp_ext_status) & CMD_ABORTED)) 51395c04a7b8SAlexey Dobriyan && timeout--) { 51405c04a7b8SAlexey Dobriyan } 51411da177e4SLinus Torvalds 51421da177e4SLinus Torvalds if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) { 51431da177e4SLinus Torvalds WR_HARPOON(p_port + hp_sys_ctrl, HARD_ABORT); 51441da177e4SLinus Torvalds 51451da177e4SLinus Torvalds timeout = LONG_WAIT; 51465c04a7b8SAlexey Dobriyan while ((RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) 51475c04a7b8SAlexey Dobriyan && timeout--) { 51485c04a7b8SAlexey Dobriyan } 51491da177e4SLinus Torvalds } 51501da177e4SLinus Torvalds 51511da177e4SLinus Torvalds RD_HARPOON(p_port + hp_int_status); /*Clear command complete */ 51521da177e4SLinus Torvalds 51531da177e4SLinus Torvalds if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) { 51545c1b85e2SAlexey Dobriyan return 1; 51551da177e4SLinus Torvalds } 51561da177e4SLinus Torvalds 51571da177e4SLinus Torvalds else { 51585c1b85e2SAlexey Dobriyan return 0; 51591da177e4SLinus Torvalds } 51601da177e4SLinus Torvalds } 51611da177e4SLinus Torvalds 51621da177e4SLinus Torvalds /*--------------------------------------------------------------------- 51631da177e4SLinus Torvalds * 51641da177e4SLinus Torvalds * Function: Host Data Transfer Abort 51651da177e4SLinus Torvalds * 51661da177e4SLinus Torvalds * Description: Abort any in progress transfer. 51671da177e4SLinus Torvalds * 51681da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 51695c04a7b8SAlexey Dobriyan static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card, 51705c04a7b8SAlexey Dobriyan struct sccb *pCurrSCCB) 51711da177e4SLinus Torvalds { 51721da177e4SLinus Torvalds 5173d63a4cccSAlexey Dobriyan unsigned long timeout; 5174d63a4cccSAlexey Dobriyan unsigned long remain_cnt; 5175ce793215SAlexey Dobriyan unsigned int sg_ptr; 51761da177e4SLinus Torvalds 517747b5d69cSJames Bottomley FPT_BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT; 51781da177e4SLinus Torvalds 51791da177e4SLinus Torvalds if (pCurrSCCB->Sccb_XferState & F_AUTO_SENSE) { 51801da177e4SLinus Torvalds 51811da177e4SLinus Torvalds if (!(RD_HARPOON(port + hp_int_status) & INT_CMD_COMPL)) { 51821da177e4SLinus Torvalds 51835c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_bm_ctrl, 51845c04a7b8SAlexey Dobriyan (RD_HARPOON(port + hp_bm_ctrl) | 51855c04a7b8SAlexey Dobriyan FLUSH_XFER_CNTR)); 51861da177e4SLinus Torvalds timeout = LONG_WAIT; 51871da177e4SLinus Torvalds 51885c04a7b8SAlexey Dobriyan while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) 51895c04a7b8SAlexey Dobriyan && timeout--) { 51905c04a7b8SAlexey Dobriyan } 51911da177e4SLinus Torvalds 51925c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_bm_ctrl, 51935c04a7b8SAlexey Dobriyan (RD_HARPOON(port + hp_bm_ctrl) & 51945c04a7b8SAlexey Dobriyan ~FLUSH_XFER_CNTR)); 51951da177e4SLinus Torvalds 51961da177e4SLinus Torvalds if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) { 51971da177e4SLinus Torvalds 519847b5d69cSJames Bottomley if (FPT_busMstrTimeOut(port)) { 51991da177e4SLinus Torvalds 52001da177e4SLinus Torvalds if (pCurrSCCB->HostStatus == 0x00) 52011da177e4SLinus Torvalds 52025c04a7b8SAlexey Dobriyan pCurrSCCB->HostStatus = 52035c04a7b8SAlexey Dobriyan SCCB_BM_ERR; 52041da177e4SLinus Torvalds 52051da177e4SLinus Torvalds } 52061da177e4SLinus Torvalds 52075c04a7b8SAlexey Dobriyan if (RD_HARPOON(port + hp_int_status) & 52085c04a7b8SAlexey Dobriyan INT_EXT_STATUS) 52091da177e4SLinus Torvalds 52105c04a7b8SAlexey Dobriyan if (RD_HARPOON(port + hp_ext_status) & 52115c04a7b8SAlexey Dobriyan BAD_EXT_STATUS) 52121da177e4SLinus Torvalds 52135c04a7b8SAlexey Dobriyan if (pCurrSCCB->HostStatus == 52145c04a7b8SAlexey Dobriyan 0x00) 52151da177e4SLinus Torvalds { 52165c04a7b8SAlexey Dobriyan pCurrSCCB->HostStatus = 52175c04a7b8SAlexey Dobriyan SCCB_BM_ERR; 52181da177e4SLinus Torvalds } 52191da177e4SLinus Torvalds } 52201da177e4SLinus Torvalds } 52211da177e4SLinus Torvalds } 52221da177e4SLinus Torvalds 52231da177e4SLinus Torvalds else if (pCurrSCCB->Sccb_XferCnt) { 52241da177e4SLinus Torvalds 52251da177e4SLinus Torvalds if (pCurrSCCB->Sccb_XferState & F_SG_XFER) { 52261da177e4SLinus Torvalds 52275c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_page_ctrl, 52285c04a7b8SAlexey Dobriyan (RD_HARPOON(port + hp_page_ctrl) & 52291da177e4SLinus Torvalds ~SCATTER_EN)); 52301da177e4SLinus Torvalds 52311da177e4SLinus Torvalds WR_HARPOON(port + hp_sg_addr, 0x00); 52321da177e4SLinus Torvalds 52331da177e4SLinus Torvalds sg_ptr = pCurrSCCB->Sccb_sgseg + SG_BUF_CNT; 52341da177e4SLinus Torvalds 52355c04a7b8SAlexey Dobriyan if (sg_ptr > 52365c04a7b8SAlexey Dobriyan (unsigned int)(pCurrSCCB->DataLength / 52375c04a7b8SAlexey Dobriyan SG_ELEMENT_SIZE)) { 52381da177e4SLinus Torvalds 52395c04a7b8SAlexey Dobriyan sg_ptr = 52405c04a7b8SAlexey Dobriyan (unsigned int)(pCurrSCCB->DataLength / 52415c04a7b8SAlexey Dobriyan SG_ELEMENT_SIZE); 52421da177e4SLinus Torvalds } 52431da177e4SLinus Torvalds 52441da177e4SLinus Torvalds remain_cnt = pCurrSCCB->Sccb_XferCnt; 52451da177e4SLinus Torvalds 52461da177e4SLinus Torvalds while (remain_cnt < 0x01000000L) { 52471da177e4SLinus Torvalds 52481da177e4SLinus Torvalds sg_ptr--; 52491da177e4SLinus Torvalds 52505c04a7b8SAlexey Dobriyan if (remain_cnt > 52515c04a7b8SAlexey Dobriyan (unsigned 52525c04a7b8SAlexey Dobriyan long)(*(((unsigned long *)pCurrSCCB-> 52531da177e4SLinus Torvalds DataPointer) + (sg_ptr * 2)))) { 52541da177e4SLinus Torvalds 52555c04a7b8SAlexey Dobriyan remain_cnt -= 52565c04a7b8SAlexey Dobriyan (unsigned 52575c04a7b8SAlexey Dobriyan long)(*(((unsigned long *) 52585c04a7b8SAlexey Dobriyan pCurrSCCB->DataPointer) + 52595c04a7b8SAlexey Dobriyan (sg_ptr * 2))); 52601da177e4SLinus Torvalds } 52611da177e4SLinus Torvalds 52621da177e4SLinus Torvalds else { 52631da177e4SLinus Torvalds 52641da177e4SLinus Torvalds break; 52651da177e4SLinus Torvalds } 52661da177e4SLinus Torvalds } 52671da177e4SLinus Torvalds 52681da177e4SLinus Torvalds if (remain_cnt < 0x01000000L) { 52691da177e4SLinus Torvalds 52701da177e4SLinus Torvalds pCurrSCCB->Sccb_SGoffset = remain_cnt; 52711da177e4SLinus Torvalds 5272c823feebSAlexey Dobriyan pCurrSCCB->Sccb_sgseg = (unsigned short)sg_ptr; 52731da177e4SLinus Torvalds 52745c04a7b8SAlexey Dobriyan if ((unsigned long)(sg_ptr * SG_ELEMENT_SIZE) == 52755c04a7b8SAlexey Dobriyan pCurrSCCB->DataLength && (remain_cnt == 0)) 52761da177e4SLinus Torvalds 52775c04a7b8SAlexey Dobriyan pCurrSCCB->Sccb_XferState |= 52785c04a7b8SAlexey Dobriyan F_ALL_XFERRED; 52791da177e4SLinus Torvalds } 52801da177e4SLinus Torvalds 52811da177e4SLinus Torvalds else { 52821da177e4SLinus Torvalds 52831da177e4SLinus Torvalds if (pCurrSCCB->HostStatus == 0x00) { 52841da177e4SLinus Torvalds 52855c04a7b8SAlexey Dobriyan pCurrSCCB->HostStatus = 52865c04a7b8SAlexey Dobriyan SCCB_GROSS_FW_ERR; 52871da177e4SLinus Torvalds } 52881da177e4SLinus Torvalds } 52891da177e4SLinus Torvalds } 52901da177e4SLinus Torvalds 52911da177e4SLinus Torvalds if (!(pCurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)) { 52921da177e4SLinus Torvalds 52931da177e4SLinus Torvalds if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) { 52941da177e4SLinus Torvalds 529547b5d69cSJames Bottomley FPT_busMstrTimeOut(port); 52961da177e4SLinus Torvalds } 52971da177e4SLinus Torvalds 52981da177e4SLinus Torvalds else { 52991da177e4SLinus Torvalds 53005c04a7b8SAlexey Dobriyan if (RD_HARPOON(port + hp_int_status) & 53015c04a7b8SAlexey Dobriyan INT_EXT_STATUS) { 53021da177e4SLinus Torvalds 53035c04a7b8SAlexey Dobriyan if (RD_HARPOON(port + hp_ext_status) & 53045c04a7b8SAlexey Dobriyan BAD_EXT_STATUS) { 53051da177e4SLinus Torvalds 53065c04a7b8SAlexey Dobriyan if (pCurrSCCB->HostStatus == 53075c04a7b8SAlexey Dobriyan 0x00) { 53081da177e4SLinus Torvalds 53095c04a7b8SAlexey Dobriyan pCurrSCCB->HostStatus = 53105c04a7b8SAlexey Dobriyan SCCB_BM_ERR; 53111da177e4SLinus Torvalds } 53121da177e4SLinus Torvalds } 53131da177e4SLinus Torvalds } 53141da177e4SLinus Torvalds 53151da177e4SLinus Torvalds } 53161da177e4SLinus Torvalds } 53171da177e4SLinus Torvalds 53181da177e4SLinus Torvalds else { 53191da177e4SLinus Torvalds 53201da177e4SLinus Torvalds if ((RD_HARPOON(port + hp_fifo_cnt)) >= BM_THRESHOLD) { 53211da177e4SLinus Torvalds 53221da177e4SLinus Torvalds timeout = SHORT_WAIT; 53231da177e4SLinus Torvalds 53245c04a7b8SAlexey Dobriyan while ((RD_HARPOON(port + hp_ext_status) & 53255c04a7b8SAlexey Dobriyan BM_CMD_BUSY) 53265c04a7b8SAlexey Dobriyan && ((RD_HARPOON(port + hp_fifo_cnt)) >= 53275c04a7b8SAlexey Dobriyan BM_THRESHOLD) && timeout--) { 53285c04a7b8SAlexey Dobriyan } 53291da177e4SLinus Torvalds } 53301da177e4SLinus Torvalds 53311da177e4SLinus Torvalds if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) { 53321da177e4SLinus Torvalds 53335c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_bm_ctrl, 53345c04a7b8SAlexey Dobriyan (RD_HARPOON(port + hp_bm_ctrl) | 53351da177e4SLinus Torvalds FLUSH_XFER_CNTR)); 53361da177e4SLinus Torvalds 53371da177e4SLinus Torvalds timeout = LONG_WAIT; 53381da177e4SLinus Torvalds 53395c04a7b8SAlexey Dobriyan while ((RD_HARPOON(port + hp_ext_status) & 53405c04a7b8SAlexey Dobriyan BM_CMD_BUSY) && timeout--) { 53415c04a7b8SAlexey Dobriyan } 53421da177e4SLinus Torvalds 53435c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_bm_ctrl, 53445c04a7b8SAlexey Dobriyan (RD_HARPOON(port + hp_bm_ctrl) & 53451da177e4SLinus Torvalds ~FLUSH_XFER_CNTR)); 53461da177e4SLinus Torvalds 53475c04a7b8SAlexey Dobriyan if (RD_HARPOON(port + hp_ext_status) & 53485c04a7b8SAlexey Dobriyan BM_CMD_BUSY) { 53491da177e4SLinus Torvalds 53501da177e4SLinus Torvalds if (pCurrSCCB->HostStatus == 0x00) { 53511da177e4SLinus Torvalds 53525c04a7b8SAlexey Dobriyan pCurrSCCB->HostStatus = 53535c04a7b8SAlexey Dobriyan SCCB_BM_ERR; 53541da177e4SLinus Torvalds } 53551da177e4SLinus Torvalds 535647b5d69cSJames Bottomley FPT_busMstrTimeOut(port); 53571da177e4SLinus Torvalds } 53581da177e4SLinus Torvalds } 53591da177e4SLinus Torvalds 53601da177e4SLinus Torvalds if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) { 53611da177e4SLinus Torvalds 53625c04a7b8SAlexey Dobriyan if (RD_HARPOON(port + hp_ext_status) & 53635c04a7b8SAlexey Dobriyan BAD_EXT_STATUS) { 53641da177e4SLinus Torvalds 53651da177e4SLinus Torvalds if (pCurrSCCB->HostStatus == 0x00) { 53661da177e4SLinus Torvalds 53675c04a7b8SAlexey Dobriyan pCurrSCCB->HostStatus = 53685c04a7b8SAlexey Dobriyan SCCB_BM_ERR; 53691da177e4SLinus Torvalds } 53701da177e4SLinus Torvalds } 53711da177e4SLinus Torvalds } 53721da177e4SLinus Torvalds } 53731da177e4SLinus Torvalds 53741da177e4SLinus Torvalds } 53751da177e4SLinus Torvalds 53761da177e4SLinus Torvalds else { 53771da177e4SLinus Torvalds 53781da177e4SLinus Torvalds if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) { 53791da177e4SLinus Torvalds 53801da177e4SLinus Torvalds timeout = LONG_WAIT; 53811da177e4SLinus Torvalds 53825c04a7b8SAlexey Dobriyan while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) 53835c04a7b8SAlexey Dobriyan && timeout--) { 53845c04a7b8SAlexey Dobriyan } 53851da177e4SLinus Torvalds 53861da177e4SLinus Torvalds if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) { 53871da177e4SLinus Torvalds 53881da177e4SLinus Torvalds if (pCurrSCCB->HostStatus == 0x00) { 53891da177e4SLinus Torvalds 53901da177e4SLinus Torvalds pCurrSCCB->HostStatus = SCCB_BM_ERR; 53911da177e4SLinus Torvalds } 53921da177e4SLinus Torvalds 539347b5d69cSJames Bottomley FPT_busMstrTimeOut(port); 53941da177e4SLinus Torvalds } 53951da177e4SLinus Torvalds } 53961da177e4SLinus Torvalds 53971da177e4SLinus Torvalds if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) { 53981da177e4SLinus Torvalds 53991da177e4SLinus Torvalds if (RD_HARPOON(port + hp_ext_status) & BAD_EXT_STATUS) { 54001da177e4SLinus Torvalds 54011da177e4SLinus Torvalds if (pCurrSCCB->HostStatus == 0x00) { 54021da177e4SLinus Torvalds 54031da177e4SLinus Torvalds pCurrSCCB->HostStatus = SCCB_BM_ERR; 54041da177e4SLinus Torvalds } 54051da177e4SLinus Torvalds } 54061da177e4SLinus Torvalds 54071da177e4SLinus Torvalds } 54081da177e4SLinus Torvalds 54091da177e4SLinus Torvalds if (pCurrSCCB->Sccb_XferState & F_SG_XFER) { 54101da177e4SLinus Torvalds 54115c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_page_ctrl, 54125c04a7b8SAlexey Dobriyan (RD_HARPOON(port + hp_page_ctrl) & 54131da177e4SLinus Torvalds ~SCATTER_EN)); 54141da177e4SLinus Torvalds 54151da177e4SLinus Torvalds WR_HARPOON(port + hp_sg_addr, 0x00); 54161da177e4SLinus Torvalds 54171da177e4SLinus Torvalds pCurrSCCB->Sccb_sgseg += SG_BUF_CNT; 54181da177e4SLinus Torvalds 54191da177e4SLinus Torvalds pCurrSCCB->Sccb_SGoffset = 0x00; 54201da177e4SLinus Torvalds 54215c04a7b8SAlexey Dobriyan if ((unsigned long)(pCurrSCCB->Sccb_sgseg * 54225c04a7b8SAlexey Dobriyan SG_ELEMENT_SIZE) >= 54231da177e4SLinus Torvalds pCurrSCCB->DataLength) { 54241da177e4SLinus Torvalds 54251da177e4SLinus Torvalds pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED; 54261da177e4SLinus Torvalds 54275c04a7b8SAlexey Dobriyan pCurrSCCB->Sccb_sgseg = 54285c04a7b8SAlexey Dobriyan (unsigned short)(pCurrSCCB->DataLength / 54295c04a7b8SAlexey Dobriyan SG_ELEMENT_SIZE); 54301da177e4SLinus Torvalds 54311da177e4SLinus Torvalds } 54321da177e4SLinus Torvalds } 54331da177e4SLinus Torvalds 54341da177e4SLinus Torvalds else { 54351da177e4SLinus Torvalds 54361da177e4SLinus Torvalds if (!(pCurrSCCB->Sccb_XferState & F_AUTO_SENSE)) 54371da177e4SLinus Torvalds 54381da177e4SLinus Torvalds pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED; 54391da177e4SLinus Torvalds } 54401da177e4SLinus Torvalds } 54411da177e4SLinus Torvalds 54421da177e4SLinus Torvalds WR_HARPOON(port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT)); 54431da177e4SLinus Torvalds } 54441da177e4SLinus Torvalds 54451da177e4SLinus Torvalds /*--------------------------------------------------------------------- 54461da177e4SLinus Torvalds * 54471da177e4SLinus Torvalds * Function: Host Data Transfer Restart 54481da177e4SLinus Torvalds * 54491da177e4SLinus Torvalds * Description: Reset the available count due to a restore data 54501da177e4SLinus Torvalds * pointers message. 54511da177e4SLinus Torvalds * 54521da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 545369eb2ea4SAlexey Dobriyan static void FPT_hostDataXferRestart(struct sccb *currSCCB) 54541da177e4SLinus Torvalds { 5455d63a4cccSAlexey Dobriyan unsigned long data_count; 5456ce793215SAlexey Dobriyan unsigned int sg_index; 5457d63a4cccSAlexey Dobriyan unsigned long *sg_ptr; 54581da177e4SLinus Torvalds 54591da177e4SLinus Torvalds if (currSCCB->Sccb_XferState & F_SG_XFER) { 54601da177e4SLinus Torvalds 54611da177e4SLinus Torvalds currSCCB->Sccb_XferCnt = 0; 54621da177e4SLinus Torvalds 54631da177e4SLinus Torvalds sg_index = 0xffff; /*Index by long words into sg list. */ 54641da177e4SLinus Torvalds data_count = 0; /*Running count of SG xfer counts. */ 54651da177e4SLinus Torvalds 5466d63a4cccSAlexey Dobriyan sg_ptr = (unsigned long *)currSCCB->DataPointer; 54671da177e4SLinus Torvalds 54681da177e4SLinus Torvalds while (data_count < currSCCB->Sccb_ATC) { 54691da177e4SLinus Torvalds 54701da177e4SLinus Torvalds sg_index++; 54711da177e4SLinus Torvalds data_count += *(sg_ptr + (sg_index * 2)); 54721da177e4SLinus Torvalds } 54731da177e4SLinus Torvalds 54741da177e4SLinus Torvalds if (data_count == currSCCB->Sccb_ATC) { 54751da177e4SLinus Torvalds 54761da177e4SLinus Torvalds currSCCB->Sccb_SGoffset = 0; 54771da177e4SLinus Torvalds sg_index++; 54781da177e4SLinus Torvalds } 54791da177e4SLinus Torvalds 54801da177e4SLinus Torvalds else { 54815c04a7b8SAlexey Dobriyan currSCCB->Sccb_SGoffset = 54825c04a7b8SAlexey Dobriyan data_count - currSCCB->Sccb_ATC; 54831da177e4SLinus Torvalds } 54841da177e4SLinus Torvalds 5485c823feebSAlexey Dobriyan currSCCB->Sccb_sgseg = (unsigned short)sg_index; 54861da177e4SLinus Torvalds } 54871da177e4SLinus Torvalds 54881da177e4SLinus Torvalds else { 54895c04a7b8SAlexey Dobriyan currSCCB->Sccb_XferCnt = 54905c04a7b8SAlexey Dobriyan currSCCB->DataLength - currSCCB->Sccb_ATC; 54911da177e4SLinus Torvalds } 54921da177e4SLinus Torvalds } 54931da177e4SLinus Torvalds 54941da177e4SLinus Torvalds /*--------------------------------------------------------------------- 54951da177e4SLinus Torvalds * 549647b5d69cSJames Bottomley * Function: FPT_scini 54971da177e4SLinus Torvalds * 54981da177e4SLinus Torvalds * Description: Setup all data structures necessary for SCAM selection. 54991da177e4SLinus Torvalds * 55001da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 55011da177e4SLinus Torvalds 55025c04a7b8SAlexey Dobriyan static void FPT_scini(unsigned char p_card, unsigned char p_our_id, 55035c04a7b8SAlexey Dobriyan unsigned char p_power_up) 55041da177e4SLinus Torvalds { 55051da177e4SLinus Torvalds 5506db038cf8SAlexey Dobriyan unsigned char loser, assigned_id; 5507d63a4cccSAlexey Dobriyan unsigned long p_port; 55081da177e4SLinus Torvalds 5509db038cf8SAlexey Dobriyan unsigned char i, k, ScamFlg; 551013e6851aSAlexey Dobriyan struct sccb_card *currCard; 551168d0c1aeSAlexey Dobriyan struct nvram_info *pCurrNvRam; 55121da177e4SLinus Torvalds 551347b5d69cSJames Bottomley currCard = &FPT_BL_Card[p_card]; 55141da177e4SLinus Torvalds p_port = currCard->ioPort; 55151da177e4SLinus Torvalds pCurrNvRam = currCard->pNvRamInfo; 55161da177e4SLinus Torvalds 55171da177e4SLinus Torvalds if (pCurrNvRam) { 55181da177e4SLinus Torvalds ScamFlg = pCurrNvRam->niScamConf; 55191da177e4SLinus Torvalds i = pCurrNvRam->niSysConf; 55205c04a7b8SAlexey Dobriyan } else { 55215c04a7b8SAlexey Dobriyan ScamFlg = 55225c04a7b8SAlexey Dobriyan (unsigned char)FPT_utilEERead(p_port, SCAM_CONFIG / 2); 55235c04a7b8SAlexey Dobriyan i = (unsigned 55245c04a7b8SAlexey Dobriyan char)(FPT_utilEERead(p_port, (SYSTEM_CONFIG / 2))); 55251da177e4SLinus Torvalds } 55261da177e4SLinus Torvalds if (!(i & 0x02)) /* check if reset bus in AutoSCSI parameter set */ 55271da177e4SLinus Torvalds return; 55281da177e4SLinus Torvalds 552947b5d69cSJames Bottomley FPT_inisci(p_card, p_port, p_our_id); 55301da177e4SLinus Torvalds 55311da177e4SLinus Torvalds /* Force to wait 1 sec after SCSI bus reset. Some SCAM device FW 55321da177e4SLinus Torvalds too slow to return to SCAM selection */ 55331da177e4SLinus Torvalds 55341da177e4SLinus Torvalds /* if (p_power_up) 553547b5d69cSJames Bottomley FPT_Wait1Second(p_port); 55361da177e4SLinus Torvalds else 553747b5d69cSJames Bottomley FPT_Wait(p_port, TO_250ms); */ 55381da177e4SLinus Torvalds 553947b5d69cSJames Bottomley FPT_Wait1Second(p_port); 55401da177e4SLinus Torvalds 55415c04a7b8SAlexey Dobriyan if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2)) { 55425c04a7b8SAlexey Dobriyan while (!(FPT_scarb(p_port, INIT_SELTD))) { 55435c04a7b8SAlexey Dobriyan } 55441da177e4SLinus Torvalds 554547b5d69cSJames Bottomley FPT_scsel(p_port); 55461da177e4SLinus Torvalds 55471da177e4SLinus Torvalds do { 554847b5d69cSJames Bottomley FPT_scxferc(p_port, SYNC_PTRN); 554947b5d69cSJames Bottomley FPT_scxferc(p_port, DOM_MSTR); 55505c04a7b8SAlexey Dobriyan loser = 55515c04a7b8SAlexey Dobriyan FPT_scsendi(p_port, 55525c04a7b8SAlexey Dobriyan &FPT_scamInfo[p_our_id].id_string[0]); 55531da177e4SLinus Torvalds } while (loser == 0xFF); 55541da177e4SLinus Torvalds 555547b5d69cSJames Bottomley FPT_scbusf(p_port); 55561da177e4SLinus Torvalds 55575c04a7b8SAlexey Dobriyan if ((p_power_up) && (!loser)) { 555847b5d69cSJames Bottomley FPT_sresb(p_port, p_card); 555947b5d69cSJames Bottomley FPT_Wait(p_port, TO_250ms); 55601da177e4SLinus Torvalds 55615c04a7b8SAlexey Dobriyan while (!(FPT_scarb(p_port, INIT_SELTD))) { 55625c04a7b8SAlexey Dobriyan } 55631da177e4SLinus Torvalds 556447b5d69cSJames Bottomley FPT_scsel(p_port); 55651da177e4SLinus Torvalds 55661da177e4SLinus Torvalds do { 556747b5d69cSJames Bottomley FPT_scxferc(p_port, SYNC_PTRN); 556847b5d69cSJames Bottomley FPT_scxferc(p_port, DOM_MSTR); 55695c04a7b8SAlexey Dobriyan loser = 55705c04a7b8SAlexey Dobriyan FPT_scsendi(p_port, 55715c04a7b8SAlexey Dobriyan &FPT_scamInfo[p_our_id]. 55721da177e4SLinus Torvalds id_string[0]); 55731da177e4SLinus Torvalds } while (loser == 0xFF); 55741da177e4SLinus Torvalds 557547b5d69cSJames Bottomley FPT_scbusf(p_port); 55761da177e4SLinus Torvalds } 55771da177e4SLinus Torvalds } 55781da177e4SLinus Torvalds 55795c04a7b8SAlexey Dobriyan else { 558047b5d69cSJames Bottomley loser = 0; 55811da177e4SLinus Torvalds } 55821da177e4SLinus Torvalds 55835c04a7b8SAlexey Dobriyan if (!loser) { 55841da177e4SLinus Torvalds 558547b5d69cSJames Bottomley FPT_scamInfo[p_our_id].state = ID_ASSIGNED; 55861da177e4SLinus Torvalds 55875c04a7b8SAlexey Dobriyan if (ScamFlg & SCAM_ENABLED) { 55881da177e4SLinus Torvalds 55895c04a7b8SAlexey Dobriyan for (i = 0; i < MAX_SCSI_TAR; i++) { 559047b5d69cSJames Bottomley if ((FPT_scamInfo[i].state == ID_UNASSIGNED) || 55915c04a7b8SAlexey Dobriyan (FPT_scamInfo[i].state == ID_UNUSED)) { 55925c04a7b8SAlexey Dobriyan if (FPT_scsell(p_port, i)) { 559347b5d69cSJames Bottomley FPT_scamInfo[i].state = LEGACY; 55945c04a7b8SAlexey Dobriyan if ((FPT_scamInfo[i]. 55955c04a7b8SAlexey Dobriyan id_string[0] != 0xFF) 55965c04a7b8SAlexey Dobriyan || (FPT_scamInfo[i]. 55975c04a7b8SAlexey Dobriyan id_string[1] != 0xFA)) { 55981da177e4SLinus Torvalds 55995c04a7b8SAlexey Dobriyan FPT_scamInfo[i]. 56005c04a7b8SAlexey Dobriyan id_string[0] = 0xFF; 56015c04a7b8SAlexey Dobriyan FPT_scamInfo[i]. 56025c04a7b8SAlexey Dobriyan id_string[1] = 0xFA; 56031da177e4SLinus Torvalds if (pCurrNvRam == NULL) 56045c04a7b8SAlexey Dobriyan currCard-> 56055c04a7b8SAlexey Dobriyan globalFlags 56065c04a7b8SAlexey Dobriyan |= 56075c04a7b8SAlexey Dobriyan F_UPDATE_EEPROM; 56081da177e4SLinus Torvalds } 56091da177e4SLinus Torvalds } 56101da177e4SLinus Torvalds } 56111da177e4SLinus Torvalds } 56121da177e4SLinus Torvalds 561347b5d69cSJames Bottomley FPT_sresb(p_port, p_card); 561447b5d69cSJames Bottomley FPT_Wait1Second(p_port); 56155c04a7b8SAlexey Dobriyan while (!(FPT_scarb(p_port, INIT_SELTD))) { 56165c04a7b8SAlexey Dobriyan } 561747b5d69cSJames Bottomley FPT_scsel(p_port); 561847b5d69cSJames Bottomley FPT_scasid(p_card, p_port); 56191da177e4SLinus Torvalds } 56201da177e4SLinus Torvalds 56211da177e4SLinus Torvalds } 56221da177e4SLinus Torvalds 56235c04a7b8SAlexey Dobriyan else if ((loser) && (ScamFlg & SCAM_ENABLED)) { 562447b5d69cSJames Bottomley FPT_scamInfo[p_our_id].id_string[0] = SLV_TYPE_CODE0; 562547b5d69cSJames Bottomley assigned_id = 0; 562647b5d69cSJames Bottomley FPT_scwtsel(p_port); 56271da177e4SLinus Torvalds 56281da177e4SLinus Torvalds do { 56295c04a7b8SAlexey Dobriyan while (FPT_scxferc(p_port, 0x00) != SYNC_PTRN) { 56305c04a7b8SAlexey Dobriyan } 56311da177e4SLinus Torvalds 563247b5d69cSJames Bottomley i = FPT_scxferc(p_port, 0x00); 56335c04a7b8SAlexey Dobriyan if (i == ASSIGN_ID) { 56345c04a7b8SAlexey Dobriyan if (! 56355c04a7b8SAlexey Dobriyan (FPT_scsendi 56365c04a7b8SAlexey Dobriyan (p_port, 56375c04a7b8SAlexey Dobriyan &FPT_scamInfo[p_our_id].id_string[0]))) { 563847b5d69cSJames Bottomley i = FPT_scxferc(p_port, 0x00); 56395c04a7b8SAlexey Dobriyan if (FPT_scvalq(i)) { 564047b5d69cSJames Bottomley k = FPT_scxferc(p_port, 0x00); 56411da177e4SLinus Torvalds 56425c04a7b8SAlexey Dobriyan if (FPT_scvalq(k)) { 56431da177e4SLinus Torvalds currCard->ourId = 56445c04a7b8SAlexey Dobriyan ((unsigned char)(i 56455c04a7b8SAlexey Dobriyan << 56465c04a7b8SAlexey Dobriyan 3) 56475c04a7b8SAlexey Dobriyan + 56485c04a7b8SAlexey Dobriyan (k & 56495c04a7b8SAlexey Dobriyan (unsigned char)7)) 56505c04a7b8SAlexey Dobriyan & (unsigned char) 56515c04a7b8SAlexey Dobriyan 0x3F; 56525c04a7b8SAlexey Dobriyan FPT_inisci(p_card, 56535c04a7b8SAlexey Dobriyan p_port, 56545c04a7b8SAlexey Dobriyan p_our_id); 56555c04a7b8SAlexey Dobriyan FPT_scamInfo[currCard-> 56565c04a7b8SAlexey Dobriyan ourId]. 56575c04a7b8SAlexey Dobriyan state = ID_ASSIGNED; 56585c04a7b8SAlexey Dobriyan FPT_scamInfo[currCard-> 56595c04a7b8SAlexey Dobriyan ourId]. 56605c04a7b8SAlexey Dobriyan id_string[0] 56611da177e4SLinus Torvalds = SLV_TYPE_CODE0; 566247b5d69cSJames Bottomley assigned_id = 1; 56631da177e4SLinus Torvalds } 56641da177e4SLinus Torvalds } 56651da177e4SLinus Torvalds } 56661da177e4SLinus Torvalds } 56671da177e4SLinus Torvalds 56685c04a7b8SAlexey Dobriyan else if (i == SET_P_FLAG) { 566947b5d69cSJames Bottomley if (!(FPT_scsendi(p_port, 56705c04a7b8SAlexey Dobriyan &FPT_scamInfo[p_our_id]. 56715c04a7b8SAlexey Dobriyan id_string[0]))) 56725c04a7b8SAlexey Dobriyan FPT_scamInfo[p_our_id].id_string[0] |= 56735c04a7b8SAlexey Dobriyan 0x80; 56741da177e4SLinus Torvalds } 56751da177e4SLinus Torvalds } while (!assigned_id); 56761da177e4SLinus Torvalds 56775c04a7b8SAlexey Dobriyan while (FPT_scxferc(p_port, 0x00) != CFG_CMPLT) { 56785c04a7b8SAlexey Dobriyan } 56791da177e4SLinus Torvalds } 56801da177e4SLinus Torvalds 56815c04a7b8SAlexey Dobriyan if (ScamFlg & SCAM_ENABLED) { 568247b5d69cSJames Bottomley FPT_scbusf(p_port); 56835c04a7b8SAlexey Dobriyan if (currCard->globalFlags & F_UPDATE_EEPROM) { 568447b5d69cSJames Bottomley FPT_scsavdi(p_card, p_port); 56851da177e4SLinus Torvalds currCard->globalFlags &= ~F_UPDATE_EEPROM; 56861da177e4SLinus Torvalds } 56871da177e4SLinus Torvalds } 56881da177e4SLinus Torvalds 56891da177e4SLinus Torvalds /* 56901da177e4SLinus Torvalds for (i=0,k=0; i < MAX_SCSI_TAR; i++) 56911da177e4SLinus Torvalds { 569247b5d69cSJames Bottomley if ((FPT_scamInfo[i].state == ID_ASSIGNED) || 569347b5d69cSJames Bottomley (FPT_scamInfo[i].state == LEGACY)) 56941da177e4SLinus Torvalds k++; 56951da177e4SLinus Torvalds } 56961da177e4SLinus Torvalds 56971da177e4SLinus Torvalds if (k==2) 56981da177e4SLinus Torvalds currCard->globalFlags |= F_SINGLE_DEVICE; 56991da177e4SLinus Torvalds else 57001da177e4SLinus Torvalds currCard->globalFlags &= ~F_SINGLE_DEVICE; 57011da177e4SLinus Torvalds */ 57021da177e4SLinus Torvalds } 57031da177e4SLinus Torvalds 57041da177e4SLinus Torvalds /*--------------------------------------------------------------------- 57051da177e4SLinus Torvalds * 570647b5d69cSJames Bottomley * Function: FPT_scarb 57071da177e4SLinus Torvalds * 57081da177e4SLinus Torvalds * Description: Gain control of the bus and wait SCAM select time (250ms) 57091da177e4SLinus Torvalds * 57101da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 57111da177e4SLinus Torvalds 5712d63a4cccSAlexey Dobriyan static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type) 57131da177e4SLinus Torvalds { 57145c04a7b8SAlexey Dobriyan if (p_sel_type == INIT_SELTD) { 57151da177e4SLinus Torvalds 57165c04a7b8SAlexey Dobriyan while (RD_HARPOON(p_port + hp_scsisig) & (SCSI_SEL | SCSI_BSY)) { 57175c04a7b8SAlexey Dobriyan } 57181da177e4SLinus Torvalds 57191da177e4SLinus Torvalds if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL) 57205c1b85e2SAlexey Dobriyan return 0; 57211da177e4SLinus Torvalds 57221da177e4SLinus Torvalds if (RD_HARPOON(p_port + hp_scsidata_0) != 00) 57235c1b85e2SAlexey Dobriyan return 0; 57241da177e4SLinus Torvalds 57255c04a7b8SAlexey Dobriyan WR_HARPOON(p_port + hp_scsisig, 57265c04a7b8SAlexey Dobriyan (RD_HARPOON(p_port + hp_scsisig) | SCSI_BSY)); 57271da177e4SLinus Torvalds 57281da177e4SLinus Torvalds if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL) { 57291da177e4SLinus Torvalds 57305c04a7b8SAlexey Dobriyan WR_HARPOON(p_port + hp_scsisig, 57315c04a7b8SAlexey Dobriyan (RD_HARPOON(p_port + hp_scsisig) & 57321da177e4SLinus Torvalds ~SCSI_BSY)); 57335c1b85e2SAlexey Dobriyan return 0; 57341da177e4SLinus Torvalds } 57351da177e4SLinus Torvalds 57365c04a7b8SAlexey Dobriyan WR_HARPOON(p_port + hp_scsisig, 57375c04a7b8SAlexey Dobriyan (RD_HARPOON(p_port + hp_scsisig) | SCSI_SEL)); 57381da177e4SLinus Torvalds 57391da177e4SLinus Torvalds if (RD_HARPOON(p_port + hp_scsidata_0) != 00) { 57401da177e4SLinus Torvalds 57415c04a7b8SAlexey Dobriyan WR_HARPOON(p_port + hp_scsisig, 57425c04a7b8SAlexey Dobriyan (RD_HARPOON(p_port + hp_scsisig) & 57431da177e4SLinus Torvalds ~(SCSI_BSY | SCSI_SEL))); 57445c1b85e2SAlexey Dobriyan return 0; 57451da177e4SLinus Torvalds } 57461da177e4SLinus Torvalds } 57471da177e4SLinus Torvalds 57481da177e4SLinus Torvalds WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0) 57491da177e4SLinus Torvalds & ~ACTdeassert)); 57501da177e4SLinus Torvalds WR_HARPOON(p_port + hp_scsireset, SCAM_EN); 57511da177e4SLinus Torvalds WR_HARPOON(p_port + hp_scsidata_0, 0x00); 57521da177e4SLinus Torvalds WR_HARPOON(p_port + hp_scsidata_1, 0x00); 57531da177e4SLinus Torvalds WR_HARPOON(p_port + hp_portctrl_0, SCSI_BUS_EN); 57541da177e4SLinus Torvalds 57555c04a7b8SAlexey Dobriyan WR_HARPOON(p_port + hp_scsisig, 57565c04a7b8SAlexey Dobriyan (RD_HARPOON(p_port + hp_scsisig) | SCSI_MSG)); 57571da177e4SLinus Torvalds 57581da177e4SLinus Torvalds WR_HARPOON(p_port + hp_scsisig, (RD_HARPOON(p_port + hp_scsisig) 57591da177e4SLinus Torvalds & ~SCSI_BSY)); 57601da177e4SLinus Torvalds 576147b5d69cSJames Bottomley FPT_Wait(p_port, TO_250ms); 57621da177e4SLinus Torvalds 57635c1b85e2SAlexey Dobriyan return 1; 57641da177e4SLinus Torvalds } 57651da177e4SLinus Torvalds 57661da177e4SLinus Torvalds /*--------------------------------------------------------------------- 57671da177e4SLinus Torvalds * 576847b5d69cSJames Bottomley * Function: FPT_scbusf 57691da177e4SLinus Torvalds * 57701da177e4SLinus Torvalds * Description: Release the SCSI bus and disable SCAM selection. 57711da177e4SLinus Torvalds * 57721da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 57731da177e4SLinus Torvalds 5774d63a4cccSAlexey Dobriyan static void FPT_scbusf(unsigned long p_port) 57751da177e4SLinus Torvalds { 57761da177e4SLinus Torvalds WR_HARPOON(p_port + hp_page_ctrl, 57771da177e4SLinus Torvalds (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE)); 57781da177e4SLinus Torvalds 57791da177e4SLinus Torvalds WR_HARPOON(p_port + hp_scsidata_0, 0x00); 57801da177e4SLinus Torvalds 57811da177e4SLinus Torvalds WR_HARPOON(p_port + hp_portctrl_0, (RD_HARPOON(p_port + hp_portctrl_0) 57821da177e4SLinus Torvalds & ~SCSI_BUS_EN)); 57831da177e4SLinus Torvalds 57841da177e4SLinus Torvalds WR_HARPOON(p_port + hp_scsisig, 0x00); 57851da177e4SLinus Torvalds 57861da177e4SLinus Torvalds WR_HARPOON(p_port + hp_scsireset, (RD_HARPOON(p_port + hp_scsireset) 57871da177e4SLinus Torvalds & ~SCAM_EN)); 57881da177e4SLinus Torvalds 57891da177e4SLinus Torvalds WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0) 57901da177e4SLinus Torvalds | ACTdeassert)); 57911da177e4SLinus Torvalds 57921da177e4SLinus Torvalds WRW_HARPOON((p_port + hp_intstat), (BUS_FREE | AUTO_INT | SCAM_SEL)); 57931da177e4SLinus Torvalds 57941da177e4SLinus Torvalds WR_HARPOON(p_port + hp_page_ctrl, 57951da177e4SLinus Torvalds (RD_HARPOON(p_port + hp_page_ctrl) & ~G_INT_DISABLE)); 57961da177e4SLinus Torvalds } 57971da177e4SLinus Torvalds 57981da177e4SLinus Torvalds /*--------------------------------------------------------------------- 57991da177e4SLinus Torvalds * 580047b5d69cSJames Bottomley * Function: FPT_scasid 58011da177e4SLinus Torvalds * 58021da177e4SLinus Torvalds * Description: Assign an ID to all the SCAM devices. 58031da177e4SLinus Torvalds * 58041da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 58051da177e4SLinus Torvalds 5806d63a4cccSAlexey Dobriyan static void FPT_scasid(unsigned char p_card, unsigned long p_port) 58071da177e4SLinus Torvalds { 5808db038cf8SAlexey Dobriyan unsigned char temp_id_string[ID_STRING_LENGTH]; 58091da177e4SLinus Torvalds 5810db038cf8SAlexey Dobriyan unsigned char i, k, scam_id; 5811db038cf8SAlexey Dobriyan unsigned char crcBytes[3]; 581268d0c1aeSAlexey Dobriyan struct nvram_info *pCurrNvRam; 5813fd1e29edSAlexey Dobriyan unsigned short *pCrcBytes; 58141da177e4SLinus Torvalds 581547b5d69cSJames Bottomley pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo; 58161da177e4SLinus Torvalds 581747b5d69cSJames Bottomley i = 0; 58181da177e4SLinus Torvalds 58195c04a7b8SAlexey Dobriyan while (!i) { 58201da177e4SLinus Torvalds 58215c04a7b8SAlexey Dobriyan for (k = 0; k < ID_STRING_LENGTH; k++) { 5822db038cf8SAlexey Dobriyan temp_id_string[k] = (unsigned char)0x00; 58231da177e4SLinus Torvalds } 58241da177e4SLinus Torvalds 582547b5d69cSJames Bottomley FPT_scxferc(p_port, SYNC_PTRN); 582647b5d69cSJames Bottomley FPT_scxferc(p_port, ASSIGN_ID); 58271da177e4SLinus Torvalds 58285c04a7b8SAlexey Dobriyan if (!(FPT_sciso(p_port, &temp_id_string[0]))) { 58291da177e4SLinus Torvalds if (pCurrNvRam) { 5830fd1e29edSAlexey Dobriyan pCrcBytes = (unsigned short *)&crcBytes[0]; 583147b5d69cSJames Bottomley *pCrcBytes = FPT_CalcCrc16(&temp_id_string[0]); 583247b5d69cSJames Bottomley crcBytes[2] = FPT_CalcLrc(&temp_id_string[0]); 58331da177e4SLinus Torvalds temp_id_string[1] = crcBytes[2]; 58341da177e4SLinus Torvalds temp_id_string[2] = crcBytes[0]; 58351da177e4SLinus Torvalds temp_id_string[3] = crcBytes[1]; 58361da177e4SLinus Torvalds for (k = 4; k < ID_STRING_LENGTH; k++) 5837db038cf8SAlexey Dobriyan temp_id_string[k] = (unsigned char)0x00; 58381da177e4SLinus Torvalds } 583947b5d69cSJames Bottomley i = FPT_scmachid(p_card, temp_id_string); 58401da177e4SLinus Torvalds 58415c04a7b8SAlexey Dobriyan if (i == CLR_PRIORITY) { 584247b5d69cSJames Bottomley FPT_scxferc(p_port, MISC_CODE); 584347b5d69cSJames Bottomley FPT_scxferc(p_port, CLR_P_FLAG); 584447b5d69cSJames Bottomley i = 0; /*Not the last ID yet. */ 58451da177e4SLinus Torvalds } 58461da177e4SLinus Torvalds 58475c04a7b8SAlexey Dobriyan else if (i != NO_ID_AVAIL) { 58481da177e4SLinus Torvalds if (i < 8) 584947b5d69cSJames Bottomley FPT_scxferc(p_port, ID_0_7); 58501da177e4SLinus Torvalds else 585147b5d69cSJames Bottomley FPT_scxferc(p_port, ID_8_F); 58521da177e4SLinus Torvalds 5853db038cf8SAlexey Dobriyan scam_id = (i & (unsigned char)0x07); 58541da177e4SLinus Torvalds 58551da177e4SLinus Torvalds for (k = 1; k < 0x08; k <<= 1) 58561da177e4SLinus Torvalds if (!(k & i)) 58571da177e4SLinus Torvalds scam_id += 0x08; /*Count number of zeros in DB0-3. */ 58581da177e4SLinus Torvalds 585947b5d69cSJames Bottomley FPT_scxferc(p_port, scam_id); 58601da177e4SLinus Torvalds 586147b5d69cSJames Bottomley i = 0; /*Not the last ID yet. */ 58621da177e4SLinus Torvalds } 58631da177e4SLinus Torvalds } 58641da177e4SLinus Torvalds 58655c04a7b8SAlexey Dobriyan else { 586647b5d69cSJames Bottomley i = 1; 58671da177e4SLinus Torvalds } 58681da177e4SLinus Torvalds 58691da177e4SLinus Torvalds } /*End while */ 58701da177e4SLinus Torvalds 587147b5d69cSJames Bottomley FPT_scxferc(p_port, SYNC_PTRN); 587247b5d69cSJames Bottomley FPT_scxferc(p_port, CFG_CMPLT); 58731da177e4SLinus Torvalds } 58741da177e4SLinus Torvalds 58751da177e4SLinus Torvalds /*--------------------------------------------------------------------- 58761da177e4SLinus Torvalds * 587747b5d69cSJames Bottomley * Function: FPT_scsel 58781da177e4SLinus Torvalds * 58791da177e4SLinus Torvalds * Description: Select all the SCAM devices. 58801da177e4SLinus Torvalds * 58811da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 58821da177e4SLinus Torvalds 5883d63a4cccSAlexey Dobriyan static void FPT_scsel(unsigned long p_port) 58841da177e4SLinus Torvalds { 58851da177e4SLinus Torvalds 58861da177e4SLinus Torvalds WR_HARPOON(p_port + hp_scsisig, SCSI_SEL); 588747b5d69cSJames Bottomley FPT_scwiros(p_port, SCSI_MSG); 58881da177e4SLinus Torvalds 58891da177e4SLinus Torvalds WR_HARPOON(p_port + hp_scsisig, (SCSI_SEL | SCSI_BSY)); 58901da177e4SLinus Torvalds 58915c04a7b8SAlexey Dobriyan WR_HARPOON(p_port + hp_scsisig, 58925c04a7b8SAlexey Dobriyan (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD)); 58935c04a7b8SAlexey Dobriyan WR_HARPOON(p_port + hp_scsidata_0, 58945c04a7b8SAlexey Dobriyan (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) | 5895db038cf8SAlexey Dobriyan (unsigned char)(BIT(7) + BIT(6)))); 58961da177e4SLinus Torvalds 58971da177e4SLinus Torvalds WR_HARPOON(p_port + hp_scsisig, (SCSI_BSY | SCSI_IOBIT | SCSI_CD)); 589847b5d69cSJames Bottomley FPT_scwiros(p_port, SCSI_SEL); 58991da177e4SLinus Torvalds 59005c04a7b8SAlexey Dobriyan WR_HARPOON(p_port + hp_scsidata_0, 59015c04a7b8SAlexey Dobriyan (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) & 5902db038cf8SAlexey Dobriyan ~(unsigned char)BIT(6))); 590347b5d69cSJames Bottomley FPT_scwirod(p_port, BIT(6)); 59041da177e4SLinus Torvalds 59055c04a7b8SAlexey Dobriyan WR_HARPOON(p_port + hp_scsisig, 59065c04a7b8SAlexey Dobriyan (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD)); 59071da177e4SLinus Torvalds } 59081da177e4SLinus Torvalds 59091da177e4SLinus Torvalds /*--------------------------------------------------------------------- 59101da177e4SLinus Torvalds * 591147b5d69cSJames Bottomley * Function: FPT_scxferc 59121da177e4SLinus Torvalds * 59131da177e4SLinus Torvalds * Description: Handshake the p_data (DB4-0) across the bus. 59141da177e4SLinus Torvalds * 59151da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 59161da177e4SLinus Torvalds 5917d63a4cccSAlexey Dobriyan static unsigned char FPT_scxferc(unsigned long p_port, unsigned char p_data) 59181da177e4SLinus Torvalds { 5919db038cf8SAlexey Dobriyan unsigned char curr_data, ret_data; 59201da177e4SLinus Torvalds 59211da177e4SLinus Torvalds curr_data = p_data | BIT(7) | BIT(5); /*Start with DB7 & DB5 asserted. */ 59221da177e4SLinus Torvalds 59231da177e4SLinus Torvalds WR_HARPOON(p_port + hp_scsidata_0, curr_data); 59241da177e4SLinus Torvalds 59251da177e4SLinus Torvalds curr_data &= ~BIT(7); 59261da177e4SLinus Torvalds 59271da177e4SLinus Torvalds WR_HARPOON(p_port + hp_scsidata_0, curr_data); 59281da177e4SLinus Torvalds 592947b5d69cSJames Bottomley FPT_scwirod(p_port, BIT(7)); /*Wait for DB7 to be released. */ 59301da177e4SLinus Torvalds while (!(RD_HARPOON(p_port + hp_scsidata_0) & BIT(5))) ; 59311da177e4SLinus Torvalds 5932db038cf8SAlexey Dobriyan ret_data = (RD_HARPOON(p_port + hp_scsidata_0) & (unsigned char)0x1F); 59331da177e4SLinus Torvalds 59341da177e4SLinus Torvalds curr_data |= BIT(6); 59351da177e4SLinus Torvalds 59361da177e4SLinus Torvalds WR_HARPOON(p_port + hp_scsidata_0, curr_data); 59371da177e4SLinus Torvalds 59381da177e4SLinus Torvalds curr_data &= ~BIT(5); 59391da177e4SLinus Torvalds 59401da177e4SLinus Torvalds WR_HARPOON(p_port + hp_scsidata_0, curr_data); 59411da177e4SLinus Torvalds 594247b5d69cSJames Bottomley FPT_scwirod(p_port, BIT(5)); /*Wait for DB5 to be released. */ 59431da177e4SLinus Torvalds 59441da177e4SLinus Torvalds curr_data &= ~(BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0)); /*Release data bits */ 59451da177e4SLinus Torvalds curr_data |= BIT(7); 59461da177e4SLinus Torvalds 59471da177e4SLinus Torvalds WR_HARPOON(p_port + hp_scsidata_0, curr_data); 59481da177e4SLinus Torvalds 59491da177e4SLinus Torvalds curr_data &= ~BIT(6); 59501da177e4SLinus Torvalds 59511da177e4SLinus Torvalds WR_HARPOON(p_port + hp_scsidata_0, curr_data); 59521da177e4SLinus Torvalds 595347b5d69cSJames Bottomley FPT_scwirod(p_port, BIT(6)); /*Wait for DB6 to be released. */ 59541da177e4SLinus Torvalds 59555c1b85e2SAlexey Dobriyan return ret_data; 59561da177e4SLinus Torvalds } 59571da177e4SLinus Torvalds 59581da177e4SLinus Torvalds /*--------------------------------------------------------------------- 59591da177e4SLinus Torvalds * 596047b5d69cSJames Bottomley * Function: FPT_scsendi 59611da177e4SLinus Torvalds * 59621da177e4SLinus Torvalds * Description: Transfer our Identification string to determine if we 59631da177e4SLinus Torvalds * will be the dominant master. 59641da177e4SLinus Torvalds * 59651da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 59661da177e4SLinus Torvalds 59675c04a7b8SAlexey Dobriyan static unsigned char FPT_scsendi(unsigned long p_port, 59685c04a7b8SAlexey Dobriyan unsigned char p_id_string[]) 59691da177e4SLinus Torvalds { 5970db038cf8SAlexey Dobriyan unsigned char ret_data, byte_cnt, bit_cnt, defer; 59711da177e4SLinus Torvalds 597247b5d69cSJames Bottomley defer = 0; 59731da177e4SLinus Torvalds 59741da177e4SLinus Torvalds for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) { 59751da177e4SLinus Torvalds 59761da177e4SLinus Torvalds for (bit_cnt = 0x80; bit_cnt != 0; bit_cnt >>= 1) { 59771da177e4SLinus Torvalds 59781da177e4SLinus Torvalds if (defer) 597947b5d69cSJames Bottomley ret_data = FPT_scxferc(p_port, 00); 59801da177e4SLinus Torvalds 59811da177e4SLinus Torvalds else if (p_id_string[byte_cnt] & bit_cnt) 59821da177e4SLinus Torvalds 598347b5d69cSJames Bottomley ret_data = FPT_scxferc(p_port, 02); 59841da177e4SLinus Torvalds 59851da177e4SLinus Torvalds else { 59861da177e4SLinus Torvalds 598747b5d69cSJames Bottomley ret_data = FPT_scxferc(p_port, 01); 59881da177e4SLinus Torvalds if (ret_data & 02) 598947b5d69cSJames Bottomley defer = 1; 59901da177e4SLinus Torvalds } 59911da177e4SLinus Torvalds 59921da177e4SLinus Torvalds if ((ret_data & 0x1C) == 0x10) 59935c1b85e2SAlexey Dobriyan return 0x00; /*End of isolation stage, we won! */ 59941da177e4SLinus Torvalds 59951da177e4SLinus Torvalds if (ret_data & 0x1C) 59965c1b85e2SAlexey Dobriyan return 0xFF; 59971da177e4SLinus Torvalds 59981da177e4SLinus Torvalds if ((defer) && (!(ret_data & 0x1F))) 59995c1b85e2SAlexey Dobriyan return 0x01; /*End of isolation stage, we lost. */ 60001da177e4SLinus Torvalds 60011da177e4SLinus Torvalds } /*bit loop */ 60021da177e4SLinus Torvalds 60031da177e4SLinus Torvalds } /*byte loop */ 60041da177e4SLinus Torvalds 60051da177e4SLinus Torvalds if (defer) 60065c1b85e2SAlexey Dobriyan return 0x01; /*We lost */ 60071da177e4SLinus Torvalds else 60085c1b85e2SAlexey Dobriyan return 0; /*We WON! Yeeessss! */ 60091da177e4SLinus Torvalds } 60101da177e4SLinus Torvalds 60111da177e4SLinus Torvalds /*--------------------------------------------------------------------- 60121da177e4SLinus Torvalds * 601347b5d69cSJames Bottomley * Function: FPT_sciso 60141da177e4SLinus Torvalds * 60151da177e4SLinus Torvalds * Description: Transfer the Identification string. 60161da177e4SLinus Torvalds * 60171da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 60181da177e4SLinus Torvalds 60195c04a7b8SAlexey Dobriyan static unsigned char FPT_sciso(unsigned long p_port, 60205c04a7b8SAlexey Dobriyan unsigned char p_id_string[]) 60211da177e4SLinus Torvalds { 6022db038cf8SAlexey Dobriyan unsigned char ret_data, the_data, byte_cnt, bit_cnt; 60231da177e4SLinus Torvalds 60241da177e4SLinus Torvalds the_data = 0; 60251da177e4SLinus Torvalds 60261da177e4SLinus Torvalds for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) { 60271da177e4SLinus Torvalds 60281da177e4SLinus Torvalds for (bit_cnt = 0; bit_cnt < 8; bit_cnt++) { 60291da177e4SLinus Torvalds 603047b5d69cSJames Bottomley ret_data = FPT_scxferc(p_port, 0); 60311da177e4SLinus Torvalds 60321da177e4SLinus Torvalds if (ret_data & 0xFC) 60335c1b85e2SAlexey Dobriyan return 0xFF; 60341da177e4SLinus Torvalds 60351da177e4SLinus Torvalds else { 60361da177e4SLinus Torvalds 60371da177e4SLinus Torvalds the_data <<= 1; 60381da177e4SLinus Torvalds if (ret_data & BIT(1)) { 60391da177e4SLinus Torvalds the_data |= 1; 60401da177e4SLinus Torvalds } 60411da177e4SLinus Torvalds } 60421da177e4SLinus Torvalds 60435c04a7b8SAlexey Dobriyan if ((ret_data & 0x1F) == 0) { 60441da177e4SLinus Torvalds /* 60451da177e4SLinus Torvalds if(bit_cnt != 0 || bit_cnt != 8) 60461da177e4SLinus Torvalds { 60471da177e4SLinus Torvalds byte_cnt = 0; 60481da177e4SLinus Torvalds bit_cnt = 0; 604947b5d69cSJames Bottomley FPT_scxferc(p_port, SYNC_PTRN); 605047b5d69cSJames Bottomley FPT_scxferc(p_port, ASSIGN_ID); 60511da177e4SLinus Torvalds continue; 60521da177e4SLinus Torvalds } 60531da177e4SLinus Torvalds */ 60541da177e4SLinus Torvalds if (byte_cnt) 60555c1b85e2SAlexey Dobriyan return 0x00; 60561da177e4SLinus Torvalds else 60575c1b85e2SAlexey Dobriyan return 0xFF; 60581da177e4SLinus Torvalds } 60591da177e4SLinus Torvalds 60601da177e4SLinus Torvalds } /*bit loop */ 60611da177e4SLinus Torvalds 60621da177e4SLinus Torvalds p_id_string[byte_cnt] = the_data; 60631da177e4SLinus Torvalds 60641da177e4SLinus Torvalds } /*byte loop */ 60651da177e4SLinus Torvalds 60665c1b85e2SAlexey Dobriyan return 0; 60671da177e4SLinus Torvalds } 60681da177e4SLinus Torvalds 60691da177e4SLinus Torvalds /*--------------------------------------------------------------------- 60701da177e4SLinus Torvalds * 607147b5d69cSJames Bottomley * Function: FPT_scwirod 60721da177e4SLinus Torvalds * 60731da177e4SLinus Torvalds * Description: Sample the SCSI data bus making sure the signal has been 60741da177e4SLinus Torvalds * deasserted for the correct number of consecutive samples. 60751da177e4SLinus Torvalds * 60761da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 60771da177e4SLinus Torvalds 6078d63a4cccSAlexey Dobriyan static void FPT_scwirod(unsigned long p_port, unsigned char p_data_bit) 60791da177e4SLinus Torvalds { 6080db038cf8SAlexey Dobriyan unsigned char i; 60811da177e4SLinus Torvalds 60821da177e4SLinus Torvalds i = 0; 60831da177e4SLinus Torvalds while (i < MAX_SCSI_TAR) { 60841da177e4SLinus Torvalds 60851da177e4SLinus Torvalds if (RD_HARPOON(p_port + hp_scsidata_0) & p_data_bit) 60861da177e4SLinus Torvalds 60871da177e4SLinus Torvalds i = 0; 60881da177e4SLinus Torvalds 60891da177e4SLinus Torvalds else 60901da177e4SLinus Torvalds 60911da177e4SLinus Torvalds i++; 60921da177e4SLinus Torvalds 60931da177e4SLinus Torvalds } 60941da177e4SLinus Torvalds } 60951da177e4SLinus Torvalds 60961da177e4SLinus Torvalds /*--------------------------------------------------------------------- 60971da177e4SLinus Torvalds * 609847b5d69cSJames Bottomley * Function: FPT_scwiros 60991da177e4SLinus Torvalds * 61001da177e4SLinus Torvalds * Description: Sample the SCSI Signal lines making sure the signal has been 61011da177e4SLinus Torvalds * deasserted for the correct number of consecutive samples. 61021da177e4SLinus Torvalds * 61031da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 61041da177e4SLinus Torvalds 6105d63a4cccSAlexey Dobriyan static void FPT_scwiros(unsigned long p_port, unsigned char p_data_bit) 61061da177e4SLinus Torvalds { 6107db038cf8SAlexey Dobriyan unsigned char i; 61081da177e4SLinus Torvalds 61091da177e4SLinus Torvalds i = 0; 61101da177e4SLinus Torvalds while (i < MAX_SCSI_TAR) { 61111da177e4SLinus Torvalds 61121da177e4SLinus Torvalds if (RD_HARPOON(p_port + hp_scsisig) & p_data_bit) 61131da177e4SLinus Torvalds 61141da177e4SLinus Torvalds i = 0; 61151da177e4SLinus Torvalds 61161da177e4SLinus Torvalds else 61171da177e4SLinus Torvalds 61181da177e4SLinus Torvalds i++; 61191da177e4SLinus Torvalds 61201da177e4SLinus Torvalds } 61211da177e4SLinus Torvalds } 61221da177e4SLinus Torvalds 61231da177e4SLinus Torvalds /*--------------------------------------------------------------------- 61241da177e4SLinus Torvalds * 612547b5d69cSJames Bottomley * Function: FPT_scvalq 61261da177e4SLinus Torvalds * 61271da177e4SLinus Torvalds * Description: Make sure we received a valid data byte. 61281da177e4SLinus Torvalds * 61291da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 61301da177e4SLinus Torvalds 6131db038cf8SAlexey Dobriyan static unsigned char FPT_scvalq(unsigned char p_quintet) 61321da177e4SLinus Torvalds { 6133db038cf8SAlexey Dobriyan unsigned char count; 61341da177e4SLinus Torvalds 61351da177e4SLinus Torvalds for (count = 1; count < 0x08; count <<= 1) { 61361da177e4SLinus Torvalds if (!(p_quintet & count)) 61371da177e4SLinus Torvalds p_quintet -= 0x80; 61381da177e4SLinus Torvalds } 61391da177e4SLinus Torvalds 61401da177e4SLinus Torvalds if (p_quintet & 0x18) 61415c1b85e2SAlexey Dobriyan return 0; 61421da177e4SLinus Torvalds 61431da177e4SLinus Torvalds else 61445c1b85e2SAlexey Dobriyan return 1; 61451da177e4SLinus Torvalds } 61461da177e4SLinus Torvalds 61471da177e4SLinus Torvalds /*--------------------------------------------------------------------- 61481da177e4SLinus Torvalds * 614947b5d69cSJames Bottomley * Function: FPT_scsell 61501da177e4SLinus Torvalds * 61511da177e4SLinus Torvalds * Description: Select the specified device ID using a selection timeout 61521da177e4SLinus Torvalds * less than 4ms. If somebody responds then it is a legacy 61531da177e4SLinus Torvalds * drive and this ID must be marked as such. 61541da177e4SLinus Torvalds * 61551da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 61561da177e4SLinus Torvalds 6157d63a4cccSAlexey Dobriyan static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id) 61581da177e4SLinus Torvalds { 6159d63a4cccSAlexey Dobriyan unsigned long i; 61601da177e4SLinus Torvalds 61611da177e4SLinus Torvalds WR_HARPOON(p_port + hp_page_ctrl, 61621da177e4SLinus Torvalds (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE)); 61631da177e4SLinus Torvalds 61641da177e4SLinus Torvalds ARAM_ACCESS(p_port); 61651da177e4SLinus Torvalds 61665c04a7b8SAlexey Dobriyan WR_HARPOON(p_port + hp_addstat, 61675c04a7b8SAlexey Dobriyan (RD_HARPOON(p_port + hp_addstat) | SCAM_TIMER)); 61681da177e4SLinus Torvalds WR_HARPOON(p_port + hp_seltimeout, TO_4ms); 61691da177e4SLinus Torvalds 61701da177e4SLinus Torvalds for (i = p_port + CMD_STRT; i < p_port + CMD_STRT + 12; i += 2) { 61711da177e4SLinus Torvalds WRW_HARPOON(i, (MPM_OP + ACOMMAND)); 61721da177e4SLinus Torvalds } 61731da177e4SLinus Torvalds WRW_HARPOON(i, (BRH_OP + ALWAYS + NP)); 61741da177e4SLinus Torvalds 61751da177e4SLinus Torvalds WRW_HARPOON((p_port + hp_intstat), 61761da177e4SLinus Torvalds (RESET | TIMEOUT | SEL | BUS_FREE | AUTO_INT)); 61771da177e4SLinus Torvalds 61781da177e4SLinus Torvalds WR_HARPOON(p_port + hp_select_id, targ_id); 61791da177e4SLinus Torvalds 61801da177e4SLinus Torvalds WR_HARPOON(p_port + hp_portctrl_0, SCSI_PORT); 61811da177e4SLinus Torvalds WR_HARPOON(p_port + hp_autostart_3, (SELECT | CMD_ONLY_STRT)); 61821da177e4SLinus Torvalds WR_HARPOON(p_port + hp_scsictrl_0, (SEL_TAR | ENA_RESEL)); 61831da177e4SLinus Torvalds 61841da177e4SLinus Torvalds while (!(RDW_HARPOON((p_port + hp_intstat)) & 61855c04a7b8SAlexey Dobriyan (RESET | PROG_HLT | TIMEOUT | AUTO_INT))) { 61865c04a7b8SAlexey Dobriyan } 61871da177e4SLinus Torvalds 61881da177e4SLinus Torvalds if (RDW_HARPOON((p_port + hp_intstat)) & RESET) 618947b5d69cSJames Bottomley FPT_Wait(p_port, TO_250ms); 61901da177e4SLinus Torvalds 61911da177e4SLinus Torvalds DISABLE_AUTO(p_port); 61921da177e4SLinus Torvalds 61935c04a7b8SAlexey Dobriyan WR_HARPOON(p_port + hp_addstat, 61945c04a7b8SAlexey Dobriyan (RD_HARPOON(p_port + hp_addstat) & ~SCAM_TIMER)); 61951da177e4SLinus Torvalds WR_HARPOON(p_port + hp_seltimeout, TO_290ms); 61961da177e4SLinus Torvalds 61971da177e4SLinus Torvalds SGRAM_ACCESS(p_port); 61981da177e4SLinus Torvalds 61991da177e4SLinus Torvalds if (RDW_HARPOON((p_port + hp_intstat)) & (RESET | TIMEOUT)) { 62001da177e4SLinus Torvalds 62011da177e4SLinus Torvalds WRW_HARPOON((p_port + hp_intstat), 62021da177e4SLinus Torvalds (RESET | TIMEOUT | SEL | BUS_FREE | PHASE)); 62031da177e4SLinus Torvalds 62041da177e4SLinus Torvalds WR_HARPOON(p_port + hp_page_ctrl, 62055c04a7b8SAlexey Dobriyan (RD_HARPOON(p_port + hp_page_ctrl) & 62065c04a7b8SAlexey Dobriyan ~G_INT_DISABLE)); 62071da177e4SLinus Torvalds 62085c1b85e2SAlexey Dobriyan return 0; /*No legacy device */ 62091da177e4SLinus Torvalds } 62101da177e4SLinus Torvalds 62111da177e4SLinus Torvalds else { 62121da177e4SLinus Torvalds 62131da177e4SLinus Torvalds while (!(RDW_HARPOON((p_port + hp_intstat)) & BUS_FREE)) { 62145c04a7b8SAlexey Dobriyan if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ) { 62155c04a7b8SAlexey Dobriyan WR_HARPOON(p_port + hp_scsisig, 62165c04a7b8SAlexey Dobriyan (SCSI_ACK + S_ILL_PH)); 62171da177e4SLinus Torvalds ACCEPT_MSG(p_port); 62181da177e4SLinus Torvalds } 62191da177e4SLinus Torvalds } 62201da177e4SLinus Torvalds 62211da177e4SLinus Torvalds WRW_HARPOON((p_port + hp_intstat), CLR_ALL_INT_1); 62221da177e4SLinus Torvalds 62231da177e4SLinus Torvalds WR_HARPOON(p_port + hp_page_ctrl, 62245c04a7b8SAlexey Dobriyan (RD_HARPOON(p_port + hp_page_ctrl) & 62255c04a7b8SAlexey Dobriyan ~G_INT_DISABLE)); 62261da177e4SLinus Torvalds 62275c1b85e2SAlexey Dobriyan return 1; /*Found one of them oldies! */ 62281da177e4SLinus Torvalds } 62291da177e4SLinus Torvalds } 62301da177e4SLinus Torvalds 62311da177e4SLinus Torvalds /*--------------------------------------------------------------------- 62321da177e4SLinus Torvalds * 623347b5d69cSJames Bottomley * Function: FPT_scwtsel 62341da177e4SLinus Torvalds * 62351da177e4SLinus Torvalds * Description: Wait to be selected by another SCAM initiator. 62361da177e4SLinus Torvalds * 62371da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 62381da177e4SLinus Torvalds 6239d63a4cccSAlexey Dobriyan static void FPT_scwtsel(unsigned long p_port) 62401da177e4SLinus Torvalds { 62415c04a7b8SAlexey Dobriyan while (!(RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL)) { 62421da177e4SLinus Torvalds } 62435c04a7b8SAlexey Dobriyan } 62441da177e4SLinus Torvalds 62451da177e4SLinus Torvalds /*--------------------------------------------------------------------- 62461da177e4SLinus Torvalds * 624747b5d69cSJames Bottomley * Function: FPT_inisci 62481da177e4SLinus Torvalds * 62491da177e4SLinus Torvalds * Description: Setup the data Structure with the info from the EEPROM. 62501da177e4SLinus Torvalds * 62511da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 62521da177e4SLinus Torvalds 62535c04a7b8SAlexey Dobriyan static void FPT_inisci(unsigned char p_card, unsigned long p_port, 62545c04a7b8SAlexey Dobriyan unsigned char p_our_id) 62551da177e4SLinus Torvalds { 6256db038cf8SAlexey Dobriyan unsigned char i, k, max_id; 6257c823feebSAlexey Dobriyan unsigned short ee_data; 625868d0c1aeSAlexey Dobriyan struct nvram_info *pCurrNvRam; 62591da177e4SLinus Torvalds 626047b5d69cSJames Bottomley pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo; 62611da177e4SLinus Torvalds 62621da177e4SLinus Torvalds if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD) 62631da177e4SLinus Torvalds max_id = 0x08; 62641da177e4SLinus Torvalds 62651da177e4SLinus Torvalds else 62661da177e4SLinus Torvalds max_id = 0x10; 62671da177e4SLinus Torvalds 62681da177e4SLinus Torvalds if (pCurrNvRam) { 62691da177e4SLinus Torvalds for (i = 0; i < max_id; i++) { 62701da177e4SLinus Torvalds 62711da177e4SLinus Torvalds for (k = 0; k < 4; k++) 62725c04a7b8SAlexey Dobriyan FPT_scamInfo[i].id_string[k] = 62735c04a7b8SAlexey Dobriyan pCurrNvRam->niScamTbl[i][k]; 62741da177e4SLinus Torvalds for (k = 4; k < ID_STRING_LENGTH; k++) 62755c04a7b8SAlexey Dobriyan FPT_scamInfo[i].id_string[k] = 62765c04a7b8SAlexey Dobriyan (unsigned char)0x00; 62771da177e4SLinus Torvalds 627847b5d69cSJames Bottomley if (FPT_scamInfo[i].id_string[0] == 0x00) 627947b5d69cSJames Bottomley FPT_scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */ 62801da177e4SLinus Torvalds else 628147b5d69cSJames Bottomley FPT_scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */ 62821da177e4SLinus Torvalds 62831da177e4SLinus Torvalds } 62841da177e4SLinus Torvalds } else { 62855c04a7b8SAlexey Dobriyan for (i = 0; i < max_id; i++) { 62865c04a7b8SAlexey Dobriyan for (k = 0; k < ID_STRING_LENGTH; k += 2) { 62875c04a7b8SAlexey Dobriyan ee_data = 62885c04a7b8SAlexey Dobriyan FPT_utilEERead(p_port, 62895c04a7b8SAlexey Dobriyan (unsigned 62905c04a7b8SAlexey Dobriyan short)((EE_SCAMBASE / 2) + 62915c04a7b8SAlexey Dobriyan (unsigned short)(i * 62925c04a7b8SAlexey Dobriyan ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2))); 62935c04a7b8SAlexey Dobriyan FPT_scamInfo[i].id_string[k] = 62945c04a7b8SAlexey Dobriyan (unsigned char)ee_data; 62951da177e4SLinus Torvalds ee_data >>= 8; 62965c04a7b8SAlexey Dobriyan FPT_scamInfo[i].id_string[k + 1] = 62975c04a7b8SAlexey Dobriyan (unsigned char)ee_data; 62981da177e4SLinus Torvalds } 62991da177e4SLinus Torvalds 630047b5d69cSJames Bottomley if ((FPT_scamInfo[i].id_string[0] == 0x00) || 630147b5d69cSJames Bottomley (FPT_scamInfo[i].id_string[0] == 0xFF)) 63021da177e4SLinus Torvalds 630347b5d69cSJames Bottomley FPT_scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */ 63041da177e4SLinus Torvalds 63051da177e4SLinus Torvalds else 630647b5d69cSJames Bottomley FPT_scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */ 63071da177e4SLinus Torvalds 63081da177e4SLinus Torvalds } 63091da177e4SLinus Torvalds } 63101da177e4SLinus Torvalds for (k = 0; k < ID_STRING_LENGTH; k++) 631147b5d69cSJames Bottomley FPT_scamInfo[p_our_id].id_string[k] = FPT_scamHAString[k]; 63121da177e4SLinus Torvalds 63131da177e4SLinus Torvalds } 63141da177e4SLinus Torvalds 63151da177e4SLinus Torvalds /*--------------------------------------------------------------------- 63161da177e4SLinus Torvalds * 631747b5d69cSJames Bottomley * Function: FPT_scmachid 63181da177e4SLinus Torvalds * 63191da177e4SLinus Torvalds * Description: Match the Device ID string with our values stored in 63201da177e4SLinus Torvalds * the EEPROM. 63211da177e4SLinus Torvalds * 63221da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 63231da177e4SLinus Torvalds 63245c04a7b8SAlexey Dobriyan static unsigned char FPT_scmachid(unsigned char p_card, 63255c04a7b8SAlexey Dobriyan unsigned char p_id_string[]) 63261da177e4SLinus Torvalds { 63271da177e4SLinus Torvalds 6328db038cf8SAlexey Dobriyan unsigned char i, k, match; 63291da177e4SLinus Torvalds 63301da177e4SLinus Torvalds for (i = 0; i < MAX_SCSI_TAR; i++) { 63311da177e4SLinus Torvalds 633247b5d69cSJames Bottomley match = 1; 63331da177e4SLinus Torvalds 63345c04a7b8SAlexey Dobriyan for (k = 0; k < ID_STRING_LENGTH; k++) { 633547b5d69cSJames Bottomley if (p_id_string[k] != FPT_scamInfo[i].id_string[k]) 633647b5d69cSJames Bottomley match = 0; 63371da177e4SLinus Torvalds } 63381da177e4SLinus Torvalds 63395c04a7b8SAlexey Dobriyan if (match) { 634047b5d69cSJames Bottomley FPT_scamInfo[i].state = ID_ASSIGNED; 63415c1b85e2SAlexey Dobriyan return i; 63421da177e4SLinus Torvalds } 63431da177e4SLinus Torvalds 63441da177e4SLinus Torvalds } 63451da177e4SLinus Torvalds 63461da177e4SLinus Torvalds if (p_id_string[0] & BIT(5)) 63471da177e4SLinus Torvalds i = 8; 63481da177e4SLinus Torvalds else 63491da177e4SLinus Torvalds i = MAX_SCSI_TAR; 63501da177e4SLinus Torvalds 63515c04a7b8SAlexey Dobriyan if (((p_id_string[0] & 0x06) == 0x02) 63525c04a7b8SAlexey Dobriyan || ((p_id_string[0] & 0x06) == 0x04)) 6353db038cf8SAlexey Dobriyan match = p_id_string[1] & (unsigned char)0x1F; 63541da177e4SLinus Torvalds else 63551da177e4SLinus Torvalds match = 7; 63561da177e4SLinus Torvalds 63575c04a7b8SAlexey Dobriyan while (i > 0) { 63581da177e4SLinus Torvalds i--; 63591da177e4SLinus Torvalds 63605c04a7b8SAlexey Dobriyan if (FPT_scamInfo[match].state == ID_UNUSED) { 63615c04a7b8SAlexey Dobriyan for (k = 0; k < ID_STRING_LENGTH; k++) { 63625c04a7b8SAlexey Dobriyan FPT_scamInfo[match].id_string[k] = 63635c04a7b8SAlexey Dobriyan p_id_string[k]; 63641da177e4SLinus Torvalds } 63651da177e4SLinus Torvalds 636647b5d69cSJames Bottomley FPT_scamInfo[match].state = ID_ASSIGNED; 63671da177e4SLinus Torvalds 636847b5d69cSJames Bottomley if (FPT_BL_Card[p_card].pNvRamInfo == NULL) 63695c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card].globalFlags |= 63705c04a7b8SAlexey Dobriyan F_UPDATE_EEPROM; 63715c1b85e2SAlexey Dobriyan return match; 63721da177e4SLinus Torvalds 63731da177e4SLinus Torvalds } 63741da177e4SLinus Torvalds 63751da177e4SLinus Torvalds match--; 63761da177e4SLinus Torvalds 63775c04a7b8SAlexey Dobriyan if (match == 0xFF) { 63781da177e4SLinus Torvalds if (p_id_string[0] & BIT(5)) 63791da177e4SLinus Torvalds match = 7; 63801da177e4SLinus Torvalds else 63811da177e4SLinus Torvalds match = MAX_SCSI_TAR - 1; 63821da177e4SLinus Torvalds } 63831da177e4SLinus Torvalds } 63841da177e4SLinus Torvalds 63855c04a7b8SAlexey Dobriyan if (p_id_string[0] & BIT(7)) { 63865c1b85e2SAlexey Dobriyan return CLR_PRIORITY; 63871da177e4SLinus Torvalds } 63881da177e4SLinus Torvalds 63891da177e4SLinus Torvalds if (p_id_string[0] & BIT(5)) 63901da177e4SLinus Torvalds i = 8; 63911da177e4SLinus Torvalds else 63921da177e4SLinus Torvalds i = MAX_SCSI_TAR; 63931da177e4SLinus Torvalds 63945c04a7b8SAlexey Dobriyan if (((p_id_string[0] & 0x06) == 0x02) 63955c04a7b8SAlexey Dobriyan || ((p_id_string[0] & 0x06) == 0x04)) 6396db038cf8SAlexey Dobriyan match = p_id_string[1] & (unsigned char)0x1F; 63971da177e4SLinus Torvalds else 63981da177e4SLinus Torvalds match = 7; 63991da177e4SLinus Torvalds 64005c04a7b8SAlexey Dobriyan while (i > 0) { 64011da177e4SLinus Torvalds 64021da177e4SLinus Torvalds i--; 64031da177e4SLinus Torvalds 64045c04a7b8SAlexey Dobriyan if (FPT_scamInfo[match].state == ID_UNASSIGNED) { 64055c04a7b8SAlexey Dobriyan for (k = 0; k < ID_STRING_LENGTH; k++) { 64065c04a7b8SAlexey Dobriyan FPT_scamInfo[match].id_string[k] = 64075c04a7b8SAlexey Dobriyan p_id_string[k]; 64081da177e4SLinus Torvalds } 64091da177e4SLinus Torvalds 641047b5d69cSJames Bottomley FPT_scamInfo[match].id_string[0] |= BIT(7); 641147b5d69cSJames Bottomley FPT_scamInfo[match].state = ID_ASSIGNED; 641247b5d69cSJames Bottomley if (FPT_BL_Card[p_card].pNvRamInfo == NULL) 64135c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card].globalFlags |= 64145c04a7b8SAlexey Dobriyan F_UPDATE_EEPROM; 64155c1b85e2SAlexey Dobriyan return match; 64161da177e4SLinus Torvalds 64171da177e4SLinus Torvalds } 64181da177e4SLinus Torvalds 64191da177e4SLinus Torvalds match--; 64201da177e4SLinus Torvalds 64215c04a7b8SAlexey Dobriyan if (match == 0xFF) { 64221da177e4SLinus Torvalds if (p_id_string[0] & BIT(5)) 64231da177e4SLinus Torvalds match = 7; 64241da177e4SLinus Torvalds else 64251da177e4SLinus Torvalds match = MAX_SCSI_TAR - 1; 64261da177e4SLinus Torvalds } 64271da177e4SLinus Torvalds } 64281da177e4SLinus Torvalds 64295c1b85e2SAlexey Dobriyan return NO_ID_AVAIL; 64301da177e4SLinus Torvalds } 64311da177e4SLinus Torvalds 64321da177e4SLinus Torvalds /*--------------------------------------------------------------------- 64331da177e4SLinus Torvalds * 643447b5d69cSJames Bottomley * Function: FPT_scsavdi 64351da177e4SLinus Torvalds * 64361da177e4SLinus Torvalds * Description: Save off the device SCAM ID strings. 64371da177e4SLinus Torvalds * 64381da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 64391da177e4SLinus Torvalds 6440d63a4cccSAlexey Dobriyan static void FPT_scsavdi(unsigned char p_card, unsigned long p_port) 64411da177e4SLinus Torvalds { 6442db038cf8SAlexey Dobriyan unsigned char i, k, max_id; 6443c823feebSAlexey Dobriyan unsigned short ee_data, sum_data; 64441da177e4SLinus Torvalds 64451da177e4SLinus Torvalds sum_data = 0x0000; 64461da177e4SLinus Torvalds 64475c04a7b8SAlexey Dobriyan for (i = 1; i < EE_SCAMBASE / 2; i++) { 644847b5d69cSJames Bottomley sum_data += FPT_utilEERead(p_port, i); 64491da177e4SLinus Torvalds } 64501da177e4SLinus Torvalds 645147b5d69cSJames Bottomley FPT_utilEEWriteOnOff(p_port, 1); /* Enable write access to the EEPROM */ 64521da177e4SLinus Torvalds 64531da177e4SLinus Torvalds if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD) 64541da177e4SLinus Torvalds max_id = 0x08; 64551da177e4SLinus Torvalds 64561da177e4SLinus Torvalds else 64571da177e4SLinus Torvalds max_id = 0x10; 64581da177e4SLinus Torvalds 64595c04a7b8SAlexey Dobriyan for (i = 0; i < max_id; i++) { 64601da177e4SLinus Torvalds 64615c04a7b8SAlexey Dobriyan for (k = 0; k < ID_STRING_LENGTH; k += 2) { 646247b5d69cSJames Bottomley ee_data = FPT_scamInfo[i].id_string[k + 1]; 64631da177e4SLinus Torvalds ee_data <<= 8; 646447b5d69cSJames Bottomley ee_data |= FPT_scamInfo[i].id_string[k]; 64651da177e4SLinus Torvalds sum_data += ee_data; 64665c04a7b8SAlexey Dobriyan FPT_utilEEWrite(p_port, ee_data, 64675c04a7b8SAlexey Dobriyan (unsigned short)((EE_SCAMBASE / 2) + 64685c04a7b8SAlexey Dobriyan (unsigned short)(i * 64695c04a7b8SAlexey Dobriyan ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2))); 64701da177e4SLinus Torvalds } 64711da177e4SLinus Torvalds } 64721da177e4SLinus Torvalds 647347b5d69cSJames Bottomley FPT_utilEEWrite(p_port, sum_data, EEPROM_CHECK_SUM / 2); 647447b5d69cSJames Bottomley FPT_utilEEWriteOnOff(p_port, 0); /* Turn off write access */ 64751da177e4SLinus Torvalds } 64761da177e4SLinus Torvalds 64771da177e4SLinus Torvalds /*--------------------------------------------------------------------- 64781da177e4SLinus Torvalds * 647947b5d69cSJames Bottomley * Function: FPT_XbowInit 64801da177e4SLinus Torvalds * 64811da177e4SLinus Torvalds * Description: Setup the Xbow for normal operation. 64821da177e4SLinus Torvalds * 64831da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 64841da177e4SLinus Torvalds 6485d63a4cccSAlexey Dobriyan static void FPT_XbowInit(unsigned long port, unsigned char ScamFlg) 64861da177e4SLinus Torvalds { 6487db038cf8SAlexey Dobriyan unsigned char i; 64881da177e4SLinus Torvalds 64891da177e4SLinus Torvalds i = RD_HARPOON(port + hp_page_ctrl); 6490db038cf8SAlexey Dobriyan WR_HARPOON(port + hp_page_ctrl, (unsigned char)(i | G_INT_DISABLE)); 64911da177e4SLinus Torvalds 64921da177e4SLinus Torvalds WR_HARPOON(port + hp_scsireset, 0x00); 64931da177e4SLinus Torvalds WR_HARPOON(port + hp_portctrl_1, HOST_MODE8); 64941da177e4SLinus Torvalds 64955c04a7b8SAlexey Dobriyan WR_HARPOON(port + hp_scsireset, (DMA_RESET | HPSCSI_RESET | PROG_RESET | 64961da177e4SLinus Torvalds FIFO_CLR)); 64971da177e4SLinus Torvalds 64981da177e4SLinus Torvalds WR_HARPOON(port + hp_scsireset, SCSI_INI); 64991da177e4SLinus Torvalds 65001da177e4SLinus Torvalds WR_HARPOON(port + hp_clkctrl_0, CLKCTRL_DEFAULT); 65011da177e4SLinus Torvalds 65021da177e4SLinus Torvalds WR_HARPOON(port + hp_scsisig, 0x00); /* Clear any signals we might */ 65031da177e4SLinus Torvalds WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL); 65041da177e4SLinus Torvalds 65051da177e4SLinus Torvalds WRW_HARPOON((port + hp_intstat), CLR_ALL_INT); 65061da177e4SLinus Torvalds 650747b5d69cSJames Bottomley FPT_default_intena = RESET | RSEL | PROG_HLT | TIMEOUT | 65081da177e4SLinus Torvalds BUS_FREE | XFER_CNT_0 | AUTO_INT; 65091da177e4SLinus Torvalds 65101da177e4SLinus Torvalds if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2)) 651147b5d69cSJames Bottomley FPT_default_intena |= SCAM_SEL; 65121da177e4SLinus Torvalds 651347b5d69cSJames Bottomley WRW_HARPOON((port + hp_intena), FPT_default_intena); 65141da177e4SLinus Torvalds 65151da177e4SLinus Torvalds WR_HARPOON(port + hp_seltimeout, TO_290ms); 65161da177e4SLinus Torvalds 65171da177e4SLinus Torvalds /* Turn on SCSI_MODE8 for narrow cards to fix the 65181da177e4SLinus Torvalds strapping issue with the DUAL CHANNEL card */ 65191da177e4SLinus Torvalds if (RD_HARPOON(port + hp_page_ctrl) & NARROW_SCSI_CARD) 65201da177e4SLinus Torvalds WR_HARPOON(port + hp_addstat, SCSI_MODE8); 65211da177e4SLinus Torvalds 65221da177e4SLinus Torvalds WR_HARPOON(port + hp_page_ctrl, i); 65231da177e4SLinus Torvalds 65241da177e4SLinus Torvalds } 65251da177e4SLinus Torvalds 65261da177e4SLinus Torvalds /*--------------------------------------------------------------------- 65271da177e4SLinus Torvalds * 652847b5d69cSJames Bottomley * Function: FPT_BusMasterInit 65291da177e4SLinus Torvalds * 65301da177e4SLinus Torvalds * Description: Initialize the BusMaster for normal operations. 65311da177e4SLinus Torvalds * 65321da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 65331da177e4SLinus Torvalds 6534d63a4cccSAlexey Dobriyan static void FPT_BusMasterInit(unsigned long p_port) 65351da177e4SLinus Torvalds { 65361da177e4SLinus Torvalds 65371da177e4SLinus Torvalds WR_HARPOON(p_port + hp_sys_ctrl, DRVR_RST); 65381da177e4SLinus Torvalds WR_HARPOON(p_port + hp_sys_ctrl, 0x00); 65391da177e4SLinus Torvalds 65401da177e4SLinus Torvalds WR_HARPOON(p_port + hp_host_blk_cnt, XFER_BLK64); 65411da177e4SLinus Torvalds 65421da177e4SLinus Torvalds WR_HARPOON(p_port + hp_bm_ctrl, (BMCTRL_DEFAULT)); 65431da177e4SLinus Torvalds 65441da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, (SCSI_TERM_ENA_H)); 65451da177e4SLinus Torvalds 65461da177e4SLinus Torvalds RD_HARPOON(p_port + hp_int_status); /*Clear interrupts. */ 65471da177e4SLinus Torvalds WR_HARPOON(p_port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT)); 65481da177e4SLinus Torvalds WR_HARPOON(p_port + hp_page_ctrl, (RD_HARPOON(p_port + hp_page_ctrl) & 65491da177e4SLinus Torvalds ~SCATTER_EN)); 65501da177e4SLinus Torvalds } 65511da177e4SLinus Torvalds 65521da177e4SLinus Torvalds /*--------------------------------------------------------------------- 65531da177e4SLinus Torvalds * 655447b5d69cSJames Bottomley * Function: FPT_DiagEEPROM 65551da177e4SLinus Torvalds * 65561da177e4SLinus Torvalds * Description: Verfiy checksum and 'Key' and initialize the EEPROM if 65571da177e4SLinus Torvalds * necessary. 65581da177e4SLinus Torvalds * 65591da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 65601da177e4SLinus Torvalds 6561d63a4cccSAlexey Dobriyan static void FPT_DiagEEPROM(unsigned long p_port) 65621da177e4SLinus Torvalds { 6563c823feebSAlexey Dobriyan unsigned short index, temp, max_wd_cnt; 65641da177e4SLinus Torvalds 65651da177e4SLinus Torvalds if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD) 65661da177e4SLinus Torvalds max_wd_cnt = EEPROM_WD_CNT; 65671da177e4SLinus Torvalds else 65681da177e4SLinus Torvalds max_wd_cnt = EEPROM_WD_CNT * 2; 65691da177e4SLinus Torvalds 657047b5d69cSJames Bottomley temp = FPT_utilEERead(p_port, FW_SIGNATURE / 2); 65711da177e4SLinus Torvalds 65721da177e4SLinus Torvalds if (temp == 0x4641) { 65731da177e4SLinus Torvalds 65741da177e4SLinus Torvalds for (index = 2; index < max_wd_cnt; index++) { 65751da177e4SLinus Torvalds 657647b5d69cSJames Bottomley temp += FPT_utilEERead(p_port, index); 65771da177e4SLinus Torvalds 65781da177e4SLinus Torvalds } 65791da177e4SLinus Torvalds 658047b5d69cSJames Bottomley if (temp == FPT_utilEERead(p_port, EEPROM_CHECK_SUM / 2)) { 65811da177e4SLinus Torvalds 65821da177e4SLinus Torvalds return; /*EEPROM is Okay so return now! */ 65831da177e4SLinus Torvalds } 65841da177e4SLinus Torvalds } 65851da177e4SLinus Torvalds 6586db038cf8SAlexey Dobriyan FPT_utilEEWriteOnOff(p_port, (unsigned char)1); 65871da177e4SLinus Torvalds 65881da177e4SLinus Torvalds for (index = 0; index < max_wd_cnt; index++) { 65891da177e4SLinus Torvalds 659047b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x0000, index); 65911da177e4SLinus Torvalds } 65921da177e4SLinus Torvalds 65931da177e4SLinus Torvalds temp = 0; 65941da177e4SLinus Torvalds 659547b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x4641, FW_SIGNATURE / 2); 65961da177e4SLinus Torvalds temp += 0x4641; 659747b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x3920, MODEL_NUMB_0 / 2); 65981da177e4SLinus Torvalds temp += 0x3920; 659947b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x3033, MODEL_NUMB_2 / 2); 66001da177e4SLinus Torvalds temp += 0x3033; 660147b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x2020, MODEL_NUMB_4 / 2); 66021da177e4SLinus Torvalds temp += 0x2020; 660347b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x70D3, SYSTEM_CONFIG / 2); 66041da177e4SLinus Torvalds temp += 0x70D3; 660547b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x0010, BIOS_CONFIG / 2); 66061da177e4SLinus Torvalds temp += 0x0010; 660747b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x0003, SCAM_CONFIG / 2); 66081da177e4SLinus Torvalds temp += 0x0003; 660947b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x0007, ADAPTER_SCSI_ID / 2); 66101da177e4SLinus Torvalds temp += 0x0007; 66111da177e4SLinus Torvalds 661247b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x0000, IGNORE_B_SCAN / 2); 66131da177e4SLinus Torvalds temp += 0x0000; 661447b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x0000, SEND_START_ENA / 2); 66151da177e4SLinus Torvalds temp += 0x0000; 661647b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x0000, DEVICE_ENABLE / 2); 66171da177e4SLinus Torvalds temp += 0x0000; 66181da177e4SLinus Torvalds 661947b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL01 / 2); 66201da177e4SLinus Torvalds temp += 0x4242; 662147b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL23 / 2); 66221da177e4SLinus Torvalds temp += 0x4242; 662347b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL45 / 2); 66241da177e4SLinus Torvalds temp += 0x4242; 662547b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL67 / 2); 66261da177e4SLinus Torvalds temp += 0x4242; 662747b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL89 / 2); 66281da177e4SLinus Torvalds temp += 0x4242; 662947b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLab / 2); 66301da177e4SLinus Torvalds temp += 0x4242; 663147b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLcd / 2); 66321da177e4SLinus Torvalds temp += 0x4242; 663347b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLef / 2); 66341da177e4SLinus Torvalds temp += 0x4242; 66351da177e4SLinus Torvalds 663647b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x6C46, 64 / 2); /*PRODUCT ID */ 66371da177e4SLinus Torvalds temp += 0x6C46; 663847b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x7361, 66 / 2); /* FlashPoint LT */ 66391da177e4SLinus Torvalds temp += 0x7361; 664047b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x5068, 68 / 2); 66411da177e4SLinus Torvalds temp += 0x5068; 664247b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x696F, 70 / 2); 66431da177e4SLinus Torvalds temp += 0x696F; 664447b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x746E, 72 / 2); 66451da177e4SLinus Torvalds temp += 0x746E; 664647b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x4C20, 74 / 2); 66471da177e4SLinus Torvalds temp += 0x4C20; 664847b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x2054, 76 / 2); 66491da177e4SLinus Torvalds temp += 0x2054; 665047b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x2020, 78 / 2); 66511da177e4SLinus Torvalds temp += 0x2020; 66521da177e4SLinus Torvalds 66531da177e4SLinus Torvalds index = ((EE_SCAMBASE / 2) + (7 * 16)); 665447b5d69cSJames Bottomley FPT_utilEEWrite(p_port, (0x0700 + TYPE_CODE0), index); 66551da177e4SLinus Torvalds temp += (0x0700 + TYPE_CODE0); 66561da177e4SLinus Torvalds index++; 665747b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x5542, index); /*Vendor ID code */ 66581da177e4SLinus Torvalds temp += 0x5542; /* BUSLOGIC */ 66591da177e4SLinus Torvalds index++; 666047b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x4C53, index); 66611da177e4SLinus Torvalds temp += 0x4C53; 66621da177e4SLinus Torvalds index++; 666347b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x474F, index); 66641da177e4SLinus Torvalds temp += 0x474F; 66651da177e4SLinus Torvalds index++; 666647b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x4349, index); 66671da177e4SLinus Torvalds temp += 0x4349; 66681da177e4SLinus Torvalds index++; 666947b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x5442, index); /*Vendor unique code */ 66701da177e4SLinus Torvalds temp += 0x5442; /* BT- 930 */ 66711da177e4SLinus Torvalds index++; 667247b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x202D, index); 66731da177e4SLinus Torvalds temp += 0x202D; 66741da177e4SLinus Torvalds index++; 667547b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x3339, index); 66761da177e4SLinus Torvalds temp += 0x3339; 66771da177e4SLinus Torvalds index++; /*Serial # */ 667847b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x2030, index); /* 01234567 */ 66791da177e4SLinus Torvalds temp += 0x2030; 66801da177e4SLinus Torvalds index++; 668147b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x5453, index); 66821da177e4SLinus Torvalds temp += 0x5453; 66831da177e4SLinus Torvalds index++; 668447b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x5645, index); 66851da177e4SLinus Torvalds temp += 0x5645; 66861da177e4SLinus Torvalds index++; 668747b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x2045, index); 66881da177e4SLinus Torvalds temp += 0x2045; 66891da177e4SLinus Torvalds index++; 669047b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x202F, index); 66911da177e4SLinus Torvalds temp += 0x202F; 66921da177e4SLinus Torvalds index++; 669347b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x4F4A, index); 66941da177e4SLinus Torvalds temp += 0x4F4A; 66951da177e4SLinus Torvalds index++; 669647b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x204E, index); 66971da177e4SLinus Torvalds temp += 0x204E; 66981da177e4SLinus Torvalds index++; 669947b5d69cSJames Bottomley FPT_utilEEWrite(p_port, 0x3539, index); 67001da177e4SLinus Torvalds temp += 0x3539; 67011da177e4SLinus Torvalds 670247b5d69cSJames Bottomley FPT_utilEEWrite(p_port, temp, EEPROM_CHECK_SUM / 2); 67031da177e4SLinus Torvalds 6704db038cf8SAlexey Dobriyan FPT_utilEEWriteOnOff(p_port, (unsigned char)0); 67051da177e4SLinus Torvalds 67061da177e4SLinus Torvalds } 67071da177e4SLinus Torvalds 67081da177e4SLinus Torvalds /*--------------------------------------------------------------------- 67091da177e4SLinus Torvalds * 67101da177e4SLinus Torvalds * Function: Queue Search Select 67111da177e4SLinus Torvalds * 67121da177e4SLinus Torvalds * Description: Try to find a new command to execute. 67131da177e4SLinus Torvalds * 67141da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 67151da177e4SLinus Torvalds 67165c04a7b8SAlexey Dobriyan static void FPT_queueSearchSelect(struct sccb_card *pCurrCard, 67175c04a7b8SAlexey Dobriyan unsigned char p_card) 67181da177e4SLinus Torvalds { 6719db038cf8SAlexey Dobriyan unsigned char scan_ptr, lun; 6720f31dc0cdSAlexey Dobriyan struct sccb_mgr_tar_info *currTar_Info; 672169eb2ea4SAlexey Dobriyan struct sccb *pOldSccb; 67221da177e4SLinus Torvalds 67231da177e4SLinus Torvalds scan_ptr = pCurrCard->scanIndex; 67245c04a7b8SAlexey Dobriyan do { 672547b5d69cSJames Bottomley currTar_Info = &FPT_sccbMgrTbl[p_card][scan_ptr]; 67261da177e4SLinus Torvalds if ((pCurrCard->globalFlags & F_CONLUN_IO) && 67275c04a7b8SAlexey Dobriyan ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != 67285c04a7b8SAlexey Dobriyan TAG_Q_TRYING)) { 67295c04a7b8SAlexey Dobriyan if (currTar_Info->TarSelQ_Cnt != 0) { 67301da177e4SLinus Torvalds 67311da177e4SLinus Torvalds scan_ptr++; 67321da177e4SLinus Torvalds if (scan_ptr == MAX_SCSI_TAR) 67331da177e4SLinus Torvalds scan_ptr = 0; 67341da177e4SLinus Torvalds 67355c04a7b8SAlexey Dobriyan for (lun = 0; lun < MAX_LUN; lun++) { 67365c04a7b8SAlexey Dobriyan if (currTar_Info->TarLUNBusy[lun] == 0) { 67371da177e4SLinus Torvalds 67385c04a7b8SAlexey Dobriyan pCurrCard->currentSCCB = 67395c04a7b8SAlexey Dobriyan currTar_Info->TarSelQ_Head; 67401da177e4SLinus Torvalds pOldSccb = NULL; 67411da177e4SLinus Torvalds 67425c04a7b8SAlexey Dobriyan while ((pCurrCard-> 67435c04a7b8SAlexey Dobriyan currentSCCB != NULL) 67445c04a7b8SAlexey Dobriyan && (lun != 67455c04a7b8SAlexey Dobriyan pCurrCard-> 67465c04a7b8SAlexey Dobriyan currentSCCB->Lun)) { 67475c04a7b8SAlexey Dobriyan pOldSccb = 67485c04a7b8SAlexey Dobriyan pCurrCard-> 67495c04a7b8SAlexey Dobriyan currentSCCB; 67505c04a7b8SAlexey Dobriyan pCurrCard->currentSCCB = 67515c04a7b8SAlexey Dobriyan (struct sccb 67525c04a7b8SAlexey Dobriyan *)(pCurrCard-> 67535c04a7b8SAlexey Dobriyan currentSCCB)-> 67541da177e4SLinus Torvalds Sccb_forwardlink; 67551da177e4SLinus Torvalds } 67565c04a7b8SAlexey Dobriyan if (pCurrCard->currentSCCB == 67575c04a7b8SAlexey Dobriyan NULL) 67581da177e4SLinus Torvalds continue; 67595c04a7b8SAlexey Dobriyan if (pOldSccb != NULL) { 67605c04a7b8SAlexey Dobriyan pOldSccb-> 67615c04a7b8SAlexey Dobriyan Sccb_forwardlink = 67625c04a7b8SAlexey Dobriyan (struct sccb 67635c04a7b8SAlexey Dobriyan *)(pCurrCard-> 67645c04a7b8SAlexey Dobriyan currentSCCB)-> 67651da177e4SLinus Torvalds Sccb_forwardlink; 67665c04a7b8SAlexey Dobriyan pOldSccb-> 67675c04a7b8SAlexey Dobriyan Sccb_backlink = 67685c04a7b8SAlexey Dobriyan (struct sccb 67695c04a7b8SAlexey Dobriyan *)(pCurrCard-> 67705c04a7b8SAlexey Dobriyan currentSCCB)-> 67711da177e4SLinus Torvalds Sccb_backlink; 67725c04a7b8SAlexey Dobriyan currTar_Info-> 67735c04a7b8SAlexey Dobriyan TarSelQ_Cnt--; 67745c04a7b8SAlexey Dobriyan } else { 67755c04a7b8SAlexey Dobriyan currTar_Info-> 67765c04a7b8SAlexey Dobriyan TarSelQ_Head = 67775c04a7b8SAlexey Dobriyan (struct sccb 67785c04a7b8SAlexey Dobriyan *)(pCurrCard-> 67795c04a7b8SAlexey Dobriyan currentSCCB)-> 67805c04a7b8SAlexey Dobriyan Sccb_forwardlink; 67811da177e4SLinus Torvalds 67825c04a7b8SAlexey Dobriyan if (currTar_Info-> 67835c04a7b8SAlexey Dobriyan TarSelQ_Head == 67845c04a7b8SAlexey Dobriyan NULL) { 67855c04a7b8SAlexey Dobriyan currTar_Info-> 67865c04a7b8SAlexey Dobriyan TarSelQ_Tail 67875c04a7b8SAlexey Dobriyan = NULL; 67885c04a7b8SAlexey Dobriyan currTar_Info-> 67895c04a7b8SAlexey Dobriyan TarSelQ_Cnt 67905c04a7b8SAlexey Dobriyan = 0; 67915c04a7b8SAlexey Dobriyan } else { 67925c04a7b8SAlexey Dobriyan currTar_Info-> 67935c04a7b8SAlexey Dobriyan TarSelQ_Cnt--; 67945c04a7b8SAlexey Dobriyan currTar_Info-> 67955c04a7b8SAlexey Dobriyan TarSelQ_Head-> 67965c04a7b8SAlexey Dobriyan Sccb_backlink 67975c04a7b8SAlexey Dobriyan = 67985c04a7b8SAlexey Dobriyan (struct sccb 67995c04a7b8SAlexey Dobriyan *)NULL; 68001da177e4SLinus Torvalds } 68011da177e4SLinus Torvalds } 68021da177e4SLinus Torvalds pCurrCard->scanIndex = scan_ptr; 68031da177e4SLinus Torvalds 68045c04a7b8SAlexey Dobriyan pCurrCard->globalFlags |= 68055c04a7b8SAlexey Dobriyan F_NEW_SCCB_CMD; 68061da177e4SLinus Torvalds 68071da177e4SLinus Torvalds break; 68081da177e4SLinus Torvalds } 68091da177e4SLinus Torvalds } 68101da177e4SLinus Torvalds } 68111da177e4SLinus Torvalds 68125c04a7b8SAlexey Dobriyan else { 68131da177e4SLinus Torvalds scan_ptr++; 68141da177e4SLinus Torvalds if (scan_ptr == MAX_SCSI_TAR) { 68151da177e4SLinus Torvalds scan_ptr = 0; 68161da177e4SLinus Torvalds } 68171da177e4SLinus Torvalds } 68181da177e4SLinus Torvalds 68195c04a7b8SAlexey Dobriyan } else { 68201da177e4SLinus Torvalds if ((currTar_Info->TarSelQ_Cnt != 0) && 68215c04a7b8SAlexey Dobriyan (currTar_Info->TarLUNBusy[0] == 0)) { 68221da177e4SLinus Torvalds 68235c04a7b8SAlexey Dobriyan pCurrCard->currentSCCB = 68245c04a7b8SAlexey Dobriyan currTar_Info->TarSelQ_Head; 68251da177e4SLinus Torvalds 68265c04a7b8SAlexey Dobriyan currTar_Info->TarSelQ_Head = 68275c04a7b8SAlexey Dobriyan (struct sccb *)(pCurrCard->currentSCCB)-> 68285c04a7b8SAlexey Dobriyan Sccb_forwardlink; 68291da177e4SLinus Torvalds 68305c04a7b8SAlexey Dobriyan if (currTar_Info->TarSelQ_Head == NULL) { 68311da177e4SLinus Torvalds currTar_Info->TarSelQ_Tail = NULL; 68321da177e4SLinus Torvalds currTar_Info->TarSelQ_Cnt = 0; 68335c04a7b8SAlexey Dobriyan } else { 68341da177e4SLinus Torvalds currTar_Info->TarSelQ_Cnt--; 68355c04a7b8SAlexey Dobriyan currTar_Info->TarSelQ_Head-> 68365c04a7b8SAlexey Dobriyan Sccb_backlink = (struct sccb *)NULL; 68371da177e4SLinus Torvalds } 68381da177e4SLinus Torvalds 68391da177e4SLinus Torvalds scan_ptr++; 68401da177e4SLinus Torvalds if (scan_ptr == MAX_SCSI_TAR) 68411da177e4SLinus Torvalds scan_ptr = 0; 68421da177e4SLinus Torvalds 68431da177e4SLinus Torvalds pCurrCard->scanIndex = scan_ptr; 68441da177e4SLinus Torvalds 68451da177e4SLinus Torvalds pCurrCard->globalFlags |= F_NEW_SCCB_CMD; 68461da177e4SLinus Torvalds 68471da177e4SLinus Torvalds break; 68481da177e4SLinus Torvalds } 68491da177e4SLinus Torvalds 68505c04a7b8SAlexey Dobriyan else { 68511da177e4SLinus Torvalds scan_ptr++; 68525c04a7b8SAlexey Dobriyan if (scan_ptr == MAX_SCSI_TAR) { 68531da177e4SLinus Torvalds scan_ptr = 0; 68541da177e4SLinus Torvalds } 68551da177e4SLinus Torvalds } 68561da177e4SLinus Torvalds } 68571da177e4SLinus Torvalds } while (scan_ptr != pCurrCard->scanIndex); 68581da177e4SLinus Torvalds } 68591da177e4SLinus Torvalds 68601da177e4SLinus Torvalds /*--------------------------------------------------------------------- 68611da177e4SLinus Torvalds * 68621da177e4SLinus Torvalds * Function: Queue Select Fail 68631da177e4SLinus Torvalds * 68641da177e4SLinus Torvalds * Description: Add the current SCCB to the head of the Queue. 68651da177e4SLinus Torvalds * 68661da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 68671da177e4SLinus Torvalds 68685c04a7b8SAlexey Dobriyan static void FPT_queueSelectFail(struct sccb_card *pCurrCard, 68695c04a7b8SAlexey Dobriyan unsigned char p_card) 68701da177e4SLinus Torvalds { 6871db038cf8SAlexey Dobriyan unsigned char thisTarg; 6872f31dc0cdSAlexey Dobriyan struct sccb_mgr_tar_info *currTar_Info; 68731da177e4SLinus Torvalds 68745c04a7b8SAlexey Dobriyan if (pCurrCard->currentSCCB != NULL) { 68755c04a7b8SAlexey Dobriyan thisTarg = 68765c04a7b8SAlexey Dobriyan (unsigned char)(((struct sccb *)(pCurrCard->currentSCCB))-> 68775c04a7b8SAlexey Dobriyan TargID); 687847b5d69cSJames Bottomley currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg]; 68791da177e4SLinus Torvalds 688069eb2ea4SAlexey Dobriyan pCurrCard->currentSCCB->Sccb_backlink = (struct sccb *)NULL; 68811da177e4SLinus Torvalds 68825c04a7b8SAlexey Dobriyan pCurrCard->currentSCCB->Sccb_forwardlink = 68835c04a7b8SAlexey Dobriyan currTar_Info->TarSelQ_Head; 68841da177e4SLinus Torvalds 68855c04a7b8SAlexey Dobriyan if (currTar_Info->TarSelQ_Cnt == 0) { 68861da177e4SLinus Torvalds currTar_Info->TarSelQ_Tail = pCurrCard->currentSCCB; 68871da177e4SLinus Torvalds } 68881da177e4SLinus Torvalds 68895c04a7b8SAlexey Dobriyan else { 68905c04a7b8SAlexey Dobriyan currTar_Info->TarSelQ_Head->Sccb_backlink = 68915c04a7b8SAlexey Dobriyan pCurrCard->currentSCCB; 68921da177e4SLinus Torvalds } 68931da177e4SLinus Torvalds 68941da177e4SLinus Torvalds currTar_Info->TarSelQ_Head = pCurrCard->currentSCCB; 68951da177e4SLinus Torvalds 68961da177e4SLinus Torvalds pCurrCard->currentSCCB = NULL; 68971da177e4SLinus Torvalds currTar_Info->TarSelQ_Cnt++; 68981da177e4SLinus Torvalds } 68991da177e4SLinus Torvalds } 69005c04a7b8SAlexey Dobriyan 69011da177e4SLinus Torvalds /*--------------------------------------------------------------------- 69021da177e4SLinus Torvalds * 69031da177e4SLinus Torvalds * Function: Queue Command Complete 69041da177e4SLinus Torvalds * 69051da177e4SLinus Torvalds * Description: Call the callback function with the current SCCB. 69061da177e4SLinus Torvalds * 69071da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 69081da177e4SLinus Torvalds 69095c04a7b8SAlexey Dobriyan static void FPT_queueCmdComplete(struct sccb_card *pCurrCard, 69105c04a7b8SAlexey Dobriyan struct sccb *p_sccb, unsigned char p_card) 69111da177e4SLinus Torvalds { 69121da177e4SLinus Torvalds 6913db038cf8SAlexey Dobriyan unsigned char i, SCSIcmd; 69141da177e4SLinus Torvalds CALL_BK_FN callback; 6915f31dc0cdSAlexey Dobriyan struct sccb_mgr_tar_info *currTar_Info; 69161da177e4SLinus Torvalds 69171da177e4SLinus Torvalds SCSIcmd = p_sccb->Cdb[0]; 69181da177e4SLinus Torvalds 69191da177e4SLinus Torvalds if (!(p_sccb->Sccb_XferState & F_ALL_XFERRED)) { 69201da177e4SLinus Torvalds 69215c04a7b8SAlexey Dobriyan if ((p_sccb-> 69225c04a7b8SAlexey Dobriyan ControlByte & (SCCB_DATA_XFER_OUT | SCCB_DATA_XFER_IN)) 69235c04a7b8SAlexey Dobriyan && (p_sccb->HostStatus == SCCB_COMPLETE) 69245c04a7b8SAlexey Dobriyan && (p_sccb->TargetStatus != SSCHECK)) 69251da177e4SLinus Torvalds 69261da177e4SLinus Torvalds if ((SCSIcmd == SCSI_READ) || 69271da177e4SLinus Torvalds (SCSIcmd == SCSI_WRITE) || 69281da177e4SLinus Torvalds (SCSIcmd == SCSI_READ_EXTENDED) || 69291da177e4SLinus Torvalds (SCSIcmd == SCSI_WRITE_EXTENDED) || 69301da177e4SLinus Torvalds (SCSIcmd == SCSI_WRITE_AND_VERIFY) || 69311da177e4SLinus Torvalds (SCSIcmd == SCSI_START_STOP_UNIT) || 69321da177e4SLinus Torvalds (pCurrCard->globalFlags & F_NO_FILTER) 69331da177e4SLinus Torvalds ) 69341da177e4SLinus Torvalds p_sccb->HostStatus = SCCB_DATA_UNDER_RUN; 69351da177e4SLinus Torvalds } 69361da177e4SLinus Torvalds 69375c04a7b8SAlexey Dobriyan if (p_sccb->SccbStatus == SCCB_IN_PROCESS) { 69381da177e4SLinus Torvalds if (p_sccb->HostStatus || p_sccb->TargetStatus) 69391da177e4SLinus Torvalds p_sccb->SccbStatus = SCCB_ERROR; 69401da177e4SLinus Torvalds else 69411da177e4SLinus Torvalds p_sccb->SccbStatus = SCCB_SUCCESS; 69421da177e4SLinus Torvalds } 69431da177e4SLinus Torvalds 69441da177e4SLinus Torvalds if (p_sccb->Sccb_XferState & F_AUTO_SENSE) { 69451da177e4SLinus Torvalds 69461da177e4SLinus Torvalds p_sccb->CdbLength = p_sccb->Save_CdbLen; 69471da177e4SLinus Torvalds for (i = 0; i < 6; i++) { 69481da177e4SLinus Torvalds p_sccb->Cdb[i] = p_sccb->Save_Cdb[i]; 69491da177e4SLinus Torvalds } 69501da177e4SLinus Torvalds } 69511da177e4SLinus Torvalds 69521da177e4SLinus Torvalds if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) || 69531da177e4SLinus Torvalds (p_sccb->OperationCode == RESIDUAL_COMMAND)) { 69541da177e4SLinus Torvalds 695547b5d69cSJames Bottomley FPT_utilUpdateResidual(p_sccb); 69561da177e4SLinus Torvalds } 69571da177e4SLinus Torvalds 69581da177e4SLinus Torvalds pCurrCard->cmdCounter--; 69591da177e4SLinus Torvalds if (!pCurrCard->cmdCounter) { 69601da177e4SLinus Torvalds 69611da177e4SLinus Torvalds if (pCurrCard->globalFlags & F_GREEN_PC) { 69625c04a7b8SAlexey Dobriyan WR_HARPOON(pCurrCard->ioPort + hp_clkctrl_0, 69635c04a7b8SAlexey Dobriyan (PWR_DWN | CLKCTRL_DEFAULT)); 69641da177e4SLinus Torvalds WR_HARPOON(pCurrCard->ioPort + hp_sys_ctrl, STOP_CLK); 69651da177e4SLinus Torvalds } 69661da177e4SLinus Torvalds 69671da177e4SLinus Torvalds WR_HARPOON(pCurrCard->ioPort + hp_semaphore, 69685c04a7b8SAlexey Dobriyan (RD_HARPOON(pCurrCard->ioPort + hp_semaphore) & 69695c04a7b8SAlexey Dobriyan ~SCCB_MGR_ACTIVE)); 69701da177e4SLinus Torvalds 69711da177e4SLinus Torvalds } 69721da177e4SLinus Torvalds 69735c04a7b8SAlexey Dobriyan if (pCurrCard->discQCount != 0) { 697447b5d69cSJames Bottomley currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID]; 69751da177e4SLinus Torvalds if (((pCurrCard->globalFlags & F_CONLUN_IO) && 69765c04a7b8SAlexey Dobriyan ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != 69775c04a7b8SAlexey Dobriyan TAG_Q_TRYING))) { 69781da177e4SLinus Torvalds pCurrCard->discQCount--; 69795c04a7b8SAlexey Dobriyan pCurrCard->discQ_Tbl[currTar_Info-> 69805c04a7b8SAlexey Dobriyan LunDiscQ_Idx[p_sccb->Lun]] = NULL; 69815c04a7b8SAlexey Dobriyan } else { 69825c04a7b8SAlexey Dobriyan if (p_sccb->Sccb_tag) { 69831da177e4SLinus Torvalds pCurrCard->discQCount--; 69841da177e4SLinus Torvalds pCurrCard->discQ_Tbl[p_sccb->Sccb_tag] = NULL; 69855c04a7b8SAlexey Dobriyan } else { 69861da177e4SLinus Torvalds pCurrCard->discQCount--; 69875c04a7b8SAlexey Dobriyan pCurrCard->discQ_Tbl[currTar_Info-> 69885c04a7b8SAlexey Dobriyan LunDiscQ_Idx[0]] = NULL; 69891da177e4SLinus Torvalds } 69901da177e4SLinus Torvalds } 69911da177e4SLinus Torvalds 69921da177e4SLinus Torvalds } 69931da177e4SLinus Torvalds 69941da177e4SLinus Torvalds callback = (CALL_BK_FN) p_sccb->SccbCallback; 69951da177e4SLinus Torvalds callback(p_sccb); 69961da177e4SLinus Torvalds pCurrCard->globalFlags |= F_NEW_SCCB_CMD; 69971da177e4SLinus Torvalds pCurrCard->currentSCCB = NULL; 69981da177e4SLinus Torvalds } 69991da177e4SLinus Torvalds 70001da177e4SLinus Torvalds /*--------------------------------------------------------------------- 70011da177e4SLinus Torvalds * 70021da177e4SLinus Torvalds * Function: Queue Disconnect 70031da177e4SLinus Torvalds * 70041da177e4SLinus Torvalds * Description: Add SCCB to our disconnect array. 70051da177e4SLinus Torvalds * 70061da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 700769eb2ea4SAlexey Dobriyan static void FPT_queueDisconnect(struct sccb *p_sccb, unsigned char p_card) 70081da177e4SLinus Torvalds { 7009f31dc0cdSAlexey Dobriyan struct sccb_mgr_tar_info *currTar_Info; 70101da177e4SLinus Torvalds 701147b5d69cSJames Bottomley currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID]; 70121da177e4SLinus Torvalds 701347b5d69cSJames Bottomley if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) && 70145c04a7b8SAlexey Dobriyan ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) { 70155c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card].discQ_Tbl[currTar_Info-> 70165c04a7b8SAlexey Dobriyan LunDiscQ_Idx[p_sccb->Lun]] = 70175c04a7b8SAlexey Dobriyan p_sccb; 70185c04a7b8SAlexey Dobriyan } else { 70195c04a7b8SAlexey Dobriyan if (p_sccb->Sccb_tag) { 70205c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card].discQ_Tbl[p_sccb->Sccb_tag] = 70215c04a7b8SAlexey Dobriyan p_sccb; 70225c04a7b8SAlexey Dobriyan FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarLUNBusy[0] = 70235c04a7b8SAlexey Dobriyan 0; 702447b5d69cSJames Bottomley FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarTagQ_Cnt++; 70255c04a7b8SAlexey Dobriyan } else { 70265c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card].discQ_Tbl[currTar_Info-> 70275c04a7b8SAlexey Dobriyan LunDiscQ_Idx[0]] = p_sccb; 70281da177e4SLinus Torvalds } 70291da177e4SLinus Torvalds } 703047b5d69cSJames Bottomley FPT_BL_Card[p_card].currentSCCB = NULL; 70311da177e4SLinus Torvalds } 70321da177e4SLinus Torvalds 70331da177e4SLinus Torvalds /*--------------------------------------------------------------------- 70341da177e4SLinus Torvalds * 70351da177e4SLinus Torvalds * Function: Queue Flush SCCB 70361da177e4SLinus Torvalds * 70371da177e4SLinus Torvalds * Description: Flush all SCCB's back to the host driver for this target. 70381da177e4SLinus Torvalds * 70391da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 70401da177e4SLinus Torvalds 7041db038cf8SAlexey Dobriyan static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code) 70421da177e4SLinus Torvalds { 7043db038cf8SAlexey Dobriyan unsigned char qtag, thisTarg; 704469eb2ea4SAlexey Dobriyan struct sccb *currSCCB; 7045f31dc0cdSAlexey Dobriyan struct sccb_mgr_tar_info *currTar_Info; 70461da177e4SLinus Torvalds 704747b5d69cSJames Bottomley currSCCB = FPT_BL_Card[p_card].currentSCCB; 70485c04a7b8SAlexey Dobriyan if (currSCCB != NULL) { 7049db038cf8SAlexey Dobriyan thisTarg = (unsigned char)currSCCB->TargID; 705047b5d69cSJames Bottomley currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg]; 70511da177e4SLinus Torvalds 70521da177e4SLinus Torvalds for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) { 70531da177e4SLinus Torvalds 705447b5d69cSJames Bottomley if (FPT_BL_Card[p_card].discQ_Tbl[qtag] && 70555c04a7b8SAlexey Dobriyan (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == 70565c04a7b8SAlexey Dobriyan thisTarg)) { 70571da177e4SLinus Torvalds 70585c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card].discQ_Tbl[qtag]-> 70595c04a7b8SAlexey Dobriyan HostStatus = (unsigned char)error_code; 70601da177e4SLinus Torvalds 70615c04a7b8SAlexey Dobriyan FPT_queueCmdComplete(&FPT_BL_Card[p_card], 70625c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card]. 70635c04a7b8SAlexey Dobriyan discQ_Tbl[qtag], p_card); 70641da177e4SLinus Torvalds 706547b5d69cSJames Bottomley FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL; 70661da177e4SLinus Torvalds currTar_Info->TarTagQ_Cnt--; 70671da177e4SLinus Torvalds 70681da177e4SLinus Torvalds } 70691da177e4SLinus Torvalds } 70701da177e4SLinus Torvalds } 70711da177e4SLinus Torvalds 70721da177e4SLinus Torvalds } 70731da177e4SLinus Torvalds 70741da177e4SLinus Torvalds /*--------------------------------------------------------------------- 70751da177e4SLinus Torvalds * 70761da177e4SLinus Torvalds * Function: Queue Flush Target SCCB 70771da177e4SLinus Torvalds * 70781da177e4SLinus Torvalds * Description: Flush all SCCB's back to the host driver for this target. 70791da177e4SLinus Torvalds * 70801da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 70811da177e4SLinus Torvalds 7082db038cf8SAlexey Dobriyan static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg, 7083db038cf8SAlexey Dobriyan unsigned char error_code) 70841da177e4SLinus Torvalds { 7085db038cf8SAlexey Dobriyan unsigned char qtag; 7086f31dc0cdSAlexey Dobriyan struct sccb_mgr_tar_info *currTar_Info; 70871da177e4SLinus Torvalds 708847b5d69cSJames Bottomley currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg]; 70891da177e4SLinus Torvalds 70901da177e4SLinus Torvalds for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) { 70911da177e4SLinus Torvalds 709247b5d69cSJames Bottomley if (FPT_BL_Card[p_card].discQ_Tbl[qtag] && 70935c04a7b8SAlexey Dobriyan (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg)) { 70941da177e4SLinus Torvalds 70955c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus = 70965c04a7b8SAlexey Dobriyan (unsigned char)error_code; 70971da177e4SLinus Torvalds 70985c04a7b8SAlexey Dobriyan FPT_queueCmdComplete(&FPT_BL_Card[p_card], 70995c04a7b8SAlexey Dobriyan FPT_BL_Card[p_card]. 71005c04a7b8SAlexey Dobriyan discQ_Tbl[qtag], p_card); 71011da177e4SLinus Torvalds 710247b5d69cSJames Bottomley FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL; 71031da177e4SLinus Torvalds currTar_Info->TarTagQ_Cnt--; 71041da177e4SLinus Torvalds 71051da177e4SLinus Torvalds } 71061da177e4SLinus Torvalds } 71071da177e4SLinus Torvalds 71081da177e4SLinus Torvalds } 71091da177e4SLinus Torvalds 711069eb2ea4SAlexey Dobriyan static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char p_card) 71111da177e4SLinus Torvalds { 7112f31dc0cdSAlexey Dobriyan struct sccb_mgr_tar_info *currTar_Info; 711347b5d69cSJames Bottomley currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID]; 71141da177e4SLinus Torvalds 71151da177e4SLinus Torvalds p_SCCB->Sccb_forwardlink = NULL; 71161da177e4SLinus Torvalds 71171da177e4SLinus Torvalds p_SCCB->Sccb_backlink = currTar_Info->TarSelQ_Tail; 71181da177e4SLinus Torvalds 71191da177e4SLinus Torvalds if (currTar_Info->TarSelQ_Cnt == 0) { 71201da177e4SLinus Torvalds 71211da177e4SLinus Torvalds currTar_Info->TarSelQ_Head = p_SCCB; 71221da177e4SLinus Torvalds } 71231da177e4SLinus Torvalds 71241da177e4SLinus Torvalds else { 71251da177e4SLinus Torvalds 71261da177e4SLinus Torvalds currTar_Info->TarSelQ_Tail->Sccb_forwardlink = p_SCCB; 71271da177e4SLinus Torvalds } 71281da177e4SLinus Torvalds 71291da177e4SLinus Torvalds currTar_Info->TarSelQ_Tail = p_SCCB; 71301da177e4SLinus Torvalds currTar_Info->TarSelQ_Cnt++; 71311da177e4SLinus Torvalds } 71321da177e4SLinus Torvalds 71331da177e4SLinus Torvalds /*--------------------------------------------------------------------- 71341da177e4SLinus Torvalds * 71351da177e4SLinus Torvalds * Function: Queue Find SCCB 71361da177e4SLinus Torvalds * 71371da177e4SLinus Torvalds * Description: Search the target select Queue for this SCCB, and 71381da177e4SLinus Torvalds * remove it if found. 71391da177e4SLinus Torvalds * 71401da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 71411da177e4SLinus Torvalds 71425c04a7b8SAlexey Dobriyan static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB, 71435c04a7b8SAlexey Dobriyan unsigned char p_card) 71441da177e4SLinus Torvalds { 714569eb2ea4SAlexey Dobriyan struct sccb *q_ptr; 7146f31dc0cdSAlexey Dobriyan struct sccb_mgr_tar_info *currTar_Info; 71471da177e4SLinus Torvalds 714847b5d69cSJames Bottomley currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID]; 71491da177e4SLinus Torvalds 71501da177e4SLinus Torvalds q_ptr = currTar_Info->TarSelQ_Head; 71511da177e4SLinus Torvalds 71521da177e4SLinus Torvalds while (q_ptr != NULL) { 71531da177e4SLinus Torvalds 71541da177e4SLinus Torvalds if (q_ptr == p_SCCB) { 71551da177e4SLinus Torvalds 71561da177e4SLinus Torvalds if (currTar_Info->TarSelQ_Head == q_ptr) { 71571da177e4SLinus Torvalds 71585c04a7b8SAlexey Dobriyan currTar_Info->TarSelQ_Head = 71595c04a7b8SAlexey Dobriyan q_ptr->Sccb_forwardlink; 71601da177e4SLinus Torvalds } 71611da177e4SLinus Torvalds 71621da177e4SLinus Torvalds if (currTar_Info->TarSelQ_Tail == q_ptr) { 71631da177e4SLinus Torvalds 71645c04a7b8SAlexey Dobriyan currTar_Info->TarSelQ_Tail = 71655c04a7b8SAlexey Dobriyan q_ptr->Sccb_backlink; 71661da177e4SLinus Torvalds } 71671da177e4SLinus Torvalds 71681da177e4SLinus Torvalds if (q_ptr->Sccb_forwardlink != NULL) { 71695c04a7b8SAlexey Dobriyan q_ptr->Sccb_forwardlink->Sccb_backlink = 71705c04a7b8SAlexey Dobriyan q_ptr->Sccb_backlink; 71711da177e4SLinus Torvalds } 71721da177e4SLinus Torvalds 71731da177e4SLinus Torvalds if (q_ptr->Sccb_backlink != NULL) { 71745c04a7b8SAlexey Dobriyan q_ptr->Sccb_backlink->Sccb_forwardlink = 71755c04a7b8SAlexey Dobriyan q_ptr->Sccb_forwardlink; 71761da177e4SLinus Torvalds } 71771da177e4SLinus Torvalds 71781da177e4SLinus Torvalds currTar_Info->TarSelQ_Cnt--; 71791da177e4SLinus Torvalds 71805c1b85e2SAlexey Dobriyan return 1; 71811da177e4SLinus Torvalds } 71821da177e4SLinus Torvalds 71831da177e4SLinus Torvalds else { 71841da177e4SLinus Torvalds q_ptr = q_ptr->Sccb_forwardlink; 71851da177e4SLinus Torvalds } 71861da177e4SLinus Torvalds } 71871da177e4SLinus Torvalds 71885c1b85e2SAlexey Dobriyan return 0; 71891da177e4SLinus Torvalds 71901da177e4SLinus Torvalds } 71911da177e4SLinus Torvalds 71921da177e4SLinus Torvalds /*--------------------------------------------------------------------- 71931da177e4SLinus Torvalds * 71941da177e4SLinus Torvalds * Function: Utility Update Residual Count 71951da177e4SLinus Torvalds * 71961da177e4SLinus Torvalds * Description: Update the XferCnt to the remaining byte count. 71971da177e4SLinus Torvalds * If we transferred all the data then just write zero. 71981da177e4SLinus Torvalds * If Non-SG transfer then report Total Cnt - Actual Transfer 71991da177e4SLinus Torvalds * Cnt. For SG transfers add the count fields of all 72001da177e4SLinus Torvalds * remaining SG elements, as well as any partial remaining 72011da177e4SLinus Torvalds * element. 72021da177e4SLinus Torvalds * 72031da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 72041da177e4SLinus Torvalds 720569eb2ea4SAlexey Dobriyan static void FPT_utilUpdateResidual(struct sccb *p_SCCB) 72061da177e4SLinus Torvalds { 7207d63a4cccSAlexey Dobriyan unsigned long partial_cnt; 7208ce793215SAlexey Dobriyan unsigned int sg_index; 7209d63a4cccSAlexey Dobriyan unsigned long *sg_ptr; 72101da177e4SLinus Torvalds 72111da177e4SLinus Torvalds if (p_SCCB->Sccb_XferState & F_ALL_XFERRED) { 72121da177e4SLinus Torvalds 72131da177e4SLinus Torvalds p_SCCB->DataLength = 0x0000; 72141da177e4SLinus Torvalds } 72151da177e4SLinus Torvalds 72161da177e4SLinus Torvalds else if (p_SCCB->Sccb_XferState & F_SG_XFER) { 72171da177e4SLinus Torvalds 72181da177e4SLinus Torvalds partial_cnt = 0x0000; 72191da177e4SLinus Torvalds 72201da177e4SLinus Torvalds sg_index = p_SCCB->Sccb_sgseg; 72211da177e4SLinus Torvalds 7222d63a4cccSAlexey Dobriyan sg_ptr = (unsigned long *)p_SCCB->DataPointer; 72231da177e4SLinus Torvalds 72241da177e4SLinus Torvalds if (p_SCCB->Sccb_SGoffset) { 72251da177e4SLinus Torvalds 72261da177e4SLinus Torvalds partial_cnt = p_SCCB->Sccb_SGoffset; 72271da177e4SLinus Torvalds sg_index++; 72281da177e4SLinus Torvalds } 72291da177e4SLinus Torvalds 72305c04a7b8SAlexey Dobriyan while (((unsigned long)sg_index * 72315c04a7b8SAlexey Dobriyan (unsigned long)SG_ELEMENT_SIZE) < p_SCCB->DataLength) { 72321da177e4SLinus Torvalds 72331da177e4SLinus Torvalds partial_cnt += *(sg_ptr + (sg_index * 2)); 72341da177e4SLinus Torvalds sg_index++; 72351da177e4SLinus Torvalds } 72361da177e4SLinus Torvalds 72371da177e4SLinus Torvalds p_SCCB->DataLength = partial_cnt; 72381da177e4SLinus Torvalds } 72391da177e4SLinus Torvalds 72401da177e4SLinus Torvalds else { 72411da177e4SLinus Torvalds 72421da177e4SLinus Torvalds p_SCCB->DataLength -= p_SCCB->Sccb_ATC; 72431da177e4SLinus Torvalds } 72441da177e4SLinus Torvalds } 72451da177e4SLinus Torvalds 72461da177e4SLinus Torvalds /*--------------------------------------------------------------------- 72471da177e4SLinus Torvalds * 72481da177e4SLinus Torvalds * Function: Wait 1 Second 72491da177e4SLinus Torvalds * 72501da177e4SLinus Torvalds * Description: Wait for 1 second. 72511da177e4SLinus Torvalds * 72521da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 72531da177e4SLinus Torvalds 7254d63a4cccSAlexey Dobriyan static void FPT_Wait1Second(unsigned long p_port) 72551da177e4SLinus Torvalds { 7256db038cf8SAlexey Dobriyan unsigned char i; 72571da177e4SLinus Torvalds 72581da177e4SLinus Torvalds for (i = 0; i < 4; i++) { 72591da177e4SLinus Torvalds 726047b5d69cSJames Bottomley FPT_Wait(p_port, TO_250ms); 72611da177e4SLinus Torvalds 72621da177e4SLinus Torvalds if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST)) 72631da177e4SLinus Torvalds break; 72641da177e4SLinus Torvalds 72651da177e4SLinus Torvalds if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL)) 72661da177e4SLinus Torvalds break; 72671da177e4SLinus Torvalds } 72681da177e4SLinus Torvalds } 72691da177e4SLinus Torvalds 72701da177e4SLinus Torvalds /*--------------------------------------------------------------------- 72711da177e4SLinus Torvalds * 727247b5d69cSJames Bottomley * Function: FPT_Wait 72731da177e4SLinus Torvalds * 72741da177e4SLinus Torvalds * Description: Wait the desired delay. 72751da177e4SLinus Torvalds * 72761da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 72771da177e4SLinus Torvalds 7278d63a4cccSAlexey Dobriyan static void FPT_Wait(unsigned long p_port, unsigned char p_delay) 72791da177e4SLinus Torvalds { 7280db038cf8SAlexey Dobriyan unsigned char old_timer; 7281db038cf8SAlexey Dobriyan unsigned char green_flag; 72821da177e4SLinus Torvalds 72831da177e4SLinus Torvalds old_timer = RD_HARPOON(p_port + hp_seltimeout); 72841da177e4SLinus Torvalds 72851da177e4SLinus Torvalds green_flag = RD_HARPOON(p_port + hp_clkctrl_0); 72861da177e4SLinus Torvalds WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT); 72871da177e4SLinus Torvalds 72881da177e4SLinus Torvalds WR_HARPOON(p_port + hp_seltimeout, p_delay); 72891da177e4SLinus Torvalds WRW_HARPOON((p_port + hp_intstat), TIMEOUT); 729047b5d69cSJames Bottomley WRW_HARPOON((p_port + hp_intena), (FPT_default_intena & ~TIMEOUT)); 72911da177e4SLinus Torvalds 72921da177e4SLinus Torvalds WR_HARPOON(p_port + hp_portctrl_0, 72931da177e4SLinus Torvalds (RD_HARPOON(p_port + hp_portctrl_0) | START_TO)); 72941da177e4SLinus Torvalds 72951da177e4SLinus Torvalds while (!(RDW_HARPOON((p_port + hp_intstat)) & TIMEOUT)) { 72961da177e4SLinus Torvalds 72971da177e4SLinus Torvalds if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST)) 72981da177e4SLinus Torvalds break; 72991da177e4SLinus Torvalds 73001da177e4SLinus Torvalds if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL)) 73011da177e4SLinus Torvalds break; 73021da177e4SLinus Torvalds } 73031da177e4SLinus Torvalds 73041da177e4SLinus Torvalds WR_HARPOON(p_port + hp_portctrl_0, 73051da177e4SLinus Torvalds (RD_HARPOON(p_port + hp_portctrl_0) & ~START_TO)); 73061da177e4SLinus Torvalds 73071da177e4SLinus Torvalds WRW_HARPOON((p_port + hp_intstat), TIMEOUT); 730847b5d69cSJames Bottomley WRW_HARPOON((p_port + hp_intena), FPT_default_intena); 73091da177e4SLinus Torvalds 73101da177e4SLinus Torvalds WR_HARPOON(p_port + hp_clkctrl_0, green_flag); 73111da177e4SLinus Torvalds 73121da177e4SLinus Torvalds WR_HARPOON(p_port + hp_seltimeout, old_timer); 73131da177e4SLinus Torvalds } 73141da177e4SLinus Torvalds 73151da177e4SLinus Torvalds /*--------------------------------------------------------------------- 73161da177e4SLinus Torvalds * 73171da177e4SLinus Torvalds * Function: Enable/Disable Write to EEPROM 73181da177e4SLinus Torvalds * 73191da177e4SLinus Torvalds * Description: The EEPROM must first be enabled for writes 73201da177e4SLinus Torvalds * A total of 9 clocks are needed. 73211da177e4SLinus Torvalds * 73221da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 73231da177e4SLinus Torvalds 7324d63a4cccSAlexey Dobriyan static void FPT_utilEEWriteOnOff(unsigned long p_port, unsigned char p_mode) 73251da177e4SLinus Torvalds { 7326db038cf8SAlexey Dobriyan unsigned char ee_value; 73271da177e4SLinus Torvalds 73285c04a7b8SAlexey Dobriyan ee_value = 73295c04a7b8SAlexey Dobriyan (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) & 73305c04a7b8SAlexey Dobriyan (EXT_ARB_ACK | SCSI_TERM_ENA_H)); 73311da177e4SLinus Torvalds 73321da177e4SLinus Torvalds if (p_mode) 73331da177e4SLinus Torvalds 733447b5d69cSJames Bottomley FPT_utilEESendCmdAddr(p_port, EWEN, EWEN_ADDR); 73351da177e4SLinus Torvalds 73361da177e4SLinus Torvalds else 73371da177e4SLinus Torvalds 733847b5d69cSJames Bottomley FPT_utilEESendCmdAddr(p_port, EWDS, EWDS_ADDR); 73391da177e4SLinus Torvalds 73401da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */ 73411da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /*Turn off Master Select */ 73421da177e4SLinus Torvalds } 73431da177e4SLinus Torvalds 73441da177e4SLinus Torvalds /*--------------------------------------------------------------------- 73451da177e4SLinus Torvalds * 73461da177e4SLinus Torvalds * Function: Write EEPROM 73471da177e4SLinus Torvalds * 73481da177e4SLinus Torvalds * Description: Write a word to the EEPROM at the specified 73491da177e4SLinus Torvalds * address. 73501da177e4SLinus Torvalds * 73511da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 73521da177e4SLinus Torvalds 73535c04a7b8SAlexey Dobriyan static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data, 73545c04a7b8SAlexey Dobriyan unsigned short ee_addr) 73551da177e4SLinus Torvalds { 73561da177e4SLinus Torvalds 7357db038cf8SAlexey Dobriyan unsigned char ee_value; 7358c823feebSAlexey Dobriyan unsigned short i; 73591da177e4SLinus Torvalds 73605c04a7b8SAlexey Dobriyan ee_value = 73615c04a7b8SAlexey Dobriyan (unsigned 73625c04a7b8SAlexey Dobriyan char)((RD_HARPOON(p_port + hp_ee_ctrl) & 73635c04a7b8SAlexey Dobriyan (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS)); 73641da177e4SLinus Torvalds 736547b5d69cSJames Bottomley FPT_utilEESendCmdAddr(p_port, EE_WRITE, ee_addr); 73661da177e4SLinus Torvalds 73671da177e4SLinus Torvalds ee_value |= (SEE_MS + SEE_CS); 73681da177e4SLinus Torvalds 73691da177e4SLinus Torvalds for (i = 0x8000; i != 0; i >>= 1) { 73701da177e4SLinus Torvalds 73711da177e4SLinus Torvalds if (i & ee_data) 73721da177e4SLinus Torvalds ee_value |= SEE_DO; 73731da177e4SLinus Torvalds else 73741da177e4SLinus Torvalds ee_value &= ~SEE_DO; 73751da177e4SLinus Torvalds 73761da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); 73771da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); 73781da177e4SLinus Torvalds ee_value |= SEE_CLK; /* Clock data! */ 73791da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); 73801da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); 73811da177e4SLinus Torvalds ee_value &= ~SEE_CLK; 73821da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); 73831da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); 73841da177e4SLinus Torvalds } 73851da177e4SLinus Torvalds ee_value &= (EXT_ARB_ACK | SCSI_TERM_ENA_H); 73861da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); 73871da177e4SLinus Torvalds 738847b5d69cSJames Bottomley FPT_Wait(p_port, TO_10ms); 73891da177e4SLinus Torvalds 73901da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS | SEE_CS)); /* Set CS to EEPROM */ 73911da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /* Turn off CS */ 73921da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /* Turn off Master Select */ 73931da177e4SLinus Torvalds } 73941da177e4SLinus Torvalds 73951da177e4SLinus Torvalds /*--------------------------------------------------------------------- 73961da177e4SLinus Torvalds * 73971da177e4SLinus Torvalds * Function: Read EEPROM 73981da177e4SLinus Torvalds * 73991da177e4SLinus Torvalds * Description: Read a word from the EEPROM at the desired 74001da177e4SLinus Torvalds * address. 74011da177e4SLinus Torvalds * 74021da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 74031da177e4SLinus Torvalds 74045c04a7b8SAlexey Dobriyan static unsigned short FPT_utilEERead(unsigned long p_port, 74055c04a7b8SAlexey Dobriyan unsigned short ee_addr) 74061da177e4SLinus Torvalds { 7407c823feebSAlexey Dobriyan unsigned short i, ee_data1, ee_data2; 74081da177e4SLinus Torvalds 74091da177e4SLinus Torvalds i = 0; 741047b5d69cSJames Bottomley ee_data1 = FPT_utilEEReadOrg(p_port, ee_addr); 74115c04a7b8SAlexey Dobriyan do { 741247b5d69cSJames Bottomley ee_data2 = FPT_utilEEReadOrg(p_port, ee_addr); 74131da177e4SLinus Torvalds 74141da177e4SLinus Torvalds if (ee_data1 == ee_data2) 74155c1b85e2SAlexey Dobriyan return ee_data1; 74161da177e4SLinus Torvalds 74171da177e4SLinus Torvalds ee_data1 = ee_data2; 74181da177e4SLinus Torvalds i++; 74191da177e4SLinus Torvalds 74201da177e4SLinus Torvalds } while (i < 4); 74211da177e4SLinus Torvalds 74225c1b85e2SAlexey Dobriyan return ee_data1; 74231da177e4SLinus Torvalds } 74241da177e4SLinus Torvalds 74251da177e4SLinus Torvalds /*--------------------------------------------------------------------- 74261da177e4SLinus Torvalds * 74271da177e4SLinus Torvalds * Function: Read EEPROM Original 74281da177e4SLinus Torvalds * 74291da177e4SLinus Torvalds * Description: Read a word from the EEPROM at the desired 74301da177e4SLinus Torvalds * address. 74311da177e4SLinus Torvalds * 74321da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 74331da177e4SLinus Torvalds 74345c04a7b8SAlexey Dobriyan static unsigned short FPT_utilEEReadOrg(unsigned long p_port, 74355c04a7b8SAlexey Dobriyan unsigned short ee_addr) 74361da177e4SLinus Torvalds { 74371da177e4SLinus Torvalds 7438db038cf8SAlexey Dobriyan unsigned char ee_value; 7439c823feebSAlexey Dobriyan unsigned short i, ee_data; 74401da177e4SLinus Torvalds 74415c04a7b8SAlexey Dobriyan ee_value = 74425c04a7b8SAlexey Dobriyan (unsigned 74435c04a7b8SAlexey Dobriyan char)((RD_HARPOON(p_port + hp_ee_ctrl) & 74445c04a7b8SAlexey Dobriyan (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS)); 74451da177e4SLinus Torvalds 744647b5d69cSJames Bottomley FPT_utilEESendCmdAddr(p_port, EE_READ, ee_addr); 74471da177e4SLinus Torvalds 74481da177e4SLinus Torvalds ee_value |= (SEE_MS + SEE_CS); 74491da177e4SLinus Torvalds ee_data = 0; 74501da177e4SLinus Torvalds 74511da177e4SLinus Torvalds for (i = 1; i <= 16; i++) { 74521da177e4SLinus Torvalds 74531da177e4SLinus Torvalds ee_value |= SEE_CLK; /* Clock data! */ 74541da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); 74551da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); 74561da177e4SLinus Torvalds ee_value &= ~SEE_CLK; 74571da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); 74581da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); 74591da177e4SLinus Torvalds 74601da177e4SLinus Torvalds ee_data <<= 1; 74611da177e4SLinus Torvalds 74621da177e4SLinus Torvalds if (RD_HARPOON(p_port + hp_ee_ctrl) & SEE_DI) 74631da177e4SLinus Torvalds ee_data |= 1; 74641da177e4SLinus Torvalds } 74651da177e4SLinus Torvalds 74661da177e4SLinus Torvalds ee_value &= ~(SEE_MS + SEE_CS); 74671da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */ 74681da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /*Turn off Master Select */ 74691da177e4SLinus Torvalds 74705c1b85e2SAlexey Dobriyan return ee_data; 74711da177e4SLinus Torvalds } 74721da177e4SLinus Torvalds 74731da177e4SLinus Torvalds /*--------------------------------------------------------------------- 74741da177e4SLinus Torvalds * 74751da177e4SLinus Torvalds * Function: Send EE command and Address to the EEPROM 74761da177e4SLinus Torvalds * 74771da177e4SLinus Torvalds * Description: Transfers the correct command and sends the address 74781da177e4SLinus Torvalds * to the eeprom. 74791da177e4SLinus Torvalds * 74801da177e4SLinus Torvalds *---------------------------------------------------------------------*/ 74811da177e4SLinus Torvalds 74825c04a7b8SAlexey Dobriyan static void FPT_utilEESendCmdAddr(unsigned long p_port, unsigned char ee_cmd, 74835c04a7b8SAlexey Dobriyan unsigned short ee_addr) 74841da177e4SLinus Torvalds { 7485db038cf8SAlexey Dobriyan unsigned char ee_value; 7486db038cf8SAlexey Dobriyan unsigned char narrow_flg; 74871da177e4SLinus Torvalds 7488c823feebSAlexey Dobriyan unsigned short i; 74891da177e4SLinus Torvalds 74905c04a7b8SAlexey Dobriyan narrow_flg = 74915c04a7b8SAlexey Dobriyan (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) & 74925c04a7b8SAlexey Dobriyan NARROW_SCSI_CARD); 74931da177e4SLinus Torvalds 74941da177e4SLinus Torvalds ee_value = SEE_MS; 74951da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); 74961da177e4SLinus Torvalds 74971da177e4SLinus Torvalds ee_value |= SEE_CS; /* Set CS to EEPROM */ 74981da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); 74991da177e4SLinus Torvalds 75001da177e4SLinus Torvalds for (i = 0x04; i != 0; i >>= 1) { 75011da177e4SLinus Torvalds 75021da177e4SLinus Torvalds if (i & ee_cmd) 75031da177e4SLinus Torvalds ee_value |= SEE_DO; 75041da177e4SLinus Torvalds else 75051da177e4SLinus Torvalds ee_value &= ~SEE_DO; 75061da177e4SLinus Torvalds 75071da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); 75081da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); 75091da177e4SLinus Torvalds ee_value |= SEE_CLK; /* Clock data! */ 75101da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); 75111da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); 75121da177e4SLinus Torvalds ee_value &= ~SEE_CLK; 75131da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); 75141da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); 75151da177e4SLinus Torvalds } 75161da177e4SLinus Torvalds 75171da177e4SLinus Torvalds if (narrow_flg) 75181da177e4SLinus Torvalds i = 0x0080; 75191da177e4SLinus Torvalds 75201da177e4SLinus Torvalds else 75211da177e4SLinus Torvalds i = 0x0200; 75221da177e4SLinus Torvalds 75231da177e4SLinus Torvalds while (i != 0) { 75241da177e4SLinus Torvalds 75251da177e4SLinus Torvalds if (i & ee_addr) 75261da177e4SLinus Torvalds ee_value |= SEE_DO; 75271da177e4SLinus Torvalds else 75281da177e4SLinus Torvalds ee_value &= ~SEE_DO; 75291da177e4SLinus Torvalds 75301da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); 75311da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); 75321da177e4SLinus Torvalds ee_value |= SEE_CLK; /* Clock data! */ 75331da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); 75341da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); 75351da177e4SLinus Torvalds ee_value &= ~SEE_CLK; 75361da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); 75371da177e4SLinus Torvalds WR_HARPOON(p_port + hp_ee_ctrl, ee_value); 75381da177e4SLinus Torvalds 75391da177e4SLinus Torvalds i >>= 1; 75401da177e4SLinus Torvalds } 75411da177e4SLinus Torvalds } 75421da177e4SLinus Torvalds 7543c823feebSAlexey Dobriyan static unsigned short FPT_CalcCrc16(unsigned char buffer[]) 75441da177e4SLinus Torvalds { 7545c823feebSAlexey Dobriyan unsigned short crc = 0; 75461da177e4SLinus Torvalds int i, j; 7547c823feebSAlexey Dobriyan unsigned short ch; 75485c04a7b8SAlexey Dobriyan for (i = 0; i < ID_STRING_LENGTH; i++) { 7549c823feebSAlexey Dobriyan ch = (unsigned short)buffer[i]; 75505c04a7b8SAlexey Dobriyan for (j = 0; j < 8; j++) { 75511da177e4SLinus Torvalds if ((crc ^ ch) & 1) 75521da177e4SLinus Torvalds crc = (crc >> 1) ^ CRCMASK; 75531da177e4SLinus Torvalds else 75541da177e4SLinus Torvalds crc >>= 1; 75551da177e4SLinus Torvalds ch >>= 1; 75561da177e4SLinus Torvalds } 75571da177e4SLinus Torvalds } 75585c1b85e2SAlexey Dobriyan return crc; 75591da177e4SLinus Torvalds } 75601da177e4SLinus Torvalds 7561db038cf8SAlexey Dobriyan static unsigned char FPT_CalcLrc(unsigned char buffer[]) 75621da177e4SLinus Torvalds { 75631da177e4SLinus Torvalds int i; 7564db038cf8SAlexey Dobriyan unsigned char lrc; 75651da177e4SLinus Torvalds lrc = 0; 75661da177e4SLinus Torvalds for (i = 0; i < ID_STRING_LENGTH; i++) 75671da177e4SLinus Torvalds lrc ^= buffer[i]; 75685c1b85e2SAlexey Dobriyan return lrc; 75691da177e4SLinus Torvalds } 75701da177e4SLinus Torvalds 75711da177e4SLinus Torvalds /* 75721da177e4SLinus Torvalds The following inline definitions avoid type conflicts. 75731da177e4SLinus Torvalds */ 75741da177e4SLinus Torvalds 75751da177e4SLinus Torvalds static inline unsigned char 75761da177e4SLinus Torvalds FlashPoint__ProbeHostAdapter(struct FlashPoint_Info *FlashPointInfo) 75771da177e4SLinus Torvalds { 75785c04a7b8SAlexey Dobriyan return FlashPoint_ProbeHostAdapter((struct sccb_mgr_info *) 75795c04a7b8SAlexey Dobriyan FlashPointInfo); 75801da177e4SLinus Torvalds } 75811da177e4SLinus Torvalds 75821da177e4SLinus Torvalds static inline FlashPoint_CardHandle_T 75831da177e4SLinus Torvalds FlashPoint__HardwareResetHostAdapter(struct FlashPoint_Info *FlashPointInfo) 75841da177e4SLinus Torvalds { 75855c04a7b8SAlexey Dobriyan return FlashPoint_HardwareResetHostAdapter((struct sccb_mgr_info *) 75865c04a7b8SAlexey Dobriyan FlashPointInfo); 75871da177e4SLinus Torvalds } 75881da177e4SLinus Torvalds 75891da177e4SLinus Torvalds static inline void 75901da177e4SLinus Torvalds FlashPoint__ReleaseHostAdapter(FlashPoint_CardHandle_T CardHandle) 75911da177e4SLinus Torvalds { 75921da177e4SLinus Torvalds FlashPoint_ReleaseHostAdapter(CardHandle); 75931da177e4SLinus Torvalds } 75941da177e4SLinus Torvalds 75951da177e4SLinus Torvalds static inline void 75965c04a7b8SAlexey Dobriyan FlashPoint__StartCCB(FlashPoint_CardHandle_T CardHandle, 75975c04a7b8SAlexey Dobriyan struct BusLogic_CCB *CCB) 75981da177e4SLinus Torvalds { 759969eb2ea4SAlexey Dobriyan FlashPoint_StartCCB(CardHandle, (struct sccb *)CCB); 76001da177e4SLinus Torvalds } 76011da177e4SLinus Torvalds 76021da177e4SLinus Torvalds static inline void 76035c04a7b8SAlexey Dobriyan FlashPoint__AbortCCB(FlashPoint_CardHandle_T CardHandle, 76045c04a7b8SAlexey Dobriyan struct BusLogic_CCB *CCB) 76051da177e4SLinus Torvalds { 760669eb2ea4SAlexey Dobriyan FlashPoint_AbortCCB(CardHandle, (struct sccb *)CCB); 76071da177e4SLinus Torvalds } 76081da177e4SLinus Torvalds 76092065e310SRichard Knutsson static inline bool 76101da177e4SLinus Torvalds FlashPoint__InterruptPending(FlashPoint_CardHandle_T CardHandle) 76111da177e4SLinus Torvalds { 76121da177e4SLinus Torvalds return FlashPoint_InterruptPending(CardHandle); 76131da177e4SLinus Torvalds } 76141da177e4SLinus Torvalds 76151da177e4SLinus Torvalds static inline int 76161da177e4SLinus Torvalds FlashPoint__HandleInterrupt(FlashPoint_CardHandle_T CardHandle) 76171da177e4SLinus Torvalds { 76181da177e4SLinus Torvalds return FlashPoint_HandleInterrupt(CardHandle); 76191da177e4SLinus Torvalds } 76201da177e4SLinus Torvalds 76211da177e4SLinus Torvalds #define FlashPoint_ProbeHostAdapter FlashPoint__ProbeHostAdapter 76221da177e4SLinus Torvalds #define FlashPoint_HardwareResetHostAdapter FlashPoint__HardwareResetHostAdapter 76231da177e4SLinus Torvalds #define FlashPoint_ReleaseHostAdapter FlashPoint__ReleaseHostAdapter 76241da177e4SLinus Torvalds #define FlashPoint_StartCCB FlashPoint__StartCCB 76251da177e4SLinus Torvalds #define FlashPoint_AbortCCB FlashPoint__AbortCCB 76261da177e4SLinus Torvalds #define FlashPoint_InterruptPending FlashPoint__InterruptPending 76271da177e4SLinus Torvalds #define FlashPoint_HandleInterrupt FlashPoint__HandleInterrupt 76281da177e4SLinus Torvalds 762978b4b05dSMatthew Wilcox #else /* !CONFIG_SCSI_FLASHPOINT */ 76301da177e4SLinus Torvalds 76311da177e4SLinus Torvalds /* 76321da177e4SLinus Torvalds Define prototypes for the FlashPoint SCCB Manager Functions. 76331da177e4SLinus Torvalds */ 76341da177e4SLinus Torvalds 76351da177e4SLinus Torvalds extern unsigned char FlashPoint_ProbeHostAdapter(struct FlashPoint_Info *); 76361da177e4SLinus Torvalds extern FlashPoint_CardHandle_T 76371da177e4SLinus Torvalds FlashPoint_HardwareResetHostAdapter(struct FlashPoint_Info *); 76381da177e4SLinus Torvalds extern void FlashPoint_StartCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *); 76391da177e4SLinus Torvalds extern int FlashPoint_AbortCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *); 76402065e310SRichard Knutsson extern bool FlashPoint_InterruptPending(FlashPoint_CardHandle_T); 76411da177e4SLinus Torvalds extern int FlashPoint_HandleInterrupt(FlashPoint_CardHandle_T); 76421da177e4SLinus Torvalds extern void FlashPoint_ReleaseHostAdapter(FlashPoint_CardHandle_T); 76431da177e4SLinus Torvalds 764478b4b05dSMatthew Wilcox #endif /* CONFIG_SCSI_FLASHPOINT */ 7645