allow coexistance of N build and AC build.
[tomato.git] / release / src-rt-6.x / linux / linux-2.6 / drivers / scsi / FlashPoint.c
blobcf549ffe4baa5054e43206c172c36c2056a565d4
1 /*
3 FlashPoint.c -- FlashPoint SCCB Manager for Linux
5 This file contains the FlashPoint SCCB Manager from BusLogic's FlashPoint
6 Driver Developer's Kit, with minor modifications by Leonard N. Zubkoff for
7 Linux compatibility. It was provided by BusLogic in the form of 16 separate
8 source files, which would have unnecessarily cluttered the scsi directory, so
9 the individual files have been combined into this single file.
11 Copyright 1995-1996 by Mylex Corporation. All Rights Reserved
13 This file is available under both the GNU General Public License
14 and a BSD-style copyright; see LICENSE.FlashPoint for details.
19 #ifndef CONFIG_SCSI_OMIT_FLASHPOINT
21 #define MAX_CARDS 8
22 #undef BUSTYPE_PCI
24 #define CRCMASK 0xA001
26 #define FAILURE 0xFFFFFFFFL
28 #define BITW(x) ((unsigned short)(1<<(x))) /* single-bit mask in bit position x */
30 struct sccb;
31 typedef void (*CALL_BK_FN) (struct sccb *);
33 struct sccb_mgr_info {
34 unsigned long si_baseaddr;
35 unsigned char si_present;
36 unsigned char si_intvect;
37 unsigned char si_id;
38 unsigned char si_lun;
39 unsigned short si_fw_revision;
40 unsigned short si_per_targ_init_sync;
41 unsigned short si_per_targ_fast_nego;
42 unsigned short si_per_targ_ultra_nego;
43 unsigned short si_per_targ_no_disc;
44 unsigned short si_per_targ_wide_nego;
45 unsigned short si_flags;
46 unsigned char si_card_family;
47 unsigned char si_bustype;
48 unsigned char si_card_model[3];
49 unsigned char si_relative_cardnum;
50 unsigned char si_reserved[4];
51 unsigned long si_OS_reserved;
52 unsigned char si_XlatInfo[4];
53 unsigned long si_reserved2[5];
54 unsigned long si_secondary_range;
57 #define SCSI_PARITY_ENA 0x0001
58 #define LOW_BYTE_TERM 0x0010
59 #define HIGH_BYTE_TERM 0x0020
60 #define BUSTYPE_PCI 0x3
62 #define SUPPORT_16TAR_32LUN 0x0002
63 #define SOFT_RESET 0x0004
64 #define EXTENDED_TRANSLATION 0x0008
65 #define POST_ALL_UNDERRRUNS 0x0040
66 #define FLAG_SCAM_ENABLED 0x0080
67 #define FLAG_SCAM_LEVEL2 0x0100
69 #define HARPOON_FAMILY 0x02
71 /* SCCB struct used for both SCCB and UCB manager compiles!
72 * The UCB Manager treats the SCCB as it's 'native hardware structure'
75 #pragma pack(1)
76 struct sccb {
77 unsigned char OperationCode;
78 unsigned char ControlByte;
79 unsigned char CdbLength;
80 unsigned char RequestSenseLength;
81 unsigned long DataLength;
82 unsigned long DataPointer;
83 unsigned char CcbRes[2];
84 unsigned char HostStatus;
85 unsigned char TargetStatus;
86 unsigned char TargID;
87 unsigned char Lun;
88 unsigned char Cdb[12];
89 unsigned char CcbRes1;
90 unsigned char Reserved1;
91 unsigned long Reserved2;
92 unsigned long SensePointer;
94 CALL_BK_FN SccbCallback; /* VOID (*SccbCallback)(); */
95 unsigned long SccbIOPort; /* Identifies board base port */
96 unsigned char SccbStatus;
97 unsigned char SCCBRes2;
98 unsigned short SccbOSFlags;
100 unsigned long Sccb_XferCnt; /* actual transfer count */
101 unsigned long Sccb_ATC;
102 unsigned long SccbVirtDataPtr; /* virtual addr for OS/2 */
103 unsigned long Sccb_res1;
104 unsigned short Sccb_MGRFlags;
105 unsigned short Sccb_sgseg;
106 unsigned char Sccb_scsimsg; /* identify msg for selection */
107 unsigned char Sccb_tag;
108 unsigned char Sccb_scsistat;
109 unsigned char Sccb_idmsg; /* image of last msg in */
110 struct sccb *Sccb_forwardlink;
111 struct sccb *Sccb_backlink;
112 unsigned long Sccb_savedATC;
113 unsigned char Save_Cdb[6];
114 unsigned char Save_CdbLen;
115 unsigned char Sccb_XferState;
116 unsigned long Sccb_SGoffset;
119 #pragma pack()
121 #define SCATTER_GATHER_COMMAND 0x02
122 #define RESIDUAL_COMMAND 0x03
123 #define RESIDUAL_SG_COMMAND 0x04
124 #define RESET_COMMAND 0x81
126 #define F_USE_CMD_Q 0x20 /*Inidcates TAGGED command. */
127 #define TAG_TYPE_MASK 0xC0 /*Type of tag msg to send. */
128 #define SCCB_DATA_XFER_OUT 0x10 /* Write */
129 #define SCCB_DATA_XFER_IN 0x08 /* Read */
131 #define NO_AUTO_REQUEST_SENSE 0x01 /* No Request Sense Buffer */
133 #define BUS_FREE_ST 0
134 #define SELECT_ST 1
135 #define SELECT_BDR_ST 2 /* Select w\ Bus Device Reset */
136 #define SELECT_SN_ST 3 /* Select w\ Sync Nego */
137 #define SELECT_WN_ST 4 /* Select w\ Wide Data Nego */
138 #define SELECT_Q_ST 5 /* Select w\ Tagged Q'ing */
139 #define COMMAND_ST 6
140 #define DATA_OUT_ST 7
141 #define DATA_IN_ST 8
142 #define DISCONNECT_ST 9
143 #define ABORT_ST 11
145 #define F_HOST_XFER_DIR 0x01
146 #define F_ALL_XFERRED 0x02
147 #define F_SG_XFER 0x04
148 #define F_AUTO_SENSE 0x08
149 #define F_ODD_BALL_CNT 0x10
150 #define F_NO_DATA_YET 0x80
152 #define F_STATUSLOADED 0x01
153 #define F_DEV_SELECTED 0x04
155 #define SCCB_COMPLETE 0x00 /* SCCB completed without error */
156 #define SCCB_DATA_UNDER_RUN 0x0C
157 #define SCCB_SELECTION_TIMEOUT 0x11 /* Set SCSI selection timed out */
158 #define SCCB_DATA_OVER_RUN 0x12
159 #define SCCB_PHASE_SEQUENCE_FAIL 0x14 /* Target bus phase sequence failure */
161 #define SCCB_GROSS_FW_ERR 0x27 /* Major problem! */
162 #define SCCB_BM_ERR 0x30 /* BusMaster error. */
163 #define SCCB_PARITY_ERR 0x34 /* SCSI parity error */
165 #define SCCB_IN_PROCESS 0x00
166 #define SCCB_SUCCESS 0x01
167 #define SCCB_ABORT 0x02
168 #define SCCB_ERROR 0x04
170 #define ORION_FW_REV 3110
172 #define QUEUE_DEPTH 254+1 /*1 for Normal disconnect 32 for Q'ing. */
174 #define MAX_MB_CARDS 4 /* Max. no of cards suppoerted on Mother Board */
176 #define MAX_SCSI_TAR 16
177 #define MAX_LUN 32
178 #define LUN_MASK 0x1f
180 #define SG_BUF_CNT 16 /*Number of prefetched elements. */
182 #define SG_ELEMENT_SIZE 8 /*Eight byte per element. */
184 #define RD_HARPOON(ioport) inb((u32)ioport)
185 #define RDW_HARPOON(ioport) inw((u32)ioport)
186 #define RD_HARP32(ioport,offset,data) (data = inl((u32)(ioport + offset)))
187 #define WR_HARPOON(ioport,val) outb((u8) val, (u32)ioport)
188 #define WRW_HARPOON(ioport,val) outw((u16)val, (u32)ioport)
189 #define WR_HARP32(ioport,offset,data) outl(data, (u32)(ioport + offset))
191 #define TAR_SYNC_MASK (BIT(7)+BIT(6))
192 #define SYNC_TRYING BIT(6)
193 #define SYNC_SUPPORTED (BIT(7)+BIT(6))
195 #define TAR_WIDE_MASK (BIT(5)+BIT(4))
196 #define WIDE_ENABLED BIT(4)
197 #define WIDE_NEGOCIATED BIT(5)
199 #define TAR_TAG_Q_MASK (BIT(3)+BIT(2))
200 #define TAG_Q_TRYING BIT(2)
201 #define TAG_Q_REJECT BIT(3)
203 #define TAR_ALLOW_DISC BIT(0)
205 #define EE_SYNC_MASK (BIT(0)+BIT(1))
206 #define EE_SYNC_5MB BIT(0)
207 #define EE_SYNC_10MB BIT(1)
208 #define EE_SYNC_20MB (BIT(0)+BIT(1))
210 #define EE_WIDE_SCSI BIT(7)
212 struct sccb_mgr_tar_info {
214 struct sccb *TarSelQ_Head;
215 struct sccb *TarSelQ_Tail;
216 unsigned char TarLUN_CA; /*Contingent Allgiance */
217 unsigned char TarTagQ_Cnt;
218 unsigned char TarSelQ_Cnt;
219 unsigned char TarStatus;
220 unsigned char TarEEValue;
221 unsigned char TarSyncCtrl;
222 unsigned char TarReserved[2]; /* for alignment */
223 unsigned char LunDiscQ_Idx[MAX_LUN];
224 unsigned char TarLUNBusy[MAX_LUN];
227 struct nvram_info {
228 unsigned char niModel; /* Model No. of card */
229 unsigned char niCardNo; /* Card no. */
230 unsigned long niBaseAddr; /* Port Address of card */
231 unsigned char niSysConf; /* Adapter Configuration byte - Byte 16 of eeprom map */
232 unsigned char niScsiConf; /* SCSI Configuration byte - Byte 17 of eeprom map */
233 unsigned char niScamConf; /* SCAM Configuration byte - Byte 20 of eeprom map */
234 unsigned char niAdapId; /* Host Adapter ID - Byte 24 of eerpom map */
235 unsigned char niSyncTbl[MAX_SCSI_TAR / 2]; /* Sync/Wide byte of targets */
236 unsigned char niScamTbl[MAX_SCSI_TAR][4]; /* Compressed Scam name string of Targets */
239 #define MODEL_LT 1
240 #define MODEL_DL 2
241 #define MODEL_LW 3
242 #define MODEL_DW 4
244 struct sccb_card {
245 struct sccb *currentSCCB;
246 struct sccb_mgr_info *cardInfo;
248 unsigned long ioPort;
250 unsigned short cmdCounter;
251 unsigned char discQCount;
252 unsigned char tagQ_Lst;
253 unsigned char cardIndex;
254 unsigned char scanIndex;
255 unsigned char globalFlags;
256 unsigned char ourId;
257 struct nvram_info *pNvRamInfo;
258 struct sccb *discQ_Tbl[QUEUE_DEPTH];
262 #define F_TAG_STARTED 0x01
263 #define F_CONLUN_IO 0x02
264 #define F_DO_RENEGO 0x04
265 #define F_NO_FILTER 0x08
266 #define F_GREEN_PC 0x10
267 #define F_HOST_XFER_ACT 0x20
268 #define F_NEW_SCCB_CMD 0x40
269 #define F_UPDATE_EEPROM 0x80
271 #define ID_STRING_LENGTH 32
272 #define TYPE_CODE0 0x63 /*Level2 Mstr (bits 7-6), */
274 #define SLV_TYPE_CODE0 0xA3 /*Priority Bit set (bits 7-6), */
276 #define ASSIGN_ID 0x00
277 #define SET_P_FLAG 0x01
278 #define CFG_CMPLT 0x03
279 #define DOM_MSTR 0x0F
280 #define SYNC_PTRN 0x1F
282 #define ID_0_7 0x18
283 #define ID_8_F 0x11
284 #define MISC_CODE 0x14
285 #define CLR_P_FLAG 0x18
287 #define INIT_SELTD 0x01
288 #define LEVEL2_TAR 0x02
290 enum scam_id_st { ID0, ID1, ID2, ID3, ID4, ID5, ID6, ID7, ID8, ID9, ID10, ID11,
291 ID12,
292 ID13, ID14, ID15, ID_UNUSED, ID_UNASSIGNED, ID_ASSIGNED, LEGACY,
293 CLR_PRIORITY, NO_ID_AVAIL
296 typedef struct SCCBscam_info {
298 unsigned char id_string[ID_STRING_LENGTH];
299 enum scam_id_st state;
301 } SCCBSCAM_INFO;
303 #define SCSI_REQUEST_SENSE 0x03
304 #define SCSI_READ 0x08
305 #define SCSI_WRITE 0x0A
306 #define SCSI_START_STOP_UNIT 0x1B
307 #define SCSI_READ_EXTENDED 0x28
308 #define SCSI_WRITE_EXTENDED 0x2A
309 #define SCSI_WRITE_AND_VERIFY 0x2E
311 #define SSGOOD 0x00
312 #define SSCHECK 0x02
313 #define SSQ_FULL 0x28
315 #define SMCMD_COMP 0x00
316 #define SMEXT 0x01
317 #define SMSAVE_DATA_PTR 0x02
318 #define SMREST_DATA_PTR 0x03
319 #define SMDISC 0x04
320 #define SMABORT 0x06
321 #define SMREJECT 0x07
322 #define SMNO_OP 0x08
323 #define SMPARITY 0x09
324 #define SMDEV_RESET 0x0C
325 #define SMABORT_TAG 0x0D
326 #define SMINIT_RECOVERY 0x0F
327 #define SMREL_RECOVERY 0x10
329 #define SMIDENT 0x80
330 #define DISC_PRIV 0x40
332 #define SMSYNC 0x01
333 #define SMWDTR 0x03
334 #define SM8BIT 0x00
335 #define SM16BIT 0x01
336 #define SMIGNORWR 0x23 /* Ignore Wide Residue */
338 #define SIX_BYTE_CMD 0x06
339 #define TWELVE_BYTE_CMD 0x0C
341 #define ASYNC 0x00
342 #define MAX_OFFSET 0x0F /* Maxbyteoffset for Sync Xfers */
344 #define EEPROM_WD_CNT 256
346 #define EEPROM_CHECK_SUM 0
347 #define FW_SIGNATURE 2
348 #define MODEL_NUMB_0 4
349 #define MODEL_NUMB_2 6
350 #define MODEL_NUMB_4 8
351 #define SYSTEM_CONFIG 16
352 #define SCSI_CONFIG 17
353 #define BIOS_CONFIG 18
354 #define SCAM_CONFIG 20
355 #define ADAPTER_SCSI_ID 24
357 #define IGNORE_B_SCAN 32
358 #define SEND_START_ENA 34
359 #define DEVICE_ENABLE 36
361 #define SYNC_RATE_TBL 38
362 #define SYNC_RATE_TBL01 38
363 #define SYNC_RATE_TBL23 40
364 #define SYNC_RATE_TBL45 42
365 #define SYNC_RATE_TBL67 44
366 #define SYNC_RATE_TBL89 46
367 #define SYNC_RATE_TBLab 48
368 #define SYNC_RATE_TBLcd 50
369 #define SYNC_RATE_TBLef 52
371 #define EE_SCAMBASE 256
373 #define SCAM_ENABLED BIT(2)
374 #define SCAM_LEVEL2 BIT(3)
376 #define RENEGO_ENA BITW(10)
377 #define CONNIO_ENA BITW(11)
378 #define GREEN_PC_ENA BITW(12)
380 #define AUTO_RATE_00 00
381 #define AUTO_RATE_05 01
382 #define AUTO_RATE_10 02
383 #define AUTO_RATE_20 03
385 #define WIDE_NEGO_BIT BIT(7)
386 #define DISC_ENABLE_BIT BIT(6)
388 #define hp_vendor_id_0 0x00 /* LSB */
389 #define ORION_VEND_0 0x4B
391 #define hp_vendor_id_1 0x01 /* MSB */
392 #define ORION_VEND_1 0x10
394 #define hp_device_id_0 0x02 /* LSB */
395 #define ORION_DEV_0 0x30
397 #define hp_device_id_1 0x03 /* MSB */
398 #define ORION_DEV_1 0x81
400 /* Sub Vendor ID and Sub Device ID only available in
401 Harpoon Version 2 and higher */
403 #define hp_sub_device_id_0 0x06 /* LSB */
405 #define hp_semaphore 0x0C
406 #define SCCB_MGR_ACTIVE BIT(0)
407 #define TICKLE_ME BIT(1)
408 #define SCCB_MGR_PRESENT BIT(3)
409 #define BIOS_IN_USE BIT(4)
411 #define hp_sys_ctrl 0x0F
413 #define STOP_CLK BIT(0) /*Turn off BusMaster Clock */
414 #define DRVR_RST BIT(1) /*Firmware Reset to 80C15 chip */
415 #define HALT_MACH BIT(3) /*Halt State Machine */
416 #define HARD_ABORT BIT(4) /*Hard Abort */
418 #define hp_host_blk_cnt 0x13
420 #define XFER_BLK64 0x06 /* 1 1 0 64 byte per block */
422 #define BM_THRESHOLD 0x40 /* PCI mode can only xfer 16 bytes */
424 #define hp_int_mask 0x17
426 #define INT_CMD_COMPL BIT(0) /* DMA command complete */
427 #define INT_EXT_STATUS BIT(1) /* Extended Status Set */
429 #define hp_xfer_cnt_lo 0x18
430 #define hp_xfer_cnt_hi 0x1A
431 #define hp_xfer_cmd 0x1B
433 #define XFER_HOST_DMA 0x00 /* 0 0 0 Transfer Host -> DMA */
434 #define XFER_DMA_HOST 0x01 /* 0 0 1 Transfer DMA -> Host */
436 #define XFER_HOST_AUTO 0x00 /* 0 0 Auto Transfer Size */
438 #define XFER_DMA_8BIT 0x20 /* 0 1 8 BIT Transfer Size */
440 #define DISABLE_INT BIT(7) /*Do not interrupt at end of cmd. */
442 #define HOST_WRT_CMD ((DISABLE_INT + XFER_HOST_DMA + XFER_HOST_AUTO + XFER_DMA_8BIT))
443 #define HOST_RD_CMD ((DISABLE_INT + XFER_DMA_HOST + XFER_HOST_AUTO + XFER_DMA_8BIT))
445 #define hp_host_addr_lo 0x1C
446 #define hp_host_addr_hmi 0x1E
448 #define hp_ee_ctrl 0x22
450 #define EXT_ARB_ACK BIT(7)
451 #define SCSI_TERM_ENA_H BIT(6) /* SCSI high byte terminator */
452 #define SEE_MS BIT(5)
453 #define SEE_CS BIT(3)
454 #define SEE_CLK BIT(2)
455 #define SEE_DO BIT(1)
456 #define SEE_DI BIT(0)
458 #define EE_READ 0x06
459 #define EE_WRITE 0x05
460 #define EWEN 0x04
461 #define EWEN_ADDR 0x03C0
462 #define EWDS 0x04
463 #define EWDS_ADDR 0x0000
465 #define hp_bm_ctrl 0x26
467 #define SCSI_TERM_ENA_L BIT(0) /*Enable/Disable external terminators */
468 #define FLUSH_XFER_CNTR BIT(1) /*Flush transfer counter */
469 #define FORCE1_XFER BIT(5) /*Always xfer one byte in byte mode */
470 #define FAST_SINGLE BIT(6) /*?? */
472 #define BMCTRL_DEFAULT (FORCE1_XFER|FAST_SINGLE|SCSI_TERM_ENA_L)
474 #define hp_sg_addr 0x28
475 #define hp_page_ctrl 0x29
477 #define SCATTER_EN BIT(0)
478 #define SGRAM_ARAM BIT(1)
479 #define G_INT_DISABLE BIT(3) /* Enable/Disable all Interrupts */
480 #define NARROW_SCSI_CARD BIT(4) /* NARROW/WIDE SCSI config pin */
482 #define hp_pci_stat_cfg 0x2D
484 #define REC_MASTER_ABORT BIT(5) /*received Master abort */
486 #define hp_rev_num 0x33
488 #define hp_stack_data 0x34
489 #define hp_stack_addr 0x35
491 #define hp_ext_status 0x36
493 #define BM_FORCE_OFF BIT(0) /*Bus Master is forced to get off */
494 #define PCI_TGT_ABORT BIT(0) /*PCI bus master transaction aborted */
495 #define PCI_DEV_TMOUT BIT(1) /*PCI Device Time out */
496 #define CMD_ABORTED BIT(4) /*Command aborted */
497 #define BM_PARITY_ERR BIT(5) /*parity error on data received */
498 #define PIO_OVERRUN BIT(6) /*Slave data overrun */
499 #define BM_CMD_BUSY BIT(7) /*Bus master transfer command busy */
500 #define BAD_EXT_STATUS (BM_FORCE_OFF | PCI_DEV_TMOUT | CMD_ABORTED | \
501 BM_PARITY_ERR | PIO_OVERRUN)
503 #define hp_int_status 0x37
505 #define EXT_STATUS_ON BIT(1) /*Extended status is valid */
506 #define SCSI_INTERRUPT BIT(2) /*Global indication of a SCSI int. */
507 #define INT_ASSERTED BIT(5) /* */
509 #define hp_fifo_cnt 0x38
511 #define hp_intena 0x40
513 #define RESET BITW(7)
514 #define PROG_HLT BITW(6)
515 #define PARITY BITW(5)
516 #define FIFO BITW(4)
517 #define SEL BITW(3)
518 #define SCAM_SEL BITW(2)
519 #define RSEL BITW(1)
520 #define TIMEOUT BITW(0)
521 #define BUS_FREE BITW(15)
522 #define XFER_CNT_0 BITW(14)
523 #define PHASE BITW(13)
524 #define IUNKWN BITW(12)
525 #define ICMD_COMP BITW(11)
526 #define ITICKLE BITW(10)
527 #define IDO_STRT BITW(9)
528 #define ITAR_DISC BITW(8)
529 #define AUTO_INT (BITW(12)+BITW(11)+BITW(10)+BITW(9)+BITW(8))
530 #define CLR_ALL_INT 0xFFFF
531 #define CLR_ALL_INT_1 0xFF00
533 #define hp_intstat 0x42
535 #define hp_scsisig 0x44
537 #define SCSI_SEL BIT(7)
538 #define SCSI_BSY BIT(6)
539 #define SCSI_REQ BIT(5)
540 #define SCSI_ACK BIT(4)
541 #define SCSI_ATN BIT(3)
542 #define SCSI_CD BIT(2)
543 #define SCSI_MSG BIT(1)
544 #define SCSI_IOBIT BIT(0)
546 #define S_SCSI_PHZ (BIT(2)+BIT(1)+BIT(0))
547 #define S_MSGO_PH (BIT(2)+BIT(1) )
548 #define S_MSGI_PH (BIT(2)+BIT(1)+BIT(0))
549 #define S_DATAI_PH ( BIT(0))
550 #define S_DATAO_PH 0x00
551 #define S_ILL_PH ( BIT(1) )
553 #define hp_scsictrl_0 0x45
555 #define SEL_TAR BIT(6)
556 #define ENA_ATN BIT(4)
557 #define ENA_RESEL BIT(2)
558 #define SCSI_RST BIT(1)
559 #define ENA_SCAM_SEL BIT(0)
561 #define hp_portctrl_0 0x46
563 #define SCSI_PORT BIT(7)
564 #define SCSI_INBIT BIT(6)
565 #define DMA_PORT BIT(5)
566 #define DMA_RD BIT(4)
567 #define HOST_PORT BIT(3)
568 #define HOST_WRT BIT(2)
569 #define SCSI_BUS_EN BIT(1)
570 #define START_TO BIT(0)
572 #define hp_scsireset 0x47
574 #define SCSI_INI BIT(6)
575 #define SCAM_EN BIT(5)
576 #define DMA_RESET BIT(3)
577 #define HPSCSI_RESET BIT(2)
578 #define PROG_RESET BIT(1)
579 #define FIFO_CLR BIT(0)
581 #define hp_xfercnt_0 0x48
582 #define hp_xfercnt_2 0x4A
584 #define hp_fifodata_0 0x4C
585 #define hp_addstat 0x4E
587 #define SCAM_TIMER BIT(7)
588 #define SCSI_MODE8 BIT(3)
589 #define SCSI_PAR_ERR BIT(0)
591 #define hp_prgmcnt_0 0x4F
593 #define hp_selfid_0 0x50
594 #define hp_selfid_1 0x51
595 #define hp_arb_id 0x52
597 #define hp_select_id 0x53
599 #define hp_synctarg_base 0x54
600 #define hp_synctarg_12 0x54
601 #define hp_synctarg_13 0x55
602 #define hp_synctarg_14 0x56
603 #define hp_synctarg_15 0x57
605 #define hp_synctarg_8 0x58
606 #define hp_synctarg_9 0x59
607 #define hp_synctarg_10 0x5A
608 #define hp_synctarg_11 0x5B
610 #define hp_synctarg_4 0x5C
611 #define hp_synctarg_5 0x5D
612 #define hp_synctarg_6 0x5E
613 #define hp_synctarg_7 0x5F
615 #define hp_synctarg_0 0x60
616 #define hp_synctarg_1 0x61
617 #define hp_synctarg_2 0x62
618 #define hp_synctarg_3 0x63
620 #define NARROW_SCSI BIT(4)
621 #define DEFAULT_OFFSET 0x0F
623 #define hp_autostart_0 0x64
624 #define hp_autostart_1 0x65
625 #define hp_autostart_3 0x67
627 #define AUTO_IMMED BIT(5)
628 #define SELECT BIT(6)
629 #define END_DATA (BIT(7)+BIT(6))
631 #define hp_gp_reg_0 0x68
632 #define hp_gp_reg_1 0x69
633 #define hp_gp_reg_3 0x6B
635 #define hp_seltimeout 0x6C
637 #define TO_4ms 0x67 /* 3.9959ms */
639 #define TO_5ms 0x03 /* 4.9152ms */
640 #define TO_10ms 0x07 /* 11.xxxms */
641 #define TO_250ms 0x99 /* 250.68ms */
642 #define TO_290ms 0xB1 /* 289.99ms */
644 #define hp_clkctrl_0 0x6D
646 #define PWR_DWN BIT(6)
647 #define ACTdeassert BIT(4)
648 #define CLK_40MHZ (BIT(1) + BIT(0))
650 #define CLKCTRL_DEFAULT (ACTdeassert | CLK_40MHZ)
652 #define hp_fiforead 0x6E
653 #define hp_fifowrite 0x6F
655 #define hp_offsetctr 0x70
656 #define hp_xferstat 0x71
658 #define FIFO_EMPTY BIT(6)
660 #define hp_portctrl_1 0x72
662 #define CHK_SCSI_P BIT(3)
663 #define HOST_MODE8 BIT(0)
665 #define hp_xfer_pad 0x73
667 #define ID_UNLOCK BIT(3)
669 #define hp_scsidata_0 0x74
670 #define hp_scsidata_1 0x75
672 #define hp_aramBase 0x80
673 #define BIOS_DATA_OFFSET 0x60
674 #define BIOS_RELATIVE_CARD 0x64
676 #define AR3 (BITW(9) + BITW(8))
677 #define SDATA BITW(10)
679 #define CRD_OP BITW(11) /* Cmp Reg. w/ Data */
681 #define CRR_OP BITW(12) /* Cmp Reg. w. Reg. */
683 #define CPE_OP (BITW(14)+BITW(11)) /* Cmp SCSI phs & Branch EQ */
685 #define CPN_OP (BITW(14)+BITW(12)) /* Cmp SCSI phs & Branch NOT EQ */
687 #define ADATA_OUT 0x00
688 #define ADATA_IN BITW(8)
689 #define ACOMMAND BITW(10)
690 #define ASTATUS (BITW(10)+BITW(8))
691 #define AMSG_OUT (BITW(10)+BITW(9))
692 #define AMSG_IN (BITW(10)+BITW(9)+BITW(8))
694 #define BRH_OP BITW(13) /* Branch */
696 #define ALWAYS 0x00
697 #define EQUAL BITW(8)
698 #define NOT_EQ BITW(9)
700 #define TCB_OP (BITW(13)+BITW(11)) /* Test condition & branch */
702 #define FIFO_0 BITW(10)
704 #define MPM_OP BITW(15) /* Match phase and move data */
706 #define MRR_OP BITW(14) /* Move DReg. to Reg. */
708 #define S_IDREG (BIT(2)+BIT(1)+BIT(0))
710 #define D_AR0 0x00
711 #define D_AR1 BIT(0)
712 #define D_BUCKET (BIT(2) + BIT(1) + BIT(0))
714 #define RAT_OP (BITW(14)+BITW(13)+BITW(11))
716 #define SSI_OP (BITW(15)+BITW(11))
718 #define SSI_ITAR_DISC (ITAR_DISC >> 8)
719 #define SSI_IDO_STRT (IDO_STRT >> 8)
721 #define SSI_ICMD_COMP (ICMD_COMP >> 8)
722 #define SSI_ITICKLE (ITICKLE >> 8)
724 #define SSI_IUNKWN (IUNKWN >> 8)
725 #define SSI_INO_CC (IUNKWN >> 8)
726 #define SSI_IRFAIL (IUNKWN >> 8)
728 #define NP 0x10 /*Next Phase */
729 #define NTCMD 0x02 /*Non- Tagged Command start */
730 #define CMDPZ 0x04 /*Command phase */
731 #define DINT 0x12 /*Data Out/In interrupt */
732 #define DI 0x13 /*Data Out */
733 #define DC 0x19 /*Disconnect Message */
734 #define ST 0x1D /*Status Phase */
735 #define UNKNWN 0x24 /*Unknown bus action */
736 #define CC 0x25 /*Command Completion failure */
737 #define TICK 0x26 /*New target reselected us. */
738 #define SELCHK 0x28 /*Select & Check SCSI ID latch reg */
740 #define ID_MSG_STRT hp_aramBase + 0x00
741 #define NON_TAG_ID_MSG hp_aramBase + 0x06
742 #define CMD_STRT hp_aramBase + 0x08
743 #define SYNC_MSGS hp_aramBase + 0x08
745 #define TAG_STRT 0x00
746 #define DISCONNECT_START 0x10/2
747 #define END_DATA_START 0x14/2
748 #define CMD_ONLY_STRT CMDPZ/2
749 #define SELCHK_STRT SELCHK/2
751 #define GET_XFER_CNT(port, xfercnt) {RD_HARP32(port,hp_xfercnt_0,xfercnt); xfercnt &= 0xFFFFFF;}
752 /* #define GET_XFER_CNT(port, xfercnt) (xfercnt = RD_HARPOON(port+hp_xfercnt_2), \
753 xfercnt <<= 16,\
754 xfercnt |= RDW_HARPOON((unsigned short)(port+hp_xfercnt_0)))
756 #define HP_SETUP_ADDR_CNT(port,addr,count) (WRW_HARPOON((port+hp_host_addr_lo), (unsigned short)(addr & 0x0000FFFFL)),\
757 addr >>= 16,\
758 WRW_HARPOON((port+hp_host_addr_hmi), (unsigned short)(addr & 0x0000FFFFL)),\
759 WR_HARP32(port,hp_xfercnt_0,count),\
760 WRW_HARPOON((port+hp_xfer_cnt_lo), (unsigned short)(count & 0x0000FFFFL)),\
761 count >>= 16,\
762 WR_HARPOON(port+hp_xfer_cnt_hi, (count & 0xFF)))
764 #define ACCEPT_MSG(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
765 WR_HARPOON(port+hp_scsisig, S_ILL_PH);}
767 #define ACCEPT_MSG_ATN(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
768 WR_HARPOON(port+hp_scsisig, (S_ILL_PH|SCSI_ATN));}
770 #define DISABLE_AUTO(port) (WR_HARPOON(port+hp_scsireset, PROG_RESET),\
771 WR_HARPOON(port+hp_scsireset, 0x00))
773 #define ARAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
774 (RD_HARPOON(p_port+hp_page_ctrl) | SGRAM_ARAM)))
776 #define SGRAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
777 (RD_HARPOON(p_port+hp_page_ctrl) & ~SGRAM_ARAM)))
779 #define MDISABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
780 (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE)))
782 #define MENABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
783 (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE)))
785 static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card,
786 unsigned char syncFlag);
787 static void FPT_ssel(unsigned long port, unsigned char p_card);
788 static void FPT_sres(unsigned long port, unsigned char p_card,
789 struct sccb_card *pCurrCard);
790 static void FPT_shandem(unsigned long port, unsigned char p_card,
791 struct sccb *pCurrSCCB);
792 static void FPT_stsyncn(unsigned long port, unsigned char p_card);
793 static void FPT_sisyncr(unsigned long port, unsigned char sync_pulse,
794 unsigned char offset);
795 static void FPT_sssyncv(unsigned long p_port, unsigned char p_id,
796 unsigned char p_sync_value,
797 struct sccb_mgr_tar_info *currTar_Info);
798 static void FPT_sresb(unsigned long port, unsigned char p_card);
799 static void FPT_sxfrp(unsigned long p_port, unsigned char p_card);
800 static void FPT_schkdd(unsigned long port, unsigned char p_card);
801 static unsigned char FPT_RdStack(unsigned long port, unsigned char index);
802 static void FPT_WrStack(unsigned long portBase, unsigned char index,
803 unsigned char data);
804 static unsigned char FPT_ChkIfChipInitialized(unsigned long ioPort);
806 static void FPT_SendMsg(unsigned long port, unsigned char message);
807 static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
808 unsigned char error_code);
810 static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card);
811 static void FPT_RNVRamData(struct nvram_info *pNvRamInfo);
813 static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card);
814 static void FPT_stwidn(unsigned long port, unsigned char p_card);
815 static void FPT_siwidr(unsigned long port, unsigned char width);
817 static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
818 unsigned char p_card);
819 static void FPT_queueDisconnect(struct sccb *p_SCCB, unsigned char p_card);
820 static void FPT_queueCmdComplete(struct sccb_card *pCurrCard,
821 struct sccb *p_SCCB, unsigned char p_card);
822 static void FPT_queueSearchSelect(struct sccb_card *pCurrCard,
823 unsigned char p_card);
824 static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code);
825 static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char card);
826 static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB,
827 unsigned char p_card);
828 static void FPT_utilUpdateResidual(struct sccb *p_SCCB);
829 static unsigned short FPT_CalcCrc16(unsigned char buffer[]);
830 static unsigned char FPT_CalcLrc(unsigned char buffer[]);
832 static void FPT_Wait1Second(unsigned long p_port);
833 static void FPT_Wait(unsigned long p_port, unsigned char p_delay);
834 static void FPT_utilEEWriteOnOff(unsigned long p_port, unsigned char p_mode);
835 static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data,
836 unsigned short ee_addr);
837 static unsigned short FPT_utilEERead(unsigned long p_port,
838 unsigned short ee_addr);
839 static unsigned short FPT_utilEEReadOrg(unsigned long p_port,
840 unsigned short ee_addr);
841 static void FPT_utilEESendCmdAddr(unsigned long p_port, unsigned char ee_cmd,
842 unsigned short ee_addr);
844 static void FPT_phaseDataOut(unsigned long port, unsigned char p_card);
845 static void FPT_phaseDataIn(unsigned long port, unsigned char p_card);
846 static void FPT_phaseCommand(unsigned long port, unsigned char p_card);
847 static void FPT_phaseStatus(unsigned long port, unsigned char p_card);
848 static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card);
849 static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card);
850 static void FPT_phaseIllegal(unsigned long port, unsigned char p_card);
852 static void FPT_phaseDecode(unsigned long port, unsigned char p_card);
853 static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card);
854 static void FPT_phaseBusFree(unsigned long p_port, unsigned char p_card);
856 static void FPT_XbowInit(unsigned long port, unsigned char scamFlg);
857 static void FPT_BusMasterInit(unsigned long p_port);
858 static void FPT_DiagEEPROM(unsigned long p_port);
860 static void FPT_dataXferProcessor(unsigned long port,
861 struct sccb_card *pCurrCard);
862 static void FPT_busMstrSGDataXferStart(unsigned long port,
863 struct sccb *pCurrSCCB);
864 static void FPT_busMstrDataXferStart(unsigned long port,
865 struct sccb *pCurrSCCB);
866 static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card,
867 struct sccb *pCurrSCCB);
868 static void FPT_hostDataXferRestart(struct sccb *currSCCB);
870 static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port,
871 unsigned char p_card,
872 struct sccb_card *pCurrCard,
873 unsigned short p_int);
875 static void FPT_SccbMgrTableInitAll(void);
876 static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard,
877 unsigned char p_card);
878 static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
879 unsigned char target);
881 static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
882 unsigned char p_power_up);
884 static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type);
885 static void FPT_scbusf(unsigned long p_port);
886 static void FPT_scsel(unsigned long p_port);
887 static void FPT_scasid(unsigned char p_card, unsigned long p_port);
888 static unsigned char FPT_scxferc(unsigned long p_port, unsigned char p_data);
889 static unsigned char FPT_scsendi(unsigned long p_port,
890 unsigned char p_id_string[]);
891 static unsigned char FPT_sciso(unsigned long p_port,
892 unsigned char p_id_string[]);
893 static void FPT_scwirod(unsigned long p_port, unsigned char p_data_bit);
894 static void FPT_scwiros(unsigned long p_port, unsigned char p_data_bit);
895 static unsigned char FPT_scvalq(unsigned char p_quintet);
896 static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id);
897 static void FPT_scwtsel(unsigned long p_port);
898 static void FPT_inisci(unsigned char p_card, unsigned long p_port,
899 unsigned char p_our_id);
900 static void FPT_scsavdi(unsigned char p_card, unsigned long p_port);
901 static unsigned char FPT_scmachid(unsigned char p_card,
902 unsigned char p_id_string[]);
904 static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card);
905 static void FPT_autoLoadDefaultMap(unsigned long p_port);
907 static struct sccb_mgr_tar_info FPT_sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] =
908 { {{0}} };
909 static struct sccb_card FPT_BL_Card[MAX_CARDS] = { {0} };
910 static SCCBSCAM_INFO FPT_scamInfo[MAX_SCSI_TAR] = { {{0}} };
911 static struct nvram_info FPT_nvRamInfo[MAX_MB_CARDS] = { {0} };
913 static unsigned char FPT_mbCards = 0;
914 static unsigned char FPT_scamHAString[] =
915 { 0x63, 0x07, 'B', 'U', 'S', 'L', 'O', 'G', 'I', 'C',
916 ' ', 'B', 'T', '-', '9', '3', '0',
917 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
918 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
921 static unsigned short FPT_default_intena = 0;
923 static void (*FPT_s_PhaseTbl[8]) (unsigned long, unsigned char) = {
926 /*---------------------------------------------------------------------
928 * Function: FlashPoint_ProbeHostAdapter
930 * Description: Setup and/or Search for cards and return info to caller.
932 *---------------------------------------------------------------------*/
934 static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo)
936 static unsigned char first_time = 1;
938 unsigned char i, j, id, ScamFlg;
939 unsigned short temp, temp2, temp3, temp4, temp5, temp6;
940 unsigned long ioport;
941 struct nvram_info *pCurrNvRam;
943 ioport = pCardInfo->si_baseaddr;
945 if (RD_HARPOON(ioport + hp_vendor_id_0) != ORION_VEND_0)
946 return (int)FAILURE;
948 if ((RD_HARPOON(ioport + hp_vendor_id_1) != ORION_VEND_1))
949 return (int)FAILURE;
951 if ((RD_HARPOON(ioport + hp_device_id_0) != ORION_DEV_0))
952 return (int)FAILURE;
954 if ((RD_HARPOON(ioport + hp_device_id_1) != ORION_DEV_1))
955 return (int)FAILURE;
957 if (RD_HARPOON(ioport + hp_rev_num) != 0x0f) {
959 /* For new Harpoon then check for sub_device ID LSB
960 the bits(0-3) must be all ZERO for compatible with
961 current version of SCCBMgr, else skip this Harpoon
962 device. */
964 if (RD_HARPOON(ioport + hp_sub_device_id_0) & 0x0f)
965 return (int)FAILURE;
968 if (first_time) {
969 FPT_SccbMgrTableInitAll();
970 first_time = 0;
971 FPT_mbCards = 0;
974 if (FPT_RdStack(ioport, 0) != 0x00) {
975 if (FPT_ChkIfChipInitialized(ioport) == 0) {
976 pCurrNvRam = NULL;
977 WR_HARPOON(ioport + hp_semaphore, 0x00);
978 FPT_XbowInit(ioport, 0); /*Must Init the SCSI before attempting */
979 FPT_DiagEEPROM(ioport);
980 } else {
981 if (FPT_mbCards < MAX_MB_CARDS) {
982 pCurrNvRam = &FPT_nvRamInfo[FPT_mbCards];
983 FPT_mbCards++;
984 pCurrNvRam->niBaseAddr = ioport;
985 FPT_RNVRamData(pCurrNvRam);
986 } else
987 return (int)FAILURE;
989 } else
990 pCurrNvRam = NULL;
992 WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT);
993 WR_HARPOON(ioport + hp_sys_ctrl, 0x00);
995 if (pCurrNvRam)
996 pCardInfo->si_id = pCurrNvRam->niAdapId;
997 else
998 pCardInfo->si_id =
999 (unsigned
1000 char)(FPT_utilEERead(ioport,
1001 (ADAPTER_SCSI_ID /
1002 2)) & (unsigned char)0x0FF);
1004 pCardInfo->si_lun = 0x00;
1005 pCardInfo->si_fw_revision = ORION_FW_REV;
1006 temp2 = 0x0000;
1007 temp3 = 0x0000;
1008 temp4 = 0x0000;
1009 temp5 = 0x0000;
1010 temp6 = 0x0000;
1012 for (id = 0; id < (16 / 2); id++) {
1014 if (pCurrNvRam) {
1015 temp = (unsigned short)pCurrNvRam->niSyncTbl[id];
1016 temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
1017 (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
1018 } else
1019 temp =
1020 FPT_utilEERead(ioport,
1021 (unsigned short)((SYNC_RATE_TBL / 2)
1022 + id));
1024 for (i = 0; i < 2; temp >>= 8, i++) {
1026 temp2 >>= 1;
1027 temp3 >>= 1;
1028 temp4 >>= 1;
1029 temp5 >>= 1;
1030 temp6 >>= 1;
1031 switch (temp & 0x3) {
1032 case AUTO_RATE_20: /* Synchronous, 20 mega-transfers/second */
1033 temp6 |= 0x8000; /* Fall through */
1034 case AUTO_RATE_10: /* Synchronous, 10 mega-transfers/second */
1035 temp5 |= 0x8000; /* Fall through */
1036 case AUTO_RATE_05: /* Synchronous, 5 mega-transfers/second */
1037 temp2 |= 0x8000; /* Fall through */
1038 case AUTO_RATE_00: /* Asynchronous */
1039 break;
1042 if (temp & DISC_ENABLE_BIT)
1043 temp3 |= 0x8000;
1045 if (temp & WIDE_NEGO_BIT)
1046 temp4 |= 0x8000;
1051 pCardInfo->si_per_targ_init_sync = temp2;
1052 pCardInfo->si_per_targ_no_disc = temp3;
1053 pCardInfo->si_per_targ_wide_nego = temp4;
1054 pCardInfo->si_per_targ_fast_nego = temp5;
1055 pCardInfo->si_per_targ_ultra_nego = temp6;
1057 if (pCurrNvRam)
1058 i = pCurrNvRam->niSysConf;
1059 else
1060 i = (unsigned
1061 char)(FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)));
1063 if (pCurrNvRam)
1064 ScamFlg = pCurrNvRam->niScamConf;
1065 else
1066 ScamFlg =
1067 (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
1069 pCardInfo->si_flags = 0x0000;
1071 if (i & 0x01)
1072 pCardInfo->si_flags |= SCSI_PARITY_ENA;
1074 if (!(i & 0x02))
1075 pCardInfo->si_flags |= SOFT_RESET;
1077 if (i & 0x10)
1078 pCardInfo->si_flags |= EXTENDED_TRANSLATION;
1080 if (ScamFlg & SCAM_ENABLED)
1081 pCardInfo->si_flags |= FLAG_SCAM_ENABLED;
1083 if (ScamFlg & SCAM_LEVEL2)
1084 pCardInfo->si_flags |= FLAG_SCAM_LEVEL2;
1086 j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
1087 if (i & 0x04) {
1088 j |= SCSI_TERM_ENA_L;
1090 WR_HARPOON(ioport + hp_bm_ctrl, j);
1092 j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
1093 if (i & 0x08) {
1094 j |= SCSI_TERM_ENA_H;
1096 WR_HARPOON(ioport + hp_ee_ctrl, j);
1098 if (!(RD_HARPOON(ioport + hp_page_ctrl) & NARROW_SCSI_CARD))
1100 pCardInfo->si_flags |= SUPPORT_16TAR_32LUN;
1102 pCardInfo->si_card_family = HARPOON_FAMILY;
1103 pCardInfo->si_bustype = BUSTYPE_PCI;
1105 if (pCurrNvRam) {
1106 pCardInfo->si_card_model[0] = '9';
1107 switch (pCurrNvRam->niModel & 0x0f) {
1108 case MODEL_LT:
1109 pCardInfo->si_card_model[1] = '3';
1110 pCardInfo->si_card_model[2] = '0';
1111 break;
1112 case MODEL_LW:
1113 pCardInfo->si_card_model[1] = '5';
1114 pCardInfo->si_card_model[2] = '0';
1115 break;
1116 case MODEL_DL:
1117 pCardInfo->si_card_model[1] = '3';
1118 pCardInfo->si_card_model[2] = '2';
1119 break;
1120 case MODEL_DW:
1121 pCardInfo->si_card_model[1] = '5';
1122 pCardInfo->si_card_model[2] = '2';
1123 break;
1125 } else {
1126 temp = FPT_utilEERead(ioport, (MODEL_NUMB_0 / 2));
1127 pCardInfo->si_card_model[0] = (unsigned char)(temp >> 8);
1128 temp = FPT_utilEERead(ioport, (MODEL_NUMB_2 / 2));
1130 pCardInfo->si_card_model[1] = (unsigned char)(temp & 0x00FF);
1131 pCardInfo->si_card_model[2] = (unsigned char)(temp >> 8);
1134 if (pCardInfo->si_card_model[1] == '3') {
1135 if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
1136 pCardInfo->si_flags |= LOW_BYTE_TERM;
1137 } else if (pCardInfo->si_card_model[2] == '0') {
1138 temp = RD_HARPOON(ioport + hp_xfer_pad);
1139 WR_HARPOON(ioport + hp_xfer_pad, (temp & ~BIT(4)));
1140 if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
1141 pCardInfo->si_flags |= LOW_BYTE_TERM;
1142 WR_HARPOON(ioport + hp_xfer_pad, (temp | BIT(4)));
1143 if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
1144 pCardInfo->si_flags |= HIGH_BYTE_TERM;
1145 WR_HARPOON(ioport + hp_xfer_pad, temp);
1146 } else {
1147 temp = RD_HARPOON(ioport + hp_ee_ctrl);
1148 temp2 = RD_HARPOON(ioport + hp_xfer_pad);
1149 WR_HARPOON(ioport + hp_ee_ctrl, (temp | SEE_CS));
1150 WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4)));
1151 temp3 = 0;
1152 for (i = 0; i < 8; i++) {
1153 temp3 <<= 1;
1154 if (!(RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7)))
1155 temp3 |= 1;
1156 WR_HARPOON(ioport + hp_xfer_pad, (temp2 & ~BIT(4)));
1157 WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4)));
1159 WR_HARPOON(ioport + hp_ee_ctrl, temp);
1160 WR_HARPOON(ioport + hp_xfer_pad, temp2);
1161 if (!(temp3 & BIT(7)))
1162 pCardInfo->si_flags |= LOW_BYTE_TERM;
1163 if (!(temp3 & BIT(6)))
1164 pCardInfo->si_flags |= HIGH_BYTE_TERM;
1167 ARAM_ACCESS(ioport);
1169 for (i = 0; i < 4; i++) {
1171 pCardInfo->si_XlatInfo[i] =
1172 RD_HARPOON(ioport + hp_aramBase + BIOS_DATA_OFFSET + i);
1175 /* return with -1 if no sort, else return with
1176 logical card number sorted by BIOS (zero-based) */
1178 pCardInfo->si_relative_cardnum =
1179 (unsigned
1180 char)(RD_HARPOON(ioport + hp_aramBase + BIOS_RELATIVE_CARD) - 1);
1182 SGRAM_ACCESS(ioport);
1184 FPT_s_PhaseTbl[0] = FPT_phaseDataOut;
1185 FPT_s_PhaseTbl[1] = FPT_phaseDataIn;
1186 FPT_s_PhaseTbl[2] = FPT_phaseIllegal;
1187 FPT_s_PhaseTbl[3] = FPT_phaseIllegal;
1188 FPT_s_PhaseTbl[4] = FPT_phaseCommand;
1189 FPT_s_PhaseTbl[5] = FPT_phaseStatus;
1190 FPT_s_PhaseTbl[6] = FPT_phaseMsgOut;
1191 FPT_s_PhaseTbl[7] = FPT_phaseMsgIn;
1193 pCardInfo->si_present = 0x01;
1195 return 0;
1198 /*---------------------------------------------------------------------
1200 * Function: FlashPoint_HardwareResetHostAdapter
1202 * Description: Setup adapter for normal operation (hard reset).
1204 *---------------------------------------------------------------------*/
1206 static unsigned long FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info
1207 *pCardInfo)
1209 struct sccb_card *CurrCard = NULL;
1210 struct nvram_info *pCurrNvRam;
1211 unsigned char i, j, thisCard, ScamFlg;
1212 unsigned short temp, sync_bit_map, id;
1213 unsigned long ioport;
1215 ioport = pCardInfo->si_baseaddr;
1217 for (thisCard = 0; thisCard <= MAX_CARDS; thisCard++) {
1219 if (thisCard == MAX_CARDS) {
1221 return FAILURE;
1224 if (FPT_BL_Card[thisCard].ioPort == ioport) {
1226 CurrCard = &FPT_BL_Card[thisCard];
1227 FPT_SccbMgrTableInitCard(CurrCard, thisCard);
1228 break;
1231 else if (FPT_BL_Card[thisCard].ioPort == 0x00) {
1233 FPT_BL_Card[thisCard].ioPort = ioport;
1234 CurrCard = &FPT_BL_Card[thisCard];
1236 if (FPT_mbCards)
1237 for (i = 0; i < FPT_mbCards; i++) {
1238 if (CurrCard->ioPort ==
1239 FPT_nvRamInfo[i].niBaseAddr)
1240 CurrCard->pNvRamInfo =
1241 &FPT_nvRamInfo[i];
1243 FPT_SccbMgrTableInitCard(CurrCard, thisCard);
1244 CurrCard->cardIndex = thisCard;
1245 CurrCard->cardInfo = pCardInfo;
1247 break;
1251 pCurrNvRam = CurrCard->pNvRamInfo;
1253 if (pCurrNvRam) {
1254 ScamFlg = pCurrNvRam->niScamConf;
1255 } else {
1256 ScamFlg =
1257 (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
1260 FPT_BusMasterInit(ioport);
1261 FPT_XbowInit(ioport, ScamFlg);
1263 FPT_autoLoadDefaultMap(ioport);
1265 for (i = 0, id = 0x01; i != pCardInfo->si_id; i++, id <<= 1) {
1268 WR_HARPOON(ioport + hp_selfid_0, id);
1269 WR_HARPOON(ioport + hp_selfid_1, 0x00);
1270 WR_HARPOON(ioport + hp_arb_id, pCardInfo->si_id);
1271 CurrCard->ourId = pCardInfo->si_id;
1273 i = (unsigned char)pCardInfo->si_flags;
1274 if (i & SCSI_PARITY_ENA)
1275 WR_HARPOON(ioport + hp_portctrl_1, (HOST_MODE8 | CHK_SCSI_P));
1277 j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
1278 if (i & LOW_BYTE_TERM)
1279 j |= SCSI_TERM_ENA_L;
1280 WR_HARPOON(ioport + hp_bm_ctrl, j);
1282 j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
1283 if (i & HIGH_BYTE_TERM)
1284 j |= SCSI_TERM_ENA_H;
1285 WR_HARPOON(ioport + hp_ee_ctrl, j);
1287 if (!(pCardInfo->si_flags & SOFT_RESET)) {
1289 FPT_sresb(ioport, thisCard);
1291 FPT_scini(thisCard, pCardInfo->si_id, 0);
1294 if (pCardInfo->si_flags & POST_ALL_UNDERRRUNS)
1295 CurrCard->globalFlags |= F_NO_FILTER;
1297 if (pCurrNvRam) {
1298 if (pCurrNvRam->niSysConf & 0x10)
1299 CurrCard->globalFlags |= F_GREEN_PC;
1300 } else {
1301 if (FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)) & GREEN_PC_ENA)
1302 CurrCard->globalFlags |= F_GREEN_PC;
1305 /* Set global flag to indicate Re-Negotiation to be done on all
1306 ckeck condition */
1307 if (pCurrNvRam) {
1308 if (pCurrNvRam->niScsiConf & 0x04)
1309 CurrCard->globalFlags |= F_DO_RENEGO;
1310 } else {
1311 if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & RENEGO_ENA)
1312 CurrCard->globalFlags |= F_DO_RENEGO;
1315 if (pCurrNvRam) {
1316 if (pCurrNvRam->niScsiConf & 0x08)
1317 CurrCard->globalFlags |= F_CONLUN_IO;
1318 } else {
1319 if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & CONNIO_ENA)
1320 CurrCard->globalFlags |= F_CONLUN_IO;
1323 temp = pCardInfo->si_per_targ_no_disc;
1325 for (i = 0, id = 1; i < MAX_SCSI_TAR; i++, id <<= 1) {
1327 if (temp & id)
1328 FPT_sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC;
1331 sync_bit_map = 0x0001;
1333 for (id = 0; id < (MAX_SCSI_TAR / 2); id++) {
1335 if (pCurrNvRam) {
1336 temp = (unsigned short)pCurrNvRam->niSyncTbl[id];
1337 temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
1338 (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
1339 } else
1340 temp =
1341 FPT_utilEERead(ioport,
1342 (unsigned short)((SYNC_RATE_TBL / 2)
1343 + id));
1345 for (i = 0; i < 2; temp >>= 8, i++) {
1347 if (pCardInfo->si_per_targ_init_sync & sync_bit_map) {
1349 FPT_sccbMgrTbl[thisCard][id * 2 +
1350 i].TarEEValue =
1351 (unsigned char)temp;
1354 else {
1355 FPT_sccbMgrTbl[thisCard][id * 2 +
1356 i].TarStatus |=
1357 SYNC_SUPPORTED;
1358 FPT_sccbMgrTbl[thisCard][id * 2 +
1359 i].TarEEValue =
1360 (unsigned char)(temp & ~EE_SYNC_MASK);
1363 /* if ((pCardInfo->si_per_targ_wide_nego & sync_bit_map) ||
1364 (id*2+i >= 8)){
1366 if (pCardInfo->si_per_targ_wide_nego & sync_bit_map) {
1368 FPT_sccbMgrTbl[thisCard][id * 2 +
1369 i].TarEEValue |=
1370 EE_WIDE_SCSI;
1374 else { /* NARROW SCSI */
1375 FPT_sccbMgrTbl[thisCard][id * 2 +
1376 i].TarStatus |=
1377 WIDE_NEGOCIATED;
1380 sync_bit_map <<= 1;
1385 WR_HARPOON((ioport + hp_semaphore),
1386 (unsigned char)(RD_HARPOON((ioport + hp_semaphore)) |
1387 SCCB_MGR_PRESENT));
1389 return (unsigned long)CurrCard;
1392 static void FlashPoint_ReleaseHostAdapter(unsigned long pCurrCard)
1394 unsigned char i;
1395 unsigned long portBase;
1396 unsigned long regOffset;
1397 unsigned long scamData;
1398 unsigned long *pScamTbl;
1399 struct nvram_info *pCurrNvRam;
1401 pCurrNvRam = ((struct sccb_card *)pCurrCard)->pNvRamInfo;
1403 if (pCurrNvRam) {
1404 FPT_WrStack(pCurrNvRam->niBaseAddr, 0, pCurrNvRam->niModel);
1405 FPT_WrStack(pCurrNvRam->niBaseAddr, 1, pCurrNvRam->niSysConf);
1406 FPT_WrStack(pCurrNvRam->niBaseAddr, 2, pCurrNvRam->niScsiConf);
1407 FPT_WrStack(pCurrNvRam->niBaseAddr, 3, pCurrNvRam->niScamConf);
1408 FPT_WrStack(pCurrNvRam->niBaseAddr, 4, pCurrNvRam->niAdapId);
1410 for (i = 0; i < MAX_SCSI_TAR / 2; i++)
1411 FPT_WrStack(pCurrNvRam->niBaseAddr,
1412 (unsigned char)(i + 5),
1413 pCurrNvRam->niSyncTbl[i]);
1415 portBase = pCurrNvRam->niBaseAddr;
1417 for (i = 0; i < MAX_SCSI_TAR; i++) {
1418 regOffset = hp_aramBase + 64 + i * 4;
1419 pScamTbl = (unsigned long *)&pCurrNvRam->niScamTbl[i];
1420 scamData = *pScamTbl;
1421 WR_HARP32(portBase, regOffset, scamData);
1424 } else {
1425 FPT_WrStack(((struct sccb_card *)pCurrCard)->ioPort, 0, 0);
1429 static void FPT_RNVRamData(struct nvram_info *pNvRamInfo)
1431 unsigned char i;
1432 unsigned long portBase;
1433 unsigned long regOffset;
1434 unsigned long scamData;
1435 unsigned long *pScamTbl;
1437 pNvRamInfo->niModel = FPT_RdStack(pNvRamInfo->niBaseAddr, 0);
1438 pNvRamInfo->niSysConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 1);
1439 pNvRamInfo->niScsiConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 2);
1440 pNvRamInfo->niScamConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 3);
1441 pNvRamInfo->niAdapId = FPT_RdStack(pNvRamInfo->niBaseAddr, 4);
1443 for (i = 0; i < MAX_SCSI_TAR / 2; i++)
1444 pNvRamInfo->niSyncTbl[i] =
1445 FPT_RdStack(pNvRamInfo->niBaseAddr, (unsigned char)(i + 5));
1447 portBase = pNvRamInfo->niBaseAddr;
1449 for (i = 0; i < MAX_SCSI_TAR; i++) {
1450 regOffset = hp_aramBase + 64 + i * 4;
1451 RD_HARP32(portBase, regOffset, scamData);
1452 pScamTbl = (unsigned long *)&pNvRamInfo->niScamTbl[i];
1453 *pScamTbl = scamData;
1458 static unsigned char FPT_RdStack(unsigned long portBase, unsigned char index)
1460 WR_HARPOON(portBase + hp_stack_addr, index);
1461 return RD_HARPOON(portBase + hp_stack_data);
1464 static void FPT_WrStack(unsigned long portBase, unsigned char index,
1465 unsigned char data)
1467 WR_HARPOON(portBase + hp_stack_addr, index);
1468 WR_HARPOON(portBase + hp_stack_data, data);
1471 static unsigned char FPT_ChkIfChipInitialized(unsigned long ioPort)
1473 if ((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != FPT_RdStack(ioPort, 4))
1474 return 0;
1475 if ((RD_HARPOON(ioPort + hp_clkctrl_0) & CLKCTRL_DEFAULT)
1476 != CLKCTRL_DEFAULT)
1477 return 0;
1478 if ((RD_HARPOON(ioPort + hp_seltimeout) == TO_250ms) ||
1479 (RD_HARPOON(ioPort + hp_seltimeout) == TO_290ms))
1480 return 1;
1481 return 0;
1485 /*---------------------------------------------------------------------
1487 * Function: FlashPoint_StartCCB
1489 * Description: Start a command pointed to by p_Sccb. When the
1490 * command is completed it will be returned via the
1491 * callback function.
1493 *---------------------------------------------------------------------*/
1494 static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb *p_Sccb)
1496 unsigned long ioport;
1497 unsigned char thisCard, lun;
1498 struct sccb *pSaveSccb;
1499 CALL_BK_FN callback;
1501 thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
1502 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
1504 if ((p_Sccb->TargID > MAX_SCSI_TAR) || (p_Sccb->Lun > MAX_LUN)) {
1506 p_Sccb->HostStatus = SCCB_COMPLETE;
1507 p_Sccb->SccbStatus = SCCB_ERROR;
1508 callback = (CALL_BK_FN) p_Sccb->SccbCallback;
1509 if (callback)
1510 callback(p_Sccb);
1512 return;
1515 FPT_sinits(p_Sccb, thisCard);
1517 if (!((struct sccb_card *)pCurrCard)->cmdCounter) {
1518 WR_HARPOON(ioport + hp_semaphore,
1519 (RD_HARPOON(ioport + hp_semaphore)
1520 | SCCB_MGR_ACTIVE));
1522 if (((struct sccb_card *)pCurrCard)->globalFlags & F_GREEN_PC) {
1523 WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT);
1524 WR_HARPOON(ioport + hp_sys_ctrl, 0x00);
1528 ((struct sccb_card *)pCurrCard)->cmdCounter++;
1530 if (RD_HARPOON(ioport + hp_semaphore) & BIOS_IN_USE) {
1532 WR_HARPOON(ioport + hp_semaphore,
1533 (RD_HARPOON(ioport + hp_semaphore)
1534 | TICKLE_ME));
1535 if (p_Sccb->OperationCode == RESET_COMMAND) {
1536 pSaveSccb =
1537 ((struct sccb_card *)pCurrCard)->currentSCCB;
1538 ((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb;
1539 FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
1540 ((struct sccb_card *)pCurrCard)->currentSCCB =
1541 pSaveSccb;
1542 } else {
1543 FPT_queueAddSccb(p_Sccb, thisCard);
1547 else if ((RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) {
1549 if (p_Sccb->OperationCode == RESET_COMMAND) {
1550 pSaveSccb =
1551 ((struct sccb_card *)pCurrCard)->currentSCCB;
1552 ((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb;
1553 FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
1554 ((struct sccb_card *)pCurrCard)->currentSCCB =
1555 pSaveSccb;
1556 } else {
1557 FPT_queueAddSccb(p_Sccb, thisCard);
1561 else {
1563 MDISABLE_INT(ioport);
1565 if ((((struct sccb_card *)pCurrCard)->globalFlags & F_CONLUN_IO)
1567 ((FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].
1568 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
1569 lun = p_Sccb->Lun;
1570 else
1571 lun = 0;
1572 if ((((struct sccb_card *)pCurrCard)->currentSCCB == NULL) &&
1573 (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarSelQ_Cnt == 0)
1574 && (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarLUNBusy[lun]
1575 == 0)) {
1577 ((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb;
1578 FPT_ssel(p_Sccb->SccbIOPort, thisCard);
1581 else {
1583 if (p_Sccb->OperationCode == RESET_COMMAND) {
1584 pSaveSccb =
1585 ((struct sccb_card *)pCurrCard)->
1586 currentSCCB;
1587 ((struct sccb_card *)pCurrCard)->currentSCCB =
1588 p_Sccb;
1589 FPT_queueSelectFail(&FPT_BL_Card[thisCard],
1590 thisCard);
1591 ((struct sccb_card *)pCurrCard)->currentSCCB =
1592 pSaveSccb;
1593 } else {
1594 FPT_queueAddSccb(p_Sccb, thisCard);
1598 MENABLE_INT(ioport);
1603 /*---------------------------------------------------------------------
1605 * Function: FlashPoint_AbortCCB
1607 * Description: Abort the command pointed to by p_Sccb. When the
1608 * command is completed it will be returned via the
1609 * callback function.
1611 *---------------------------------------------------------------------*/
1612 static int FlashPoint_AbortCCB(unsigned long pCurrCard, struct sccb *p_Sccb)
1614 unsigned long ioport;
1616 unsigned char thisCard;
1617 CALL_BK_FN callback;
1618 unsigned char TID;
1619 struct sccb *pSaveSCCB;
1620 struct sccb_mgr_tar_info *currTar_Info;
1622 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
1624 thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
1626 if (!(RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) {
1628 if (FPT_queueFindSccb(p_Sccb, thisCard)) {
1630 ((struct sccb_card *)pCurrCard)->cmdCounter--;
1632 if (!((struct sccb_card *)pCurrCard)->cmdCounter)
1633 WR_HARPOON(ioport + hp_semaphore,
1634 (RD_HARPOON(ioport + hp_semaphore)
1635 & (unsigned
1636 char)(~(SCCB_MGR_ACTIVE |
1637 TICKLE_ME))));
1639 p_Sccb->SccbStatus = SCCB_ABORT;
1640 callback = p_Sccb->SccbCallback;
1641 callback(p_Sccb);
1643 return 0;
1646 else {
1647 if (((struct sccb_card *)pCurrCard)->currentSCCB ==
1648 p_Sccb) {
1649 p_Sccb->SccbStatus = SCCB_ABORT;
1650 return 0;
1654 else {
1656 TID = p_Sccb->TargID;
1658 if (p_Sccb->Sccb_tag) {
1659 MDISABLE_INT(ioport);
1660 if (((struct sccb_card *)pCurrCard)->
1661 discQ_Tbl[p_Sccb->Sccb_tag] ==
1662 p_Sccb) {
1663 p_Sccb->SccbStatus = SCCB_ABORT;
1664 p_Sccb->Sccb_scsistat =
1665 ABORT_ST;
1666 p_Sccb->Sccb_scsimsg =
1667 SMABORT_TAG;
1669 if (((struct sccb_card *)
1670 pCurrCard)->currentSCCB ==
1671 NULL) {
1672 ((struct sccb_card *)
1673 pCurrCard)->
1674 currentSCCB = p_Sccb;
1675 FPT_ssel(ioport,
1676 thisCard);
1677 } else {
1678 pSaveSCCB =
1679 ((struct sccb_card
1680 *)pCurrCard)->
1681 currentSCCB;
1682 ((struct sccb_card *)
1683 pCurrCard)->
1684 currentSCCB = p_Sccb;
1685 FPT_queueSelectFail((struct sccb_card *)pCurrCard, thisCard);
1686 ((struct sccb_card *)
1687 pCurrCard)->
1688 currentSCCB = pSaveSCCB;
1691 MENABLE_INT(ioport);
1692 return 0;
1693 } else {
1694 currTar_Info =
1695 &FPT_sccbMgrTbl[thisCard][p_Sccb->
1696 TargID];
1698 if (FPT_BL_Card[thisCard].
1699 discQ_Tbl[currTar_Info->
1700 LunDiscQ_Idx[p_Sccb->Lun]]
1701 == p_Sccb) {
1702 p_Sccb->SccbStatus = SCCB_ABORT;
1703 return 0;
1709 return -1;
1712 /*---------------------------------------------------------------------
1714 * Function: FlashPoint_InterruptPending
1716 * Description: Do a quick check to determine if there is a pending
1717 * interrupt for this card and disable the IRQ Pin if so.
1719 *---------------------------------------------------------------------*/
1720 static unsigned char FlashPoint_InterruptPending(unsigned long pCurrCard)
1722 unsigned long ioport;
1724 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
1726 if (RD_HARPOON(ioport + hp_int_status) & INT_ASSERTED) {
1727 return 1;
1730 else
1732 return 0;
1735 /*---------------------------------------------------------------------
1737 * Function: FlashPoint_HandleInterrupt
1739 * Description: This is our entry point when an interrupt is generated
1740 * by the card and the upper level driver passes it on to
1741 * us.
1743 *---------------------------------------------------------------------*/
1744 static int FlashPoint_HandleInterrupt(unsigned long pCurrCard)
1746 struct sccb *currSCCB;
1747 unsigned char thisCard, result, bm_status, bm_int_st;
1748 unsigned short hp_int;
1749 unsigned char i, target;
1750 unsigned long ioport;
1752 thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
1753 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
1755 MDISABLE_INT(ioport);
1757 if ((bm_int_st = RD_HARPOON(ioport + hp_int_status)) & EXT_STATUS_ON)
1758 bm_status =
1759 RD_HARPOON(ioport +
1760 hp_ext_status) & (unsigned char)BAD_EXT_STATUS;
1761 else
1762 bm_status = 0;
1764 WR_HARPOON(ioport + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
1766 while ((hp_int =
1767 RDW_HARPOON((ioport +
1768 hp_intstat)) & FPT_default_intena) | bm_status) {
1770 currSCCB = ((struct sccb_card *)pCurrCard)->currentSCCB;
1772 if (hp_int & (FIFO | TIMEOUT | RESET | SCAM_SEL) || bm_status) {
1773 result =
1774 FPT_SccbMgr_bad_isr(ioport, thisCard,
1775 ((struct sccb_card *)pCurrCard),
1776 hp_int);
1777 WRW_HARPOON((ioport + hp_intstat),
1778 (FIFO | TIMEOUT | RESET | SCAM_SEL));
1779 bm_status = 0;
1781 if (result) {
1783 MENABLE_INT(ioport);
1784 return result;
1788 else if (hp_int & ICMD_COMP) {
1790 if (!(hp_int & BUS_FREE)) {
1791 /* Wait for the BusFree before starting a new command. We
1792 must also check for being reselected since the BusFree
1793 may not show up if another device reselects us in 1.5us or
1794 less. SRR Wednesday, 3/8/1995.
1796 while (!
1797 (RDW_HARPOON((ioport + hp_intstat)) &
1798 (BUS_FREE | RSEL))) ;
1801 if (((struct sccb_card *)pCurrCard)->
1802 globalFlags & F_HOST_XFER_ACT)
1804 FPT_phaseChkFifo(ioport, thisCard);
1806 /* WRW_HARPOON((ioport+hp_intstat),
1807 (BUS_FREE | ICMD_COMP | ITAR_DISC | XFER_CNT_0));
1810 WRW_HARPOON((ioport + hp_intstat), CLR_ALL_INT_1);
1812 FPT_autoCmdCmplt(ioport, thisCard);
1816 else if (hp_int & ITAR_DISC) {
1818 if (((struct sccb_card *)pCurrCard)->
1819 globalFlags & F_HOST_XFER_ACT) {
1821 FPT_phaseChkFifo(ioport, thisCard);
1825 if (RD_HARPOON(ioport + hp_gp_reg_1) == SMSAVE_DATA_PTR) {
1827 WR_HARPOON(ioport + hp_gp_reg_1, 0x00);
1828 currSCCB->Sccb_XferState |= F_NO_DATA_YET;
1830 currSCCB->Sccb_savedATC = currSCCB->Sccb_ATC;
1833 currSCCB->Sccb_scsistat = DISCONNECT_ST;
1834 FPT_queueDisconnect(currSCCB, thisCard);
1836 /* Wait for the BusFree before starting a new command. We
1837 must also check for being reselected since the BusFree
1838 may not show up if another device reselects us in 1.5us or
1839 less. SRR Wednesday, 3/8/1995.
1841 while (!
1842 (RDW_HARPOON((ioport + hp_intstat)) &
1843 (BUS_FREE | RSEL))
1844 && !((RDW_HARPOON((ioport + hp_intstat)) & PHASE)
1845 && RD_HARPOON((ioport + hp_scsisig)) ==
1846 (SCSI_BSY | SCSI_REQ | SCSI_CD | SCSI_MSG |
1847 SCSI_IOBIT))) ;
1850 The additional loop exit condition above detects a timing problem
1851 with the revision D/E harpoon chips. The caller should reset the
1852 host adapter to recover when 0xFE is returned.
1854 if (!
1855 (RDW_HARPOON((ioport + hp_intstat)) &
1856 (BUS_FREE | RSEL))) {
1857 MENABLE_INT(ioport);
1858 return 0xFE;
1861 WRW_HARPOON((ioport + hp_intstat),
1862 (BUS_FREE | ITAR_DISC));
1864 ((struct sccb_card *)pCurrCard)->globalFlags |=
1865 F_NEW_SCCB_CMD;
1869 else if (hp_int & RSEL) {
1871 WRW_HARPOON((ioport + hp_intstat),
1872 (PROG_HLT | RSEL | PHASE | BUS_FREE));
1874 if (RDW_HARPOON((ioport + hp_intstat)) & ITAR_DISC) {
1875 if (((struct sccb_card *)pCurrCard)->
1876 globalFlags & F_HOST_XFER_ACT) {
1877 FPT_phaseChkFifo(ioport, thisCard);
1880 if (RD_HARPOON(ioport + hp_gp_reg_1) ==
1881 SMSAVE_DATA_PTR) {
1882 WR_HARPOON(ioport + hp_gp_reg_1, 0x00);
1883 currSCCB->Sccb_XferState |=
1884 F_NO_DATA_YET;
1885 currSCCB->Sccb_savedATC =
1886 currSCCB->Sccb_ATC;
1889 WRW_HARPOON((ioport + hp_intstat),
1890 (BUS_FREE | ITAR_DISC));
1891 currSCCB->Sccb_scsistat = DISCONNECT_ST;
1892 FPT_queueDisconnect(currSCCB, thisCard);
1895 FPT_sres(ioport, thisCard,
1896 ((struct sccb_card *)pCurrCard));
1897 FPT_phaseDecode(ioport, thisCard);
1901 else if ((hp_int & IDO_STRT) && (!(hp_int & BUS_FREE))) {
1903 WRW_HARPOON((ioport + hp_intstat),
1904 (IDO_STRT | XFER_CNT_0));
1905 FPT_phaseDecode(ioport, thisCard);
1909 else if ((hp_int & IUNKWN) || (hp_int & PROG_HLT)) {
1910 WRW_HARPOON((ioport + hp_intstat),
1911 (PHASE | IUNKWN | PROG_HLT));
1912 if ((RD_HARPOON(ioport + hp_prgmcnt_0) & (unsigned char)
1913 0x3f) < (unsigned char)SELCHK) {
1914 FPT_phaseDecode(ioport, thisCard);
1915 } else {
1916 /* Harpoon problem some SCSI target device respond to selection
1917 with short BUSY pulse (<400ns) this will make the Harpoon is not able
1918 to latch the correct Target ID into reg. x53.
1919 The work around require to correct this reg. But when write to this
1920 reg. (0x53) also increment the FIFO write addr reg (0x6f), thus we
1921 need to read this reg first then restore it later. After update to 0x53 */
1923 i = (unsigned
1924 char)(RD_HARPOON(ioport + hp_fifowrite));
1925 target =
1926 (unsigned
1927 char)(RD_HARPOON(ioport + hp_gp_reg_3));
1928 WR_HARPOON(ioport + hp_xfer_pad,
1929 (unsigned char)ID_UNLOCK);
1930 WR_HARPOON(ioport + hp_select_id,
1931 (unsigned char)(target | target <<
1932 4));
1933 WR_HARPOON(ioport + hp_xfer_pad,
1934 (unsigned char)0x00);
1935 WR_HARPOON(ioport + hp_fifowrite, i);
1936 WR_HARPOON(ioport + hp_autostart_3,
1937 (AUTO_IMMED + TAG_STRT));
1941 else if (hp_int & XFER_CNT_0) {
1943 WRW_HARPOON((ioport + hp_intstat), XFER_CNT_0);
1945 FPT_schkdd(ioport, thisCard);
1949 else if (hp_int & BUS_FREE) {
1951 WRW_HARPOON((ioport + hp_intstat), BUS_FREE);
1953 if (((struct sccb_card *)pCurrCard)->
1954 globalFlags & F_HOST_XFER_ACT) {
1956 FPT_hostDataXferAbort(ioport, thisCard,
1957 currSCCB);
1960 FPT_phaseBusFree(ioport, thisCard);
1963 else if (hp_int & ITICKLE) {
1965 WRW_HARPOON((ioport + hp_intstat), ITICKLE);
1966 ((struct sccb_card *)pCurrCard)->globalFlags |=
1967 F_NEW_SCCB_CMD;
1970 if (((struct sccb_card *)pCurrCard)->
1971 globalFlags & F_NEW_SCCB_CMD) {
1973 ((struct sccb_card *)pCurrCard)->globalFlags &=
1974 ~F_NEW_SCCB_CMD;
1976 if (((struct sccb_card *)pCurrCard)->currentSCCB ==
1977 NULL) {
1979 FPT_queueSearchSelect(((struct sccb_card *)
1980 pCurrCard), thisCard);
1983 if (((struct sccb_card *)pCurrCard)->currentSCCB !=
1984 NULL) {
1985 ((struct sccb_card *)pCurrCard)->globalFlags &=
1986 ~F_NEW_SCCB_CMD;
1987 FPT_ssel(ioport, thisCard);
1990 break;
1994 } /*end while */
1996 MENABLE_INT(ioport);
1998 return 0;
2001 /*---------------------------------------------------------------------
2003 * Function: Sccb_bad_isr
2005 * Description: Some type of interrupt has occurred which is slightly
2006 * out of the ordinary. We will now decode it fully, in
2007 * this routine. This is broken up in an attempt to save
2008 * processing time.
2010 *---------------------------------------------------------------------*/
2011 static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port,
2012 unsigned char p_card,
2013 struct sccb_card *pCurrCard,
2014 unsigned short p_int)
2016 unsigned char temp, ScamFlg;
2017 struct sccb_mgr_tar_info *currTar_Info;
2018 struct nvram_info *pCurrNvRam;
2020 if (RD_HARPOON(p_port + hp_ext_status) &
2021 (BM_FORCE_OFF | PCI_DEV_TMOUT | BM_PARITY_ERR | PIO_OVERRUN)) {
2023 if (pCurrCard->globalFlags & F_HOST_XFER_ACT) {
2025 FPT_hostDataXferAbort(p_port, p_card,
2026 pCurrCard->currentSCCB);
2029 if (RD_HARPOON(p_port + hp_pci_stat_cfg) & REC_MASTER_ABORT)
2031 WR_HARPOON(p_port + hp_pci_stat_cfg,
2032 (RD_HARPOON(p_port + hp_pci_stat_cfg) &
2033 ~REC_MASTER_ABORT));
2035 WR_HARPOON(p_port + hp_host_blk_cnt, 0x00);
2039 if (pCurrCard->currentSCCB != NULL) {
2041 if (!pCurrCard->currentSCCB->HostStatus)
2042 pCurrCard->currentSCCB->HostStatus =
2043 SCCB_BM_ERR;
2045 FPT_sxfrp(p_port, p_card);
2047 temp = (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
2048 (EXT_ARB_ACK | SCSI_TERM_ENA_H));
2049 WR_HARPOON(p_port + hp_ee_ctrl,
2050 ((unsigned char)temp | SEE_MS | SEE_CS));
2051 WR_HARPOON(p_port + hp_ee_ctrl, temp);
2053 if (!
2054 (RDW_HARPOON((p_port + hp_intstat)) &
2055 (BUS_FREE | RESET))) {
2056 FPT_phaseDecode(p_port, p_card);
2061 else if (p_int & RESET) {
2063 WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
2064 WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
2065 if (pCurrCard->currentSCCB != NULL) {
2067 if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
2069 FPT_hostDataXferAbort(p_port, p_card,
2070 pCurrCard->currentSCCB);
2073 DISABLE_AUTO(p_port);
2075 FPT_sresb(p_port, p_card);
2077 while (RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST) {
2080 pCurrNvRam = pCurrCard->pNvRamInfo;
2081 if (pCurrNvRam) {
2082 ScamFlg = pCurrNvRam->niScamConf;
2083 } else {
2084 ScamFlg =
2085 (unsigned char)FPT_utilEERead(p_port,
2086 SCAM_CONFIG / 2);
2089 FPT_XbowInit(p_port, ScamFlg);
2091 FPT_scini(p_card, pCurrCard->ourId, 0);
2093 return 0xFF;
2096 else if (p_int & FIFO) {
2098 WRW_HARPOON((p_port + hp_intstat), FIFO);
2100 if (pCurrCard->currentSCCB != NULL)
2101 FPT_sxfrp(p_port, p_card);
2104 else if (p_int & TIMEOUT) {
2106 DISABLE_AUTO(p_port);
2108 WRW_HARPOON((p_port + hp_intstat),
2109 (PROG_HLT | TIMEOUT | SEL | BUS_FREE | PHASE |
2110 IUNKWN));
2112 pCurrCard->currentSCCB->HostStatus = SCCB_SELECTION_TIMEOUT;
2114 currTar_Info =
2115 &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
2116 if ((pCurrCard->globalFlags & F_CONLUN_IO)
2117 && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
2118 TAG_Q_TRYING))
2119 currTar_Info->TarLUNBusy[pCurrCard->currentSCCB->Lun] =
2121 else
2122 currTar_Info->TarLUNBusy[0] = 0;
2124 if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
2125 currTar_Info->TarSyncCtrl = 0;
2126 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2129 if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
2130 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2133 FPT_sssyncv(p_port, pCurrCard->currentSCCB->TargID, NARROW_SCSI,
2134 currTar_Info);
2136 FPT_queueCmdComplete(pCurrCard, pCurrCard->currentSCCB, p_card);
2140 else if (p_int & SCAM_SEL) {
2142 FPT_scarb(p_port, LEVEL2_TAR);
2143 FPT_scsel(p_port);
2144 FPT_scasid(p_card, p_port);
2146 FPT_scbusf(p_port);
2148 WRW_HARPOON((p_port + hp_intstat), SCAM_SEL);
2151 return 0x00;
2154 /*---------------------------------------------------------------------
2156 * Function: SccbMgrTableInit
2158 * Description: Initialize all Sccb manager data structures.
2160 *---------------------------------------------------------------------*/
2162 static void FPT_SccbMgrTableInitAll()
2164 unsigned char thisCard;
2166 for (thisCard = 0; thisCard < MAX_CARDS; thisCard++) {
2167 FPT_SccbMgrTableInitCard(&FPT_BL_Card[thisCard], thisCard);
2169 FPT_BL_Card[thisCard].ioPort = 0x00;
2170 FPT_BL_Card[thisCard].cardInfo = NULL;
2171 FPT_BL_Card[thisCard].cardIndex = 0xFF;
2172 FPT_BL_Card[thisCard].ourId = 0x00;
2173 FPT_BL_Card[thisCard].pNvRamInfo = NULL;
2177 /*---------------------------------------------------------------------
2179 * Function: SccbMgrTableInit
2181 * Description: Initialize all Sccb manager data structures.
2183 *---------------------------------------------------------------------*/
2185 static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard,
2186 unsigned char p_card)
2188 unsigned char scsiID, qtag;
2190 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
2191 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
2194 for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
2195 FPT_sccbMgrTbl[p_card][scsiID].TarStatus = 0;
2196 FPT_sccbMgrTbl[p_card][scsiID].TarEEValue = 0;
2197 FPT_SccbMgrTableInitTarget(p_card, scsiID);
2200 pCurrCard->scanIndex = 0x00;
2201 pCurrCard->currentSCCB = NULL;
2202 pCurrCard->globalFlags = 0x00;
2203 pCurrCard->cmdCounter = 0x00;
2204 pCurrCard->tagQ_Lst = 0x01;
2205 pCurrCard->discQCount = 0;
2209 /*---------------------------------------------------------------------
2211 * Function: SccbMgrTableInit
2213 * Description: Initialize all Sccb manager data structures.
2215 *---------------------------------------------------------------------*/
2217 static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
2218 unsigned char target)
2221 unsigned char lun, qtag;
2222 struct sccb_mgr_tar_info *currTar_Info;
2224 currTar_Info = &FPT_sccbMgrTbl[p_card][target];
2226 currTar_Info->TarSelQ_Cnt = 0;
2227 currTar_Info->TarSyncCtrl = 0;
2229 currTar_Info->TarSelQ_Head = NULL;
2230 currTar_Info->TarSelQ_Tail = NULL;
2231 currTar_Info->TarTagQ_Cnt = 0;
2232 currTar_Info->TarLUN_CA = 0;
2234 for (lun = 0; lun < MAX_LUN; lun++) {
2235 currTar_Info->TarLUNBusy[lun] = 0;
2236 currTar_Info->LunDiscQ_Idx[lun] = 0;
2239 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
2240 if (FPT_BL_Card[p_card].discQ_Tbl[qtag] != NULL) {
2241 if (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
2242 target) {
2243 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
2244 FPT_BL_Card[p_card].discQCount--;
2250 /*---------------------------------------------------------------------
2252 * Function: sfetm
2254 * Description: Read in a message byte from the SCSI bus, and check
2255 * for a parity error.
2257 *---------------------------------------------------------------------*/
2259 static unsigned char FPT_sfm(unsigned long port, struct sccb *pCurrSCCB)
2261 unsigned char message;
2262 unsigned short TimeOutLoop;
2264 TimeOutLoop = 0;
2265 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2266 (TimeOutLoop++ < 20000)) {
2269 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
2271 message = RD_HARPOON(port + hp_scsidata_0);
2273 WR_HARPOON(port + hp_scsisig, SCSI_ACK + S_MSGI_PH);
2275 if (TimeOutLoop > 20000)
2276 message = 0x00; /* force message byte = 0 if Time Out on Req */
2278 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
2279 (RD_HARPOON(port + hp_addstat) & SCSI_PAR_ERR)) {
2280 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2281 WR_HARPOON(port + hp_xferstat, 0);
2282 WR_HARPOON(port + hp_fiforead, 0);
2283 WR_HARPOON(port + hp_fifowrite, 0);
2284 if (pCurrSCCB != NULL) {
2285 pCurrSCCB->Sccb_scsimsg = SMPARITY;
2287 message = 0x00;
2288 do {
2289 ACCEPT_MSG_ATN(port);
2290 TimeOutLoop = 0;
2291 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2292 (TimeOutLoop++ < 20000)) {
2294 if (TimeOutLoop > 20000) {
2295 WRW_HARPOON((port + hp_intstat), PARITY);
2296 return message;
2298 if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) !=
2299 S_MSGI_PH) {
2300 WRW_HARPOON((port + hp_intstat), PARITY);
2301 return message;
2303 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
2305 RD_HARPOON(port + hp_scsidata_0);
2307 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2309 } while (1);
2312 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2313 WR_HARPOON(port + hp_xferstat, 0);
2314 WR_HARPOON(port + hp_fiforead, 0);
2315 WR_HARPOON(port + hp_fifowrite, 0);
2316 return message;
2319 /*---------------------------------------------------------------------
2321 * Function: FPT_ssel
2323 * Description: Load up automation and select target device.
2325 *---------------------------------------------------------------------*/
2327 static void FPT_ssel(unsigned long port, unsigned char p_card)
2330 unsigned char auto_loaded, i, target, *theCCB;
2332 unsigned long cdb_reg;
2333 struct sccb_card *CurrCard;
2334 struct sccb *currSCCB;
2335 struct sccb_mgr_tar_info *currTar_Info;
2336 unsigned char lastTag, lun;
2338 CurrCard = &FPT_BL_Card[p_card];
2339 currSCCB = CurrCard->currentSCCB;
2340 target = currSCCB->TargID;
2341 currTar_Info = &FPT_sccbMgrTbl[p_card][target];
2342 lastTag = CurrCard->tagQ_Lst;
2344 ARAM_ACCESS(port);
2346 if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
2347 currSCCB->ControlByte &= ~F_USE_CMD_Q;
2349 if (((CurrCard->globalFlags & F_CONLUN_IO) &&
2350 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
2352 lun = currSCCB->Lun;
2353 else
2354 lun = 0;
2356 if (CurrCard->globalFlags & F_TAG_STARTED) {
2357 if (!(currSCCB->ControlByte & F_USE_CMD_Q)) {
2358 if ((currTar_Info->TarLUN_CA == 0)
2359 && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
2360 == TAG_Q_TRYING)) {
2362 if (currTar_Info->TarTagQ_Cnt != 0) {
2363 currTar_Info->TarLUNBusy[lun] = 1;
2364 FPT_queueSelectFail(CurrCard, p_card);
2365 SGRAM_ACCESS(port);
2366 return;
2369 else {
2370 currTar_Info->TarLUNBusy[lun] = 1;
2374 /*End non-tagged */
2375 else {
2376 currTar_Info->TarLUNBusy[lun] = 1;
2380 /*!Use cmd Q Tagged */
2381 else {
2382 if (currTar_Info->TarLUN_CA == 1) {
2383 FPT_queueSelectFail(CurrCard, p_card);
2384 SGRAM_ACCESS(port);
2385 return;
2388 currTar_Info->TarLUNBusy[lun] = 1;
2390 } /*else use cmd Q tagged */
2393 /*if glob tagged started */
2394 else {
2395 currTar_Info->TarLUNBusy[lun] = 1;
2398 if ((((CurrCard->globalFlags & F_CONLUN_IO) &&
2399 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
2400 || (!(currSCCB->ControlByte & F_USE_CMD_Q)))) {
2401 if (CurrCard->discQCount >= QUEUE_DEPTH) {
2402 currTar_Info->TarLUNBusy[lun] = 1;
2403 FPT_queueSelectFail(CurrCard, p_card);
2404 SGRAM_ACCESS(port);
2405 return;
2407 for (i = 1; i < QUEUE_DEPTH; i++) {
2408 if (++lastTag >= QUEUE_DEPTH)
2409 lastTag = 1;
2410 if (CurrCard->discQ_Tbl[lastTag] == NULL) {
2411 CurrCard->tagQ_Lst = lastTag;
2412 currTar_Info->LunDiscQ_Idx[lun] = lastTag;
2413 CurrCard->discQ_Tbl[lastTag] = currSCCB;
2414 CurrCard->discQCount++;
2415 break;
2418 if (i == QUEUE_DEPTH) {
2419 currTar_Info->TarLUNBusy[lun] = 1;
2420 FPT_queueSelectFail(CurrCard, p_card);
2421 SGRAM_ACCESS(port);
2422 return;
2426 auto_loaded = 0;
2428 WR_HARPOON(port + hp_select_id, target);
2429 WR_HARPOON(port + hp_gp_reg_3, target); /* Use by new automation logic */
2431 if (currSCCB->OperationCode == RESET_COMMAND) {
2432 WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
2433 (currSCCB->
2434 Sccb_idmsg & ~DISC_PRIV)));
2436 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + NP);
2438 currSCCB->Sccb_scsimsg = SMDEV_RESET;
2440 WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
2441 auto_loaded = 1;
2442 currSCCB->Sccb_scsistat = SELECT_BDR_ST;
2444 if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
2445 currTar_Info->TarSyncCtrl = 0;
2446 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2449 if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
2450 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2453 FPT_sssyncv(port, target, NARROW_SCSI, currTar_Info);
2454 FPT_SccbMgrTableInitTarget(p_card, target);
2458 else if (currSCCB->Sccb_scsistat == ABORT_ST) {
2459 WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
2460 (currSCCB->
2461 Sccb_idmsg & ~DISC_PRIV)));
2463 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
2465 WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT +
2466 (((unsigned
2467 char)(currSCCB->
2468 ControlByte &
2469 TAG_TYPE_MASK)
2470 >> 6) | (unsigned char)
2471 0x20)));
2472 WRW_HARPOON((port + SYNC_MSGS + 2),
2473 (MPM_OP + AMSG_OUT + currSCCB->Sccb_tag));
2474 WRW_HARPOON((port + SYNC_MSGS + 4), (BRH_OP + ALWAYS + NP));
2476 WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
2477 auto_loaded = 1;
2481 else if (!(currTar_Info->TarStatus & WIDE_NEGOCIATED)) {
2482 auto_loaded = FPT_siwidn(port, p_card);
2483 currSCCB->Sccb_scsistat = SELECT_WN_ST;
2486 else if (!((currTar_Info->TarStatus & TAR_SYNC_MASK)
2487 == SYNC_SUPPORTED)) {
2488 auto_loaded = FPT_sisyncn(port, p_card, 0);
2489 currSCCB->Sccb_scsistat = SELECT_SN_ST;
2492 if (!auto_loaded) {
2494 if (currSCCB->ControlByte & F_USE_CMD_Q) {
2496 CurrCard->globalFlags |= F_TAG_STARTED;
2498 if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
2499 == TAG_Q_REJECT) {
2500 currSCCB->ControlByte &= ~F_USE_CMD_Q;
2502 /* Fix up the start instruction with a jump to
2503 Non-Tag-CMD handling */
2504 WRW_HARPOON((port + ID_MSG_STRT),
2505 BRH_OP + ALWAYS + NTCMD);
2507 WRW_HARPOON((port + NON_TAG_ID_MSG),
2508 (MPM_OP + AMSG_OUT +
2509 currSCCB->Sccb_idmsg));
2511 WR_HARPOON(port + hp_autostart_3,
2512 (SELECT + SELCHK_STRT));
2514 /* Setup our STATE so we know what happend when
2515 the wheels fall off. */
2516 currSCCB->Sccb_scsistat = SELECT_ST;
2518 currTar_Info->TarLUNBusy[lun] = 1;
2521 else {
2522 WRW_HARPOON((port + ID_MSG_STRT),
2523 (MPM_OP + AMSG_OUT +
2524 currSCCB->Sccb_idmsg));
2526 WRW_HARPOON((port + ID_MSG_STRT + 2),
2527 (MPM_OP + AMSG_OUT +
2528 (((unsigned char)(currSCCB->
2529 ControlByte &
2530 TAG_TYPE_MASK)
2531 >> 6) | (unsigned char)0x20)));
2533 for (i = 1; i < QUEUE_DEPTH; i++) {
2534 if (++lastTag >= QUEUE_DEPTH)
2535 lastTag = 1;
2536 if (CurrCard->discQ_Tbl[lastTag] ==
2537 NULL) {
2538 WRW_HARPOON((port +
2539 ID_MSG_STRT + 6),
2540 (MPM_OP + AMSG_OUT +
2541 lastTag));
2542 CurrCard->tagQ_Lst = lastTag;
2543 currSCCB->Sccb_tag = lastTag;
2544 CurrCard->discQ_Tbl[lastTag] =
2545 currSCCB;
2546 CurrCard->discQCount++;
2547 break;
2551 if (i == QUEUE_DEPTH) {
2552 currTar_Info->TarLUNBusy[lun] = 1;
2553 FPT_queueSelectFail(CurrCard, p_card);
2554 SGRAM_ACCESS(port);
2555 return;
2558 currSCCB->Sccb_scsistat = SELECT_Q_ST;
2560 WR_HARPOON(port + hp_autostart_3,
2561 (SELECT + SELCHK_STRT));
2565 else {
2567 WRW_HARPOON((port + ID_MSG_STRT),
2568 BRH_OP + ALWAYS + NTCMD);
2570 WRW_HARPOON((port + NON_TAG_ID_MSG),
2571 (MPM_OP + AMSG_OUT + currSCCB->Sccb_idmsg));
2573 currSCCB->Sccb_scsistat = SELECT_ST;
2575 WR_HARPOON(port + hp_autostart_3,
2576 (SELECT + SELCHK_STRT));
2579 theCCB = (unsigned char *)&currSCCB->Cdb[0];
2581 cdb_reg = port + CMD_STRT;
2583 for (i = 0; i < currSCCB->CdbLength; i++) {
2584 WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + *theCCB));
2585 cdb_reg += 2;
2586 theCCB++;
2589 if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
2590 WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
2593 /* auto_loaded */
2594 WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
2595 WR_HARPOON(port + hp_xferstat, 0x00);
2597 WRW_HARPOON((port + hp_intstat), (PROG_HLT | TIMEOUT | SEL | BUS_FREE));
2599 WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT));
2601 if (!(currSCCB->Sccb_MGRFlags & F_DEV_SELECTED)) {
2602 WR_HARPOON(port + hp_scsictrl_0,
2603 (SEL_TAR | ENA_ATN | ENA_RESEL | ENA_SCAM_SEL));
2604 } else {
2606 /* auto_loaded = (RD_HARPOON(port+hp_autostart_3) & (unsigned char)0x1F);
2607 auto_loaded |= AUTO_IMMED; */
2608 auto_loaded = AUTO_IMMED;
2610 DISABLE_AUTO(port);
2612 WR_HARPOON(port + hp_autostart_3, auto_loaded);
2615 SGRAM_ACCESS(port);
2618 /*---------------------------------------------------------------------
2620 * Function: FPT_sres
2622 * Description: Hookup the correct CCB and handle the incoming messages.
2624 *---------------------------------------------------------------------*/
2626 static void FPT_sres(unsigned long port, unsigned char p_card,
2627 struct sccb_card *pCurrCard)
2630 unsigned char our_target, message, lun = 0, tag, msgRetryCount;
2632 struct sccb_mgr_tar_info *currTar_Info;
2633 struct sccb *currSCCB;
2635 if (pCurrCard->currentSCCB != NULL) {
2636 currTar_Info =
2637 &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
2638 DISABLE_AUTO(port);
2640 WR_HARPOON((port + hp_scsictrl_0), (ENA_RESEL | ENA_SCAM_SEL));
2642 currSCCB = pCurrCard->currentSCCB;
2643 if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
2644 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2645 currSCCB->Sccb_scsistat = BUS_FREE_ST;
2647 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
2648 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2649 currSCCB->Sccb_scsistat = BUS_FREE_ST;
2651 if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
2652 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
2653 TAG_Q_TRYING))) {
2654 currTar_Info->TarLUNBusy[currSCCB->Lun] = 0;
2655 if (currSCCB->Sccb_scsistat != ABORT_ST) {
2656 pCurrCard->discQCount--;
2657 pCurrCard->discQ_Tbl[currTar_Info->
2658 LunDiscQ_Idx[currSCCB->
2659 Lun]]
2660 = NULL;
2662 } else {
2663 currTar_Info->TarLUNBusy[0] = 0;
2664 if (currSCCB->Sccb_tag) {
2665 if (currSCCB->Sccb_scsistat != ABORT_ST) {
2666 pCurrCard->discQCount--;
2667 pCurrCard->discQ_Tbl[currSCCB->
2668 Sccb_tag] = NULL;
2670 } else {
2671 if (currSCCB->Sccb_scsistat != ABORT_ST) {
2672 pCurrCard->discQCount--;
2673 pCurrCard->discQ_Tbl[currTar_Info->
2674 LunDiscQ_Idx[0]] =
2675 NULL;
2680 FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
2683 WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
2685 our_target = (unsigned char)(RD_HARPOON(port + hp_select_id) >> 4);
2686 currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
2688 msgRetryCount = 0;
2689 do {
2691 currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
2692 tag = 0;
2694 while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
2695 if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
2697 WRW_HARPOON((port + hp_intstat), PHASE);
2698 return;
2702 WRW_HARPOON((port + hp_intstat), PHASE);
2703 if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH) {
2705 message = FPT_sfm(port, pCurrCard->currentSCCB);
2706 if (message) {
2708 if (message <= (0x80 | LUN_MASK)) {
2709 lun = message & (unsigned char)LUN_MASK;
2711 if ((currTar_Info->
2712 TarStatus & TAR_TAG_Q_MASK) ==
2713 TAG_Q_TRYING) {
2714 if (currTar_Info->TarTagQ_Cnt !=
2715 0) {
2717 if (!
2718 (currTar_Info->
2719 TarLUN_CA)) {
2720 ACCEPT_MSG(port); /*Release the ACK for ID msg. */
2722 message =
2723 FPT_sfm
2724 (port,
2725 pCurrCard->
2726 currentSCCB);
2727 if (message) {
2728 ACCEPT_MSG
2729 (port);
2732 else
2733 message
2734 = 0;
2736 if (message !=
2737 0) {
2738 tag =
2739 FPT_sfm
2740 (port,
2741 pCurrCard->
2742 currentSCCB);
2744 if (!
2745 (tag))
2746 message
2752 /*C.A. exists! */
2754 /*End Q cnt != 0 */
2756 /*End Tag cmds supported! */
2758 /*End valid ID message. */
2759 else {
2761 ACCEPT_MSG_ATN(port);
2765 /* End good id message. */
2766 else {
2768 message = 0;
2770 } else {
2771 ACCEPT_MSG_ATN(port);
2773 while (!
2774 (RDW_HARPOON((port + hp_intstat)) &
2775 (PHASE | RESET))
2776 && !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
2777 && (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
2779 return;
2782 if (message == 0) {
2783 msgRetryCount++;
2784 if (msgRetryCount == 1) {
2785 FPT_SendMsg(port, SMPARITY);
2786 } else {
2787 FPT_SendMsg(port, SMDEV_RESET);
2789 FPT_sssyncv(port, our_target, NARROW_SCSI,
2790 currTar_Info);
2792 if (FPT_sccbMgrTbl[p_card][our_target].
2793 TarEEValue & EE_SYNC_MASK) {
2795 FPT_sccbMgrTbl[p_card][our_target].
2796 TarStatus &= ~TAR_SYNC_MASK;
2800 if (FPT_sccbMgrTbl[p_card][our_target].
2801 TarEEValue & EE_WIDE_SCSI) {
2803 FPT_sccbMgrTbl[p_card][our_target].
2804 TarStatus &= ~TAR_WIDE_MASK;
2807 FPT_queueFlushTargSccb(p_card, our_target,
2808 SCCB_COMPLETE);
2809 FPT_SccbMgrTableInitTarget(p_card, our_target);
2810 return;
2813 } while (message == 0);
2815 if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
2816 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
2817 currTar_Info->TarLUNBusy[lun] = 1;
2818 pCurrCard->currentSCCB =
2819 pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[lun]];
2820 if (pCurrCard->currentSCCB != NULL) {
2821 ACCEPT_MSG(port);
2822 } else {
2823 ACCEPT_MSG_ATN(port);
2825 } else {
2826 currTar_Info->TarLUNBusy[0] = 1;
2828 if (tag) {
2829 if (pCurrCard->discQ_Tbl[tag] != NULL) {
2830 pCurrCard->currentSCCB =
2831 pCurrCard->discQ_Tbl[tag];
2832 currTar_Info->TarTagQ_Cnt--;
2833 ACCEPT_MSG(port);
2834 } else {
2835 ACCEPT_MSG_ATN(port);
2837 } else {
2838 pCurrCard->currentSCCB =
2839 pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]];
2840 if (pCurrCard->currentSCCB != NULL) {
2841 ACCEPT_MSG(port);
2842 } else {
2843 ACCEPT_MSG_ATN(port);
2848 if (pCurrCard->currentSCCB != NULL) {
2849 if (pCurrCard->currentSCCB->Sccb_scsistat == ABORT_ST) {
2850 /* During Abort Tag command, the target could have got re-selected
2851 and completed the command. Check the select Q and remove the CCB
2852 if it is in the Select Q */
2853 FPT_queueFindSccb(pCurrCard->currentSCCB, p_card);
2857 while (!(RDW_HARPOON((port + hp_intstat)) & (PHASE | RESET)) &&
2858 !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ) &&
2859 (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
2862 static void FPT_SendMsg(unsigned long port, unsigned char message)
2864 while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
2865 if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
2867 WRW_HARPOON((port + hp_intstat), PHASE);
2868 return;
2872 WRW_HARPOON((port + hp_intstat), PHASE);
2873 if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGO_PH) {
2874 WRW_HARPOON((port + hp_intstat),
2875 (BUS_FREE | PHASE | XFER_CNT_0));
2877 WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
2879 WR_HARPOON(port + hp_scsidata_0, message);
2881 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2883 ACCEPT_MSG(port);
2885 WR_HARPOON(port + hp_portctrl_0, 0x00);
2887 if ((message == SMABORT) || (message == SMDEV_RESET) ||
2888 (message == SMABORT_TAG)) {
2889 while (!
2890 (RDW_HARPOON((port + hp_intstat)) &
2891 (BUS_FREE | PHASE))) {
2894 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
2895 WRW_HARPOON((port + hp_intstat), BUS_FREE);
2901 /*---------------------------------------------------------------------
2903 * Function: FPT_sdecm
2905 * Description: Determine the proper responce to the message from the
2906 * target device.
2908 *---------------------------------------------------------------------*/
2909 static void FPT_sdecm(unsigned char message, unsigned long port,
2910 unsigned char p_card)
2912 struct sccb *currSCCB;
2913 struct sccb_card *CurrCard;
2914 struct sccb_mgr_tar_info *currTar_Info;
2916 CurrCard = &FPT_BL_Card[p_card];
2917 currSCCB = CurrCard->currentSCCB;
2919 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
2921 if (message == SMREST_DATA_PTR) {
2922 if (!(currSCCB->Sccb_XferState & F_NO_DATA_YET)) {
2923 currSCCB->Sccb_ATC = currSCCB->Sccb_savedATC;
2925 FPT_hostDataXferRestart(currSCCB);
2928 ACCEPT_MSG(port);
2929 WR_HARPOON(port + hp_autostart_1,
2930 (AUTO_IMMED + DISCONNECT_START));
2933 else if (message == SMCMD_COMP) {
2935 if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
2936 currTar_Info->TarStatus &=
2937 ~(unsigned char)TAR_TAG_Q_MASK;
2938 currTar_Info->TarStatus |= (unsigned char)TAG_Q_REJECT;
2941 ACCEPT_MSG(port);
2945 else if ((message == SMNO_OP) || (message >= SMIDENT)
2946 || (message == SMINIT_RECOVERY) || (message == SMREL_RECOVERY)) {
2948 ACCEPT_MSG(port);
2949 WR_HARPOON(port + hp_autostart_1,
2950 (AUTO_IMMED + DISCONNECT_START));
2953 else if (message == SMREJECT) {
2955 if ((currSCCB->Sccb_scsistat == SELECT_SN_ST) ||
2956 (currSCCB->Sccb_scsistat == SELECT_WN_ST) ||
2957 ((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)
2958 || ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) ==
2959 TAG_Q_TRYING))
2961 WRW_HARPOON((port + hp_intstat), BUS_FREE);
2963 ACCEPT_MSG(port);
2965 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2966 (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
2970 if (currSCCB->Lun == 0x00) {
2971 if ((currSCCB->Sccb_scsistat == SELECT_SN_ST)) {
2973 currTar_Info->TarStatus |=
2974 (unsigned char)SYNC_SUPPORTED;
2976 currTar_Info->TarEEValue &=
2977 ~EE_SYNC_MASK;
2980 else if ((currSCCB->Sccb_scsistat ==
2981 SELECT_WN_ST)) {
2983 currTar_Info->TarStatus =
2984 (currTar_Info->
2985 TarStatus & ~WIDE_ENABLED) |
2986 WIDE_NEGOCIATED;
2988 currTar_Info->TarEEValue &=
2989 ~EE_WIDE_SCSI;
2993 else if ((currTar_Info->
2994 TarStatus & TAR_TAG_Q_MASK) ==
2995 TAG_Q_TRYING) {
2996 currTar_Info->TarStatus =
2997 (currTar_Info->
2998 TarStatus & ~(unsigned char)
2999 TAR_TAG_Q_MASK) | TAG_Q_REJECT;
3001 currSCCB->ControlByte &= ~F_USE_CMD_Q;
3002 CurrCard->discQCount--;
3003 CurrCard->discQ_Tbl[currSCCB->
3004 Sccb_tag] = NULL;
3005 currSCCB->Sccb_tag = 0x00;
3010 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
3012 if (currSCCB->Lun == 0x00) {
3013 WRW_HARPOON((port + hp_intstat),
3014 BUS_FREE);
3015 CurrCard->globalFlags |= F_NEW_SCCB_CMD;
3019 else {
3021 if ((CurrCard->globalFlags & F_CONLUN_IO) &&
3022 ((currTar_Info->
3023 TarStatus & TAR_TAG_Q_MASK) !=
3024 TAG_Q_TRYING))
3025 currTar_Info->TarLUNBusy[currSCCB->
3026 Lun] = 1;
3027 else
3028 currTar_Info->TarLUNBusy[0] = 1;
3030 currSCCB->ControlByte &=
3031 ~(unsigned char)F_USE_CMD_Q;
3033 WR_HARPOON(port + hp_autostart_1,
3034 (AUTO_IMMED + DISCONNECT_START));
3039 else {
3040 ACCEPT_MSG(port);
3042 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
3043 (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
3047 if (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)) {
3048 WR_HARPOON(port + hp_autostart_1,
3049 (AUTO_IMMED + DISCONNECT_START));
3054 else if (message == SMEXT) {
3056 ACCEPT_MSG(port);
3057 FPT_shandem(port, p_card, currSCCB);
3060 else if (message == SMIGNORWR) {
3062 ACCEPT_MSG(port); /* ACK the RESIDUE MSG */
3064 message = FPT_sfm(port, currSCCB);
3066 if (currSCCB->Sccb_scsimsg != SMPARITY)
3067 ACCEPT_MSG(port);
3068 WR_HARPOON(port + hp_autostart_1,
3069 (AUTO_IMMED + DISCONNECT_START));
3072 else {
3074 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
3075 currSCCB->Sccb_scsimsg = SMREJECT;
3077 ACCEPT_MSG_ATN(port);
3078 WR_HARPOON(port + hp_autostart_1,
3079 (AUTO_IMMED + DISCONNECT_START));
3083 /*---------------------------------------------------------------------
3085 * Function: FPT_shandem
3087 * Description: Decide what to do with the extended message.
3089 *---------------------------------------------------------------------*/
3090 static void FPT_shandem(unsigned long port, unsigned char p_card,
3091 struct sccb *pCurrSCCB)
3093 unsigned char length, message;
3095 length = FPT_sfm(port, pCurrSCCB);
3096 if (length) {
3098 ACCEPT_MSG(port);
3099 message = FPT_sfm(port, pCurrSCCB);
3100 if (message) {
3102 if (message == SMSYNC) {
3104 if (length == 0x03) {
3106 ACCEPT_MSG(port);
3107 FPT_stsyncn(port, p_card);
3108 } else {
3110 pCurrSCCB->Sccb_scsimsg = SMREJECT;
3111 ACCEPT_MSG_ATN(port);
3113 } else if (message == SMWDTR) {
3115 if (length == 0x02) {
3117 ACCEPT_MSG(port);
3118 FPT_stwidn(port, p_card);
3119 } else {
3121 pCurrSCCB->Sccb_scsimsg = SMREJECT;
3122 ACCEPT_MSG_ATN(port);
3124 WR_HARPOON(port + hp_autostart_1,
3125 (AUTO_IMMED +
3126 DISCONNECT_START));
3128 } else {
3130 pCurrSCCB->Sccb_scsimsg = SMREJECT;
3131 ACCEPT_MSG_ATN(port);
3133 WR_HARPOON(port + hp_autostart_1,
3134 (AUTO_IMMED + DISCONNECT_START));
3136 } else {
3137 if (pCurrSCCB->Sccb_scsimsg != SMPARITY)
3138 ACCEPT_MSG(port);
3139 WR_HARPOON(port + hp_autostart_1,
3140 (AUTO_IMMED + DISCONNECT_START));
3142 } else {
3143 if (pCurrSCCB->Sccb_scsimsg == SMPARITY)
3144 WR_HARPOON(port + hp_autostart_1,
3145 (AUTO_IMMED + DISCONNECT_START));
3149 /*---------------------------------------------------------------------
3151 * Function: FPT_sisyncn
3153 * Description: Read in a message byte from the SCSI bus, and check
3154 * for a parity error.
3156 *---------------------------------------------------------------------*/
3158 static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card,
3159 unsigned char syncFlag)
3161 struct sccb *currSCCB;
3162 struct sccb_mgr_tar_info *currTar_Info;
3164 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3165 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
3167 if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)) {
3169 WRW_HARPOON((port + ID_MSG_STRT),
3170 (MPM_OP + AMSG_OUT +
3171 (currSCCB->
3172 Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
3174 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
3176 WRW_HARPOON((port + SYNC_MSGS + 0),
3177 (MPM_OP + AMSG_OUT + SMEXT));
3178 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
3179 WRW_HARPOON((port + SYNC_MSGS + 4),
3180 (MPM_OP + AMSG_OUT + SMSYNC));
3182 if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
3184 WRW_HARPOON((port + SYNC_MSGS + 6),
3185 (MPM_OP + AMSG_OUT + 12));
3187 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
3188 EE_SYNC_10MB)
3190 WRW_HARPOON((port + SYNC_MSGS + 6),
3191 (MPM_OP + AMSG_OUT + 25));
3193 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
3194 EE_SYNC_5MB)
3196 WRW_HARPOON((port + SYNC_MSGS + 6),
3197 (MPM_OP + AMSG_OUT + 50));
3199 else
3200 WRW_HARPOON((port + SYNC_MSGS + 6),
3201 (MPM_OP + AMSG_OUT + 00));
3203 WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
3204 WRW_HARPOON((port + SYNC_MSGS + 10),
3205 (MPM_OP + AMSG_OUT + DEFAULT_OFFSET));
3206 WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
3208 if (syncFlag == 0) {
3209 WR_HARPOON(port + hp_autostart_3,
3210 (SELECT + SELCHK_STRT));
3211 currTar_Info->TarStatus =
3212 ((currTar_Info->
3213 TarStatus & ~(unsigned char)TAR_SYNC_MASK) |
3214 (unsigned char)SYNC_TRYING);
3215 } else {
3216 WR_HARPOON(port + hp_autostart_3,
3217 (AUTO_IMMED + CMD_ONLY_STRT));
3220 return 1;
3223 else {
3225 currTar_Info->TarStatus |= (unsigned char)SYNC_SUPPORTED;
3226 currTar_Info->TarEEValue &= ~EE_SYNC_MASK;
3227 return 0;
3231 /*---------------------------------------------------------------------
3233 * Function: FPT_stsyncn
3235 * Description: The has sent us a Sync Nego message so handle it as
3236 * necessary.
3238 *---------------------------------------------------------------------*/
3239 static void FPT_stsyncn(unsigned long port, unsigned char p_card)
3241 unsigned char sync_msg, offset, sync_reg, our_sync_msg;
3242 struct sccb *currSCCB;
3243 struct sccb_mgr_tar_info *currTar_Info;
3245 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3246 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
3248 sync_msg = FPT_sfm(port, currSCCB);
3250 if ((sync_msg == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3251 WR_HARPOON(port + hp_autostart_1,
3252 (AUTO_IMMED + DISCONNECT_START));
3253 return;
3256 ACCEPT_MSG(port);
3258 offset = FPT_sfm(port, currSCCB);
3260 if ((offset == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3261 WR_HARPOON(port + hp_autostart_1,
3262 (AUTO_IMMED + DISCONNECT_START));
3263 return;
3266 if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
3268 our_sync_msg = 12; /* Setup our Message to 20mb/s */
3270 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_10MB)
3272 our_sync_msg = 25; /* Setup our Message to 10mb/s */
3274 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_5MB)
3276 our_sync_msg = 50; /* Setup our Message to 5mb/s */
3277 else
3279 our_sync_msg = 0; /* Message = Async */
3281 if (sync_msg < our_sync_msg) {
3282 sync_msg = our_sync_msg; /*if faster, then set to max. */
3285 if (offset == ASYNC)
3286 sync_msg = ASYNC;
3288 if (offset > MAX_OFFSET)
3289 offset = MAX_OFFSET;
3291 sync_reg = 0x00;
3293 if (sync_msg > 12)
3295 sync_reg = 0x20; /* Use 10MB/s */
3297 if (sync_msg > 25)
3299 sync_reg = 0x40; /* Use 6.6MB/s */
3301 if (sync_msg > 38)
3303 sync_reg = 0x60; /* Use 5MB/s */
3305 if (sync_msg > 50)
3307 sync_reg = 0x80; /* Use 4MB/s */
3309 if (sync_msg > 62)
3311 sync_reg = 0xA0; /* Use 3.33MB/s */
3313 if (sync_msg > 75)
3315 sync_reg = 0xC0; /* Use 2.85MB/s */
3317 if (sync_msg > 87)
3319 sync_reg = 0xE0; /* Use 2.5MB/s */
3321 if (sync_msg > 100) {
3323 sync_reg = 0x00; /* Use ASYNC */
3324 offset = 0x00;
3327 if (currTar_Info->TarStatus & WIDE_ENABLED)
3329 sync_reg |= offset;
3331 else
3333 sync_reg |= (offset | NARROW_SCSI);
3335 FPT_sssyncv(port, currSCCB->TargID, sync_reg, currTar_Info);
3337 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
3339 ACCEPT_MSG(port);
3341 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3342 ~(unsigned char)TAR_SYNC_MASK) |
3343 (unsigned char)SYNC_SUPPORTED);
3345 WR_HARPOON(port + hp_autostart_1,
3346 (AUTO_IMMED + DISCONNECT_START));
3349 else {
3351 ACCEPT_MSG_ATN(port);
3353 FPT_sisyncr(port, sync_msg, offset);
3355 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3356 ~(unsigned char)TAR_SYNC_MASK) |
3357 (unsigned char)SYNC_SUPPORTED);
3361 /*---------------------------------------------------------------------
3363 * Function: FPT_sisyncr
3365 * Description: Answer the targets sync message.
3367 *---------------------------------------------------------------------*/
3368 static void FPT_sisyncr(unsigned long port, unsigned char sync_pulse,
3369 unsigned char offset)
3371 ARAM_ACCESS(port);
3372 WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT));
3373 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
3374 WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMSYNC));
3375 WRW_HARPOON((port + SYNC_MSGS + 6), (MPM_OP + AMSG_OUT + sync_pulse));
3376 WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
3377 WRW_HARPOON((port + SYNC_MSGS + 10), (MPM_OP + AMSG_OUT + offset));
3378 WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
3379 SGRAM_ACCESS(port);
3381 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3382 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
3384 WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
3386 while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
3390 /*---------------------------------------------------------------------
3392 * Function: FPT_siwidn
3394 * Description: Read in a message byte from the SCSI bus, and check
3395 * for a parity error.
3397 *---------------------------------------------------------------------*/
3399 static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card)
3401 struct sccb *currSCCB;
3402 struct sccb_mgr_tar_info *currTar_Info;
3404 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3405 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
3407 if (!((currTar_Info->TarStatus & TAR_WIDE_MASK) == WIDE_NEGOCIATED)) {
3409 WRW_HARPOON((port + ID_MSG_STRT),
3410 (MPM_OP + AMSG_OUT +
3411 (currSCCB->
3412 Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
3414 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
3416 WRW_HARPOON((port + SYNC_MSGS + 0),
3417 (MPM_OP + AMSG_OUT + SMEXT));
3418 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
3419 WRW_HARPOON((port + SYNC_MSGS + 4),
3420 (MPM_OP + AMSG_OUT + SMWDTR));
3421 WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
3422 WRW_HARPOON((port + SYNC_MSGS + 8),
3423 (MPM_OP + AMSG_OUT + SM16BIT));
3424 WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
3426 WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
3428 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3429 ~(unsigned char)TAR_WIDE_MASK) |
3430 (unsigned char)WIDE_ENABLED);
3432 return 1;
3435 else {
3437 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3438 ~(unsigned char)TAR_WIDE_MASK) |
3439 WIDE_NEGOCIATED);
3441 currTar_Info->TarEEValue &= ~EE_WIDE_SCSI;
3442 return 0;
3446 /*---------------------------------------------------------------------
3448 * Function: FPT_stwidn
3450 * Description: The has sent us a Wide Nego message so handle it as
3451 * necessary.
3453 *---------------------------------------------------------------------*/
3454 static void FPT_stwidn(unsigned long port, unsigned char p_card)
3456 unsigned char width;
3457 struct sccb *currSCCB;
3458 struct sccb_mgr_tar_info *currTar_Info;
3460 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3461 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
3463 width = FPT_sfm(port, currSCCB);
3465 if ((width == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3466 WR_HARPOON(port + hp_autostart_1,
3467 (AUTO_IMMED + DISCONNECT_START));
3468 return;
3471 if (!(currTar_Info->TarEEValue & EE_WIDE_SCSI))
3472 width = 0;
3474 if (width) {
3475 currTar_Info->TarStatus |= WIDE_ENABLED;
3476 width = 0;
3477 } else {
3478 width = NARROW_SCSI;
3479 currTar_Info->TarStatus &= ~WIDE_ENABLED;
3482 FPT_sssyncv(port, currSCCB->TargID, width, currTar_Info);
3484 if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
3486 currTar_Info->TarStatus |= WIDE_NEGOCIATED;
3488 if (!
3489 ((currTar_Info->TarStatus & TAR_SYNC_MASK) ==
3490 SYNC_SUPPORTED)) {
3491 ACCEPT_MSG_ATN(port);
3492 ARAM_ACCESS(port);
3493 FPT_sisyncn(port, p_card, 1);
3494 currSCCB->Sccb_scsistat = SELECT_SN_ST;
3495 SGRAM_ACCESS(port);
3496 } else {
3497 ACCEPT_MSG(port);
3498 WR_HARPOON(port + hp_autostart_1,
3499 (AUTO_IMMED + DISCONNECT_START));
3503 else {
3505 ACCEPT_MSG_ATN(port);
3507 if (currTar_Info->TarEEValue & EE_WIDE_SCSI)
3508 width = SM16BIT;
3509 else
3510 width = SM8BIT;
3512 FPT_siwidr(port, width);
3514 currTar_Info->TarStatus |= (WIDE_NEGOCIATED | WIDE_ENABLED);
3518 /*---------------------------------------------------------------------
3520 * Function: FPT_siwidr
3522 * Description: Answer the targets Wide nego message.
3524 *---------------------------------------------------------------------*/
3525 static void FPT_siwidr(unsigned long port, unsigned char width)
3527 ARAM_ACCESS(port);
3528 WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT));
3529 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
3530 WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMWDTR));
3531 WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
3532 WRW_HARPOON((port + SYNC_MSGS + 8), (MPM_OP + AMSG_OUT + width));
3533 WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
3534 SGRAM_ACCESS(port);
3536 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3537 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
3539 WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
3541 while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
3545 /*---------------------------------------------------------------------
3547 * Function: FPT_sssyncv
3549 * Description: Write the desired value to the Sync Register for the
3550 * ID specified.
3552 *---------------------------------------------------------------------*/
3553 static void FPT_sssyncv(unsigned long p_port, unsigned char p_id,
3554 unsigned char p_sync_value,
3555 struct sccb_mgr_tar_info *currTar_Info)
3557 unsigned char index;
3559 index = p_id;
3561 switch (index) {
3563 case 0:
3564 index = 12; /* hp_synctarg_0 */
3565 break;
3566 case 1:
3567 index = 13; /* hp_synctarg_1 */
3568 break;
3569 case 2:
3570 index = 14; /* hp_synctarg_2 */
3571 break;
3572 case 3:
3573 index = 15; /* hp_synctarg_3 */
3574 break;
3575 case 4:
3576 index = 8; /* hp_synctarg_4 */
3577 break;
3578 case 5:
3579 index = 9; /* hp_synctarg_5 */
3580 break;
3581 case 6:
3582 index = 10; /* hp_synctarg_6 */
3583 break;
3584 case 7:
3585 index = 11; /* hp_synctarg_7 */
3586 break;
3587 case 8:
3588 index = 4; /* hp_synctarg_8 */
3589 break;
3590 case 9:
3591 index = 5; /* hp_synctarg_9 */
3592 break;
3593 case 10:
3594 index = 6; /* hp_synctarg_10 */
3595 break;
3596 case 11:
3597 index = 7; /* hp_synctarg_11 */
3598 break;
3599 case 12:
3600 index = 0; /* hp_synctarg_12 */
3601 break;
3602 case 13:
3603 index = 1; /* hp_synctarg_13 */
3604 break;
3605 case 14:
3606 index = 2; /* hp_synctarg_14 */
3607 break;
3608 case 15:
3609 index = 3; /* hp_synctarg_15 */
3613 WR_HARPOON(p_port + hp_synctarg_base + index, p_sync_value);
3615 currTar_Info->TarSyncCtrl = p_sync_value;
3618 /*---------------------------------------------------------------------
3620 * Function: FPT_sresb
3622 * Description: Reset the desired card's SCSI bus.
3624 *---------------------------------------------------------------------*/
3625 static void FPT_sresb(unsigned long port, unsigned char p_card)
3627 unsigned char scsiID, i;
3629 struct sccb_mgr_tar_info *currTar_Info;
3631 WR_HARPOON(port + hp_page_ctrl,
3632 (RD_HARPOON(port + hp_page_ctrl) | G_INT_DISABLE));
3633 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
3635 WR_HARPOON(port + hp_scsictrl_0, SCSI_RST);
3637 scsiID = RD_HARPOON(port + hp_seltimeout);
3638 WR_HARPOON(port + hp_seltimeout, TO_5ms);
3639 WRW_HARPOON((port + hp_intstat), TIMEOUT);
3641 WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT | START_TO));
3643 while (!(RDW_HARPOON((port + hp_intstat)) & TIMEOUT)) {
3646 WR_HARPOON(port + hp_seltimeout, scsiID);
3648 WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
3650 FPT_Wait(port, TO_5ms);
3652 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
3654 WR_HARPOON(port + hp_int_mask, (RD_HARPOON(port + hp_int_mask) | 0x00));
3656 for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
3657 currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
3659 if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
3660 currTar_Info->TarSyncCtrl = 0;
3661 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
3664 if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
3665 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
3668 FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
3670 FPT_SccbMgrTableInitTarget(p_card, scsiID);
3673 FPT_BL_Card[p_card].scanIndex = 0x00;
3674 FPT_BL_Card[p_card].currentSCCB = NULL;
3675 FPT_BL_Card[p_card].globalFlags &= ~(F_TAG_STARTED | F_HOST_XFER_ACT
3676 | F_NEW_SCCB_CMD);
3677 FPT_BL_Card[p_card].cmdCounter = 0x00;
3678 FPT_BL_Card[p_card].discQCount = 0x00;
3679 FPT_BL_Card[p_card].tagQ_Lst = 0x01;
3681 for (i = 0; i < QUEUE_DEPTH; i++)
3682 FPT_BL_Card[p_card].discQ_Tbl[i] = NULL;
3684 WR_HARPOON(port + hp_page_ctrl,
3685 (RD_HARPOON(port + hp_page_ctrl) & ~G_INT_DISABLE));
3689 /*---------------------------------------------------------------------
3691 * Function: FPT_ssenss
3693 * Description: Setup for the Auto Sense command.
3695 *---------------------------------------------------------------------*/
3696 static void FPT_ssenss(struct sccb_card *pCurrCard)
3698 unsigned char i;
3699 struct sccb *currSCCB;
3701 currSCCB = pCurrCard->currentSCCB;
3703 currSCCB->Save_CdbLen = currSCCB->CdbLength;
3705 for (i = 0; i < 6; i++) {
3707 currSCCB->Save_Cdb[i] = currSCCB->Cdb[i];
3710 currSCCB->CdbLength = SIX_BYTE_CMD;
3711 currSCCB->Cdb[0] = SCSI_REQUEST_SENSE;
3712 currSCCB->Cdb[1] = currSCCB->Cdb[1] & (unsigned char)0xE0; /*Keep LUN. */
3713 currSCCB->Cdb[2] = 0x00;
3714 currSCCB->Cdb[3] = 0x00;
3715 currSCCB->Cdb[4] = currSCCB->RequestSenseLength;
3716 currSCCB->Cdb[5] = 0x00;
3718 currSCCB->Sccb_XferCnt = (unsigned long)currSCCB->RequestSenseLength;
3720 currSCCB->Sccb_ATC = 0x00;
3722 currSCCB->Sccb_XferState |= F_AUTO_SENSE;
3724 currSCCB->Sccb_XferState &= ~F_SG_XFER;
3726 currSCCB->Sccb_idmsg = currSCCB->Sccb_idmsg & ~(unsigned char)DISC_PRIV;
3728 currSCCB->ControlByte = 0x00;
3730 currSCCB->Sccb_MGRFlags &= F_STATUSLOADED;
3733 /*---------------------------------------------------------------------
3735 * Function: FPT_sxfrp
3737 * Description: Transfer data into the bit bucket until the device
3738 * decides to switch phase.
3740 *---------------------------------------------------------------------*/
3742 static void FPT_sxfrp(unsigned long p_port, unsigned char p_card)
3744 unsigned char curr_phz;
3746 DISABLE_AUTO(p_port);
3748 if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
3750 FPT_hostDataXferAbort(p_port, p_card,
3751 FPT_BL_Card[p_card].currentSCCB);
3755 /* If the Automation handled the end of the transfer then do not
3756 match the phase or we will get out of sync with the ISR. */
3758 if (RDW_HARPOON((p_port + hp_intstat)) &
3759 (BUS_FREE | XFER_CNT_0 | AUTO_INT))
3760 return;
3762 WR_HARPOON(p_port + hp_xfercnt_0, 0x00);
3764 curr_phz = RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ;
3766 WRW_HARPOON((p_port + hp_intstat), XFER_CNT_0);
3768 WR_HARPOON(p_port + hp_scsisig, curr_phz);
3770 while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET)) &&
3771 (curr_phz ==
3772 (RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ)))
3774 if (curr_phz & (unsigned char)SCSI_IOBIT) {
3775 WR_HARPOON(p_port + hp_portctrl_0,
3776 (SCSI_PORT | HOST_PORT | SCSI_INBIT));
3778 if (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
3779 RD_HARPOON(p_port + hp_fifodata_0);
3781 } else {
3782 WR_HARPOON(p_port + hp_portctrl_0,
3783 (SCSI_PORT | HOST_PORT | HOST_WRT));
3784 if (RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY) {
3785 WR_HARPOON(p_port + hp_fifodata_0, 0xFA);
3788 } /* End of While loop for padding data I/O phase */
3790 while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
3791 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ)
3792 break;
3795 WR_HARPOON(p_port + hp_portctrl_0,
3796 (SCSI_PORT | HOST_PORT | SCSI_INBIT));
3797 while (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
3798 RD_HARPOON(p_port + hp_fifodata_0);
3801 if (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
3802 WR_HARPOON(p_port + hp_autostart_0,
3803 (AUTO_IMMED + DISCONNECT_START));
3804 while (!(RDW_HARPOON((p_port + hp_intstat)) & AUTO_INT)) {
3807 if (RDW_HARPOON((p_port + hp_intstat)) &
3808 (ICMD_COMP | ITAR_DISC))
3809 while (!
3810 (RDW_HARPOON((p_port + hp_intstat)) &
3811 (BUS_FREE | RSEL))) ;
3815 /*---------------------------------------------------------------------
3817 * Function: FPT_schkdd
3819 * Description: Make sure data has been flushed from both FIFOs and abort
3820 * the operations if necessary.
3822 *---------------------------------------------------------------------*/
3824 static void FPT_schkdd(unsigned long port, unsigned char p_card)
3826 unsigned short TimeOutLoop;
3827 unsigned char sPhase;
3829 struct sccb *currSCCB;
3831 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3833 if ((currSCCB->Sccb_scsistat != DATA_OUT_ST) &&
3834 (currSCCB->Sccb_scsistat != DATA_IN_ST)) {
3835 return;
3838 if (currSCCB->Sccb_XferState & F_ODD_BALL_CNT) {
3840 currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - 1);
3842 currSCCB->Sccb_XferCnt = 1;
3844 currSCCB->Sccb_XferState &= ~F_ODD_BALL_CNT;
3845 WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
3846 WR_HARPOON(port + hp_xferstat, 0x00);
3849 else {
3851 currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
3853 currSCCB->Sccb_XferCnt = 0;
3856 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
3857 (currSCCB->HostStatus == SCCB_COMPLETE)) {
3859 currSCCB->HostStatus = SCCB_PARITY_ERR;
3860 WRW_HARPOON((port + hp_intstat), PARITY);
3863 FPT_hostDataXferAbort(port, p_card, currSCCB);
3865 while (RD_HARPOON(port + hp_scsisig) & SCSI_ACK) {
3868 TimeOutLoop = 0;
3870 while (RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY) {
3871 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
3872 return;
3874 if (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) {
3875 break;
3877 if (RDW_HARPOON((port + hp_intstat)) & RESET) {
3878 return;
3880 if ((RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
3881 || (TimeOutLoop++ > 0x3000))
3882 break;
3885 sPhase = RD_HARPOON(port + hp_scsisig) & (SCSI_BSY | S_SCSI_PHZ);
3886 if ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) ||
3887 (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) ||
3888 (sPhase == (SCSI_BSY | S_DATAO_PH)) ||
3889 (sPhase == (SCSI_BSY | S_DATAI_PH))) {
3891 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3893 if (!(currSCCB->Sccb_XferState & F_ALL_XFERRED)) {
3894 if (currSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
3895 FPT_phaseDataIn(port, p_card);
3898 else {
3899 FPT_phaseDataOut(port, p_card);
3901 } else {
3902 FPT_sxfrp(port, p_card);
3903 if (!(RDW_HARPOON((port + hp_intstat)) &
3904 (BUS_FREE | ICMD_COMP | ITAR_DISC | RESET))) {
3905 WRW_HARPOON((port + hp_intstat), AUTO_INT);
3906 FPT_phaseDecode(port, p_card);
3912 else {
3913 WR_HARPOON(port + hp_portctrl_0, 0x00);
3917 /*---------------------------------------------------------------------
3919 * Function: FPT_sinits
3921 * Description: Setup SCCB manager fields in this SCCB.
3923 *---------------------------------------------------------------------*/
3925 static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card)
3927 struct sccb_mgr_tar_info *currTar_Info;
3929 if ((p_sccb->TargID > MAX_SCSI_TAR) || (p_sccb->Lun > MAX_LUN)) {
3930 return;
3932 currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
3934 p_sccb->Sccb_XferState = 0x00;
3935 p_sccb->Sccb_XferCnt = p_sccb->DataLength;
3937 if ((p_sccb->OperationCode == SCATTER_GATHER_COMMAND) ||
3938 (p_sccb->OperationCode == RESIDUAL_SG_COMMAND)) {
3940 p_sccb->Sccb_SGoffset = 0;
3941 p_sccb->Sccb_XferState = F_SG_XFER;
3942 p_sccb->Sccb_XferCnt = 0x00;
3945 if (p_sccb->DataLength == 0x00)
3947 p_sccb->Sccb_XferState |= F_ALL_XFERRED;
3949 if (p_sccb->ControlByte & F_USE_CMD_Q) {
3950 if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
3951 p_sccb->ControlByte &= ~F_USE_CMD_Q;
3953 else
3954 currTar_Info->TarStatus |= TAG_Q_TRYING;
3957 /* For !single SCSI device in system & device allow Disconnect
3958 or command is tag_q type then send Cmd with Disconnect Enable
3959 else send Cmd with Disconnect Disable */
3962 if (((!(FPT_BL_Card[p_card].globalFlags & F_SINGLE_DEVICE)) &&
3963 (currTar_Info->TarStatus & TAR_ALLOW_DISC)) ||
3964 (currTar_Info->TarStatus & TAG_Q_TRYING)) {
3966 if ((currTar_Info->TarStatus & TAR_ALLOW_DISC) ||
3967 (currTar_Info->TarStatus & TAG_Q_TRYING)) {
3968 p_sccb->Sccb_idmsg =
3969 (unsigned char)(SMIDENT | DISC_PRIV) | p_sccb->Lun;
3972 else {
3974 p_sccb->Sccb_idmsg = (unsigned char)SMIDENT | p_sccb->Lun;
3977 p_sccb->HostStatus = 0x00;
3978 p_sccb->TargetStatus = 0x00;
3979 p_sccb->Sccb_tag = 0x00;
3980 p_sccb->Sccb_MGRFlags = 0x00;
3981 p_sccb->Sccb_sgseg = 0x00;
3982 p_sccb->Sccb_ATC = 0x00;
3983 p_sccb->Sccb_savedATC = 0x00;
3985 p_sccb->SccbVirtDataPtr = 0x00;
3986 p_sccb->Sccb_forwardlink = NULL;
3987 p_sccb->Sccb_backlink = NULL;
3989 p_sccb->Sccb_scsistat = BUS_FREE_ST;
3990 p_sccb->SccbStatus = SCCB_IN_PROCESS;
3991 p_sccb->Sccb_scsimsg = SMNO_OP;
3995 /*---------------------------------------------------------------------
3997 * Function: Phase Decode
3999 * Description: Determine the phase and call the appropriate function.
4001 *---------------------------------------------------------------------*/
4003 static void FPT_phaseDecode(unsigned long p_port, unsigned char p_card)
4005 unsigned char phase_ref;
4006 void (*phase) (unsigned long, unsigned char);
4008 DISABLE_AUTO(p_port);
4010 phase_ref =
4011 (unsigned char)(RD_HARPOON(p_port + hp_scsisig) & S_SCSI_PHZ);
4013 phase = FPT_s_PhaseTbl[phase_ref];
4015 (*phase) (p_port, p_card); /* Call the correct phase func */
4018 /*---------------------------------------------------------------------
4020 * Function: Data Out Phase
4022 * Description: Start up both the BusMaster and Xbow.
4024 *---------------------------------------------------------------------*/
4026 static void FPT_phaseDataOut(unsigned long port, unsigned char p_card)
4029 struct sccb *currSCCB;
4031 currSCCB = FPT_BL_Card[p_card].currentSCCB;
4032 if (currSCCB == NULL) {
4033 return; /* Exit if No SCCB record */
4036 currSCCB->Sccb_scsistat = DATA_OUT_ST;
4037 currSCCB->Sccb_XferState &= ~(F_HOST_XFER_DIR | F_NO_DATA_YET);
4039 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
4041 WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
4043 WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
4045 FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
4047 if (currSCCB->Sccb_XferCnt == 0) {
4049 if ((currSCCB->ControlByte & SCCB_DATA_XFER_OUT) &&
4050 (currSCCB->HostStatus == SCCB_COMPLETE))
4051 currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
4053 FPT_sxfrp(port, p_card);
4054 if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
4055 FPT_phaseDecode(port, p_card);
4059 /*---------------------------------------------------------------------
4061 * Function: Data In Phase
4063 * Description: Startup the BusMaster and the XBOW.
4065 *---------------------------------------------------------------------*/
4067 static void FPT_phaseDataIn(unsigned long port, unsigned char p_card)
4070 struct sccb *currSCCB;
4072 currSCCB = FPT_BL_Card[p_card].currentSCCB;
4074 if (currSCCB == NULL) {
4075 return; /* Exit if No SCCB record */
4078 currSCCB->Sccb_scsistat = DATA_IN_ST;
4079 currSCCB->Sccb_XferState |= F_HOST_XFER_DIR;
4080 currSCCB->Sccb_XferState &= ~F_NO_DATA_YET;
4082 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
4084 WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
4086 WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
4088 FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
4090 if (currSCCB->Sccb_XferCnt == 0) {
4092 if ((currSCCB->ControlByte & SCCB_DATA_XFER_IN) &&
4093 (currSCCB->HostStatus == SCCB_COMPLETE))
4094 currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
4096 FPT_sxfrp(port, p_card);
4097 if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
4098 FPT_phaseDecode(port, p_card);
4103 /*---------------------------------------------------------------------
4105 * Function: Command Phase
4107 * Description: Load the CDB into the automation and start it up.
4109 *---------------------------------------------------------------------*/
4111 static void FPT_phaseCommand(unsigned long p_port, unsigned char p_card)
4113 struct sccb *currSCCB;
4114 unsigned long cdb_reg;
4115 unsigned char i;
4117 currSCCB = FPT_BL_Card[p_card].currentSCCB;
4119 if (currSCCB->OperationCode == RESET_COMMAND) {
4121 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4122 currSCCB->CdbLength = SIX_BYTE_CMD;
4125 WR_HARPOON(p_port + hp_scsisig, 0x00);
4127 ARAM_ACCESS(p_port);
4129 cdb_reg = p_port + CMD_STRT;
4131 for (i = 0; i < currSCCB->CdbLength; i++) {
4133 if (currSCCB->OperationCode == RESET_COMMAND)
4135 WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + 0x00));
4137 else
4138 WRW_HARPOON(cdb_reg,
4139 (MPM_OP + ACOMMAND + currSCCB->Cdb[i]));
4140 cdb_reg += 2;
4143 if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
4144 WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
4146 WR_HARPOON(p_port + hp_portctrl_0, (SCSI_PORT));
4148 currSCCB->Sccb_scsistat = COMMAND_ST;
4150 WR_HARPOON(p_port + hp_autostart_3, (AUTO_IMMED | CMD_ONLY_STRT));
4151 SGRAM_ACCESS(p_port);
4154 /*---------------------------------------------------------------------
4156 * Function: Status phase
4158 * Description: Bring in the status and command complete message bytes
4160 *---------------------------------------------------------------------*/
4162 static void FPT_phaseStatus(unsigned long port, unsigned char p_card)
4164 /* Start-up the automation to finish off this command and let the
4165 isr handle the interrupt for command complete when it comes in.
4166 We could wait here for the interrupt to be generated?
4169 WR_HARPOON(port + hp_scsisig, 0x00);
4171 WR_HARPOON(port + hp_autostart_0, (AUTO_IMMED + END_DATA_START));
4174 /*---------------------------------------------------------------------
4176 * Function: Phase Message Out
4178 * Description: Send out our message (if we have one) and handle whatever
4179 * else is involed.
4181 *---------------------------------------------------------------------*/
4183 static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card)
4185 unsigned char message, scsiID;
4186 struct sccb *currSCCB;
4187 struct sccb_mgr_tar_info *currTar_Info;
4189 currSCCB = FPT_BL_Card[p_card].currentSCCB;
4191 if (currSCCB != NULL) {
4193 message = currSCCB->Sccb_scsimsg;
4194 scsiID = currSCCB->TargID;
4196 if (message == SMDEV_RESET) {
4198 currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
4199 currTar_Info->TarSyncCtrl = 0;
4200 FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
4202 if (FPT_sccbMgrTbl[p_card][scsiID].
4203 TarEEValue & EE_SYNC_MASK) {
4205 FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
4206 ~TAR_SYNC_MASK;
4210 if (FPT_sccbMgrTbl[p_card][scsiID].
4211 TarEEValue & EE_WIDE_SCSI) {
4213 FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
4214 ~TAR_WIDE_MASK;
4217 FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
4218 FPT_SccbMgrTableInitTarget(p_card, scsiID);
4219 } else if (currSCCB->Sccb_scsistat == ABORT_ST) {
4220 currSCCB->HostStatus = SCCB_COMPLETE;
4221 if (FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] !=
4222 NULL) {
4223 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4224 Sccb_tag] = NULL;
4225 FPT_sccbMgrTbl[p_card][scsiID].TarTagQ_Cnt--;
4230 else if (currSCCB->Sccb_scsistat < COMMAND_ST) {
4232 if (message == SMNO_OP) {
4233 currSCCB->Sccb_MGRFlags |= F_DEV_SELECTED;
4235 FPT_ssel(port, p_card);
4236 return;
4238 } else {
4240 if (message == SMABORT)
4242 FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
4245 } else {
4246 message = SMABORT;
4249 WRW_HARPOON((port + hp_intstat), (BUS_FREE | PHASE | XFER_CNT_0));
4251 WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
4253 WR_HARPOON(port + hp_scsidata_0, message);
4255 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
4257 ACCEPT_MSG(port);
4259 WR_HARPOON(port + hp_portctrl_0, 0x00);
4261 if ((message == SMABORT) || (message == SMDEV_RESET) ||
4262 (message == SMABORT_TAG)) {
4264 while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | PHASE))) {
4267 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
4268 WRW_HARPOON((port + hp_intstat), BUS_FREE);
4270 if (currSCCB != NULL) {
4272 if ((FPT_BL_Card[p_card].
4273 globalFlags & F_CONLUN_IO)
4275 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4276 TarStatus & TAR_TAG_Q_MASK) !=
4277 TAG_Q_TRYING))
4278 FPT_sccbMgrTbl[p_card][currSCCB->
4279 TargID].
4280 TarLUNBusy[currSCCB->Lun] = 0;
4281 else
4282 FPT_sccbMgrTbl[p_card][currSCCB->
4283 TargID].
4284 TarLUNBusy[0] = 0;
4286 FPT_queueCmdComplete(&FPT_BL_Card[p_card],
4287 currSCCB, p_card);
4290 else {
4291 FPT_BL_Card[p_card].globalFlags |=
4292 F_NEW_SCCB_CMD;
4296 else {
4298 FPT_sxfrp(port, p_card);
4302 else {
4304 if (message == SMPARITY) {
4305 currSCCB->Sccb_scsimsg = SMNO_OP;
4306 WR_HARPOON(port + hp_autostart_1,
4307 (AUTO_IMMED + DISCONNECT_START));
4308 } else {
4309 FPT_sxfrp(port, p_card);
4314 /*---------------------------------------------------------------------
4316 * Function: Message In phase
4318 * Description: Bring in the message and determine what to do with it.
4320 *---------------------------------------------------------------------*/
4322 static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card)
4324 unsigned char message;
4325 struct sccb *currSCCB;
4327 currSCCB = FPT_BL_Card[p_card].currentSCCB;
4329 if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
4331 FPT_phaseChkFifo(port, p_card);
4334 message = RD_HARPOON(port + hp_scsidata_0);
4335 if ((message == SMDISC) || (message == SMSAVE_DATA_PTR)) {
4337 WR_HARPOON(port + hp_autostart_1,
4338 (AUTO_IMMED + END_DATA_START));
4342 else {
4344 message = FPT_sfm(port, currSCCB);
4345 if (message) {
4347 FPT_sdecm(message, port, p_card);
4349 } else {
4350 if (currSCCB->Sccb_scsimsg != SMPARITY)
4351 ACCEPT_MSG(port);
4352 WR_HARPOON(port + hp_autostart_1,
4353 (AUTO_IMMED + DISCONNECT_START));
4359 /*---------------------------------------------------------------------
4361 * Function: Illegal phase
4363 * Description: Target switched to some illegal phase, so all we can do
4364 * is report an error back to the host (if that is possible)
4365 * and send an ABORT message to the misbehaving target.
4367 *---------------------------------------------------------------------*/
4369 static void FPT_phaseIllegal(unsigned long port, unsigned char p_card)
4371 struct sccb *currSCCB;
4373 currSCCB = FPT_BL_Card[p_card].currentSCCB;
4375 WR_HARPOON(port + hp_scsisig, RD_HARPOON(port + hp_scsisig));
4376 if (currSCCB != NULL) {
4378 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4379 currSCCB->Sccb_scsistat = ABORT_ST;
4380 currSCCB->Sccb_scsimsg = SMABORT;
4383 ACCEPT_MSG_ATN(port);
4386 /*---------------------------------------------------------------------
4388 * Function: Phase Check FIFO
4390 * Description: Make sure data has been flushed from both FIFOs and abort
4391 * the operations if necessary.
4393 *---------------------------------------------------------------------*/
4395 static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card)
4397 unsigned long xfercnt;
4398 struct sccb *currSCCB;
4400 currSCCB = FPT_BL_Card[p_card].currentSCCB;
4402 if (currSCCB->Sccb_scsistat == DATA_IN_ST) {
4404 while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) &&
4405 (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)) {
4408 if (!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) {
4409 currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
4411 currSCCB->Sccb_XferCnt = 0;
4413 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
4414 (currSCCB->HostStatus == SCCB_COMPLETE)) {
4415 currSCCB->HostStatus = SCCB_PARITY_ERR;
4416 WRW_HARPOON((port + hp_intstat), PARITY);
4419 FPT_hostDataXferAbort(port, p_card, currSCCB);
4421 FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
4423 while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY))
4424 && (RD_HARPOON(port + hp_ext_status) &
4425 BM_CMD_BUSY)) {
4431 /*End Data In specific code. */
4432 GET_XFER_CNT(port, xfercnt);
4434 WR_HARPOON(port + hp_xfercnt_0, 0x00);
4436 WR_HARPOON(port + hp_portctrl_0, 0x00);
4438 currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - xfercnt);
4440 currSCCB->Sccb_XferCnt = xfercnt;
4442 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
4443 (currSCCB->HostStatus == SCCB_COMPLETE)) {
4445 currSCCB->HostStatus = SCCB_PARITY_ERR;
4446 WRW_HARPOON((port + hp_intstat), PARITY);
4449 FPT_hostDataXferAbort(port, p_card, currSCCB);
4451 WR_HARPOON(port + hp_fifowrite, 0x00);
4452 WR_HARPOON(port + hp_fiforead, 0x00);
4453 WR_HARPOON(port + hp_xferstat, 0x00);
4455 WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
4458 /*---------------------------------------------------------------------
4460 * Function: Phase Bus Free
4462 * Description: We just went bus free so figure out if it was
4463 * because of command complete or from a disconnect.
4465 *---------------------------------------------------------------------*/
4466 static void FPT_phaseBusFree(unsigned long port, unsigned char p_card)
4468 struct sccb *currSCCB;
4470 currSCCB = FPT_BL_Card[p_card].currentSCCB;
4472 if (currSCCB != NULL) {
4474 DISABLE_AUTO(port);
4476 if (currSCCB->OperationCode == RESET_COMMAND) {
4478 if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4479 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4480 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4481 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4482 TarLUNBusy[currSCCB->Lun] = 0;
4483 else
4484 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4485 TarLUNBusy[0] = 0;
4487 FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
4488 p_card);
4490 FPT_queueSearchSelect(&FPT_BL_Card[p_card], p_card);
4494 else if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
4495 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4496 (unsigned char)SYNC_SUPPORTED;
4497 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4498 ~EE_SYNC_MASK;
4501 else if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
4502 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
4503 (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4504 TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
4506 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4507 ~EE_WIDE_SCSI;
4510 else if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
4511 /* Make sure this is not a phony BUS_FREE. If we were
4512 reselected or if BUSY is NOT on then this is a
4513 valid BUS FREE. SRR Wednesday, 5/10/1995. */
4515 if ((!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ||
4516 (RDW_HARPOON((port + hp_intstat)) & RSEL)) {
4517 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4518 TarStatus &= ~TAR_TAG_Q_MASK;
4519 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4520 TarStatus |= TAG_Q_REJECT;
4523 else {
4524 return;
4528 else {
4530 currSCCB->Sccb_scsistat = BUS_FREE_ST;
4532 if (!currSCCB->HostStatus) {
4533 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4536 if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4537 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4538 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4539 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4540 TarLUNBusy[currSCCB->Lun] = 0;
4541 else
4542 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4543 TarLUNBusy[0] = 0;
4545 FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
4546 p_card);
4547 return;
4550 FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
4552 } /*end if !=null */
4555 /*---------------------------------------------------------------------
4557 * Function: Auto Load Default Map
4559 * Description: Load the Automation RAM with the defualt map values.
4561 *---------------------------------------------------------------------*/
4562 static void FPT_autoLoadDefaultMap(unsigned long p_port)
4564 unsigned long map_addr;
4566 ARAM_ACCESS(p_port);
4567 map_addr = p_port + hp_aramBase;
4569 WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0xC0)); /*ID MESSAGE */
4570 map_addr += 2;
4571 WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x20)); /*SIMPLE TAG QUEUEING MSG */
4572 map_addr += 2;
4573 WRW_HARPOON(map_addr, RAT_OP); /*RESET ATTENTION */
4574 map_addr += 2;
4575 WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x00)); /*TAG ID MSG */
4576 map_addr += 2;
4577 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 0 */
4578 map_addr += 2;
4579 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 1 */
4580 map_addr += 2;
4581 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 2 */
4582 map_addr += 2;
4583 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 3 */
4584 map_addr += 2;
4585 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 4 */
4586 map_addr += 2;
4587 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 5 */
4588 map_addr += 2;
4589 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 6 */
4590 map_addr += 2;
4591 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 7 */
4592 map_addr += 2;
4593 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 8 */
4594 map_addr += 2;
4595 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 9 */
4596 map_addr += 2;
4597 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 10 */
4598 map_addr += 2;
4599 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 11 */
4600 map_addr += 2;
4601 WRW_HARPOON(map_addr, (CPE_OP + ADATA_OUT + DINT)); /*JUMP IF DATA OUT */
4602 map_addr += 2;
4603 WRW_HARPOON(map_addr, (TCB_OP + FIFO_0 + DI)); /*JUMP IF NO DATA IN FIFO */
4604 map_addr += 2; /*This means AYNC DATA IN */
4605 WRW_HARPOON(map_addr, (SSI_OP + SSI_IDO_STRT)); /*STOP AND INTERRUPT */
4606 map_addr += 2;
4607 WRW_HARPOON(map_addr, (CPE_OP + ADATA_IN + DINT)); /*JUMP IF NOT DATA IN PHZ */
4608 map_addr += 2;
4609 WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST)); /*IF NOT MSG IN CHECK 4 DATA IN */
4610 map_addr += 2;
4611 WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x02)); /*SAVE DATA PTR MSG? */
4612 map_addr += 2;
4613 WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + DC)); /*GO CHECK FOR DISCONNECT MSG */
4614 map_addr += 2;
4615 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR1)); /*SAVE DATA PTRS MSG */
4616 map_addr += 2;
4617 WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST)); /*IF NOT MSG IN CHECK DATA IN */
4618 map_addr += 2;
4619 WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x04)); /*DISCONNECT MSG? */
4620 map_addr += 2;
4621 WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + UNKNWN)); /*UKNKNOWN MSG */
4622 map_addr += 2;
4623 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET)); /*XFER DISCONNECT MSG */
4624 map_addr += 2;
4625 WRW_HARPOON(map_addr, (SSI_OP + SSI_ITAR_DISC)); /*STOP AND INTERRUPT */
4626 map_addr += 2;
4627 WRW_HARPOON(map_addr, (CPN_OP + ASTATUS + UNKNWN)); /*JUMP IF NOT STATUS PHZ. */
4628 map_addr += 2;
4629 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR0)); /*GET STATUS BYTE */
4630 map_addr += 2;
4631 WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + CC)); /*ERROR IF NOT MSG IN PHZ */
4632 map_addr += 2;
4633 WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x00)); /*CHECK FOR CMD COMPLETE MSG. */
4634 map_addr += 2;
4635 WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + CC)); /*ERROR IF NOT CMD COMPLETE MSG. */
4636 map_addr += 2;
4637 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET)); /*GET CMD COMPLETE MSG */
4638 map_addr += 2;
4639 WRW_HARPOON(map_addr, (SSI_OP + SSI_ICMD_COMP)); /*END OF COMMAND */
4640 map_addr += 2;
4642 WRW_HARPOON(map_addr, (SSI_OP + SSI_IUNKWN)); /*RECEIVED UNKNOWN MSG BYTE */
4643 map_addr += 2;
4644 WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */
4645 map_addr += 2;
4646 WRW_HARPOON(map_addr, (SSI_OP + SSI_ITICKLE)); /*BIOS Tickled the Mgr */
4647 map_addr += 2;
4648 WRW_HARPOON(map_addr, (SSI_OP + SSI_IRFAIL)); /*EXPECTED ID/TAG MESSAGES AND */
4649 map_addr += 2; /* DIDN'T GET ONE */
4650 WRW_HARPOON(map_addr, (CRR_OP + AR3 + S_IDREG)); /* comp SCSI SEL ID & AR3 */
4651 map_addr += 2;
4652 WRW_HARPOON(map_addr, (BRH_OP + EQUAL + 0x00)); /*SEL ID OK then Conti. */
4653 map_addr += 2;
4654 WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */
4656 SGRAM_ACCESS(p_port);
4659 /*---------------------------------------------------------------------
4661 * Function: Auto Command Complete
4663 * Description: Post command back to host and find another command
4664 * to execute.
4666 *---------------------------------------------------------------------*/
4668 static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card)
4670 struct sccb *currSCCB;
4671 unsigned char status_byte;
4673 currSCCB = FPT_BL_Card[p_card].currentSCCB;
4675 status_byte = RD_HARPOON(p_port + hp_gp_reg_0);
4677 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA = 0;
4679 if (status_byte != SSGOOD) {
4681 if (status_byte == SSQ_FULL) {
4683 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4684 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4685 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4686 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4687 TarLUNBusy[currSCCB->Lun] = 1;
4688 if (FPT_BL_Card[p_card].discQCount != 0)
4689 FPT_BL_Card[p_card].discQCount--;
4690 FPT_BL_Card[p_card].
4691 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4692 [currSCCB->TargID].
4693 LunDiscQ_Idx[currSCCB->Lun]] =
4694 NULL;
4695 } else {
4696 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4697 TarLUNBusy[0] = 1;
4698 if (currSCCB->Sccb_tag) {
4699 if (FPT_BL_Card[p_card].discQCount != 0)
4700 FPT_BL_Card[p_card].
4701 discQCount--;
4702 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4703 Sccb_tag]
4704 = NULL;
4705 } else {
4706 if (FPT_BL_Card[p_card].discQCount != 0)
4707 FPT_BL_Card[p_card].
4708 discQCount--;
4709 FPT_BL_Card[p_card].
4710 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4711 [currSCCB->TargID].
4712 LunDiscQ_Idx[0]] = NULL;
4716 currSCCB->Sccb_MGRFlags |= F_STATUSLOADED;
4718 FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
4720 return;
4723 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
4724 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4725 (unsigned char)SYNC_SUPPORTED;
4727 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4728 ~EE_SYNC_MASK;
4729 FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
4731 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4732 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4733 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4734 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4735 TarLUNBusy[currSCCB->Lun] = 1;
4736 if (FPT_BL_Card[p_card].discQCount != 0)
4737 FPT_BL_Card[p_card].discQCount--;
4738 FPT_BL_Card[p_card].
4739 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4740 [currSCCB->TargID].
4741 LunDiscQ_Idx[currSCCB->Lun]] =
4742 NULL;
4743 } else {
4744 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4745 TarLUNBusy[0] = 1;
4746 if (currSCCB->Sccb_tag) {
4747 if (FPT_BL_Card[p_card].discQCount != 0)
4748 FPT_BL_Card[p_card].
4749 discQCount--;
4750 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4751 Sccb_tag]
4752 = NULL;
4753 } else {
4754 if (FPT_BL_Card[p_card].discQCount != 0)
4755 FPT_BL_Card[p_card].
4756 discQCount--;
4757 FPT_BL_Card[p_card].
4758 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4759 [currSCCB->TargID].
4760 LunDiscQ_Idx[0]] = NULL;
4763 return;
4767 if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
4769 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
4770 (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4771 TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
4773 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4774 ~EE_WIDE_SCSI;
4775 FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
4777 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4778 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4779 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4780 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4781 TarLUNBusy[currSCCB->Lun] = 1;
4782 if (FPT_BL_Card[p_card].discQCount != 0)
4783 FPT_BL_Card[p_card].discQCount--;
4784 FPT_BL_Card[p_card].
4785 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4786 [currSCCB->TargID].
4787 LunDiscQ_Idx[currSCCB->Lun]] =
4788 NULL;
4789 } else {
4790 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4791 TarLUNBusy[0] = 1;
4792 if (currSCCB->Sccb_tag) {
4793 if (FPT_BL_Card[p_card].discQCount != 0)
4794 FPT_BL_Card[p_card].
4795 discQCount--;
4796 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4797 Sccb_tag]
4798 = NULL;
4799 } else {
4800 if (FPT_BL_Card[p_card].discQCount != 0)
4801 FPT_BL_Card[p_card].
4802 discQCount--;
4803 FPT_BL_Card[p_card].
4804 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4805 [currSCCB->TargID].
4806 LunDiscQ_Idx[0]] = NULL;
4809 return;
4813 if (status_byte == SSCHECK) {
4814 if (FPT_BL_Card[p_card].globalFlags & F_DO_RENEGO) {
4815 if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4816 TarEEValue & EE_SYNC_MASK) {
4817 FPT_sccbMgrTbl[p_card][currSCCB->
4818 TargID].
4819 TarStatus &= ~TAR_SYNC_MASK;
4821 if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4822 TarEEValue & EE_WIDE_SCSI) {
4823 FPT_sccbMgrTbl[p_card][currSCCB->
4824 TargID].
4825 TarStatus &= ~TAR_WIDE_MASK;
4830 if (!(currSCCB->Sccb_XferState & F_AUTO_SENSE)) {
4832 currSCCB->SccbStatus = SCCB_ERROR;
4833 currSCCB->TargetStatus = status_byte;
4835 if (status_byte == SSCHECK) {
4837 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4838 TarLUN_CA = 1;
4840 if (currSCCB->RequestSenseLength !=
4841 NO_AUTO_REQUEST_SENSE) {
4843 if (currSCCB->RequestSenseLength == 0)
4844 currSCCB->RequestSenseLength =
4847 FPT_ssenss(&FPT_BL_Card[p_card]);
4848 FPT_BL_Card[p_card].globalFlags |=
4849 F_NEW_SCCB_CMD;
4851 if (((FPT_BL_Card[p_card].
4852 globalFlags & F_CONLUN_IO)
4854 ((FPT_sccbMgrTbl[p_card]
4855 [currSCCB->TargID].
4856 TarStatus & TAR_TAG_Q_MASK) !=
4857 TAG_Q_TRYING))) {
4858 FPT_sccbMgrTbl[p_card]
4859 [currSCCB->TargID].
4860 TarLUNBusy[currSCCB->Lun] =
4862 if (FPT_BL_Card[p_card].
4863 discQCount != 0)
4864 FPT_BL_Card[p_card].
4865 discQCount--;
4866 FPT_BL_Card[p_card].
4867 discQ_Tbl[FPT_sccbMgrTbl
4868 [p_card]
4869 [currSCCB->
4870 TargID].
4871 LunDiscQ_Idx
4872 [currSCCB->Lun]] =
4873 NULL;
4874 } else {
4875 FPT_sccbMgrTbl[p_card]
4876 [currSCCB->TargID].
4877 TarLUNBusy[0] = 1;
4878 if (currSCCB->Sccb_tag) {
4879 if (FPT_BL_Card[p_card].
4880 discQCount != 0)
4881 FPT_BL_Card
4882 [p_card].
4883 discQCount--;
4884 FPT_BL_Card[p_card].
4885 discQ_Tbl[currSCCB->
4886 Sccb_tag]
4887 = NULL;
4888 } else {
4889 if (FPT_BL_Card[p_card].
4890 discQCount != 0)
4891 FPT_BL_Card
4892 [p_card].
4893 discQCount--;
4894 FPT_BL_Card[p_card].
4895 discQ_Tbl
4896 [FPT_sccbMgrTbl
4897 [p_card][currSCCB->
4898 TargID].
4899 LunDiscQ_Idx[0]] =
4900 NULL;
4903 return;
4909 if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4910 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4911 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4912 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->
4913 Lun] = 0;
4914 else
4915 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0;
4917 FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, p_card);
4920 #define SHORT_WAIT 0x0000000F
4921 #define LONG_WAIT 0x0000FFFFL
4923 /*---------------------------------------------------------------------
4925 * Function: Data Transfer Processor
4927 * Description: This routine performs two tasks.
4928 * (1) Start data transfer by calling HOST_DATA_XFER_START
4929 * function. Once data transfer is started, (2) Depends
4930 * on the type of data transfer mode Scatter/Gather mode
4931 * or NON Scatter/Gather mode. In NON Scatter/Gather mode,
4932 * this routine checks Sccb_MGRFlag (F_HOST_XFER_ACT bit) for
4933 * data transfer done. In Scatter/Gather mode, this routine
4934 * checks bus master command complete and dual rank busy
4935 * bit to keep chaining SC transfer command. Similarly,
4936 * in Scatter/Gather mode, it checks Sccb_MGRFlag
4937 * (F_HOST_XFER_ACT bit) for data transfer done.
4939 *---------------------------------------------------------------------*/
4941 static void FPT_dataXferProcessor(unsigned long port,
4942 struct sccb_card *pCurrCard)
4944 struct sccb *currSCCB;
4946 currSCCB = pCurrCard->currentSCCB;
4948 if (currSCCB->Sccb_XferState & F_SG_XFER) {
4949 if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
4951 currSCCB->Sccb_sgseg += (unsigned char)SG_BUF_CNT;
4952 currSCCB->Sccb_SGoffset = 0x00;
4954 pCurrCard->globalFlags |= F_HOST_XFER_ACT;
4956 FPT_busMstrSGDataXferStart(port, currSCCB);
4959 else {
4960 if (!(pCurrCard->globalFlags & F_HOST_XFER_ACT)) {
4961 pCurrCard->globalFlags |= F_HOST_XFER_ACT;
4963 FPT_busMstrDataXferStart(port, currSCCB);
4968 /*---------------------------------------------------------------------
4970 * Function: BusMaster Scatter Gather Data Transfer Start
4972 * Description:
4974 *---------------------------------------------------------------------*/
4975 static void FPT_busMstrSGDataXferStart(unsigned long p_port,
4976 struct sccb *pcurrSCCB)
4978 unsigned long count, addr, tmpSGCnt;
4979 unsigned int sg_index;
4980 unsigned char sg_count, i;
4981 unsigned long reg_offset;
4983 if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
4985 count = ((unsigned long)HOST_RD_CMD) << 24;
4988 else {
4989 count = ((unsigned long)HOST_WRT_CMD) << 24;
4992 sg_count = 0;
4993 tmpSGCnt = 0;
4994 sg_index = pcurrSCCB->Sccb_sgseg;
4995 reg_offset = hp_aramBase;
4997 i = (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
4998 ~(SGRAM_ARAM | SCATTER_EN));
5000 WR_HARPOON(p_port + hp_page_ctrl, i);
5002 while ((sg_count < (unsigned char)SG_BUF_CNT) &&
5003 ((unsigned long)(sg_index * (unsigned int)SG_ELEMENT_SIZE) <
5004 pcurrSCCB->DataLength)) {
5006 tmpSGCnt += *(((unsigned long *)pcurrSCCB->DataPointer) +
5007 (sg_index * 2));
5009 count |= *(((unsigned long *)pcurrSCCB->DataPointer) +
5010 (sg_index * 2));
5012 addr = *(((unsigned long *)pcurrSCCB->DataPointer) +
5013 ((sg_index * 2) + 1));
5015 if ((!sg_count) && (pcurrSCCB->Sccb_SGoffset)) {
5017 addr +=
5018 ((count & 0x00FFFFFFL) - pcurrSCCB->Sccb_SGoffset);
5019 count =
5020 (count & 0xFF000000L) | pcurrSCCB->Sccb_SGoffset;
5022 tmpSGCnt = count & 0x00FFFFFFL;
5025 WR_HARP32(p_port, reg_offset, addr);
5026 reg_offset += 4;
5028 WR_HARP32(p_port, reg_offset, count);
5029 reg_offset += 4;
5031 count &= 0xFF000000L;
5032 sg_index++;
5033 sg_count++;
5035 } /*End While */
5037 pcurrSCCB->Sccb_XferCnt = tmpSGCnt;
5039 WR_HARPOON(p_port + hp_sg_addr, (sg_count << 4));
5041 if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
5043 WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
5045 WR_HARPOON(p_port + hp_portctrl_0,
5046 (DMA_PORT | SCSI_PORT | SCSI_INBIT));
5047 WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
5050 else {
5052 if ((!(RD_HARPOON(p_port + hp_synctarg_0) & NARROW_SCSI)) &&
5053 (tmpSGCnt & 0x000000001)) {
5055 pcurrSCCB->Sccb_XferState |= F_ODD_BALL_CNT;
5056 tmpSGCnt--;
5059 WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
5061 WR_HARPOON(p_port + hp_portctrl_0,
5062 (SCSI_PORT | DMA_PORT | DMA_RD));
5063 WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
5066 WR_HARPOON(p_port + hp_page_ctrl, (unsigned char)(i | SCATTER_EN));
5070 /*---------------------------------------------------------------------
5072 * Function: BusMaster Data Transfer Start
5074 * Description:
5076 *---------------------------------------------------------------------*/
5077 static void FPT_busMstrDataXferStart(unsigned long p_port,
5078 struct sccb *pcurrSCCB)
5080 unsigned long addr, count;
5082 if (!(pcurrSCCB->Sccb_XferState & F_AUTO_SENSE)) {
5084 count = pcurrSCCB->Sccb_XferCnt;
5086 addr =
5087 (unsigned long)pcurrSCCB->DataPointer + pcurrSCCB->Sccb_ATC;
5090 else {
5091 addr = pcurrSCCB->SensePointer;
5092 count = pcurrSCCB->RequestSenseLength;
5096 HP_SETUP_ADDR_CNT(p_port, addr, count);
5098 if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
5100 WR_HARPOON(p_port + hp_portctrl_0,
5101 (DMA_PORT | SCSI_PORT | SCSI_INBIT));
5102 WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
5104 WR_HARPOON(p_port + hp_xfer_cmd,
5105 (XFER_DMA_HOST | XFER_HOST_AUTO | XFER_DMA_8BIT));
5108 else {
5110 WR_HARPOON(p_port + hp_portctrl_0,
5111 (SCSI_PORT | DMA_PORT | DMA_RD));
5112 WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
5114 WR_HARPOON(p_port + hp_xfer_cmd,
5115 (XFER_HOST_DMA | XFER_HOST_AUTO | XFER_DMA_8BIT));
5120 /*---------------------------------------------------------------------
5122 * Function: BusMaster Timeout Handler
5124 * Description: This function is called after a bus master command busy time
5125 * out is detected. This routines issue halt state machine
5126 * with a software time out for command busy. If command busy
5127 * is still asserted at the end of the time out, it issues
5128 * hard abort with another software time out. It hard abort
5129 * command busy is also time out, it'll just give up.
5131 *---------------------------------------------------------------------*/
5132 static unsigned char FPT_busMstrTimeOut(unsigned long p_port)
5134 unsigned long timeout;
5136 timeout = LONG_WAIT;
5138 WR_HARPOON(p_port + hp_sys_ctrl, HALT_MACH);
5140 while ((!(RD_HARPOON(p_port + hp_ext_status) & CMD_ABORTED))
5141 && timeout--) {
5144 if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
5145 WR_HARPOON(p_port + hp_sys_ctrl, HARD_ABORT);
5147 timeout = LONG_WAIT;
5148 while ((RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY)
5149 && timeout--) {
5153 RD_HARPOON(p_port + hp_int_status); /*Clear command complete */
5155 if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
5156 return 1;
5159 else {
5160 return 0;
5164 /*---------------------------------------------------------------------
5166 * Function: Host Data Transfer Abort
5168 * Description: Abort any in progress transfer.
5170 *---------------------------------------------------------------------*/
5171 static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card,
5172 struct sccb *pCurrSCCB)
5175 unsigned long timeout;
5176 unsigned long remain_cnt;
5177 unsigned int sg_ptr;
5179 FPT_BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT;
5181 if (pCurrSCCB->Sccb_XferState & F_AUTO_SENSE) {
5183 if (!(RD_HARPOON(port + hp_int_status) & INT_CMD_COMPL)) {
5185 WR_HARPOON(port + hp_bm_ctrl,
5186 (RD_HARPOON(port + hp_bm_ctrl) |
5187 FLUSH_XFER_CNTR));
5188 timeout = LONG_WAIT;
5190 while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
5191 && timeout--) {
5194 WR_HARPOON(port + hp_bm_ctrl,
5195 (RD_HARPOON(port + hp_bm_ctrl) &
5196 ~FLUSH_XFER_CNTR));
5198 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
5200 if (FPT_busMstrTimeOut(port)) {
5202 if (pCurrSCCB->HostStatus == 0x00)
5204 pCurrSCCB->HostStatus =
5205 SCCB_BM_ERR;
5209 if (RD_HARPOON(port + hp_int_status) &
5210 INT_EXT_STATUS)
5212 if (RD_HARPOON(port + hp_ext_status) &
5213 BAD_EXT_STATUS)
5215 if (pCurrSCCB->HostStatus ==
5216 0x00)
5218 pCurrSCCB->HostStatus =
5219 SCCB_BM_ERR;
5225 else if (pCurrSCCB->Sccb_XferCnt) {
5227 if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
5229 WR_HARPOON(port + hp_page_ctrl,
5230 (RD_HARPOON(port + hp_page_ctrl) &
5231 ~SCATTER_EN));
5233 WR_HARPOON(port + hp_sg_addr, 0x00);
5235 sg_ptr = pCurrSCCB->Sccb_sgseg + SG_BUF_CNT;
5237 if (sg_ptr >
5238 (unsigned int)(pCurrSCCB->DataLength /
5239 SG_ELEMENT_SIZE)) {
5241 sg_ptr =
5242 (unsigned int)(pCurrSCCB->DataLength /
5243 SG_ELEMENT_SIZE);
5246 remain_cnt = pCurrSCCB->Sccb_XferCnt;
5248 while (remain_cnt < 0x01000000L) {
5250 sg_ptr--;
5252 if (remain_cnt >
5253 (unsigned
5254 long)(*(((unsigned long *)pCurrSCCB->
5255 DataPointer) + (sg_ptr * 2)))) {
5257 remain_cnt -=
5258 (unsigned
5259 long)(*(((unsigned long *)
5260 pCurrSCCB->DataPointer) +
5261 (sg_ptr * 2)));
5264 else {
5266 break;
5270 if (remain_cnt < 0x01000000L) {
5272 pCurrSCCB->Sccb_SGoffset = remain_cnt;
5274 pCurrSCCB->Sccb_sgseg = (unsigned short)sg_ptr;
5276 if ((unsigned long)(sg_ptr * SG_ELEMENT_SIZE) ==
5277 pCurrSCCB->DataLength && (remain_cnt == 0))
5279 pCurrSCCB->Sccb_XferState |=
5280 F_ALL_XFERRED;
5283 else {
5285 if (pCurrSCCB->HostStatus == 0x00) {
5287 pCurrSCCB->HostStatus =
5288 SCCB_GROSS_FW_ERR;
5293 if (!(pCurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)) {
5295 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
5297 FPT_busMstrTimeOut(port);
5300 else {
5302 if (RD_HARPOON(port + hp_int_status) &
5303 INT_EXT_STATUS) {
5305 if (RD_HARPOON(port + hp_ext_status) &
5306 BAD_EXT_STATUS) {
5308 if (pCurrSCCB->HostStatus ==
5309 0x00) {
5311 pCurrSCCB->HostStatus =
5312 SCCB_BM_ERR;
5320 else {
5322 if ((RD_HARPOON(port + hp_fifo_cnt)) >= BM_THRESHOLD) {
5324 timeout = SHORT_WAIT;
5326 while ((RD_HARPOON(port + hp_ext_status) &
5327 BM_CMD_BUSY)
5328 && ((RD_HARPOON(port + hp_fifo_cnt)) >=
5329 BM_THRESHOLD) && timeout--) {
5333 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
5335 WR_HARPOON(port + hp_bm_ctrl,
5336 (RD_HARPOON(port + hp_bm_ctrl) |
5337 FLUSH_XFER_CNTR));
5339 timeout = LONG_WAIT;
5341 while ((RD_HARPOON(port + hp_ext_status) &
5342 BM_CMD_BUSY) && timeout--) {
5345 WR_HARPOON(port + hp_bm_ctrl,
5346 (RD_HARPOON(port + hp_bm_ctrl) &
5347 ~FLUSH_XFER_CNTR));
5349 if (RD_HARPOON(port + hp_ext_status) &
5350 BM_CMD_BUSY) {
5352 if (pCurrSCCB->HostStatus == 0x00) {
5354 pCurrSCCB->HostStatus =
5355 SCCB_BM_ERR;
5358 FPT_busMstrTimeOut(port);
5362 if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
5364 if (RD_HARPOON(port + hp_ext_status) &
5365 BAD_EXT_STATUS) {
5367 if (pCurrSCCB->HostStatus == 0x00) {
5369 pCurrSCCB->HostStatus =
5370 SCCB_BM_ERR;
5378 else {
5380 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
5382 timeout = LONG_WAIT;
5384 while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
5385 && timeout--) {
5388 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
5390 if (pCurrSCCB->HostStatus == 0x00) {
5392 pCurrSCCB->HostStatus = SCCB_BM_ERR;
5395 FPT_busMstrTimeOut(port);
5399 if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
5401 if (RD_HARPOON(port + hp_ext_status) & BAD_EXT_STATUS) {
5403 if (pCurrSCCB->HostStatus == 0x00) {
5405 pCurrSCCB->HostStatus = SCCB_BM_ERR;
5411 if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
5413 WR_HARPOON(port + hp_page_ctrl,
5414 (RD_HARPOON(port + hp_page_ctrl) &
5415 ~SCATTER_EN));
5417 WR_HARPOON(port + hp_sg_addr, 0x00);
5419 pCurrSCCB->Sccb_sgseg += SG_BUF_CNT;
5421 pCurrSCCB->Sccb_SGoffset = 0x00;
5423 if ((unsigned long)(pCurrSCCB->Sccb_sgseg *
5424 SG_ELEMENT_SIZE) >=
5425 pCurrSCCB->DataLength) {
5427 pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
5429 pCurrSCCB->Sccb_sgseg =
5430 (unsigned short)(pCurrSCCB->DataLength /
5431 SG_ELEMENT_SIZE);
5436 else {
5438 if (!(pCurrSCCB->Sccb_XferState & F_AUTO_SENSE))
5440 pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
5444 WR_HARPOON(port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
5447 /*---------------------------------------------------------------------
5449 * Function: Host Data Transfer Restart
5451 * Description: Reset the available count due to a restore data
5452 * pointers message.
5454 *---------------------------------------------------------------------*/
5455 static void FPT_hostDataXferRestart(struct sccb *currSCCB)
5457 unsigned long data_count;
5458 unsigned int sg_index;
5459 unsigned long *sg_ptr;
5461 if (currSCCB->Sccb_XferState & F_SG_XFER) {
5463 currSCCB->Sccb_XferCnt = 0;
5465 sg_index = 0xffff; /*Index by long words into sg list. */
5466 data_count = 0; /*Running count of SG xfer counts. */
5468 sg_ptr = (unsigned long *)currSCCB->DataPointer;
5470 while (data_count < currSCCB->Sccb_ATC) {
5472 sg_index++;
5473 data_count += *(sg_ptr + (sg_index * 2));
5476 if (data_count == currSCCB->Sccb_ATC) {
5478 currSCCB->Sccb_SGoffset = 0;
5479 sg_index++;
5482 else {
5483 currSCCB->Sccb_SGoffset =
5484 data_count - currSCCB->Sccb_ATC;
5487 currSCCB->Sccb_sgseg = (unsigned short)sg_index;
5490 else {
5491 currSCCB->Sccb_XferCnt =
5492 currSCCB->DataLength - currSCCB->Sccb_ATC;
5496 /*---------------------------------------------------------------------
5498 * Function: FPT_scini
5500 * Description: Setup all data structures necessary for SCAM selection.
5502 *---------------------------------------------------------------------*/
5504 static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
5505 unsigned char p_power_up)
5508 unsigned char loser, assigned_id;
5509 unsigned long p_port;
5511 unsigned char i, k, ScamFlg;
5512 struct sccb_card *currCard;
5513 struct nvram_info *pCurrNvRam;
5515 currCard = &FPT_BL_Card[p_card];
5516 p_port = currCard->ioPort;
5517 pCurrNvRam = currCard->pNvRamInfo;
5519 if (pCurrNvRam) {
5520 ScamFlg = pCurrNvRam->niScamConf;
5521 i = pCurrNvRam->niSysConf;
5522 } else {
5523 ScamFlg =
5524 (unsigned char)FPT_utilEERead(p_port, SCAM_CONFIG / 2);
5525 i = (unsigned
5526 char)(FPT_utilEERead(p_port, (SYSTEM_CONFIG / 2)));
5528 if (!(i & 0x02)) /* check if reset bus in AutoSCSI parameter set */
5529 return;
5531 FPT_inisci(p_card, p_port, p_our_id);
5533 /* Force to wait 1 sec after SCSI bus reset. Some SCAM device FW
5534 too slow to return to SCAM selection */
5536 /* if (p_power_up)
5537 FPT_Wait1Second(p_port);
5538 else
5539 FPT_Wait(p_port, TO_250ms); */
5541 FPT_Wait1Second(p_port);
5543 if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2)) {
5544 while (!(FPT_scarb(p_port, INIT_SELTD))) {
5547 FPT_scsel(p_port);
5549 do {
5550 FPT_scxferc(p_port, SYNC_PTRN);
5551 FPT_scxferc(p_port, DOM_MSTR);
5552 loser =
5553 FPT_scsendi(p_port,
5554 &FPT_scamInfo[p_our_id].id_string[0]);
5555 } while (loser == 0xFF);
5557 FPT_scbusf(p_port);
5559 if ((p_power_up) && (!loser)) {
5560 FPT_sresb(p_port, p_card);
5561 FPT_Wait(p_port, TO_250ms);
5563 while (!(FPT_scarb(p_port, INIT_SELTD))) {
5566 FPT_scsel(p_port);
5568 do {
5569 FPT_scxferc(p_port, SYNC_PTRN);
5570 FPT_scxferc(p_port, DOM_MSTR);
5571 loser =
5572 FPT_scsendi(p_port,
5573 &FPT_scamInfo[p_our_id].
5574 id_string[0]);
5575 } while (loser == 0xFF);
5577 FPT_scbusf(p_port);
5581 else {
5582 loser = 0;
5585 if (!loser) {
5587 FPT_scamInfo[p_our_id].state = ID_ASSIGNED;
5589 if (ScamFlg & SCAM_ENABLED) {
5591 for (i = 0; i < MAX_SCSI_TAR; i++) {
5592 if ((FPT_scamInfo[i].state == ID_UNASSIGNED) ||
5593 (FPT_scamInfo[i].state == ID_UNUSED)) {
5594 if (FPT_scsell(p_port, i)) {
5595 FPT_scamInfo[i].state = LEGACY;
5596 if ((FPT_scamInfo[i].
5597 id_string[0] != 0xFF)
5598 || (FPT_scamInfo[i].
5599 id_string[1] != 0xFA)) {
5601 FPT_scamInfo[i].
5602 id_string[0] = 0xFF;
5603 FPT_scamInfo[i].
5604 id_string[1] = 0xFA;
5605 if (pCurrNvRam == NULL)
5606 currCard->
5607 globalFlags
5609 F_UPDATE_EEPROM;
5615 FPT_sresb(p_port, p_card);
5616 FPT_Wait1Second(p_port);
5617 while (!(FPT_scarb(p_port, INIT_SELTD))) {
5619 FPT_scsel(p_port);
5620 FPT_scasid(p_card, p_port);
5625 else if ((loser) && (ScamFlg & SCAM_ENABLED)) {
5626 FPT_scamInfo[p_our_id].id_string[0] = SLV_TYPE_CODE0;
5627 assigned_id = 0;
5628 FPT_scwtsel(p_port);
5630 do {
5631 while (FPT_scxferc(p_port, 0x00) != SYNC_PTRN) {
5634 i = FPT_scxferc(p_port, 0x00);
5635 if (i == ASSIGN_ID) {
5636 if (!
5637 (FPT_scsendi
5638 (p_port,
5639 &FPT_scamInfo[p_our_id].id_string[0]))) {
5640 i = FPT_scxferc(p_port, 0x00);
5641 if (FPT_scvalq(i)) {
5642 k = FPT_scxferc(p_port, 0x00);
5644 if (FPT_scvalq(k)) {
5645 currCard->ourId =
5646 ((unsigned char)(i
5650 (k &
5651 (unsigned char)7))
5652 & (unsigned char)
5653 0x3F;
5654 FPT_inisci(p_card,
5655 p_port,
5656 p_our_id);
5657 FPT_scamInfo[currCard->
5658 ourId].
5659 state = ID_ASSIGNED;
5660 FPT_scamInfo[currCard->
5661 ourId].
5662 id_string[0]
5663 = SLV_TYPE_CODE0;
5664 assigned_id = 1;
5670 else if (i == SET_P_FLAG) {
5671 if (!(FPT_scsendi(p_port,
5672 &FPT_scamInfo[p_our_id].
5673 id_string[0])))
5674 FPT_scamInfo[p_our_id].id_string[0] |=
5675 0x80;
5677 } while (!assigned_id);
5679 while (FPT_scxferc(p_port, 0x00) != CFG_CMPLT) {
5683 if (ScamFlg & SCAM_ENABLED) {
5684 FPT_scbusf(p_port);
5685 if (currCard->globalFlags & F_UPDATE_EEPROM) {
5686 FPT_scsavdi(p_card, p_port);
5687 currCard->globalFlags &= ~F_UPDATE_EEPROM;
5692 for (i=0,k=0; i < MAX_SCSI_TAR; i++)
5694 if ((FPT_scamInfo[i].state == ID_ASSIGNED) ||
5695 (FPT_scamInfo[i].state == LEGACY))
5696 k++;
5699 if (k==2)
5700 currCard->globalFlags |= F_SINGLE_DEVICE;
5701 else
5702 currCard->globalFlags &= ~F_SINGLE_DEVICE;
5706 /*---------------------------------------------------------------------
5708 * Function: FPT_scarb
5710 * Description: Gain control of the bus and wait SCAM select time (250ms)
5712 *---------------------------------------------------------------------*/
5714 static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type)
5716 if (p_sel_type == INIT_SELTD) {
5718 while (RD_HARPOON(p_port + hp_scsisig) & (SCSI_SEL | SCSI_BSY)) {
5721 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL)
5722 return 0;
5724 if (RD_HARPOON(p_port + hp_scsidata_0) != 00)
5725 return 0;
5727 WR_HARPOON(p_port + hp_scsisig,
5728 (RD_HARPOON(p_port + hp_scsisig) | SCSI_BSY));
5730 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL) {
5732 WR_HARPOON(p_port + hp_scsisig,
5733 (RD_HARPOON(p_port + hp_scsisig) &
5734 ~SCSI_BSY));
5735 return 0;
5738 WR_HARPOON(p_port + hp_scsisig,
5739 (RD_HARPOON(p_port + hp_scsisig) | SCSI_SEL));
5741 if (RD_HARPOON(p_port + hp_scsidata_0) != 00) {
5743 WR_HARPOON(p_port + hp_scsisig,
5744 (RD_HARPOON(p_port + hp_scsisig) &
5745 ~(SCSI_BSY | SCSI_SEL)));
5746 return 0;
5750 WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
5751 & ~ACTdeassert));
5752 WR_HARPOON(p_port + hp_scsireset, SCAM_EN);
5753 WR_HARPOON(p_port + hp_scsidata_0, 0x00);
5754 WR_HARPOON(p_port + hp_scsidata_1, 0x00);
5755 WR_HARPOON(p_port + hp_portctrl_0, SCSI_BUS_EN);
5757 WR_HARPOON(p_port + hp_scsisig,
5758 (RD_HARPOON(p_port + hp_scsisig) | SCSI_MSG));
5760 WR_HARPOON(p_port + hp_scsisig, (RD_HARPOON(p_port + hp_scsisig)
5761 & ~SCSI_BSY));
5763 FPT_Wait(p_port, TO_250ms);
5765 return 1;
5768 /*---------------------------------------------------------------------
5770 * Function: FPT_scbusf
5772 * Description: Release the SCSI bus and disable SCAM selection.
5774 *---------------------------------------------------------------------*/
5776 static void FPT_scbusf(unsigned long p_port)
5778 WR_HARPOON(p_port + hp_page_ctrl,
5779 (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
5781 WR_HARPOON(p_port + hp_scsidata_0, 0x00);
5783 WR_HARPOON(p_port + hp_portctrl_0, (RD_HARPOON(p_port + hp_portctrl_0)
5784 & ~SCSI_BUS_EN));
5786 WR_HARPOON(p_port + hp_scsisig, 0x00);
5788 WR_HARPOON(p_port + hp_scsireset, (RD_HARPOON(p_port + hp_scsireset)
5789 & ~SCAM_EN));
5791 WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
5792 | ACTdeassert));
5794 WRW_HARPOON((p_port + hp_intstat), (BUS_FREE | AUTO_INT | SCAM_SEL));
5796 WR_HARPOON(p_port + hp_page_ctrl,
5797 (RD_HARPOON(p_port + hp_page_ctrl) & ~G_INT_DISABLE));
5800 /*---------------------------------------------------------------------
5802 * Function: FPT_scasid
5804 * Description: Assign an ID to all the SCAM devices.
5806 *---------------------------------------------------------------------*/
5808 static void FPT_scasid(unsigned char p_card, unsigned long p_port)
5810 unsigned char temp_id_string[ID_STRING_LENGTH];
5812 unsigned char i, k, scam_id;
5813 unsigned char crcBytes[3];
5814 struct nvram_info *pCurrNvRam;
5815 unsigned short *pCrcBytes;
5817 pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
5819 i = 0;
5821 while (!i) {
5823 for (k = 0; k < ID_STRING_LENGTH; k++) {
5824 temp_id_string[k] = (unsigned char)0x00;
5827 FPT_scxferc(p_port, SYNC_PTRN);
5828 FPT_scxferc(p_port, ASSIGN_ID);
5830 if (!(FPT_sciso(p_port, &temp_id_string[0]))) {
5831 if (pCurrNvRam) {
5832 pCrcBytes = (unsigned short *)&crcBytes[0];
5833 *pCrcBytes = FPT_CalcCrc16(&temp_id_string[0]);
5834 crcBytes[2] = FPT_CalcLrc(&temp_id_string[0]);
5835 temp_id_string[1] = crcBytes[2];
5836 temp_id_string[2] = crcBytes[0];
5837 temp_id_string[3] = crcBytes[1];
5838 for (k = 4; k < ID_STRING_LENGTH; k++)
5839 temp_id_string[k] = (unsigned char)0x00;
5841 i = FPT_scmachid(p_card, temp_id_string);
5843 if (i == CLR_PRIORITY) {
5844 FPT_scxferc(p_port, MISC_CODE);
5845 FPT_scxferc(p_port, CLR_P_FLAG);
5846 i = 0; /*Not the last ID yet. */
5849 else if (i != NO_ID_AVAIL) {
5850 if (i < 8)
5851 FPT_scxferc(p_port, ID_0_7);
5852 else
5853 FPT_scxferc(p_port, ID_8_F);
5855 scam_id = (i & (unsigned char)0x07);
5857 for (k = 1; k < 0x08; k <<= 1)
5858 if (!(k & i))
5859 scam_id += 0x08; /*Count number of zeros in DB0-3. */
5861 FPT_scxferc(p_port, scam_id);
5863 i = 0; /*Not the last ID yet. */
5867 else {
5868 i = 1;
5871 } /*End while */
5873 FPT_scxferc(p_port, SYNC_PTRN);
5874 FPT_scxferc(p_port, CFG_CMPLT);
5877 /*---------------------------------------------------------------------
5879 * Function: FPT_scsel
5881 * Description: Select all the SCAM devices.
5883 *---------------------------------------------------------------------*/
5885 static void FPT_scsel(unsigned long p_port)
5888 WR_HARPOON(p_port + hp_scsisig, SCSI_SEL);
5889 FPT_scwiros(p_port, SCSI_MSG);
5891 WR_HARPOON(p_port + hp_scsisig, (SCSI_SEL | SCSI_BSY));
5893 WR_HARPOON(p_port + hp_scsisig,
5894 (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5895 WR_HARPOON(p_port + hp_scsidata_0,
5896 (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) |
5897 (unsigned char)(BIT(7) + BIT(6))));
5899 WR_HARPOON(p_port + hp_scsisig, (SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5900 FPT_scwiros(p_port, SCSI_SEL);
5902 WR_HARPOON(p_port + hp_scsidata_0,
5903 (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) &
5904 ~(unsigned char)BIT(6)));
5905 FPT_scwirod(p_port, BIT(6));
5907 WR_HARPOON(p_port + hp_scsisig,
5908 (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5911 /*---------------------------------------------------------------------
5913 * Function: FPT_scxferc
5915 * Description: Handshake the p_data (DB4-0) across the bus.
5917 *---------------------------------------------------------------------*/
5919 static unsigned char FPT_scxferc(unsigned long p_port, unsigned char p_data)
5921 unsigned char curr_data, ret_data;
5923 curr_data = p_data | BIT(7) | BIT(5); /*Start with DB7 & DB5 asserted. */
5925 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5927 curr_data &= ~BIT(7);
5929 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5931 FPT_scwirod(p_port, BIT(7)); /*Wait for DB7 to be released. */
5932 while (!(RD_HARPOON(p_port + hp_scsidata_0) & BIT(5))) ;
5934 ret_data = (RD_HARPOON(p_port + hp_scsidata_0) & (unsigned char)0x1F);
5936 curr_data |= BIT(6);
5938 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5940 curr_data &= ~BIT(5);
5942 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5944 FPT_scwirod(p_port, BIT(5)); /*Wait for DB5 to be released. */
5946 curr_data &= ~(BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0)); /*Release data bits */
5947 curr_data |= BIT(7);
5949 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5951 curr_data &= ~BIT(6);
5953 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5955 FPT_scwirod(p_port, BIT(6)); /*Wait for DB6 to be released. */
5957 return ret_data;
5960 /*---------------------------------------------------------------------
5962 * Function: FPT_scsendi
5964 * Description: Transfer our Identification string to determine if we
5965 * will be the dominant master.
5967 *---------------------------------------------------------------------*/
5969 static unsigned char FPT_scsendi(unsigned long p_port,
5970 unsigned char p_id_string[])
5972 unsigned char ret_data, byte_cnt, bit_cnt, defer;
5974 defer = 0;
5976 for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
5978 for (bit_cnt = 0x80; bit_cnt != 0; bit_cnt >>= 1) {
5980 if (defer)
5981 ret_data = FPT_scxferc(p_port, 00);
5983 else if (p_id_string[byte_cnt] & bit_cnt)
5985 ret_data = FPT_scxferc(p_port, 02);
5987 else {
5989 ret_data = FPT_scxferc(p_port, 01);
5990 if (ret_data & 02)
5991 defer = 1;
5994 if ((ret_data & 0x1C) == 0x10)
5995 return 0x00; /*End of isolation stage, we won! */
5997 if (ret_data & 0x1C)
5998 return 0xFF;
6000 if ((defer) && (!(ret_data & 0x1F)))
6001 return 0x01; /*End of isolation stage, we lost. */
6003 } /*bit loop */
6005 } /*byte loop */
6007 if (defer)
6008 return 0x01; /*We lost */
6009 else
6010 return 0; /*We WON! Yeeessss! */
6013 /*---------------------------------------------------------------------
6015 * Function: FPT_sciso
6017 * Description: Transfer the Identification string.
6019 *---------------------------------------------------------------------*/
6021 static unsigned char FPT_sciso(unsigned long p_port,
6022 unsigned char p_id_string[])
6024 unsigned char ret_data, the_data, byte_cnt, bit_cnt;
6026 the_data = 0;
6028 for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
6030 for (bit_cnt = 0; bit_cnt < 8; bit_cnt++) {
6032 ret_data = FPT_scxferc(p_port, 0);
6034 if (ret_data & 0xFC)
6035 return 0xFF;
6037 else {
6039 the_data <<= 1;
6040 if (ret_data & BIT(1)) {
6041 the_data |= 1;
6045 if ((ret_data & 0x1F) == 0) {
6047 if(bit_cnt != 0 || bit_cnt != 8)
6049 byte_cnt = 0;
6050 bit_cnt = 0;
6051 FPT_scxferc(p_port, SYNC_PTRN);
6052 FPT_scxferc(p_port, ASSIGN_ID);
6053 continue;
6056 if (byte_cnt)
6057 return 0x00;
6058 else
6059 return 0xFF;
6062 } /*bit loop */
6064 p_id_string[byte_cnt] = the_data;
6066 } /*byte loop */
6068 return 0;
6071 /*---------------------------------------------------------------------
6073 * Function: FPT_scwirod
6075 * Description: Sample the SCSI data bus making sure the signal has been
6076 * deasserted for the correct number of consecutive samples.
6078 *---------------------------------------------------------------------*/
6080 static void FPT_scwirod(unsigned long p_port, unsigned char p_data_bit)
6082 unsigned char i;
6084 i = 0;
6085 while (i < MAX_SCSI_TAR) {
6087 if (RD_HARPOON(p_port + hp_scsidata_0) & p_data_bit)
6089 i = 0;
6091 else
6093 i++;
6098 /*---------------------------------------------------------------------
6100 * Function: FPT_scwiros
6102 * Description: Sample the SCSI Signal lines making sure the signal has been
6103 * deasserted for the correct number of consecutive samples.
6105 *---------------------------------------------------------------------*/
6107 static void FPT_scwiros(unsigned long p_port, unsigned char p_data_bit)
6109 unsigned char i;
6111 i = 0;
6112 while (i < MAX_SCSI_TAR) {
6114 if (RD_HARPOON(p_port + hp_scsisig) & p_data_bit)
6116 i = 0;
6118 else
6120 i++;
6125 /*---------------------------------------------------------------------
6127 * Function: FPT_scvalq
6129 * Description: Make sure we received a valid data byte.
6131 *---------------------------------------------------------------------*/
6133 static unsigned char FPT_scvalq(unsigned char p_quintet)
6135 unsigned char count;
6137 for (count = 1; count < 0x08; count <<= 1) {
6138 if (!(p_quintet & count))
6139 p_quintet -= 0x80;
6142 if (p_quintet & 0x18)
6143 return 0;
6145 else
6146 return 1;
6149 /*---------------------------------------------------------------------
6151 * Function: FPT_scsell
6153 * Description: Select the specified device ID using a selection timeout
6154 * less than 4ms. If somebody responds then it is a legacy
6155 * drive and this ID must be marked as such.
6157 *---------------------------------------------------------------------*/
6159 static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id)
6161 unsigned long i;
6163 WR_HARPOON(p_port + hp_page_ctrl,
6164 (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
6166 ARAM_ACCESS(p_port);
6168 WR_HARPOON(p_port + hp_addstat,
6169 (RD_HARPOON(p_port + hp_addstat) | SCAM_TIMER));
6170 WR_HARPOON(p_port + hp_seltimeout, TO_4ms);
6172 for (i = p_port + CMD_STRT; i < p_port + CMD_STRT + 12; i += 2) {
6173 WRW_HARPOON(i, (MPM_OP + ACOMMAND));
6175 WRW_HARPOON(i, (BRH_OP + ALWAYS + NP));
6177 WRW_HARPOON((p_port + hp_intstat),
6178 (RESET | TIMEOUT | SEL | BUS_FREE | AUTO_INT));
6180 WR_HARPOON(p_port + hp_select_id, targ_id);
6182 WR_HARPOON(p_port + hp_portctrl_0, SCSI_PORT);
6183 WR_HARPOON(p_port + hp_autostart_3, (SELECT | CMD_ONLY_STRT));
6184 WR_HARPOON(p_port + hp_scsictrl_0, (SEL_TAR | ENA_RESEL));
6186 while (!(RDW_HARPOON((p_port + hp_intstat)) &
6187 (RESET | PROG_HLT | TIMEOUT | AUTO_INT))) {
6190 if (RDW_HARPOON((p_port + hp_intstat)) & RESET)
6191 FPT_Wait(p_port, TO_250ms);
6193 DISABLE_AUTO(p_port);
6195 WR_HARPOON(p_port + hp_addstat,
6196 (RD_HARPOON(p_port + hp_addstat) & ~SCAM_TIMER));
6197 WR_HARPOON(p_port + hp_seltimeout, TO_290ms);
6199 SGRAM_ACCESS(p_port);
6201 if (RDW_HARPOON((p_port + hp_intstat)) & (RESET | TIMEOUT)) {
6203 WRW_HARPOON((p_port + hp_intstat),
6204 (RESET | TIMEOUT | SEL | BUS_FREE | PHASE));
6206 WR_HARPOON(p_port + hp_page_ctrl,
6207 (RD_HARPOON(p_port + hp_page_ctrl) &
6208 ~G_INT_DISABLE));
6210 return 0; /*No legacy device */
6213 else {
6215 while (!(RDW_HARPOON((p_port + hp_intstat)) & BUS_FREE)) {
6216 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ) {
6217 WR_HARPOON(p_port + hp_scsisig,
6218 (SCSI_ACK + S_ILL_PH));
6219 ACCEPT_MSG(p_port);
6223 WRW_HARPOON((p_port + hp_intstat), CLR_ALL_INT_1);
6225 WR_HARPOON(p_port + hp_page_ctrl,
6226 (RD_HARPOON(p_port + hp_page_ctrl) &
6227 ~G_INT_DISABLE));
6229 return 1; /*Found one of them oldies! */
6233 /*---------------------------------------------------------------------
6235 * Function: FPT_scwtsel
6237 * Description: Wait to be selected by another SCAM initiator.
6239 *---------------------------------------------------------------------*/
6241 static void FPT_scwtsel(unsigned long p_port)
6243 while (!(RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL)) {
6247 /*---------------------------------------------------------------------
6249 * Function: FPT_inisci
6251 * Description: Setup the data Structure with the info from the EEPROM.
6253 *---------------------------------------------------------------------*/
6255 static void FPT_inisci(unsigned char p_card, unsigned long p_port,
6256 unsigned char p_our_id)
6258 unsigned char i, k, max_id;
6259 unsigned short ee_data;
6260 struct nvram_info *pCurrNvRam;
6262 pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
6264 if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6265 max_id = 0x08;
6267 else
6268 max_id = 0x10;
6270 if (pCurrNvRam) {
6271 for (i = 0; i < max_id; i++) {
6273 for (k = 0; k < 4; k++)
6274 FPT_scamInfo[i].id_string[k] =
6275 pCurrNvRam->niScamTbl[i][k];
6276 for (k = 4; k < ID_STRING_LENGTH; k++)
6277 FPT_scamInfo[i].id_string[k] =
6278 (unsigned char)0x00;
6280 if (FPT_scamInfo[i].id_string[0] == 0x00)
6281 FPT_scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */
6282 else
6283 FPT_scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */
6286 } else {
6287 for (i = 0; i < max_id; i++) {
6288 for (k = 0; k < ID_STRING_LENGTH; k += 2) {
6289 ee_data =
6290 FPT_utilEERead(p_port,
6291 (unsigned
6292 short)((EE_SCAMBASE / 2) +
6293 (unsigned short)(i *
6294 ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
6295 FPT_scamInfo[i].id_string[k] =
6296 (unsigned char)ee_data;
6297 ee_data >>= 8;
6298 FPT_scamInfo[i].id_string[k + 1] =
6299 (unsigned char)ee_data;
6302 if ((FPT_scamInfo[i].id_string[0] == 0x00) ||
6303 (FPT_scamInfo[i].id_string[0] == 0xFF))
6305 FPT_scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */
6307 else
6308 FPT_scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */
6312 for (k = 0; k < ID_STRING_LENGTH; k++)
6313 FPT_scamInfo[p_our_id].id_string[k] = FPT_scamHAString[k];
6317 /*---------------------------------------------------------------------
6319 * Function: FPT_scmachid
6321 * Description: Match the Device ID string with our values stored in
6322 * the EEPROM.
6324 *---------------------------------------------------------------------*/
6326 static unsigned char FPT_scmachid(unsigned char p_card,
6327 unsigned char p_id_string[])
6330 unsigned char i, k, match;
6332 for (i = 0; i < MAX_SCSI_TAR; i++) {
6334 match = 1;
6336 for (k = 0; k < ID_STRING_LENGTH; k++) {
6337 if (p_id_string[k] != FPT_scamInfo[i].id_string[k])
6338 match = 0;
6341 if (match) {
6342 FPT_scamInfo[i].state = ID_ASSIGNED;
6343 return i;
6348 if (p_id_string[0] & BIT(5))
6349 i = 8;
6350 else
6351 i = MAX_SCSI_TAR;
6353 if (((p_id_string[0] & 0x06) == 0x02)
6354 || ((p_id_string[0] & 0x06) == 0x04))
6355 match = p_id_string[1] & (unsigned char)0x1F;
6356 else
6357 match = 7;
6359 while (i > 0) {
6360 i--;
6362 if (FPT_scamInfo[match].state == ID_UNUSED) {
6363 for (k = 0; k < ID_STRING_LENGTH; k++) {
6364 FPT_scamInfo[match].id_string[k] =
6365 p_id_string[k];
6368 FPT_scamInfo[match].state = ID_ASSIGNED;
6370 if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
6371 FPT_BL_Card[p_card].globalFlags |=
6372 F_UPDATE_EEPROM;
6373 return match;
6377 match--;
6379 if (match == 0xFF) {
6380 if (p_id_string[0] & BIT(5))
6381 match = 7;
6382 else
6383 match = MAX_SCSI_TAR - 1;
6387 if (p_id_string[0] & BIT(7)) {
6388 return CLR_PRIORITY;
6391 if (p_id_string[0] & BIT(5))
6392 i = 8;
6393 else
6394 i = MAX_SCSI_TAR;
6396 if (((p_id_string[0] & 0x06) == 0x02)
6397 || ((p_id_string[0] & 0x06) == 0x04))
6398 match = p_id_string[1] & (unsigned char)0x1F;
6399 else
6400 match = 7;
6402 while (i > 0) {
6404 i--;
6406 if (FPT_scamInfo[match].state == ID_UNASSIGNED) {
6407 for (k = 0; k < ID_STRING_LENGTH; k++) {
6408 FPT_scamInfo[match].id_string[k] =
6409 p_id_string[k];
6412 FPT_scamInfo[match].id_string[0] |= BIT(7);
6413 FPT_scamInfo[match].state = ID_ASSIGNED;
6414 if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
6415 FPT_BL_Card[p_card].globalFlags |=
6416 F_UPDATE_EEPROM;
6417 return match;
6421 match--;
6423 if (match == 0xFF) {
6424 if (p_id_string[0] & BIT(5))
6425 match = 7;
6426 else
6427 match = MAX_SCSI_TAR - 1;
6431 return NO_ID_AVAIL;
6434 /*---------------------------------------------------------------------
6436 * Function: FPT_scsavdi
6438 * Description: Save off the device SCAM ID strings.
6440 *---------------------------------------------------------------------*/
6442 static void FPT_scsavdi(unsigned char p_card, unsigned long p_port)
6444 unsigned char i, k, max_id;
6445 unsigned short ee_data, sum_data;
6447 sum_data = 0x0000;
6449 for (i = 1; i < EE_SCAMBASE / 2; i++) {
6450 sum_data += FPT_utilEERead(p_port, i);
6453 FPT_utilEEWriteOnOff(p_port, 1); /* Enable write access to the EEPROM */
6455 if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6456 max_id = 0x08;
6458 else
6459 max_id = 0x10;
6461 for (i = 0; i < max_id; i++) {
6463 for (k = 0; k < ID_STRING_LENGTH; k += 2) {
6464 ee_data = FPT_scamInfo[i].id_string[k + 1];
6465 ee_data <<= 8;
6466 ee_data |= FPT_scamInfo[i].id_string[k];
6467 sum_data += ee_data;
6468 FPT_utilEEWrite(p_port, ee_data,
6469 (unsigned short)((EE_SCAMBASE / 2) +
6470 (unsigned short)(i *
6471 ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
6475 FPT_utilEEWrite(p_port, sum_data, EEPROM_CHECK_SUM / 2);
6476 FPT_utilEEWriteOnOff(p_port, 0); /* Turn off write access */
6479 /*---------------------------------------------------------------------
6481 * Function: FPT_XbowInit
6483 * Description: Setup the Xbow for normal operation.
6485 *---------------------------------------------------------------------*/
6487 static void FPT_XbowInit(unsigned long port, unsigned char ScamFlg)
6489 unsigned char i;
6491 i = RD_HARPOON(port + hp_page_ctrl);
6492 WR_HARPOON(port + hp_page_ctrl, (unsigned char)(i | G_INT_DISABLE));
6494 WR_HARPOON(port + hp_scsireset, 0x00);
6495 WR_HARPOON(port + hp_portctrl_1, HOST_MODE8);
6497 WR_HARPOON(port + hp_scsireset, (DMA_RESET | HPSCSI_RESET | PROG_RESET |
6498 FIFO_CLR));
6500 WR_HARPOON(port + hp_scsireset, SCSI_INI);
6502 WR_HARPOON(port + hp_clkctrl_0, CLKCTRL_DEFAULT);
6504 WR_HARPOON(port + hp_scsisig, 0x00); /* Clear any signals we might */
6505 WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
6507 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
6509 FPT_default_intena = RESET | RSEL | PROG_HLT | TIMEOUT |
6510 BUS_FREE | XFER_CNT_0 | AUTO_INT;
6512 if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2))
6513 FPT_default_intena |= SCAM_SEL;
6515 WRW_HARPOON((port + hp_intena), FPT_default_intena);
6517 WR_HARPOON(port + hp_seltimeout, TO_290ms);
6519 /* Turn on SCSI_MODE8 for narrow cards to fix the
6520 strapping issue with the DUAL CHANNEL card */
6521 if (RD_HARPOON(port + hp_page_ctrl) & NARROW_SCSI_CARD)
6522 WR_HARPOON(port + hp_addstat, SCSI_MODE8);
6524 WR_HARPOON(port + hp_page_ctrl, i);
6528 /*---------------------------------------------------------------------
6530 * Function: FPT_BusMasterInit
6532 * Description: Initialize the BusMaster for normal operations.
6534 *---------------------------------------------------------------------*/
6536 static void FPT_BusMasterInit(unsigned long p_port)
6539 WR_HARPOON(p_port + hp_sys_ctrl, DRVR_RST);
6540 WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
6542 WR_HARPOON(p_port + hp_host_blk_cnt, XFER_BLK64);
6544 WR_HARPOON(p_port + hp_bm_ctrl, (BMCTRL_DEFAULT));
6546 WR_HARPOON(p_port + hp_ee_ctrl, (SCSI_TERM_ENA_H));
6548 RD_HARPOON(p_port + hp_int_status); /*Clear interrupts. */
6549 WR_HARPOON(p_port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
6550 WR_HARPOON(p_port + hp_page_ctrl, (RD_HARPOON(p_port + hp_page_ctrl) &
6551 ~SCATTER_EN));
6554 /*---------------------------------------------------------------------
6556 * Function: FPT_DiagEEPROM
6558 * Description: Verfiy checksum and 'Key' and initialize the EEPROM if
6559 * necessary.
6561 *---------------------------------------------------------------------*/
6563 static void FPT_DiagEEPROM(unsigned long p_port)
6565 unsigned short index, temp, max_wd_cnt;
6567 if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6568 max_wd_cnt = EEPROM_WD_CNT;
6569 else
6570 max_wd_cnt = EEPROM_WD_CNT * 2;
6572 temp = FPT_utilEERead(p_port, FW_SIGNATURE / 2);
6574 if (temp == 0x4641) {
6576 for (index = 2; index < max_wd_cnt; index++) {
6578 temp += FPT_utilEERead(p_port, index);
6582 if (temp == FPT_utilEERead(p_port, EEPROM_CHECK_SUM / 2)) {
6584 return; /*EEPROM is Okay so return now! */
6588 FPT_utilEEWriteOnOff(p_port, (unsigned char)1);
6590 for (index = 0; index < max_wd_cnt; index++) {
6592 FPT_utilEEWrite(p_port, 0x0000, index);
6595 temp = 0;
6597 FPT_utilEEWrite(p_port, 0x4641, FW_SIGNATURE / 2);
6598 temp += 0x4641;
6599 FPT_utilEEWrite(p_port, 0x3920, MODEL_NUMB_0 / 2);
6600 temp += 0x3920;
6601 FPT_utilEEWrite(p_port, 0x3033, MODEL_NUMB_2 / 2);
6602 temp += 0x3033;
6603 FPT_utilEEWrite(p_port, 0x2020, MODEL_NUMB_4 / 2);
6604 temp += 0x2020;
6605 FPT_utilEEWrite(p_port, 0x70D3, SYSTEM_CONFIG / 2);
6606 temp += 0x70D3;
6607 FPT_utilEEWrite(p_port, 0x0010, BIOS_CONFIG / 2);
6608 temp += 0x0010;
6609 FPT_utilEEWrite(p_port, 0x0003, SCAM_CONFIG / 2);
6610 temp += 0x0003;
6611 FPT_utilEEWrite(p_port, 0x0007, ADAPTER_SCSI_ID / 2);
6612 temp += 0x0007;
6614 FPT_utilEEWrite(p_port, 0x0000, IGNORE_B_SCAN / 2);
6615 temp += 0x0000;
6616 FPT_utilEEWrite(p_port, 0x0000, SEND_START_ENA / 2);
6617 temp += 0x0000;
6618 FPT_utilEEWrite(p_port, 0x0000, DEVICE_ENABLE / 2);
6619 temp += 0x0000;
6621 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL01 / 2);
6622 temp += 0x4242;
6623 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL23 / 2);
6624 temp += 0x4242;
6625 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL45 / 2);
6626 temp += 0x4242;
6627 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL67 / 2);
6628 temp += 0x4242;
6629 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL89 / 2);
6630 temp += 0x4242;
6631 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLab / 2);
6632 temp += 0x4242;
6633 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLcd / 2);
6634 temp += 0x4242;
6635 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLef / 2);
6636 temp += 0x4242;
6638 FPT_utilEEWrite(p_port, 0x6C46, 64 / 2); /*PRODUCT ID */
6639 temp += 0x6C46;
6640 FPT_utilEEWrite(p_port, 0x7361, 66 / 2); /* FlashPoint LT */
6641 temp += 0x7361;
6642 FPT_utilEEWrite(p_port, 0x5068, 68 / 2);
6643 temp += 0x5068;
6644 FPT_utilEEWrite(p_port, 0x696F, 70 / 2);
6645 temp += 0x696F;
6646 FPT_utilEEWrite(p_port, 0x746E, 72 / 2);
6647 temp += 0x746E;
6648 FPT_utilEEWrite(p_port, 0x4C20, 74 / 2);
6649 temp += 0x4C20;
6650 FPT_utilEEWrite(p_port, 0x2054, 76 / 2);
6651 temp += 0x2054;
6652 FPT_utilEEWrite(p_port, 0x2020, 78 / 2);
6653 temp += 0x2020;
6655 index = ((EE_SCAMBASE / 2) + (7 * 16));
6656 FPT_utilEEWrite(p_port, (0x0700 + TYPE_CODE0), index);
6657 temp += (0x0700 + TYPE_CODE0);
6658 index++;
6659 FPT_utilEEWrite(p_port, 0x5542, index); /*Vendor ID code */
6660 temp += 0x5542; /* BUSLOGIC */
6661 index++;
6662 FPT_utilEEWrite(p_port, 0x4C53, index);
6663 temp += 0x4C53;
6664 index++;
6665 FPT_utilEEWrite(p_port, 0x474F, index);
6666 temp += 0x474F;
6667 index++;
6668 FPT_utilEEWrite(p_port, 0x4349, index);
6669 temp += 0x4349;
6670 index++;
6671 FPT_utilEEWrite(p_port, 0x5442, index); /*Vendor unique code */
6672 temp += 0x5442; /* BT- 930 */
6673 index++;
6674 FPT_utilEEWrite(p_port, 0x202D, index);
6675 temp += 0x202D;
6676 index++;
6677 FPT_utilEEWrite(p_port, 0x3339, index);
6678 temp += 0x3339;
6679 index++; /*Serial # */
6680 FPT_utilEEWrite(p_port, 0x2030, index); /* 01234567 */
6681 temp += 0x2030;
6682 index++;
6683 FPT_utilEEWrite(p_port, 0x5453, index);
6684 temp += 0x5453;
6685 index++;
6686 FPT_utilEEWrite(p_port, 0x5645, index);
6687 temp += 0x5645;
6688 index++;
6689 FPT_utilEEWrite(p_port, 0x2045, index);
6690 temp += 0x2045;
6691 index++;
6692 FPT_utilEEWrite(p_port, 0x202F, index);
6693 temp += 0x202F;
6694 index++;
6695 FPT_utilEEWrite(p_port, 0x4F4A, index);
6696 temp += 0x4F4A;
6697 index++;
6698 FPT_utilEEWrite(p_port, 0x204E, index);
6699 temp += 0x204E;
6700 index++;
6701 FPT_utilEEWrite(p_port, 0x3539, index);
6702 temp += 0x3539;
6704 FPT_utilEEWrite(p_port, temp, EEPROM_CHECK_SUM / 2);
6706 FPT_utilEEWriteOnOff(p_port, (unsigned char)0);
6710 /*---------------------------------------------------------------------
6712 * Function: Queue Search Select
6714 * Description: Try to find a new command to execute.
6716 *---------------------------------------------------------------------*/
6718 static void FPT_queueSearchSelect(struct sccb_card *pCurrCard,
6719 unsigned char p_card)
6721 unsigned char scan_ptr, lun;
6722 struct sccb_mgr_tar_info *currTar_Info;
6723 struct sccb *pOldSccb;
6725 scan_ptr = pCurrCard->scanIndex;
6726 do {
6727 currTar_Info = &FPT_sccbMgrTbl[p_card][scan_ptr];
6728 if ((pCurrCard->globalFlags & F_CONLUN_IO) &&
6729 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
6730 TAG_Q_TRYING)) {
6731 if (currTar_Info->TarSelQ_Cnt != 0) {
6733 scan_ptr++;
6734 if (scan_ptr == MAX_SCSI_TAR)
6735 scan_ptr = 0;
6737 for (lun = 0; lun < MAX_LUN; lun++) {
6738 if (currTar_Info->TarLUNBusy[lun] == 0) {
6740 pCurrCard->currentSCCB =
6741 currTar_Info->TarSelQ_Head;
6742 pOldSccb = NULL;
6744 while ((pCurrCard->
6745 currentSCCB != NULL)
6746 && (lun !=
6747 pCurrCard->
6748 currentSCCB->Lun)) {
6749 pOldSccb =
6750 pCurrCard->
6751 currentSCCB;
6752 pCurrCard->currentSCCB =
6753 (struct sccb
6754 *)(pCurrCard->
6755 currentSCCB)->
6756 Sccb_forwardlink;
6758 if (pCurrCard->currentSCCB ==
6759 NULL)
6760 continue;
6761 if (pOldSccb != NULL) {
6762 pOldSccb->
6763 Sccb_forwardlink =
6764 (struct sccb
6765 *)(pCurrCard->
6766 currentSCCB)->
6767 Sccb_forwardlink;
6768 pOldSccb->
6769 Sccb_backlink =
6770 (struct sccb
6771 *)(pCurrCard->
6772 currentSCCB)->
6773 Sccb_backlink;
6774 currTar_Info->
6775 TarSelQ_Cnt--;
6776 } else {
6777 currTar_Info->
6778 TarSelQ_Head =
6779 (struct sccb
6780 *)(pCurrCard->
6781 currentSCCB)->
6782 Sccb_forwardlink;
6784 if (currTar_Info->
6785 TarSelQ_Head ==
6786 NULL) {
6787 currTar_Info->
6788 TarSelQ_Tail
6789 = NULL;
6790 currTar_Info->
6791 TarSelQ_Cnt
6792 = 0;
6793 } else {
6794 currTar_Info->
6795 TarSelQ_Cnt--;
6796 currTar_Info->
6797 TarSelQ_Head->
6798 Sccb_backlink
6800 (struct sccb
6801 *)NULL;
6804 pCurrCard->scanIndex = scan_ptr;
6806 pCurrCard->globalFlags |=
6807 F_NEW_SCCB_CMD;
6809 break;
6814 else {
6815 scan_ptr++;
6816 if (scan_ptr == MAX_SCSI_TAR) {
6817 scan_ptr = 0;
6821 } else {
6822 if ((currTar_Info->TarSelQ_Cnt != 0) &&
6823 (currTar_Info->TarLUNBusy[0] == 0)) {
6825 pCurrCard->currentSCCB =
6826 currTar_Info->TarSelQ_Head;
6828 currTar_Info->TarSelQ_Head =
6829 (struct sccb *)(pCurrCard->currentSCCB)->
6830 Sccb_forwardlink;
6832 if (currTar_Info->TarSelQ_Head == NULL) {
6833 currTar_Info->TarSelQ_Tail = NULL;
6834 currTar_Info->TarSelQ_Cnt = 0;
6835 } else {
6836 currTar_Info->TarSelQ_Cnt--;
6837 currTar_Info->TarSelQ_Head->
6838 Sccb_backlink = (struct sccb *)NULL;
6841 scan_ptr++;
6842 if (scan_ptr == MAX_SCSI_TAR)
6843 scan_ptr = 0;
6845 pCurrCard->scanIndex = scan_ptr;
6847 pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
6849 break;
6852 else {
6853 scan_ptr++;
6854 if (scan_ptr == MAX_SCSI_TAR) {
6855 scan_ptr = 0;
6859 } while (scan_ptr != pCurrCard->scanIndex);
6862 /*---------------------------------------------------------------------
6864 * Function: Queue Select Fail
6866 * Description: Add the current SCCB to the head of the Queue.
6868 *---------------------------------------------------------------------*/
6870 static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
6871 unsigned char p_card)
6873 unsigned char thisTarg;
6874 struct sccb_mgr_tar_info *currTar_Info;
6876 if (pCurrCard->currentSCCB != NULL) {
6877 thisTarg =
6878 (unsigned char)(((struct sccb *)(pCurrCard->currentSCCB))->
6879 TargID);
6880 currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
6882 pCurrCard->currentSCCB->Sccb_backlink = (struct sccb *)NULL;
6884 pCurrCard->currentSCCB->Sccb_forwardlink =
6885 currTar_Info->TarSelQ_Head;
6887 if (currTar_Info->TarSelQ_Cnt == 0) {
6888 currTar_Info->TarSelQ_Tail = pCurrCard->currentSCCB;
6891 else {
6892 currTar_Info->TarSelQ_Head->Sccb_backlink =
6893 pCurrCard->currentSCCB;
6896 currTar_Info->TarSelQ_Head = pCurrCard->currentSCCB;
6898 pCurrCard->currentSCCB = NULL;
6899 currTar_Info->TarSelQ_Cnt++;
6903 /*---------------------------------------------------------------------
6905 * Function: Queue Command Complete
6907 * Description: Call the callback function with the current SCCB.
6909 *---------------------------------------------------------------------*/
6911 static void FPT_queueCmdComplete(struct sccb_card *pCurrCard,
6912 struct sccb *p_sccb, unsigned char p_card)
6915 unsigned char i, SCSIcmd;
6916 CALL_BK_FN callback;
6917 struct sccb_mgr_tar_info *currTar_Info;
6919 SCSIcmd = p_sccb->Cdb[0];
6921 if (!(p_sccb->Sccb_XferState & F_ALL_XFERRED)) {
6923 if ((p_sccb->
6924 ControlByte & (SCCB_DATA_XFER_OUT | SCCB_DATA_XFER_IN))
6925 && (p_sccb->HostStatus == SCCB_COMPLETE)
6926 && (p_sccb->TargetStatus != SSCHECK))
6928 if ((SCSIcmd == SCSI_READ) ||
6929 (SCSIcmd == SCSI_WRITE) ||
6930 (SCSIcmd == SCSI_READ_EXTENDED) ||
6931 (SCSIcmd == SCSI_WRITE_EXTENDED) ||
6932 (SCSIcmd == SCSI_WRITE_AND_VERIFY) ||
6933 (SCSIcmd == SCSI_START_STOP_UNIT) ||
6934 (pCurrCard->globalFlags & F_NO_FILTER)
6936 p_sccb->HostStatus = SCCB_DATA_UNDER_RUN;
6939 if (p_sccb->SccbStatus == SCCB_IN_PROCESS) {
6940 if (p_sccb->HostStatus || p_sccb->TargetStatus)
6941 p_sccb->SccbStatus = SCCB_ERROR;
6942 else
6943 p_sccb->SccbStatus = SCCB_SUCCESS;
6946 if (p_sccb->Sccb_XferState & F_AUTO_SENSE) {
6948 p_sccb->CdbLength = p_sccb->Save_CdbLen;
6949 for (i = 0; i < 6; i++) {
6950 p_sccb->Cdb[i] = p_sccb->Save_Cdb[i];
6954 if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) ||
6955 (p_sccb->OperationCode == RESIDUAL_COMMAND)) {
6957 FPT_utilUpdateResidual(p_sccb);
6960 pCurrCard->cmdCounter--;
6961 if (!pCurrCard->cmdCounter) {
6963 if (pCurrCard->globalFlags & F_GREEN_PC) {
6964 WR_HARPOON(pCurrCard->ioPort + hp_clkctrl_0,
6965 (PWR_DWN | CLKCTRL_DEFAULT));
6966 WR_HARPOON(pCurrCard->ioPort + hp_sys_ctrl, STOP_CLK);
6969 WR_HARPOON(pCurrCard->ioPort + hp_semaphore,
6970 (RD_HARPOON(pCurrCard->ioPort + hp_semaphore) &
6971 ~SCCB_MGR_ACTIVE));
6975 if (pCurrCard->discQCount != 0) {
6976 currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
6977 if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
6978 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
6979 TAG_Q_TRYING))) {
6980 pCurrCard->discQCount--;
6981 pCurrCard->discQ_Tbl[currTar_Info->
6982 LunDiscQ_Idx[p_sccb->Lun]] = NULL;
6983 } else {
6984 if (p_sccb->Sccb_tag) {
6985 pCurrCard->discQCount--;
6986 pCurrCard->discQ_Tbl[p_sccb->Sccb_tag] = NULL;
6987 } else {
6988 pCurrCard->discQCount--;
6989 pCurrCard->discQ_Tbl[currTar_Info->
6990 LunDiscQ_Idx[0]] = NULL;
6996 callback = (CALL_BK_FN) p_sccb->SccbCallback;
6997 callback(p_sccb);
6998 pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
6999 pCurrCard->currentSCCB = NULL;
7002 /*---------------------------------------------------------------------
7004 * Function: Queue Disconnect
7006 * Description: Add SCCB to our disconnect array.
7008 *---------------------------------------------------------------------*/
7009 static void FPT_queueDisconnect(struct sccb *p_sccb, unsigned char p_card)
7011 struct sccb_mgr_tar_info *currTar_Info;
7013 currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
7015 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
7016 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
7017 FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
7018 LunDiscQ_Idx[p_sccb->Lun]] =
7019 p_sccb;
7020 } else {
7021 if (p_sccb->Sccb_tag) {
7022 FPT_BL_Card[p_card].discQ_Tbl[p_sccb->Sccb_tag] =
7023 p_sccb;
7024 FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarLUNBusy[0] =
7026 FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarTagQ_Cnt++;
7027 } else {
7028 FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
7029 LunDiscQ_Idx[0]] = p_sccb;
7032 FPT_BL_Card[p_card].currentSCCB = NULL;
7035 /*---------------------------------------------------------------------
7037 * Function: Queue Flush SCCB
7039 * Description: Flush all SCCB's back to the host driver for this target.
7041 *---------------------------------------------------------------------*/
7043 static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code)
7045 unsigned char qtag, thisTarg;
7046 struct sccb *currSCCB;
7047 struct sccb_mgr_tar_info *currTar_Info;
7049 currSCCB = FPT_BL_Card[p_card].currentSCCB;
7050 if (currSCCB != NULL) {
7051 thisTarg = (unsigned char)currSCCB->TargID;
7052 currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
7054 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
7056 if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
7057 (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
7058 thisTarg)) {
7060 FPT_BL_Card[p_card].discQ_Tbl[qtag]->
7061 HostStatus = (unsigned char)error_code;
7063 FPT_queueCmdComplete(&FPT_BL_Card[p_card],
7064 FPT_BL_Card[p_card].
7065 discQ_Tbl[qtag], p_card);
7067 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
7068 currTar_Info->TarTagQ_Cnt--;
7076 /*---------------------------------------------------------------------
7078 * Function: Queue Flush Target SCCB
7080 * Description: Flush all SCCB's back to the host driver for this target.
7082 *---------------------------------------------------------------------*/
7084 static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
7085 unsigned char error_code)
7087 unsigned char qtag;
7088 struct sccb_mgr_tar_info *currTar_Info;
7090 currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
7092 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
7094 if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
7095 (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg)) {
7097 FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus =
7098 (unsigned char)error_code;
7100 FPT_queueCmdComplete(&FPT_BL_Card[p_card],
7101 FPT_BL_Card[p_card].
7102 discQ_Tbl[qtag], p_card);
7104 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
7105 currTar_Info->TarTagQ_Cnt--;
7112 static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char p_card)
7114 struct sccb_mgr_tar_info *currTar_Info;
7115 currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
7117 p_SCCB->Sccb_forwardlink = NULL;
7119 p_SCCB->Sccb_backlink = currTar_Info->TarSelQ_Tail;
7121 if (currTar_Info->TarSelQ_Cnt == 0) {
7123 currTar_Info->TarSelQ_Head = p_SCCB;
7126 else {
7128 currTar_Info->TarSelQ_Tail->Sccb_forwardlink = p_SCCB;
7131 currTar_Info->TarSelQ_Tail = p_SCCB;
7132 currTar_Info->TarSelQ_Cnt++;
7135 /*---------------------------------------------------------------------
7137 * Function: Queue Find SCCB
7139 * Description: Search the target select Queue for this SCCB, and
7140 * remove it if found.
7142 *---------------------------------------------------------------------*/
7144 static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB,
7145 unsigned char p_card)
7147 struct sccb *q_ptr;
7148 struct sccb_mgr_tar_info *currTar_Info;
7150 currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
7152 q_ptr = currTar_Info->TarSelQ_Head;
7154 while (q_ptr != NULL) {
7156 if (q_ptr == p_SCCB) {
7158 if (currTar_Info->TarSelQ_Head == q_ptr) {
7160 currTar_Info->TarSelQ_Head =
7161 q_ptr->Sccb_forwardlink;
7164 if (currTar_Info->TarSelQ_Tail == q_ptr) {
7166 currTar_Info->TarSelQ_Tail =
7167 q_ptr->Sccb_backlink;
7170 if (q_ptr->Sccb_forwardlink != NULL) {
7171 q_ptr->Sccb_forwardlink->Sccb_backlink =
7172 q_ptr->Sccb_backlink;
7175 if (q_ptr->Sccb_backlink != NULL) {
7176 q_ptr->Sccb_backlink->Sccb_forwardlink =
7177 q_ptr->Sccb_forwardlink;
7180 currTar_Info->TarSelQ_Cnt--;
7182 return 1;
7185 else {
7186 q_ptr = q_ptr->Sccb_forwardlink;
7190 return 0;
7194 /*---------------------------------------------------------------------
7196 * Function: Utility Update Residual Count
7198 * Description: Update the XferCnt to the remaining byte count.
7199 * If we transferred all the data then just write zero.
7200 * If Non-SG transfer then report Total Cnt - Actual Transfer
7201 * Cnt. For SG transfers add the count fields of all
7202 * remaining SG elements, as well as any partial remaining
7203 * element.
7205 *---------------------------------------------------------------------*/
7207 static void FPT_utilUpdateResidual(struct sccb *p_SCCB)
7209 unsigned long partial_cnt;
7210 unsigned int sg_index;
7211 unsigned long *sg_ptr;
7213 if (p_SCCB->Sccb_XferState & F_ALL_XFERRED) {
7215 p_SCCB->DataLength = 0x0000;
7218 else if (p_SCCB->Sccb_XferState & F_SG_XFER) {
7220 partial_cnt = 0x0000;
7222 sg_index = p_SCCB->Sccb_sgseg;
7224 sg_ptr = (unsigned long *)p_SCCB->DataPointer;
7226 if (p_SCCB->Sccb_SGoffset) {
7228 partial_cnt = p_SCCB->Sccb_SGoffset;
7229 sg_index++;
7232 while (((unsigned long)sg_index *
7233 (unsigned long)SG_ELEMENT_SIZE) < p_SCCB->DataLength) {
7235 partial_cnt += *(sg_ptr + (sg_index * 2));
7236 sg_index++;
7239 p_SCCB->DataLength = partial_cnt;
7242 else {
7244 p_SCCB->DataLength -= p_SCCB->Sccb_ATC;
7248 /*---------------------------------------------------------------------
7250 * Function: Wait 1 Second
7252 * Description: Wait for 1 second.
7254 *---------------------------------------------------------------------*/
7256 static void FPT_Wait1Second(unsigned long p_port)
7258 unsigned char i;
7260 for (i = 0; i < 4; i++) {
7262 FPT_Wait(p_port, TO_250ms);
7264 if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
7265 break;
7267 if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
7268 break;
7272 /*---------------------------------------------------------------------
7274 * Function: FPT_Wait
7276 * Description: Wait the desired delay.
7278 *---------------------------------------------------------------------*/
7280 static void FPT_Wait(unsigned long p_port, unsigned char p_delay)
7282 unsigned char old_timer;
7283 unsigned char green_flag;
7285 old_timer = RD_HARPOON(p_port + hp_seltimeout);
7287 green_flag = RD_HARPOON(p_port + hp_clkctrl_0);
7288 WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
7290 WR_HARPOON(p_port + hp_seltimeout, p_delay);
7291 WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
7292 WRW_HARPOON((p_port + hp_intena), (FPT_default_intena & ~TIMEOUT));
7294 WR_HARPOON(p_port + hp_portctrl_0,
7295 (RD_HARPOON(p_port + hp_portctrl_0) | START_TO));
7297 while (!(RDW_HARPOON((p_port + hp_intstat)) & TIMEOUT)) {
7299 if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
7300 break;
7302 if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
7303 break;
7306 WR_HARPOON(p_port + hp_portctrl_0,
7307 (RD_HARPOON(p_port + hp_portctrl_0) & ~START_TO));
7309 WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
7310 WRW_HARPOON((p_port + hp_intena), FPT_default_intena);
7312 WR_HARPOON(p_port + hp_clkctrl_0, green_flag);
7314 WR_HARPOON(p_port + hp_seltimeout, old_timer);
7317 /*---------------------------------------------------------------------
7319 * Function: Enable/Disable Write to EEPROM
7321 * Description: The EEPROM must first be enabled for writes
7322 * A total of 9 clocks are needed.
7324 *---------------------------------------------------------------------*/
7326 static void FPT_utilEEWriteOnOff(unsigned long p_port, unsigned char p_mode)
7328 unsigned char ee_value;
7330 ee_value =
7331 (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
7332 (EXT_ARB_ACK | SCSI_TERM_ENA_H));
7334 if (p_mode)
7336 FPT_utilEESendCmdAddr(p_port, EWEN, EWEN_ADDR);
7338 else
7340 FPT_utilEESendCmdAddr(p_port, EWDS, EWDS_ADDR);
7342 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */
7343 WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /*Turn off Master Select */
7346 /*---------------------------------------------------------------------
7348 * Function: Write EEPROM
7350 * Description: Write a word to the EEPROM at the specified
7351 * address.
7353 *---------------------------------------------------------------------*/
7355 static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data,
7356 unsigned short ee_addr)
7359 unsigned char ee_value;
7360 unsigned short i;
7362 ee_value =
7363 (unsigned
7364 char)((RD_HARPOON(p_port + hp_ee_ctrl) &
7365 (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
7367 FPT_utilEESendCmdAddr(p_port, EE_WRITE, ee_addr);
7369 ee_value |= (SEE_MS + SEE_CS);
7371 for (i = 0x8000; i != 0; i >>= 1) {
7373 if (i & ee_data)
7374 ee_value |= SEE_DO;
7375 else
7376 ee_value &= ~SEE_DO;
7378 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7379 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7380 ee_value |= SEE_CLK; /* Clock data! */
7381 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7382 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7383 ee_value &= ~SEE_CLK;
7384 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7385 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7387 ee_value &= (EXT_ARB_ACK | SCSI_TERM_ENA_H);
7388 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));
7390 FPT_Wait(p_port, TO_10ms);
7392 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS | SEE_CS)); /* Set CS to EEPROM */
7393 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /* Turn off CS */
7394 WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /* Turn off Master Select */
7397 /*---------------------------------------------------------------------
7399 * Function: Read EEPROM
7401 * Description: Read a word from the EEPROM at the desired
7402 * address.
7404 *---------------------------------------------------------------------*/
7406 static unsigned short FPT_utilEERead(unsigned long p_port,
7407 unsigned short ee_addr)
7409 unsigned short i, ee_data1, ee_data2;
7411 i = 0;
7412 ee_data1 = FPT_utilEEReadOrg(p_port, ee_addr);
7413 do {
7414 ee_data2 = FPT_utilEEReadOrg(p_port, ee_addr);
7416 if (ee_data1 == ee_data2)
7417 return ee_data1;
7419 ee_data1 = ee_data2;
7420 i++;
7422 } while (i < 4);
7424 return ee_data1;
7427 /*---------------------------------------------------------------------
7429 * Function: Read EEPROM Original
7431 * Description: Read a word from the EEPROM at the desired
7432 * address.
7434 *---------------------------------------------------------------------*/
7436 static unsigned short FPT_utilEEReadOrg(unsigned long p_port,
7437 unsigned short ee_addr)
7440 unsigned char ee_value;
7441 unsigned short i, ee_data;
7443 ee_value =
7444 (unsigned
7445 char)((RD_HARPOON(p_port + hp_ee_ctrl) &
7446 (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
7448 FPT_utilEESendCmdAddr(p_port, EE_READ, ee_addr);
7450 ee_value |= (SEE_MS + SEE_CS);
7451 ee_data = 0;
7453 for (i = 1; i <= 16; i++) {
7455 ee_value |= SEE_CLK; /* Clock data! */
7456 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7457 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7458 ee_value &= ~SEE_CLK;
7459 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7460 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7462 ee_data <<= 1;
7464 if (RD_HARPOON(p_port + hp_ee_ctrl) & SEE_DI)
7465 ee_data |= 1;
7468 ee_value &= ~(SEE_MS + SEE_CS);
7469 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */
7470 WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /*Turn off Master Select */
7472 return ee_data;
7475 /*---------------------------------------------------------------------
7477 * Function: Send EE command and Address to the EEPROM
7479 * Description: Transfers the correct command and sends the address
7480 * to the eeprom.
7482 *---------------------------------------------------------------------*/
7484 static void FPT_utilEESendCmdAddr(unsigned long p_port, unsigned char ee_cmd,
7485 unsigned short ee_addr)
7487 unsigned char ee_value;
7488 unsigned char narrow_flg;
7490 unsigned short i;
7492 narrow_flg =
7493 (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
7494 NARROW_SCSI_CARD);
7496 ee_value = SEE_MS;
7497 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7499 ee_value |= SEE_CS; /* Set CS to EEPROM */
7500 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7502 for (i = 0x04; i != 0; i >>= 1) {
7504 if (i & ee_cmd)
7505 ee_value |= SEE_DO;
7506 else
7507 ee_value &= ~SEE_DO;
7509 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7510 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7511 ee_value |= SEE_CLK; /* Clock data! */
7512 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7513 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7514 ee_value &= ~SEE_CLK;
7515 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7516 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7519 if (narrow_flg)
7520 i = 0x0080;
7522 else
7523 i = 0x0200;
7525 while (i != 0) {
7527 if (i & ee_addr)
7528 ee_value |= SEE_DO;
7529 else
7530 ee_value &= ~SEE_DO;
7532 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7533 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7534 ee_value |= SEE_CLK; /* Clock data! */
7535 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7536 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7537 ee_value &= ~SEE_CLK;
7538 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7539 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7541 i >>= 1;
7545 static unsigned short FPT_CalcCrc16(unsigned char buffer[])
7547 unsigned short crc = 0;
7548 int i, j;
7549 unsigned short ch;
7550 for (i = 0; i < ID_STRING_LENGTH; i++) {
7551 ch = (unsigned short)buffer[i];
7552 for (j = 0; j < 8; j++) {
7553 if ((crc ^ ch) & 1)
7554 crc = (crc >> 1) ^ CRCMASK;
7555 else
7556 crc >>= 1;
7557 ch >>= 1;
7560 return crc;
7563 static unsigned char FPT_CalcLrc(unsigned char buffer[])
7565 int i;
7566 unsigned char lrc;
7567 lrc = 0;
7568 for (i = 0; i < ID_STRING_LENGTH; i++)
7569 lrc ^= buffer[i];
7570 return lrc;
7574 The following inline definitions avoid type conflicts.
7577 static inline unsigned char
7578 FlashPoint__ProbeHostAdapter(struct FlashPoint_Info *FlashPointInfo)
7580 return FlashPoint_ProbeHostAdapter((struct sccb_mgr_info *)
7581 FlashPointInfo);
7584 static inline FlashPoint_CardHandle_T
7585 FlashPoint__HardwareResetHostAdapter(struct FlashPoint_Info *FlashPointInfo)
7587 return FlashPoint_HardwareResetHostAdapter((struct sccb_mgr_info *)
7588 FlashPointInfo);
7591 static inline void
7592 FlashPoint__ReleaseHostAdapter(FlashPoint_CardHandle_T CardHandle)
7594 FlashPoint_ReleaseHostAdapter(CardHandle);
7597 static inline void
7598 FlashPoint__StartCCB(FlashPoint_CardHandle_T CardHandle,
7599 struct BusLogic_CCB *CCB)
7601 FlashPoint_StartCCB(CardHandle, (struct sccb *)CCB);
7604 static inline void
7605 FlashPoint__AbortCCB(FlashPoint_CardHandle_T CardHandle,
7606 struct BusLogic_CCB *CCB)
7608 FlashPoint_AbortCCB(CardHandle, (struct sccb *)CCB);
7611 static inline bool
7612 FlashPoint__InterruptPending(FlashPoint_CardHandle_T CardHandle)
7614 return FlashPoint_InterruptPending(CardHandle);
7617 static inline int
7618 FlashPoint__HandleInterrupt(FlashPoint_CardHandle_T CardHandle)
7620 return FlashPoint_HandleInterrupt(CardHandle);
7623 #define FlashPoint_ProbeHostAdapter FlashPoint__ProbeHostAdapter
7624 #define FlashPoint_HardwareResetHostAdapter FlashPoint__HardwareResetHostAdapter
7625 #define FlashPoint_ReleaseHostAdapter FlashPoint__ReleaseHostAdapter
7626 #define FlashPoint_StartCCB FlashPoint__StartCCB
7627 #define FlashPoint_AbortCCB FlashPoint__AbortCCB
7628 #define FlashPoint_InterruptPending FlashPoint__InterruptPending
7629 #define FlashPoint_HandleInterrupt FlashPoint__HandleInterrupt
7631 #else /* CONFIG_SCSI_OMIT_FLASHPOINT */
7634 Define prototypes for the FlashPoint SCCB Manager Functions.
7637 extern unsigned char FlashPoint_ProbeHostAdapter(struct FlashPoint_Info *);
7638 extern FlashPoint_CardHandle_T
7639 FlashPoint_HardwareResetHostAdapter(struct FlashPoint_Info *);
7640 extern void FlashPoint_StartCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *);
7641 extern int FlashPoint_AbortCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *);
7642 extern bool FlashPoint_InterruptPending(FlashPoint_CardHandle_T);
7643 extern int FlashPoint_HandleInterrupt(FlashPoint_CardHandle_T);
7644 extern void FlashPoint_ReleaseHostAdapter(FlashPoint_CardHandle_T);
7646 #endif /* CONFIG_SCSI_OMIT_FLASHPOINT */