mmc: add bus handler
[linux-2.6/pdupreez.git] / drivers / scsi / FlashPoint.c
bloba7f916c0c9cdcc618476eecf3dcca083065d8d9c
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 BIT(x) ((unsigned char)(1<<(x))) /* single-bit mask in bit position x */
29 #define BITW(x) ((unsigned short)(1<<(x))) /* single-bit mask in bit position x */
31 struct sccb;
32 typedef void (*CALL_BK_FN) (struct sccb *);
34 struct sccb_mgr_info {
35 unsigned long si_baseaddr;
36 unsigned char si_present;
37 unsigned char si_intvect;
38 unsigned char si_id;
39 unsigned char si_lun;
40 unsigned short si_fw_revision;
41 unsigned short si_per_targ_init_sync;
42 unsigned short si_per_targ_fast_nego;
43 unsigned short si_per_targ_ultra_nego;
44 unsigned short si_per_targ_no_disc;
45 unsigned short si_per_targ_wide_nego;
46 unsigned short si_flags;
47 unsigned char si_card_family;
48 unsigned char si_bustype;
49 unsigned char si_card_model[3];
50 unsigned char si_relative_cardnum;
51 unsigned char si_reserved[4];
52 unsigned long si_OS_reserved;
53 unsigned char si_XlatInfo[4];
54 unsigned long si_reserved2[5];
55 unsigned long si_secondary_range;
58 #define SCSI_PARITY_ENA 0x0001
59 #define LOW_BYTE_TERM 0x0010
60 #define HIGH_BYTE_TERM 0x0020
61 #define BUSTYPE_PCI 0x3
63 #define SUPPORT_16TAR_32LUN 0x0002
64 #define SOFT_RESET 0x0004
65 #define EXTENDED_TRANSLATION 0x0008
66 #define POST_ALL_UNDERRRUNS 0x0040
67 #define FLAG_SCAM_ENABLED 0x0080
68 #define FLAG_SCAM_LEVEL2 0x0100
70 #define HARPOON_FAMILY 0x02
72 /* SCCB struct used for both SCCB and UCB manager compiles!
73 * The UCB Manager treats the SCCB as it's 'native hardware structure'
76 #pragma pack(1)
77 struct sccb {
78 unsigned char OperationCode;
79 unsigned char ControlByte;
80 unsigned char CdbLength;
81 unsigned char RequestSenseLength;
82 unsigned long DataLength;
83 unsigned long DataPointer;
84 unsigned char CcbRes[2];
85 unsigned char HostStatus;
86 unsigned char TargetStatus;
87 unsigned char TargID;
88 unsigned char Lun;
89 unsigned char Cdb[12];
90 unsigned char CcbRes1;
91 unsigned char Reserved1;
92 unsigned long Reserved2;
93 unsigned long SensePointer;
95 CALL_BK_FN SccbCallback; /* VOID (*SccbCallback)(); */
96 unsigned long SccbIOPort; /* Identifies board base port */
97 unsigned char SccbStatus;
98 unsigned char SCCBRes2;
99 unsigned short SccbOSFlags;
101 unsigned long Sccb_XferCnt; /* actual transfer count */
102 unsigned long Sccb_ATC;
103 unsigned long SccbVirtDataPtr; /* virtual addr for OS/2 */
104 unsigned long Sccb_res1;
105 unsigned short Sccb_MGRFlags;
106 unsigned short Sccb_sgseg;
107 unsigned char Sccb_scsimsg; /* identify msg for selection */
108 unsigned char Sccb_tag;
109 unsigned char Sccb_scsistat;
110 unsigned char Sccb_idmsg; /* image of last msg in */
111 struct sccb *Sccb_forwardlink;
112 struct sccb *Sccb_backlink;
113 unsigned long Sccb_savedATC;
114 unsigned char Save_Cdb[6];
115 unsigned char Save_CdbLen;
116 unsigned char Sccb_XferState;
117 unsigned long Sccb_SGoffset;
120 #pragma pack()
122 #define SCATTER_GATHER_COMMAND 0x02
123 #define RESIDUAL_COMMAND 0x03
124 #define RESIDUAL_SG_COMMAND 0x04
125 #define RESET_COMMAND 0x81
127 #define F_USE_CMD_Q 0x20 /*Inidcates TAGGED command. */
128 #define TAG_TYPE_MASK 0xC0 /*Type of tag msg to send. */
129 #define SCCB_DATA_XFER_OUT 0x10 /* Write */
130 #define SCCB_DATA_XFER_IN 0x08 /* Read */
132 #define NO_AUTO_REQUEST_SENSE 0x01 /* No Request Sense Buffer */
134 #define BUS_FREE_ST 0
135 #define SELECT_ST 1
136 #define SELECT_BDR_ST 2 /* Select w\ Bus Device Reset */
137 #define SELECT_SN_ST 3 /* Select w\ Sync Nego */
138 #define SELECT_WN_ST 4 /* Select w\ Wide Data Nego */
139 #define SELECT_Q_ST 5 /* Select w\ Tagged Q'ing */
140 #define COMMAND_ST 6
141 #define DATA_OUT_ST 7
142 #define DATA_IN_ST 8
143 #define DISCONNECT_ST 9
144 #define ABORT_ST 11
146 #define F_HOST_XFER_DIR 0x01
147 #define F_ALL_XFERRED 0x02
148 #define F_SG_XFER 0x04
149 #define F_AUTO_SENSE 0x08
150 #define F_ODD_BALL_CNT 0x10
151 #define F_NO_DATA_YET 0x80
153 #define F_STATUSLOADED 0x01
154 #define F_DEV_SELECTED 0x04
156 #define SCCB_COMPLETE 0x00 /* SCCB completed without error */
157 #define SCCB_DATA_UNDER_RUN 0x0C
158 #define SCCB_SELECTION_TIMEOUT 0x11 /* Set SCSI selection timed out */
159 #define SCCB_DATA_OVER_RUN 0x12
160 #define SCCB_PHASE_SEQUENCE_FAIL 0x14 /* Target bus phase sequence failure */
162 #define SCCB_GROSS_FW_ERR 0x27 /* Major problem! */
163 #define SCCB_BM_ERR 0x30 /* BusMaster error. */
164 #define SCCB_PARITY_ERR 0x34 /* SCSI parity error */
166 #define SCCB_IN_PROCESS 0x00
167 #define SCCB_SUCCESS 0x01
168 #define SCCB_ABORT 0x02
169 #define SCCB_ERROR 0x04
171 #define ORION_FW_REV 3110
173 #define QUEUE_DEPTH 254+1 /*1 for Normal disconnect 32 for Q'ing. */
175 #define MAX_MB_CARDS 4 /* Max. no of cards suppoerted on Mother Board */
177 #define MAX_SCSI_TAR 16
178 #define MAX_LUN 32
179 #define LUN_MASK 0x1f
181 #define SG_BUF_CNT 16 /*Number of prefetched elements. */
183 #define SG_ELEMENT_SIZE 8 /*Eight byte per element. */
185 #define RD_HARPOON(ioport) inb((u32)ioport)
186 #define RDW_HARPOON(ioport) inw((u32)ioport)
187 #define RD_HARP32(ioport,offset,data) (data = inl((u32)(ioport + offset)))
188 #define WR_HARPOON(ioport,val) outb((u8) val, (u32)ioport)
189 #define WRW_HARPOON(ioport,val) outw((u16)val, (u32)ioport)
190 #define WR_HARP32(ioport,offset,data) outl(data, (u32)(ioport + offset))
192 #define TAR_SYNC_MASK (BIT(7)+BIT(6))
193 #define SYNC_TRYING BIT(6)
194 #define SYNC_SUPPORTED (BIT(7)+BIT(6))
196 #define TAR_WIDE_MASK (BIT(5)+BIT(4))
197 #define WIDE_ENABLED BIT(4)
198 #define WIDE_NEGOCIATED BIT(5)
200 #define TAR_TAG_Q_MASK (BIT(3)+BIT(2))
201 #define TAG_Q_TRYING BIT(2)
202 #define TAG_Q_REJECT BIT(3)
204 #define TAR_ALLOW_DISC BIT(0)
206 #define EE_SYNC_MASK (BIT(0)+BIT(1))
207 #define EE_SYNC_5MB BIT(0)
208 #define EE_SYNC_10MB BIT(1)
209 #define EE_SYNC_20MB (BIT(0)+BIT(1))
211 #define EE_WIDE_SCSI BIT(7)
213 struct sccb_mgr_tar_info {
215 struct sccb *TarSelQ_Head;
216 struct sccb *TarSelQ_Tail;
217 unsigned char TarLUN_CA; /*Contingent Allgiance */
218 unsigned char TarTagQ_Cnt;
219 unsigned char TarSelQ_Cnt;
220 unsigned char TarStatus;
221 unsigned char TarEEValue;
222 unsigned char TarSyncCtrl;
223 unsigned char TarReserved[2]; /* for alignment */
224 unsigned char LunDiscQ_Idx[MAX_LUN];
225 unsigned char TarLUNBusy[MAX_LUN];
228 struct nvram_info {
229 unsigned char niModel; /* Model No. of card */
230 unsigned char niCardNo; /* Card no. */
231 unsigned long niBaseAddr; /* Port Address of card */
232 unsigned char niSysConf; /* Adapter Configuration byte - Byte 16 of eeprom map */
233 unsigned char niScsiConf; /* SCSI Configuration byte - Byte 17 of eeprom map */
234 unsigned char niScamConf; /* SCAM Configuration byte - Byte 20 of eeprom map */
235 unsigned char niAdapId; /* Host Adapter ID - Byte 24 of eerpom map */
236 unsigned char niSyncTbl[MAX_SCSI_TAR / 2]; /* Sync/Wide byte of targets */
237 unsigned char niScamTbl[MAX_SCSI_TAR][4]; /* Compressed Scam name string of Targets */
240 #define MODEL_LT 1
241 #define MODEL_DL 2
242 #define MODEL_LW 3
243 #define MODEL_DW 4
245 struct sccb_card {
246 struct sccb *currentSCCB;
247 struct sccb_mgr_info *cardInfo;
249 unsigned long ioPort;
251 unsigned short cmdCounter;
252 unsigned char discQCount;
253 unsigned char tagQ_Lst;
254 unsigned char cardIndex;
255 unsigned char scanIndex;
256 unsigned char globalFlags;
257 unsigned char ourId;
258 struct nvram_info *pNvRamInfo;
259 struct sccb *discQ_Tbl[QUEUE_DEPTH];
263 #define F_TAG_STARTED 0x01
264 #define F_CONLUN_IO 0x02
265 #define F_DO_RENEGO 0x04
266 #define F_NO_FILTER 0x08
267 #define F_GREEN_PC 0x10
268 #define F_HOST_XFER_ACT 0x20
269 #define F_NEW_SCCB_CMD 0x40
270 #define F_UPDATE_EEPROM 0x80
272 #define ID_STRING_LENGTH 32
273 #define TYPE_CODE0 0x63 /*Level2 Mstr (bits 7-6), */
275 #define SLV_TYPE_CODE0 0xA3 /*Priority Bit set (bits 7-6), */
277 #define ASSIGN_ID 0x00
278 #define SET_P_FLAG 0x01
279 #define CFG_CMPLT 0x03
280 #define DOM_MSTR 0x0F
281 #define SYNC_PTRN 0x1F
283 #define ID_0_7 0x18
284 #define ID_8_F 0x11
285 #define MISC_CODE 0x14
286 #define CLR_P_FLAG 0x18
288 #define INIT_SELTD 0x01
289 #define LEVEL2_TAR 0x02
291 enum scam_id_st { ID0, ID1, ID2, ID3, ID4, ID5, ID6, ID7, ID8, ID9, ID10, ID11,
292 ID12,
293 ID13, ID14, ID15, ID_UNUSED, ID_UNASSIGNED, ID_ASSIGNED, LEGACY,
294 CLR_PRIORITY, NO_ID_AVAIL
297 typedef struct SCCBscam_info {
299 unsigned char id_string[ID_STRING_LENGTH];
300 enum scam_id_st state;
302 } SCCBSCAM_INFO;
304 #define SCSI_REQUEST_SENSE 0x03
305 #define SCSI_READ 0x08
306 #define SCSI_WRITE 0x0A
307 #define SCSI_START_STOP_UNIT 0x1B
308 #define SCSI_READ_EXTENDED 0x28
309 #define SCSI_WRITE_EXTENDED 0x2A
310 #define SCSI_WRITE_AND_VERIFY 0x2E
312 #define SSGOOD 0x00
313 #define SSCHECK 0x02
314 #define SSQ_FULL 0x28
316 #define SMCMD_COMP 0x00
317 #define SMEXT 0x01
318 #define SMSAVE_DATA_PTR 0x02
319 #define SMREST_DATA_PTR 0x03
320 #define SMDISC 0x04
321 #define SMABORT 0x06
322 #define SMREJECT 0x07
323 #define SMNO_OP 0x08
324 #define SMPARITY 0x09
325 #define SMDEV_RESET 0x0C
326 #define SMABORT_TAG 0x0D
327 #define SMINIT_RECOVERY 0x0F
328 #define SMREL_RECOVERY 0x10
330 #define SMIDENT 0x80
331 #define DISC_PRIV 0x40
333 #define SMSYNC 0x01
334 #define SMWDTR 0x03
335 #define SM8BIT 0x00
336 #define SM16BIT 0x01
337 #define SMIGNORWR 0x23 /* Ignore Wide Residue */
339 #define SIX_BYTE_CMD 0x06
340 #define TWELVE_BYTE_CMD 0x0C
342 #define ASYNC 0x00
343 #define MAX_OFFSET 0x0F /* Maxbyteoffset for Sync Xfers */
345 #define EEPROM_WD_CNT 256
347 #define EEPROM_CHECK_SUM 0
348 #define FW_SIGNATURE 2
349 #define MODEL_NUMB_0 4
350 #define MODEL_NUMB_2 6
351 #define MODEL_NUMB_4 8
352 #define SYSTEM_CONFIG 16
353 #define SCSI_CONFIG 17
354 #define BIOS_CONFIG 18
355 #define SCAM_CONFIG 20
356 #define ADAPTER_SCSI_ID 24
358 #define IGNORE_B_SCAN 32
359 #define SEND_START_ENA 34
360 #define DEVICE_ENABLE 36
362 #define SYNC_RATE_TBL 38
363 #define SYNC_RATE_TBL01 38
364 #define SYNC_RATE_TBL23 40
365 #define SYNC_RATE_TBL45 42
366 #define SYNC_RATE_TBL67 44
367 #define SYNC_RATE_TBL89 46
368 #define SYNC_RATE_TBLab 48
369 #define SYNC_RATE_TBLcd 50
370 #define SYNC_RATE_TBLef 52
372 #define EE_SCAMBASE 256
374 #define SCAM_ENABLED BIT(2)
375 #define SCAM_LEVEL2 BIT(3)
377 #define RENEGO_ENA BITW(10)
378 #define CONNIO_ENA BITW(11)
379 #define GREEN_PC_ENA BITW(12)
381 #define AUTO_RATE_00 00
382 #define AUTO_RATE_05 01
383 #define AUTO_RATE_10 02
384 #define AUTO_RATE_20 03
386 #define WIDE_NEGO_BIT BIT(7)
387 #define DISC_ENABLE_BIT BIT(6)
389 #define hp_vendor_id_0 0x00 /* LSB */
390 #define ORION_VEND_0 0x4B
392 #define hp_vendor_id_1 0x01 /* MSB */
393 #define ORION_VEND_1 0x10
395 #define hp_device_id_0 0x02 /* LSB */
396 #define ORION_DEV_0 0x30
398 #define hp_device_id_1 0x03 /* MSB */
399 #define ORION_DEV_1 0x81
401 /* Sub Vendor ID and Sub Device ID only available in
402 Harpoon Version 2 and higher */
404 #define hp_sub_device_id_0 0x06 /* LSB */
406 #define hp_semaphore 0x0C
407 #define SCCB_MGR_ACTIVE BIT(0)
408 #define TICKLE_ME BIT(1)
409 #define SCCB_MGR_PRESENT BIT(3)
410 #define BIOS_IN_USE BIT(4)
412 #define hp_sys_ctrl 0x0F
414 #define STOP_CLK BIT(0) /*Turn off BusMaster Clock */
415 #define DRVR_RST BIT(1) /*Firmware Reset to 80C15 chip */
416 #define HALT_MACH BIT(3) /*Halt State Machine */
417 #define HARD_ABORT BIT(4) /*Hard Abort */
419 #define hp_host_blk_cnt 0x13
421 #define XFER_BLK64 0x06 /* 1 1 0 64 byte per block */
423 #define BM_THRESHOLD 0x40 /* PCI mode can only xfer 16 bytes */
425 #define hp_int_mask 0x17
427 #define INT_CMD_COMPL BIT(0) /* DMA command complete */
428 #define INT_EXT_STATUS BIT(1) /* Extended Status Set */
430 #define hp_xfer_cnt_lo 0x18
431 #define hp_xfer_cnt_hi 0x1A
432 #define hp_xfer_cmd 0x1B
434 #define XFER_HOST_DMA 0x00 /* 0 0 0 Transfer Host -> DMA */
435 #define XFER_DMA_HOST 0x01 /* 0 0 1 Transfer DMA -> Host */
437 #define XFER_HOST_AUTO 0x00 /* 0 0 Auto Transfer Size */
439 #define XFER_DMA_8BIT 0x20 /* 0 1 8 BIT Transfer Size */
441 #define DISABLE_INT BIT(7) /*Do not interrupt at end of cmd. */
443 #define HOST_WRT_CMD ((DISABLE_INT + XFER_HOST_DMA + XFER_HOST_AUTO + XFER_DMA_8BIT))
444 #define HOST_RD_CMD ((DISABLE_INT + XFER_DMA_HOST + XFER_HOST_AUTO + XFER_DMA_8BIT))
446 #define hp_host_addr_lo 0x1C
447 #define hp_host_addr_hmi 0x1E
449 #define hp_ee_ctrl 0x22
451 #define EXT_ARB_ACK BIT(7)
452 #define SCSI_TERM_ENA_H BIT(6) /* SCSI high byte terminator */
453 #define SEE_MS BIT(5)
454 #define SEE_CS BIT(3)
455 #define SEE_CLK BIT(2)
456 #define SEE_DO BIT(1)
457 #define SEE_DI BIT(0)
459 #define EE_READ 0x06
460 #define EE_WRITE 0x05
461 #define EWEN 0x04
462 #define EWEN_ADDR 0x03C0
463 #define EWDS 0x04
464 #define EWDS_ADDR 0x0000
466 #define hp_bm_ctrl 0x26
468 #define SCSI_TERM_ENA_L BIT(0) /*Enable/Disable external terminators */
469 #define FLUSH_XFER_CNTR BIT(1) /*Flush transfer counter */
470 #define FORCE1_XFER BIT(5) /*Always xfer one byte in byte mode */
471 #define FAST_SINGLE BIT(6) /*?? */
473 #define BMCTRL_DEFAULT (FORCE1_XFER|FAST_SINGLE|SCSI_TERM_ENA_L)
475 #define hp_sg_addr 0x28
476 #define hp_page_ctrl 0x29
478 #define SCATTER_EN BIT(0)
479 #define SGRAM_ARAM BIT(1)
480 #define G_INT_DISABLE BIT(3) /* Enable/Disable all Interrupts */
481 #define NARROW_SCSI_CARD BIT(4) /* NARROW/WIDE SCSI config pin */
483 #define hp_pci_stat_cfg 0x2D
485 #define REC_MASTER_ABORT BIT(5) /*received Master abort */
487 #define hp_rev_num 0x33
489 #define hp_stack_data 0x34
490 #define hp_stack_addr 0x35
492 #define hp_ext_status 0x36
494 #define BM_FORCE_OFF BIT(0) /*Bus Master is forced to get off */
495 #define PCI_TGT_ABORT BIT(0) /*PCI bus master transaction aborted */
496 #define PCI_DEV_TMOUT BIT(1) /*PCI Device Time out */
497 #define CMD_ABORTED BIT(4) /*Command aborted */
498 #define BM_PARITY_ERR BIT(5) /*parity error on data received */
499 #define PIO_OVERRUN BIT(6) /*Slave data overrun */
500 #define BM_CMD_BUSY BIT(7) /*Bus master transfer command busy */
501 #define BAD_EXT_STATUS (BM_FORCE_OFF | PCI_DEV_TMOUT | CMD_ABORTED | \
502 BM_PARITY_ERR | PIO_OVERRUN)
504 #define hp_int_status 0x37
506 #define EXT_STATUS_ON BIT(1) /*Extended status is valid */
507 #define SCSI_INTERRUPT BIT(2) /*Global indication of a SCSI int. */
508 #define INT_ASSERTED BIT(5) /* */
510 #define hp_fifo_cnt 0x38
512 #define hp_intena 0x40
514 #define RESET BITW(7)
515 #define PROG_HLT BITW(6)
516 #define PARITY BITW(5)
517 #define FIFO BITW(4)
518 #define SEL BITW(3)
519 #define SCAM_SEL BITW(2)
520 #define RSEL BITW(1)
521 #define TIMEOUT BITW(0)
522 #define BUS_FREE BITW(15)
523 #define XFER_CNT_0 BITW(14)
524 #define PHASE BITW(13)
525 #define IUNKWN BITW(12)
526 #define ICMD_COMP BITW(11)
527 #define ITICKLE BITW(10)
528 #define IDO_STRT BITW(9)
529 #define ITAR_DISC BITW(8)
530 #define AUTO_INT (BITW(12)+BITW(11)+BITW(10)+BITW(9)+BITW(8))
531 #define CLR_ALL_INT 0xFFFF
532 #define CLR_ALL_INT_1 0xFF00
534 #define hp_intstat 0x42
536 #define hp_scsisig 0x44
538 #define SCSI_SEL BIT(7)
539 #define SCSI_BSY BIT(6)
540 #define SCSI_REQ BIT(5)
541 #define SCSI_ACK BIT(4)
542 #define SCSI_ATN BIT(3)
543 #define SCSI_CD BIT(2)
544 #define SCSI_MSG BIT(1)
545 #define SCSI_IOBIT BIT(0)
547 #define S_SCSI_PHZ (BIT(2)+BIT(1)+BIT(0))
548 #define S_MSGO_PH (BIT(2)+BIT(1) )
549 #define S_MSGI_PH (BIT(2)+BIT(1)+BIT(0))
550 #define S_DATAI_PH ( BIT(0))
551 #define S_DATAO_PH 0x00
552 #define S_ILL_PH ( BIT(1) )
554 #define hp_scsictrl_0 0x45
556 #define SEL_TAR BIT(6)
557 #define ENA_ATN BIT(4)
558 #define ENA_RESEL BIT(2)
559 #define SCSI_RST BIT(1)
560 #define ENA_SCAM_SEL BIT(0)
562 #define hp_portctrl_0 0x46
564 #define SCSI_PORT BIT(7)
565 #define SCSI_INBIT BIT(6)
566 #define DMA_PORT BIT(5)
567 #define DMA_RD BIT(4)
568 #define HOST_PORT BIT(3)
569 #define HOST_WRT BIT(2)
570 #define SCSI_BUS_EN BIT(1)
571 #define START_TO BIT(0)
573 #define hp_scsireset 0x47
575 #define SCSI_INI BIT(6)
576 #define SCAM_EN BIT(5)
577 #define DMA_RESET BIT(3)
578 #define HPSCSI_RESET BIT(2)
579 #define PROG_RESET BIT(1)
580 #define FIFO_CLR BIT(0)
582 #define hp_xfercnt_0 0x48
583 #define hp_xfercnt_2 0x4A
585 #define hp_fifodata_0 0x4C
586 #define hp_addstat 0x4E
588 #define SCAM_TIMER BIT(7)
589 #define SCSI_MODE8 BIT(3)
590 #define SCSI_PAR_ERR BIT(0)
592 #define hp_prgmcnt_0 0x4F
594 #define hp_selfid_0 0x50
595 #define hp_selfid_1 0x51
596 #define hp_arb_id 0x52
598 #define hp_select_id 0x53
600 #define hp_synctarg_base 0x54
601 #define hp_synctarg_12 0x54
602 #define hp_synctarg_13 0x55
603 #define hp_synctarg_14 0x56
604 #define hp_synctarg_15 0x57
606 #define hp_synctarg_8 0x58
607 #define hp_synctarg_9 0x59
608 #define hp_synctarg_10 0x5A
609 #define hp_synctarg_11 0x5B
611 #define hp_synctarg_4 0x5C
612 #define hp_synctarg_5 0x5D
613 #define hp_synctarg_6 0x5E
614 #define hp_synctarg_7 0x5F
616 #define hp_synctarg_0 0x60
617 #define hp_synctarg_1 0x61
618 #define hp_synctarg_2 0x62
619 #define hp_synctarg_3 0x63
621 #define NARROW_SCSI BIT(4)
622 #define DEFAULT_OFFSET 0x0F
624 #define hp_autostart_0 0x64
625 #define hp_autostart_1 0x65
626 #define hp_autostart_3 0x67
628 #define AUTO_IMMED BIT(5)
629 #define SELECT BIT(6)
630 #define END_DATA (BIT(7)+BIT(6))
632 #define hp_gp_reg_0 0x68
633 #define hp_gp_reg_1 0x69
634 #define hp_gp_reg_3 0x6B
636 #define hp_seltimeout 0x6C
638 #define TO_4ms 0x67 /* 3.9959ms */
640 #define TO_5ms 0x03 /* 4.9152ms */
641 #define TO_10ms 0x07 /* 11.xxxms */
642 #define TO_250ms 0x99 /* 250.68ms */
643 #define TO_290ms 0xB1 /* 289.99ms */
645 #define hp_clkctrl_0 0x6D
647 #define PWR_DWN BIT(6)
648 #define ACTdeassert BIT(4)
649 #define CLK_40MHZ (BIT(1) + BIT(0))
651 #define CLKCTRL_DEFAULT (ACTdeassert | CLK_40MHZ)
653 #define hp_fiforead 0x6E
654 #define hp_fifowrite 0x6F
656 #define hp_offsetctr 0x70
657 #define hp_xferstat 0x71
659 #define FIFO_EMPTY BIT(6)
661 #define hp_portctrl_1 0x72
663 #define CHK_SCSI_P BIT(3)
664 #define HOST_MODE8 BIT(0)
666 #define hp_xfer_pad 0x73
668 #define ID_UNLOCK BIT(3)
670 #define hp_scsidata_0 0x74
671 #define hp_scsidata_1 0x75
673 #define hp_aramBase 0x80
674 #define BIOS_DATA_OFFSET 0x60
675 #define BIOS_RELATIVE_CARD 0x64
677 #define AR3 (BITW(9) + BITW(8))
678 #define SDATA BITW(10)
680 #define CRD_OP BITW(11) /* Cmp Reg. w/ Data */
682 #define CRR_OP BITW(12) /* Cmp Reg. w. Reg. */
684 #define CPE_OP (BITW(14)+BITW(11)) /* Cmp SCSI phs & Branch EQ */
686 #define CPN_OP (BITW(14)+BITW(12)) /* Cmp SCSI phs & Branch NOT EQ */
688 #define ADATA_OUT 0x00
689 #define ADATA_IN BITW(8)
690 #define ACOMMAND BITW(10)
691 #define ASTATUS (BITW(10)+BITW(8))
692 #define AMSG_OUT (BITW(10)+BITW(9))
693 #define AMSG_IN (BITW(10)+BITW(9)+BITW(8))
695 #define BRH_OP BITW(13) /* Branch */
697 #define ALWAYS 0x00
698 #define EQUAL BITW(8)
699 #define NOT_EQ BITW(9)
701 #define TCB_OP (BITW(13)+BITW(11)) /* Test condition & branch */
703 #define FIFO_0 BITW(10)
705 #define MPM_OP BITW(15) /* Match phase and move data */
707 #define MRR_OP BITW(14) /* Move DReg. to Reg. */
709 #define S_IDREG (BIT(2)+BIT(1)+BIT(0))
711 #define D_AR0 0x00
712 #define D_AR1 BIT(0)
713 #define D_BUCKET (BIT(2) + BIT(1) + BIT(0))
715 #define RAT_OP (BITW(14)+BITW(13)+BITW(11))
717 #define SSI_OP (BITW(15)+BITW(11))
719 #define SSI_ITAR_DISC (ITAR_DISC >> 8)
720 #define SSI_IDO_STRT (IDO_STRT >> 8)
722 #define SSI_ICMD_COMP (ICMD_COMP >> 8)
723 #define SSI_ITICKLE (ITICKLE >> 8)
725 #define SSI_IUNKWN (IUNKWN >> 8)
726 #define SSI_INO_CC (IUNKWN >> 8)
727 #define SSI_IRFAIL (IUNKWN >> 8)
729 #define NP 0x10 /*Next Phase */
730 #define NTCMD 0x02 /*Non- Tagged Command start */
731 #define CMDPZ 0x04 /*Command phase */
732 #define DINT 0x12 /*Data Out/In interrupt */
733 #define DI 0x13 /*Data Out */
734 #define DC 0x19 /*Disconnect Message */
735 #define ST 0x1D /*Status Phase */
736 #define UNKNWN 0x24 /*Unknown bus action */
737 #define CC 0x25 /*Command Completion failure */
738 #define TICK 0x26 /*New target reselected us. */
739 #define SELCHK 0x28 /*Select & Check SCSI ID latch reg */
741 #define ID_MSG_STRT hp_aramBase + 0x00
742 #define NON_TAG_ID_MSG hp_aramBase + 0x06
743 #define CMD_STRT hp_aramBase + 0x08
744 #define SYNC_MSGS hp_aramBase + 0x08
746 #define TAG_STRT 0x00
747 #define DISCONNECT_START 0x10/2
748 #define END_DATA_START 0x14/2
749 #define CMD_ONLY_STRT CMDPZ/2
750 #define SELCHK_STRT SELCHK/2
752 #define GET_XFER_CNT(port, xfercnt) {RD_HARP32(port,hp_xfercnt_0,xfercnt); xfercnt &= 0xFFFFFF;}
753 /* #define GET_XFER_CNT(port, xfercnt) (xfercnt = RD_HARPOON(port+hp_xfercnt_2), \
754 xfercnt <<= 16,\
755 xfercnt |= RDW_HARPOON((unsigned short)(port+hp_xfercnt_0)))
757 #define HP_SETUP_ADDR_CNT(port,addr,count) (WRW_HARPOON((port+hp_host_addr_lo), (unsigned short)(addr & 0x0000FFFFL)),\
758 addr >>= 16,\
759 WRW_HARPOON((port+hp_host_addr_hmi), (unsigned short)(addr & 0x0000FFFFL)),\
760 WR_HARP32(port,hp_xfercnt_0,count),\
761 WRW_HARPOON((port+hp_xfer_cnt_lo), (unsigned short)(count & 0x0000FFFFL)),\
762 count >>= 16,\
763 WR_HARPOON(port+hp_xfer_cnt_hi, (count & 0xFF)))
765 #define ACCEPT_MSG(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
766 WR_HARPOON(port+hp_scsisig, S_ILL_PH);}
768 #define ACCEPT_MSG_ATN(port) {while(RD_HARPOON(port+hp_scsisig) & SCSI_REQ){}\
769 WR_HARPOON(port+hp_scsisig, (S_ILL_PH|SCSI_ATN));}
771 #define DISABLE_AUTO(port) (WR_HARPOON(port+hp_scsireset, PROG_RESET),\
772 WR_HARPOON(port+hp_scsireset, 0x00))
774 #define ARAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
775 (RD_HARPOON(p_port+hp_page_ctrl) | SGRAM_ARAM)))
777 #define SGRAM_ACCESS(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
778 (RD_HARPOON(p_port+hp_page_ctrl) & ~SGRAM_ARAM)))
780 #define MDISABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
781 (RD_HARPOON(p_port+hp_page_ctrl) | G_INT_DISABLE)))
783 #define MENABLE_INT(p_port) (WR_HARPOON(p_port+hp_page_ctrl, \
784 (RD_HARPOON(p_port+hp_page_ctrl) & ~G_INT_DISABLE)))
786 static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card,
787 unsigned char syncFlag);
788 static void FPT_ssel(unsigned long port, unsigned char p_card);
789 static void FPT_sres(unsigned long port, unsigned char p_card,
790 struct sccb_card *pCurrCard);
791 static void FPT_shandem(unsigned long port, unsigned char p_card,
792 struct sccb *pCurrSCCB);
793 static void FPT_stsyncn(unsigned long port, unsigned char p_card);
794 static void FPT_sisyncr(unsigned long port, unsigned char sync_pulse,
795 unsigned char offset);
796 static void FPT_sssyncv(unsigned long p_port, unsigned char p_id,
797 unsigned char p_sync_value,
798 struct sccb_mgr_tar_info *currTar_Info);
799 static void FPT_sresb(unsigned long port, unsigned char p_card);
800 static void FPT_sxfrp(unsigned long p_port, unsigned char p_card);
801 static void FPT_schkdd(unsigned long port, unsigned char p_card);
802 static unsigned char FPT_RdStack(unsigned long port, unsigned char index);
803 static void FPT_WrStack(unsigned long portBase, unsigned char index,
804 unsigned char data);
805 static unsigned char FPT_ChkIfChipInitialized(unsigned long ioPort);
807 static void FPT_SendMsg(unsigned long port, unsigned char message);
808 static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
809 unsigned char error_code);
811 static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card);
812 static void FPT_RNVRamData(struct nvram_info *pNvRamInfo);
814 static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card);
815 static void FPT_stwidn(unsigned long port, unsigned char p_card);
816 static void FPT_siwidr(unsigned long port, unsigned char width);
818 static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
819 unsigned char p_card);
820 static void FPT_queueDisconnect(struct sccb *p_SCCB, unsigned char p_card);
821 static void FPT_queueCmdComplete(struct sccb_card *pCurrCard,
822 struct sccb *p_SCCB, unsigned char p_card);
823 static void FPT_queueSearchSelect(struct sccb_card *pCurrCard,
824 unsigned char p_card);
825 static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code);
826 static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char card);
827 static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB,
828 unsigned char p_card);
829 static void FPT_utilUpdateResidual(struct sccb *p_SCCB);
830 static unsigned short FPT_CalcCrc16(unsigned char buffer[]);
831 static unsigned char FPT_CalcLrc(unsigned char buffer[]);
833 static void FPT_Wait1Second(unsigned long p_port);
834 static void FPT_Wait(unsigned long p_port, unsigned char p_delay);
835 static void FPT_utilEEWriteOnOff(unsigned long p_port, unsigned char p_mode);
836 static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data,
837 unsigned short ee_addr);
838 static unsigned short FPT_utilEERead(unsigned long p_port,
839 unsigned short ee_addr);
840 static unsigned short FPT_utilEEReadOrg(unsigned long p_port,
841 unsigned short ee_addr);
842 static void FPT_utilEESendCmdAddr(unsigned long p_port, unsigned char ee_cmd,
843 unsigned short ee_addr);
845 static void FPT_phaseDataOut(unsigned long port, unsigned char p_card);
846 static void FPT_phaseDataIn(unsigned long port, unsigned char p_card);
847 static void FPT_phaseCommand(unsigned long port, unsigned char p_card);
848 static void FPT_phaseStatus(unsigned long port, unsigned char p_card);
849 static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card);
850 static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card);
851 static void FPT_phaseIllegal(unsigned long port, unsigned char p_card);
853 static void FPT_phaseDecode(unsigned long port, unsigned char p_card);
854 static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card);
855 static void FPT_phaseBusFree(unsigned long p_port, unsigned char p_card);
857 static void FPT_XbowInit(unsigned long port, unsigned char scamFlg);
858 static void FPT_BusMasterInit(unsigned long p_port);
859 static void FPT_DiagEEPROM(unsigned long p_port);
861 static void FPT_dataXferProcessor(unsigned long port,
862 struct sccb_card *pCurrCard);
863 static void FPT_busMstrSGDataXferStart(unsigned long port,
864 struct sccb *pCurrSCCB);
865 static void FPT_busMstrDataXferStart(unsigned long port,
866 struct sccb *pCurrSCCB);
867 static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card,
868 struct sccb *pCurrSCCB);
869 static void FPT_hostDataXferRestart(struct sccb *currSCCB);
871 static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port,
872 unsigned char p_card,
873 struct sccb_card *pCurrCard,
874 unsigned short p_int);
876 static void FPT_SccbMgrTableInitAll(void);
877 static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard,
878 unsigned char p_card);
879 static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
880 unsigned char target);
882 static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
883 unsigned char p_power_up);
885 static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type);
886 static void FPT_scbusf(unsigned long p_port);
887 static void FPT_scsel(unsigned long p_port);
888 static void FPT_scasid(unsigned char p_card, unsigned long p_port);
889 static unsigned char FPT_scxferc(unsigned long p_port, unsigned char p_data);
890 static unsigned char FPT_scsendi(unsigned long p_port,
891 unsigned char p_id_string[]);
892 static unsigned char FPT_sciso(unsigned long p_port,
893 unsigned char p_id_string[]);
894 static void FPT_scwirod(unsigned long p_port, unsigned char p_data_bit);
895 static void FPT_scwiros(unsigned long p_port, unsigned char p_data_bit);
896 static unsigned char FPT_scvalq(unsigned char p_quintet);
897 static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id);
898 static void FPT_scwtsel(unsigned long p_port);
899 static void FPT_inisci(unsigned char p_card, unsigned long p_port,
900 unsigned char p_our_id);
901 static void FPT_scsavdi(unsigned char p_card, unsigned long p_port);
902 static unsigned char FPT_scmachid(unsigned char p_card,
903 unsigned char p_id_string[]);
905 static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card);
906 static void FPT_autoLoadDefaultMap(unsigned long p_port);
908 static struct sccb_mgr_tar_info FPT_sccbMgrTbl[MAX_CARDS][MAX_SCSI_TAR] =
909 { {{0}} };
910 static struct sccb_card FPT_BL_Card[MAX_CARDS] = { {0} };
911 static SCCBSCAM_INFO FPT_scamInfo[MAX_SCSI_TAR] = { {{0}} };
912 static struct nvram_info FPT_nvRamInfo[MAX_MB_CARDS] = { {0} };
914 static unsigned char FPT_mbCards = 0;
915 static unsigned char FPT_scamHAString[] =
916 { 0x63, 0x07, 'B', 'U', 'S', 'L', 'O', 'G', 'I', 'C',
917 ' ', 'B', 'T', '-', '9', '3', '0',
918 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
919 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
922 static unsigned short FPT_default_intena = 0;
924 static void (*FPT_s_PhaseTbl[8]) (unsigned long, unsigned char) = {
927 /*---------------------------------------------------------------------
929 * Function: FlashPoint_ProbeHostAdapter
931 * Description: Setup and/or Search for cards and return info to caller.
933 *---------------------------------------------------------------------*/
935 static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo)
937 static unsigned char first_time = 1;
939 unsigned char i, j, id, ScamFlg;
940 unsigned short temp, temp2, temp3, temp4, temp5, temp6;
941 unsigned long ioport;
942 struct nvram_info *pCurrNvRam;
944 ioport = pCardInfo->si_baseaddr;
946 if (RD_HARPOON(ioport + hp_vendor_id_0) != ORION_VEND_0)
947 return (int)FAILURE;
949 if ((RD_HARPOON(ioport + hp_vendor_id_1) != ORION_VEND_1))
950 return (int)FAILURE;
952 if ((RD_HARPOON(ioport + hp_device_id_0) != ORION_DEV_0))
953 return (int)FAILURE;
955 if ((RD_HARPOON(ioport + hp_device_id_1) != ORION_DEV_1))
956 return (int)FAILURE;
958 if (RD_HARPOON(ioport + hp_rev_num) != 0x0f) {
960 /* For new Harpoon then check for sub_device ID LSB
961 the bits(0-3) must be all ZERO for compatible with
962 current version of SCCBMgr, else skip this Harpoon
963 device. */
965 if (RD_HARPOON(ioport + hp_sub_device_id_0) & 0x0f)
966 return (int)FAILURE;
969 if (first_time) {
970 FPT_SccbMgrTableInitAll();
971 first_time = 0;
972 FPT_mbCards = 0;
975 if (FPT_RdStack(ioport, 0) != 0x00) {
976 if (FPT_ChkIfChipInitialized(ioport) == 0) {
977 pCurrNvRam = NULL;
978 WR_HARPOON(ioport + hp_semaphore, 0x00);
979 FPT_XbowInit(ioport, 0); /*Must Init the SCSI before attempting */
980 FPT_DiagEEPROM(ioport);
981 } else {
982 if (FPT_mbCards < MAX_MB_CARDS) {
983 pCurrNvRam = &FPT_nvRamInfo[FPT_mbCards];
984 FPT_mbCards++;
985 pCurrNvRam->niBaseAddr = ioport;
986 FPT_RNVRamData(pCurrNvRam);
987 } else
988 return (int)FAILURE;
990 } else
991 pCurrNvRam = NULL;
993 WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT);
994 WR_HARPOON(ioport + hp_sys_ctrl, 0x00);
996 if (pCurrNvRam)
997 pCardInfo->si_id = pCurrNvRam->niAdapId;
998 else
999 pCardInfo->si_id =
1000 (unsigned
1001 char)(FPT_utilEERead(ioport,
1002 (ADAPTER_SCSI_ID /
1003 2)) & (unsigned char)0x0FF);
1005 pCardInfo->si_lun = 0x00;
1006 pCardInfo->si_fw_revision = ORION_FW_REV;
1007 temp2 = 0x0000;
1008 temp3 = 0x0000;
1009 temp4 = 0x0000;
1010 temp5 = 0x0000;
1011 temp6 = 0x0000;
1013 for (id = 0; id < (16 / 2); id++) {
1015 if (pCurrNvRam) {
1016 temp = (unsigned short)pCurrNvRam->niSyncTbl[id];
1017 temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
1018 (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
1019 } else
1020 temp =
1021 FPT_utilEERead(ioport,
1022 (unsigned short)((SYNC_RATE_TBL / 2)
1023 + id));
1025 for (i = 0; i < 2; temp >>= 8, i++) {
1027 temp2 >>= 1;
1028 temp3 >>= 1;
1029 temp4 >>= 1;
1030 temp5 >>= 1;
1031 temp6 >>= 1;
1032 switch (temp & 0x3) {
1033 case AUTO_RATE_20: /* Synchronous, 20 mega-transfers/second */
1034 temp6 |= 0x8000; /* Fall through */
1035 case AUTO_RATE_10: /* Synchronous, 10 mega-transfers/second */
1036 temp5 |= 0x8000; /* Fall through */
1037 case AUTO_RATE_05: /* Synchronous, 5 mega-transfers/second */
1038 temp2 |= 0x8000; /* Fall through */
1039 case AUTO_RATE_00: /* Asynchronous */
1040 break;
1043 if (temp & DISC_ENABLE_BIT)
1044 temp3 |= 0x8000;
1046 if (temp & WIDE_NEGO_BIT)
1047 temp4 |= 0x8000;
1052 pCardInfo->si_per_targ_init_sync = temp2;
1053 pCardInfo->si_per_targ_no_disc = temp3;
1054 pCardInfo->si_per_targ_wide_nego = temp4;
1055 pCardInfo->si_per_targ_fast_nego = temp5;
1056 pCardInfo->si_per_targ_ultra_nego = temp6;
1058 if (pCurrNvRam)
1059 i = pCurrNvRam->niSysConf;
1060 else
1061 i = (unsigned
1062 char)(FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)));
1064 if (pCurrNvRam)
1065 ScamFlg = pCurrNvRam->niScamConf;
1066 else
1067 ScamFlg =
1068 (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
1070 pCardInfo->si_flags = 0x0000;
1072 if (i & 0x01)
1073 pCardInfo->si_flags |= SCSI_PARITY_ENA;
1075 if (!(i & 0x02))
1076 pCardInfo->si_flags |= SOFT_RESET;
1078 if (i & 0x10)
1079 pCardInfo->si_flags |= EXTENDED_TRANSLATION;
1081 if (ScamFlg & SCAM_ENABLED)
1082 pCardInfo->si_flags |= FLAG_SCAM_ENABLED;
1084 if (ScamFlg & SCAM_LEVEL2)
1085 pCardInfo->si_flags |= FLAG_SCAM_LEVEL2;
1087 j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
1088 if (i & 0x04) {
1089 j |= SCSI_TERM_ENA_L;
1091 WR_HARPOON(ioport + hp_bm_ctrl, j);
1093 j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
1094 if (i & 0x08) {
1095 j |= SCSI_TERM_ENA_H;
1097 WR_HARPOON(ioport + hp_ee_ctrl, j);
1099 if (!(RD_HARPOON(ioport + hp_page_ctrl) & NARROW_SCSI_CARD))
1101 pCardInfo->si_flags |= SUPPORT_16TAR_32LUN;
1103 pCardInfo->si_card_family = HARPOON_FAMILY;
1104 pCardInfo->si_bustype = BUSTYPE_PCI;
1106 if (pCurrNvRam) {
1107 pCardInfo->si_card_model[0] = '9';
1108 switch (pCurrNvRam->niModel & 0x0f) {
1109 case MODEL_LT:
1110 pCardInfo->si_card_model[1] = '3';
1111 pCardInfo->si_card_model[2] = '0';
1112 break;
1113 case MODEL_LW:
1114 pCardInfo->si_card_model[1] = '5';
1115 pCardInfo->si_card_model[2] = '0';
1116 break;
1117 case MODEL_DL:
1118 pCardInfo->si_card_model[1] = '3';
1119 pCardInfo->si_card_model[2] = '2';
1120 break;
1121 case MODEL_DW:
1122 pCardInfo->si_card_model[1] = '5';
1123 pCardInfo->si_card_model[2] = '2';
1124 break;
1126 } else {
1127 temp = FPT_utilEERead(ioport, (MODEL_NUMB_0 / 2));
1128 pCardInfo->si_card_model[0] = (unsigned char)(temp >> 8);
1129 temp = FPT_utilEERead(ioport, (MODEL_NUMB_2 / 2));
1131 pCardInfo->si_card_model[1] = (unsigned char)(temp & 0x00FF);
1132 pCardInfo->si_card_model[2] = (unsigned char)(temp >> 8);
1135 if (pCardInfo->si_card_model[1] == '3') {
1136 if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
1137 pCardInfo->si_flags |= LOW_BYTE_TERM;
1138 } else if (pCardInfo->si_card_model[2] == '0') {
1139 temp = RD_HARPOON(ioport + hp_xfer_pad);
1140 WR_HARPOON(ioport + hp_xfer_pad, (temp & ~BIT(4)));
1141 if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
1142 pCardInfo->si_flags |= LOW_BYTE_TERM;
1143 WR_HARPOON(ioport + hp_xfer_pad, (temp | BIT(4)));
1144 if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7))
1145 pCardInfo->si_flags |= HIGH_BYTE_TERM;
1146 WR_HARPOON(ioport + hp_xfer_pad, temp);
1147 } else {
1148 temp = RD_HARPOON(ioport + hp_ee_ctrl);
1149 temp2 = RD_HARPOON(ioport + hp_xfer_pad);
1150 WR_HARPOON(ioport + hp_ee_ctrl, (temp | SEE_CS));
1151 WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4)));
1152 temp3 = 0;
1153 for (i = 0; i < 8; i++) {
1154 temp3 <<= 1;
1155 if (!(RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7)))
1156 temp3 |= 1;
1157 WR_HARPOON(ioport + hp_xfer_pad, (temp2 & ~BIT(4)));
1158 WR_HARPOON(ioport + hp_xfer_pad, (temp2 | BIT(4)));
1160 WR_HARPOON(ioport + hp_ee_ctrl, temp);
1161 WR_HARPOON(ioport + hp_xfer_pad, temp2);
1162 if (!(temp3 & BIT(7)))
1163 pCardInfo->si_flags |= LOW_BYTE_TERM;
1164 if (!(temp3 & BIT(6)))
1165 pCardInfo->si_flags |= HIGH_BYTE_TERM;
1168 ARAM_ACCESS(ioport);
1170 for (i = 0; i < 4; i++) {
1172 pCardInfo->si_XlatInfo[i] =
1173 RD_HARPOON(ioport + hp_aramBase + BIOS_DATA_OFFSET + i);
1176 /* return with -1 if no sort, else return with
1177 logical card number sorted by BIOS (zero-based) */
1179 pCardInfo->si_relative_cardnum =
1180 (unsigned
1181 char)(RD_HARPOON(ioport + hp_aramBase + BIOS_RELATIVE_CARD) - 1);
1183 SGRAM_ACCESS(ioport);
1185 FPT_s_PhaseTbl[0] = FPT_phaseDataOut;
1186 FPT_s_PhaseTbl[1] = FPT_phaseDataIn;
1187 FPT_s_PhaseTbl[2] = FPT_phaseIllegal;
1188 FPT_s_PhaseTbl[3] = FPT_phaseIllegal;
1189 FPT_s_PhaseTbl[4] = FPT_phaseCommand;
1190 FPT_s_PhaseTbl[5] = FPT_phaseStatus;
1191 FPT_s_PhaseTbl[6] = FPT_phaseMsgOut;
1192 FPT_s_PhaseTbl[7] = FPT_phaseMsgIn;
1194 pCardInfo->si_present = 0x01;
1196 return 0;
1199 /*---------------------------------------------------------------------
1201 * Function: FlashPoint_HardwareResetHostAdapter
1203 * Description: Setup adapter for normal operation (hard reset).
1205 *---------------------------------------------------------------------*/
1207 static unsigned long FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info
1208 *pCardInfo)
1210 struct sccb_card *CurrCard = NULL;
1211 struct nvram_info *pCurrNvRam;
1212 unsigned char i, j, thisCard, ScamFlg;
1213 unsigned short temp, sync_bit_map, id;
1214 unsigned long ioport;
1216 ioport = pCardInfo->si_baseaddr;
1218 for (thisCard = 0; thisCard <= MAX_CARDS; thisCard++) {
1220 if (thisCard == MAX_CARDS) {
1222 return FAILURE;
1225 if (FPT_BL_Card[thisCard].ioPort == ioport) {
1227 CurrCard = &FPT_BL_Card[thisCard];
1228 FPT_SccbMgrTableInitCard(CurrCard, thisCard);
1229 break;
1232 else if (FPT_BL_Card[thisCard].ioPort == 0x00) {
1234 FPT_BL_Card[thisCard].ioPort = ioport;
1235 CurrCard = &FPT_BL_Card[thisCard];
1237 if (FPT_mbCards)
1238 for (i = 0; i < FPT_mbCards; i++) {
1239 if (CurrCard->ioPort ==
1240 FPT_nvRamInfo[i].niBaseAddr)
1241 CurrCard->pNvRamInfo =
1242 &FPT_nvRamInfo[i];
1244 FPT_SccbMgrTableInitCard(CurrCard, thisCard);
1245 CurrCard->cardIndex = thisCard;
1246 CurrCard->cardInfo = pCardInfo;
1248 break;
1252 pCurrNvRam = CurrCard->pNvRamInfo;
1254 if (pCurrNvRam) {
1255 ScamFlg = pCurrNvRam->niScamConf;
1256 } else {
1257 ScamFlg =
1258 (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2);
1261 FPT_BusMasterInit(ioport);
1262 FPT_XbowInit(ioport, ScamFlg);
1264 FPT_autoLoadDefaultMap(ioport);
1266 for (i = 0, id = 0x01; i != pCardInfo->si_id; i++, id <<= 1) {
1269 WR_HARPOON(ioport + hp_selfid_0, id);
1270 WR_HARPOON(ioport + hp_selfid_1, 0x00);
1271 WR_HARPOON(ioport + hp_arb_id, pCardInfo->si_id);
1272 CurrCard->ourId = pCardInfo->si_id;
1274 i = (unsigned char)pCardInfo->si_flags;
1275 if (i & SCSI_PARITY_ENA)
1276 WR_HARPOON(ioport + hp_portctrl_1, (HOST_MODE8 | CHK_SCSI_P));
1278 j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L);
1279 if (i & LOW_BYTE_TERM)
1280 j |= SCSI_TERM_ENA_L;
1281 WR_HARPOON(ioport + hp_bm_ctrl, j);
1283 j = (RD_HARPOON(ioport + hp_ee_ctrl) & ~SCSI_TERM_ENA_H);
1284 if (i & HIGH_BYTE_TERM)
1285 j |= SCSI_TERM_ENA_H;
1286 WR_HARPOON(ioport + hp_ee_ctrl, j);
1288 if (!(pCardInfo->si_flags & SOFT_RESET)) {
1290 FPT_sresb(ioport, thisCard);
1292 FPT_scini(thisCard, pCardInfo->si_id, 0);
1295 if (pCardInfo->si_flags & POST_ALL_UNDERRRUNS)
1296 CurrCard->globalFlags |= F_NO_FILTER;
1298 if (pCurrNvRam) {
1299 if (pCurrNvRam->niSysConf & 0x10)
1300 CurrCard->globalFlags |= F_GREEN_PC;
1301 } else {
1302 if (FPT_utilEERead(ioport, (SYSTEM_CONFIG / 2)) & GREEN_PC_ENA)
1303 CurrCard->globalFlags |= F_GREEN_PC;
1306 /* Set global flag to indicate Re-Negotiation to be done on all
1307 ckeck condition */
1308 if (pCurrNvRam) {
1309 if (pCurrNvRam->niScsiConf & 0x04)
1310 CurrCard->globalFlags |= F_DO_RENEGO;
1311 } else {
1312 if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & RENEGO_ENA)
1313 CurrCard->globalFlags |= F_DO_RENEGO;
1316 if (pCurrNvRam) {
1317 if (pCurrNvRam->niScsiConf & 0x08)
1318 CurrCard->globalFlags |= F_CONLUN_IO;
1319 } else {
1320 if (FPT_utilEERead(ioport, (SCSI_CONFIG / 2)) & CONNIO_ENA)
1321 CurrCard->globalFlags |= F_CONLUN_IO;
1324 temp = pCardInfo->si_per_targ_no_disc;
1326 for (i = 0, id = 1; i < MAX_SCSI_TAR; i++, id <<= 1) {
1328 if (temp & id)
1329 FPT_sccbMgrTbl[thisCard][i].TarStatus |= TAR_ALLOW_DISC;
1332 sync_bit_map = 0x0001;
1334 for (id = 0; id < (MAX_SCSI_TAR / 2); id++) {
1336 if (pCurrNvRam) {
1337 temp = (unsigned short)pCurrNvRam->niSyncTbl[id];
1338 temp = ((temp & 0x03) + ((temp << 4) & 0xc0)) +
1339 (((temp << 4) & 0x0300) + ((temp << 8) & 0xc000));
1340 } else
1341 temp =
1342 FPT_utilEERead(ioport,
1343 (unsigned short)((SYNC_RATE_TBL / 2)
1344 + id));
1346 for (i = 0; i < 2; temp >>= 8, i++) {
1348 if (pCardInfo->si_per_targ_init_sync & sync_bit_map) {
1350 FPT_sccbMgrTbl[thisCard][id * 2 +
1351 i].TarEEValue =
1352 (unsigned char)temp;
1355 else {
1356 FPT_sccbMgrTbl[thisCard][id * 2 +
1357 i].TarStatus |=
1358 SYNC_SUPPORTED;
1359 FPT_sccbMgrTbl[thisCard][id * 2 +
1360 i].TarEEValue =
1361 (unsigned char)(temp & ~EE_SYNC_MASK);
1364 /* if ((pCardInfo->si_per_targ_wide_nego & sync_bit_map) ||
1365 (id*2+i >= 8)){
1367 if (pCardInfo->si_per_targ_wide_nego & sync_bit_map) {
1369 FPT_sccbMgrTbl[thisCard][id * 2 +
1370 i].TarEEValue |=
1371 EE_WIDE_SCSI;
1375 else { /* NARROW SCSI */
1376 FPT_sccbMgrTbl[thisCard][id * 2 +
1377 i].TarStatus |=
1378 WIDE_NEGOCIATED;
1381 sync_bit_map <<= 1;
1386 WR_HARPOON((ioport + hp_semaphore),
1387 (unsigned char)(RD_HARPOON((ioport + hp_semaphore)) |
1388 SCCB_MGR_PRESENT));
1390 return (unsigned long)CurrCard;
1393 static void FlashPoint_ReleaseHostAdapter(unsigned long pCurrCard)
1395 unsigned char i;
1396 unsigned long portBase;
1397 unsigned long regOffset;
1398 unsigned long scamData;
1399 unsigned long *pScamTbl;
1400 struct nvram_info *pCurrNvRam;
1402 pCurrNvRam = ((struct sccb_card *)pCurrCard)->pNvRamInfo;
1404 if (pCurrNvRam) {
1405 FPT_WrStack(pCurrNvRam->niBaseAddr, 0, pCurrNvRam->niModel);
1406 FPT_WrStack(pCurrNvRam->niBaseAddr, 1, pCurrNvRam->niSysConf);
1407 FPT_WrStack(pCurrNvRam->niBaseAddr, 2, pCurrNvRam->niScsiConf);
1408 FPT_WrStack(pCurrNvRam->niBaseAddr, 3, pCurrNvRam->niScamConf);
1409 FPT_WrStack(pCurrNvRam->niBaseAddr, 4, pCurrNvRam->niAdapId);
1411 for (i = 0; i < MAX_SCSI_TAR / 2; i++)
1412 FPT_WrStack(pCurrNvRam->niBaseAddr,
1413 (unsigned char)(i + 5),
1414 pCurrNvRam->niSyncTbl[i]);
1416 portBase = pCurrNvRam->niBaseAddr;
1418 for (i = 0; i < MAX_SCSI_TAR; i++) {
1419 regOffset = hp_aramBase + 64 + i * 4;
1420 pScamTbl = (unsigned long *)&pCurrNvRam->niScamTbl[i];
1421 scamData = *pScamTbl;
1422 WR_HARP32(portBase, regOffset, scamData);
1425 } else {
1426 FPT_WrStack(((struct sccb_card *)pCurrCard)->ioPort, 0, 0);
1430 static void FPT_RNVRamData(struct nvram_info *pNvRamInfo)
1432 unsigned char i;
1433 unsigned long portBase;
1434 unsigned long regOffset;
1435 unsigned long scamData;
1436 unsigned long *pScamTbl;
1438 pNvRamInfo->niModel = FPT_RdStack(pNvRamInfo->niBaseAddr, 0);
1439 pNvRamInfo->niSysConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 1);
1440 pNvRamInfo->niScsiConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 2);
1441 pNvRamInfo->niScamConf = FPT_RdStack(pNvRamInfo->niBaseAddr, 3);
1442 pNvRamInfo->niAdapId = FPT_RdStack(pNvRamInfo->niBaseAddr, 4);
1444 for (i = 0; i < MAX_SCSI_TAR / 2; i++)
1445 pNvRamInfo->niSyncTbl[i] =
1446 FPT_RdStack(pNvRamInfo->niBaseAddr, (unsigned char)(i + 5));
1448 portBase = pNvRamInfo->niBaseAddr;
1450 for (i = 0; i < MAX_SCSI_TAR; i++) {
1451 regOffset = hp_aramBase + 64 + i * 4;
1452 RD_HARP32(portBase, regOffset, scamData);
1453 pScamTbl = (unsigned long *)&pNvRamInfo->niScamTbl[i];
1454 *pScamTbl = scamData;
1459 static unsigned char FPT_RdStack(unsigned long portBase, unsigned char index)
1461 WR_HARPOON(portBase + hp_stack_addr, index);
1462 return RD_HARPOON(portBase + hp_stack_data);
1465 static void FPT_WrStack(unsigned long portBase, unsigned char index,
1466 unsigned char data)
1468 WR_HARPOON(portBase + hp_stack_addr, index);
1469 WR_HARPOON(portBase + hp_stack_data, data);
1472 static unsigned char FPT_ChkIfChipInitialized(unsigned long ioPort)
1474 if ((RD_HARPOON(ioPort + hp_arb_id) & 0x0f) != FPT_RdStack(ioPort, 4))
1475 return 0;
1476 if ((RD_HARPOON(ioPort + hp_clkctrl_0) & CLKCTRL_DEFAULT)
1477 != CLKCTRL_DEFAULT)
1478 return 0;
1479 if ((RD_HARPOON(ioPort + hp_seltimeout) == TO_250ms) ||
1480 (RD_HARPOON(ioPort + hp_seltimeout) == TO_290ms))
1481 return 1;
1482 return 0;
1486 /*---------------------------------------------------------------------
1488 * Function: FlashPoint_StartCCB
1490 * Description: Start a command pointed to by p_Sccb. When the
1491 * command is completed it will be returned via the
1492 * callback function.
1494 *---------------------------------------------------------------------*/
1495 static void FlashPoint_StartCCB(unsigned long pCurrCard, struct sccb *p_Sccb)
1497 unsigned long ioport;
1498 unsigned char thisCard, lun;
1499 struct sccb *pSaveSccb;
1500 CALL_BK_FN callback;
1502 thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
1503 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
1505 if ((p_Sccb->TargID > MAX_SCSI_TAR) || (p_Sccb->Lun > MAX_LUN)) {
1507 p_Sccb->HostStatus = SCCB_COMPLETE;
1508 p_Sccb->SccbStatus = SCCB_ERROR;
1509 callback = (CALL_BK_FN) p_Sccb->SccbCallback;
1510 if (callback)
1511 callback(p_Sccb);
1513 return;
1516 FPT_sinits(p_Sccb, thisCard);
1518 if (!((struct sccb_card *)pCurrCard)->cmdCounter) {
1519 WR_HARPOON(ioport + hp_semaphore,
1520 (RD_HARPOON(ioport + hp_semaphore)
1521 | SCCB_MGR_ACTIVE));
1523 if (((struct sccb_card *)pCurrCard)->globalFlags & F_GREEN_PC) {
1524 WR_HARPOON(ioport + hp_clkctrl_0, CLKCTRL_DEFAULT);
1525 WR_HARPOON(ioport + hp_sys_ctrl, 0x00);
1529 ((struct sccb_card *)pCurrCard)->cmdCounter++;
1531 if (RD_HARPOON(ioport + hp_semaphore) & BIOS_IN_USE) {
1533 WR_HARPOON(ioport + hp_semaphore,
1534 (RD_HARPOON(ioport + hp_semaphore)
1535 | TICKLE_ME));
1536 if (p_Sccb->OperationCode == RESET_COMMAND) {
1537 pSaveSccb =
1538 ((struct sccb_card *)pCurrCard)->currentSCCB;
1539 ((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb;
1540 FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
1541 ((struct sccb_card *)pCurrCard)->currentSCCB =
1542 pSaveSccb;
1543 } else {
1544 FPT_queueAddSccb(p_Sccb, thisCard);
1548 else if ((RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) {
1550 if (p_Sccb->OperationCode == RESET_COMMAND) {
1551 pSaveSccb =
1552 ((struct sccb_card *)pCurrCard)->currentSCCB;
1553 ((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb;
1554 FPT_queueSelectFail(&FPT_BL_Card[thisCard], thisCard);
1555 ((struct sccb_card *)pCurrCard)->currentSCCB =
1556 pSaveSccb;
1557 } else {
1558 FPT_queueAddSccb(p_Sccb, thisCard);
1562 else {
1564 MDISABLE_INT(ioport);
1566 if ((((struct sccb_card *)pCurrCard)->globalFlags & F_CONLUN_IO)
1568 ((FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].
1569 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
1570 lun = p_Sccb->Lun;
1571 else
1572 lun = 0;
1573 if ((((struct sccb_card *)pCurrCard)->currentSCCB == NULL) &&
1574 (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarSelQ_Cnt == 0)
1575 && (FPT_sccbMgrTbl[thisCard][p_Sccb->TargID].TarLUNBusy[lun]
1576 == 0)) {
1578 ((struct sccb_card *)pCurrCard)->currentSCCB = p_Sccb;
1579 FPT_ssel(p_Sccb->SccbIOPort, thisCard);
1582 else {
1584 if (p_Sccb->OperationCode == RESET_COMMAND) {
1585 pSaveSccb =
1586 ((struct sccb_card *)pCurrCard)->
1587 currentSCCB;
1588 ((struct sccb_card *)pCurrCard)->currentSCCB =
1589 p_Sccb;
1590 FPT_queueSelectFail(&FPT_BL_Card[thisCard],
1591 thisCard);
1592 ((struct sccb_card *)pCurrCard)->currentSCCB =
1593 pSaveSccb;
1594 } else {
1595 FPT_queueAddSccb(p_Sccb, thisCard);
1599 MENABLE_INT(ioport);
1604 /*---------------------------------------------------------------------
1606 * Function: FlashPoint_AbortCCB
1608 * Description: Abort the command pointed to by p_Sccb. When the
1609 * command is completed it will be returned via the
1610 * callback function.
1612 *---------------------------------------------------------------------*/
1613 static int FlashPoint_AbortCCB(unsigned long pCurrCard, struct sccb *p_Sccb)
1615 unsigned long ioport;
1617 unsigned char thisCard;
1618 CALL_BK_FN callback;
1619 unsigned char TID;
1620 struct sccb *pSaveSCCB;
1621 struct sccb_mgr_tar_info *currTar_Info;
1623 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
1625 thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
1627 if (!(RD_HARPOON(ioport + hp_page_ctrl) & G_INT_DISABLE)) {
1629 if (FPT_queueFindSccb(p_Sccb, thisCard)) {
1631 ((struct sccb_card *)pCurrCard)->cmdCounter--;
1633 if (!((struct sccb_card *)pCurrCard)->cmdCounter)
1634 WR_HARPOON(ioport + hp_semaphore,
1635 (RD_HARPOON(ioport + hp_semaphore)
1636 & (unsigned
1637 char)(~(SCCB_MGR_ACTIVE |
1638 TICKLE_ME))));
1640 p_Sccb->SccbStatus = SCCB_ABORT;
1641 callback = p_Sccb->SccbCallback;
1642 callback(p_Sccb);
1644 return 0;
1647 else {
1648 if (((struct sccb_card *)pCurrCard)->currentSCCB ==
1649 p_Sccb) {
1650 p_Sccb->SccbStatus = SCCB_ABORT;
1651 return 0;
1655 else {
1657 TID = p_Sccb->TargID;
1659 if (p_Sccb->Sccb_tag) {
1660 MDISABLE_INT(ioport);
1661 if (((struct sccb_card *)pCurrCard)->
1662 discQ_Tbl[p_Sccb->Sccb_tag] ==
1663 p_Sccb) {
1664 p_Sccb->SccbStatus = SCCB_ABORT;
1665 p_Sccb->Sccb_scsistat =
1666 ABORT_ST;
1667 p_Sccb->Sccb_scsimsg =
1668 SMABORT_TAG;
1670 if (((struct sccb_card *)
1671 pCurrCard)->currentSCCB ==
1672 NULL) {
1673 ((struct sccb_card *)
1674 pCurrCard)->
1675 currentSCCB = p_Sccb;
1676 FPT_ssel(ioport,
1677 thisCard);
1678 } else {
1679 pSaveSCCB =
1680 ((struct sccb_card
1681 *)pCurrCard)->
1682 currentSCCB;
1683 ((struct sccb_card *)
1684 pCurrCard)->
1685 currentSCCB = p_Sccb;
1686 FPT_queueSelectFail((struct sccb_card *)pCurrCard, thisCard);
1687 ((struct sccb_card *)
1688 pCurrCard)->
1689 currentSCCB = pSaveSCCB;
1692 MENABLE_INT(ioport);
1693 return 0;
1694 } else {
1695 currTar_Info =
1696 &FPT_sccbMgrTbl[thisCard][p_Sccb->
1697 TargID];
1699 if (FPT_BL_Card[thisCard].
1700 discQ_Tbl[currTar_Info->
1701 LunDiscQ_Idx[p_Sccb->Lun]]
1702 == p_Sccb) {
1703 p_Sccb->SccbStatus = SCCB_ABORT;
1704 return 0;
1710 return -1;
1713 /*---------------------------------------------------------------------
1715 * Function: FlashPoint_InterruptPending
1717 * Description: Do a quick check to determine if there is a pending
1718 * interrupt for this card and disable the IRQ Pin if so.
1720 *---------------------------------------------------------------------*/
1721 static unsigned char FlashPoint_InterruptPending(unsigned long pCurrCard)
1723 unsigned long ioport;
1725 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
1727 if (RD_HARPOON(ioport + hp_int_status) & INT_ASSERTED) {
1728 return 1;
1731 else
1733 return 0;
1736 /*---------------------------------------------------------------------
1738 * Function: FlashPoint_HandleInterrupt
1740 * Description: This is our entry point when an interrupt is generated
1741 * by the card and the upper level driver passes it on to
1742 * us.
1744 *---------------------------------------------------------------------*/
1745 static int FlashPoint_HandleInterrupt(unsigned long pCurrCard)
1747 struct sccb *currSCCB;
1748 unsigned char thisCard, result, bm_status, bm_int_st;
1749 unsigned short hp_int;
1750 unsigned char i, target;
1751 unsigned long ioport;
1753 thisCard = ((struct sccb_card *)pCurrCard)->cardIndex;
1754 ioport = ((struct sccb_card *)pCurrCard)->ioPort;
1756 MDISABLE_INT(ioport);
1758 if ((bm_int_st = RD_HARPOON(ioport + hp_int_status)) & EXT_STATUS_ON)
1759 bm_status =
1760 RD_HARPOON(ioport +
1761 hp_ext_status) & (unsigned char)BAD_EXT_STATUS;
1762 else
1763 bm_status = 0;
1765 WR_HARPOON(ioport + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
1767 while ((hp_int =
1768 RDW_HARPOON((ioport +
1769 hp_intstat)) & FPT_default_intena) | bm_status) {
1771 currSCCB = ((struct sccb_card *)pCurrCard)->currentSCCB;
1773 if (hp_int & (FIFO | TIMEOUT | RESET | SCAM_SEL) || bm_status) {
1774 result =
1775 FPT_SccbMgr_bad_isr(ioport, thisCard,
1776 ((struct sccb_card *)pCurrCard),
1777 hp_int);
1778 WRW_HARPOON((ioport + hp_intstat),
1779 (FIFO | TIMEOUT | RESET | SCAM_SEL));
1780 bm_status = 0;
1782 if (result) {
1784 MENABLE_INT(ioport);
1785 return result;
1789 else if (hp_int & ICMD_COMP) {
1791 if (!(hp_int & BUS_FREE)) {
1792 /* Wait for the BusFree before starting a new command. We
1793 must also check for being reselected since the BusFree
1794 may not show up if another device reselects us in 1.5us or
1795 less. SRR Wednesday, 3/8/1995.
1797 while (!
1798 (RDW_HARPOON((ioport + hp_intstat)) &
1799 (BUS_FREE | RSEL))) ;
1802 if (((struct sccb_card *)pCurrCard)->
1803 globalFlags & F_HOST_XFER_ACT)
1805 FPT_phaseChkFifo(ioport, thisCard);
1807 /* WRW_HARPOON((ioport+hp_intstat),
1808 (BUS_FREE | ICMD_COMP | ITAR_DISC | XFER_CNT_0));
1811 WRW_HARPOON((ioport + hp_intstat), CLR_ALL_INT_1);
1813 FPT_autoCmdCmplt(ioport, thisCard);
1817 else if (hp_int & ITAR_DISC) {
1819 if (((struct sccb_card *)pCurrCard)->
1820 globalFlags & F_HOST_XFER_ACT) {
1822 FPT_phaseChkFifo(ioport, thisCard);
1826 if (RD_HARPOON(ioport + hp_gp_reg_1) == SMSAVE_DATA_PTR) {
1828 WR_HARPOON(ioport + hp_gp_reg_1, 0x00);
1829 currSCCB->Sccb_XferState |= F_NO_DATA_YET;
1831 currSCCB->Sccb_savedATC = currSCCB->Sccb_ATC;
1834 currSCCB->Sccb_scsistat = DISCONNECT_ST;
1835 FPT_queueDisconnect(currSCCB, thisCard);
1837 /* Wait for the BusFree before starting a new command. We
1838 must also check for being reselected since the BusFree
1839 may not show up if another device reselects us in 1.5us or
1840 less. SRR Wednesday, 3/8/1995.
1842 while (!
1843 (RDW_HARPOON((ioport + hp_intstat)) &
1844 (BUS_FREE | RSEL))
1845 && !((RDW_HARPOON((ioport + hp_intstat)) & PHASE)
1846 && RD_HARPOON((ioport + hp_scsisig)) ==
1847 (SCSI_BSY | SCSI_REQ | SCSI_CD | SCSI_MSG |
1848 SCSI_IOBIT))) ;
1851 The additional loop exit condition above detects a timing problem
1852 with the revision D/E harpoon chips. The caller should reset the
1853 host adapter to recover when 0xFE is returned.
1855 if (!
1856 (RDW_HARPOON((ioport + hp_intstat)) &
1857 (BUS_FREE | RSEL))) {
1858 MENABLE_INT(ioport);
1859 return 0xFE;
1862 WRW_HARPOON((ioport + hp_intstat),
1863 (BUS_FREE | ITAR_DISC));
1865 ((struct sccb_card *)pCurrCard)->globalFlags |=
1866 F_NEW_SCCB_CMD;
1870 else if (hp_int & RSEL) {
1872 WRW_HARPOON((ioport + hp_intstat),
1873 (PROG_HLT | RSEL | PHASE | BUS_FREE));
1875 if (RDW_HARPOON((ioport + hp_intstat)) & ITAR_DISC) {
1876 if (((struct sccb_card *)pCurrCard)->
1877 globalFlags & F_HOST_XFER_ACT) {
1878 FPT_phaseChkFifo(ioport, thisCard);
1881 if (RD_HARPOON(ioport + hp_gp_reg_1) ==
1882 SMSAVE_DATA_PTR) {
1883 WR_HARPOON(ioport + hp_gp_reg_1, 0x00);
1884 currSCCB->Sccb_XferState |=
1885 F_NO_DATA_YET;
1886 currSCCB->Sccb_savedATC =
1887 currSCCB->Sccb_ATC;
1890 WRW_HARPOON((ioport + hp_intstat),
1891 (BUS_FREE | ITAR_DISC));
1892 currSCCB->Sccb_scsistat = DISCONNECT_ST;
1893 FPT_queueDisconnect(currSCCB, thisCard);
1896 FPT_sres(ioport, thisCard,
1897 ((struct sccb_card *)pCurrCard));
1898 FPT_phaseDecode(ioport, thisCard);
1902 else if ((hp_int & IDO_STRT) && (!(hp_int & BUS_FREE))) {
1904 WRW_HARPOON((ioport + hp_intstat),
1905 (IDO_STRT | XFER_CNT_0));
1906 FPT_phaseDecode(ioport, thisCard);
1910 else if ((hp_int & IUNKWN) || (hp_int & PROG_HLT)) {
1911 WRW_HARPOON((ioport + hp_intstat),
1912 (PHASE | IUNKWN | PROG_HLT));
1913 if ((RD_HARPOON(ioport + hp_prgmcnt_0) & (unsigned char)
1914 0x3f) < (unsigned char)SELCHK) {
1915 FPT_phaseDecode(ioport, thisCard);
1916 } else {
1917 /* Harpoon problem some SCSI target device respond to selection
1918 with short BUSY pulse (<400ns) this will make the Harpoon is not able
1919 to latch the correct Target ID into reg. x53.
1920 The work around require to correct this reg. But when write to this
1921 reg. (0x53) also increment the FIFO write addr reg (0x6f), thus we
1922 need to read this reg first then restore it later. After update to 0x53 */
1924 i = (unsigned
1925 char)(RD_HARPOON(ioport + hp_fifowrite));
1926 target =
1927 (unsigned
1928 char)(RD_HARPOON(ioport + hp_gp_reg_3));
1929 WR_HARPOON(ioport + hp_xfer_pad,
1930 (unsigned char)ID_UNLOCK);
1931 WR_HARPOON(ioport + hp_select_id,
1932 (unsigned char)(target | target <<
1933 4));
1934 WR_HARPOON(ioport + hp_xfer_pad,
1935 (unsigned char)0x00);
1936 WR_HARPOON(ioport + hp_fifowrite, i);
1937 WR_HARPOON(ioport + hp_autostart_3,
1938 (AUTO_IMMED + TAG_STRT));
1942 else if (hp_int & XFER_CNT_0) {
1944 WRW_HARPOON((ioport + hp_intstat), XFER_CNT_0);
1946 FPT_schkdd(ioport, thisCard);
1950 else if (hp_int & BUS_FREE) {
1952 WRW_HARPOON((ioport + hp_intstat), BUS_FREE);
1954 if (((struct sccb_card *)pCurrCard)->
1955 globalFlags & F_HOST_XFER_ACT) {
1957 FPT_hostDataXferAbort(ioport, thisCard,
1958 currSCCB);
1961 FPT_phaseBusFree(ioport, thisCard);
1964 else if (hp_int & ITICKLE) {
1966 WRW_HARPOON((ioport + hp_intstat), ITICKLE);
1967 ((struct sccb_card *)pCurrCard)->globalFlags |=
1968 F_NEW_SCCB_CMD;
1971 if (((struct sccb_card *)pCurrCard)->
1972 globalFlags & F_NEW_SCCB_CMD) {
1974 ((struct sccb_card *)pCurrCard)->globalFlags &=
1975 ~F_NEW_SCCB_CMD;
1977 if (((struct sccb_card *)pCurrCard)->currentSCCB ==
1978 NULL) {
1980 FPT_queueSearchSelect(((struct sccb_card *)
1981 pCurrCard), thisCard);
1984 if (((struct sccb_card *)pCurrCard)->currentSCCB !=
1985 NULL) {
1986 ((struct sccb_card *)pCurrCard)->globalFlags &=
1987 ~F_NEW_SCCB_CMD;
1988 FPT_ssel(ioport, thisCard);
1991 break;
1995 } /*end while */
1997 MENABLE_INT(ioport);
1999 return 0;
2002 /*---------------------------------------------------------------------
2004 * Function: Sccb_bad_isr
2006 * Description: Some type of interrupt has occurred which is slightly
2007 * out of the ordinary. We will now decode it fully, in
2008 * this routine. This is broken up in an attempt to save
2009 * processing time.
2011 *---------------------------------------------------------------------*/
2012 static unsigned char FPT_SccbMgr_bad_isr(unsigned long p_port,
2013 unsigned char p_card,
2014 struct sccb_card *pCurrCard,
2015 unsigned short p_int)
2017 unsigned char temp, ScamFlg;
2018 struct sccb_mgr_tar_info *currTar_Info;
2019 struct nvram_info *pCurrNvRam;
2021 if (RD_HARPOON(p_port + hp_ext_status) &
2022 (BM_FORCE_OFF | PCI_DEV_TMOUT | BM_PARITY_ERR | PIO_OVERRUN)) {
2024 if (pCurrCard->globalFlags & F_HOST_XFER_ACT) {
2026 FPT_hostDataXferAbort(p_port, p_card,
2027 pCurrCard->currentSCCB);
2030 if (RD_HARPOON(p_port + hp_pci_stat_cfg) & REC_MASTER_ABORT)
2032 WR_HARPOON(p_port + hp_pci_stat_cfg,
2033 (RD_HARPOON(p_port + hp_pci_stat_cfg) &
2034 ~REC_MASTER_ABORT));
2036 WR_HARPOON(p_port + hp_host_blk_cnt, 0x00);
2040 if (pCurrCard->currentSCCB != NULL) {
2042 if (!pCurrCard->currentSCCB->HostStatus)
2043 pCurrCard->currentSCCB->HostStatus =
2044 SCCB_BM_ERR;
2046 FPT_sxfrp(p_port, p_card);
2048 temp = (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
2049 (EXT_ARB_ACK | SCSI_TERM_ENA_H));
2050 WR_HARPOON(p_port + hp_ee_ctrl,
2051 ((unsigned char)temp | SEE_MS | SEE_CS));
2052 WR_HARPOON(p_port + hp_ee_ctrl, temp);
2054 if (!
2055 (RDW_HARPOON((p_port + hp_intstat)) &
2056 (BUS_FREE | RESET))) {
2057 FPT_phaseDecode(p_port, p_card);
2062 else if (p_int & RESET) {
2064 WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
2065 WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
2066 if (pCurrCard->currentSCCB != NULL) {
2068 if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
2070 FPT_hostDataXferAbort(p_port, p_card,
2071 pCurrCard->currentSCCB);
2074 DISABLE_AUTO(p_port);
2076 FPT_sresb(p_port, p_card);
2078 while (RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST) {
2081 pCurrNvRam = pCurrCard->pNvRamInfo;
2082 if (pCurrNvRam) {
2083 ScamFlg = pCurrNvRam->niScamConf;
2084 } else {
2085 ScamFlg =
2086 (unsigned char)FPT_utilEERead(p_port,
2087 SCAM_CONFIG / 2);
2090 FPT_XbowInit(p_port, ScamFlg);
2092 FPT_scini(p_card, pCurrCard->ourId, 0);
2094 return 0xFF;
2097 else if (p_int & FIFO) {
2099 WRW_HARPOON((p_port + hp_intstat), FIFO);
2101 if (pCurrCard->currentSCCB != NULL)
2102 FPT_sxfrp(p_port, p_card);
2105 else if (p_int & TIMEOUT) {
2107 DISABLE_AUTO(p_port);
2109 WRW_HARPOON((p_port + hp_intstat),
2110 (PROG_HLT | TIMEOUT | SEL | BUS_FREE | PHASE |
2111 IUNKWN));
2113 pCurrCard->currentSCCB->HostStatus = SCCB_SELECTION_TIMEOUT;
2115 currTar_Info =
2116 &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
2117 if ((pCurrCard->globalFlags & F_CONLUN_IO)
2118 && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
2119 TAG_Q_TRYING))
2120 currTar_Info->TarLUNBusy[pCurrCard->currentSCCB->Lun] =
2122 else
2123 currTar_Info->TarLUNBusy[0] = 0;
2125 if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
2126 currTar_Info->TarSyncCtrl = 0;
2127 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2130 if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
2131 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2134 FPT_sssyncv(p_port, pCurrCard->currentSCCB->TargID, NARROW_SCSI,
2135 currTar_Info);
2137 FPT_queueCmdComplete(pCurrCard, pCurrCard->currentSCCB, p_card);
2141 else if (p_int & SCAM_SEL) {
2143 FPT_scarb(p_port, LEVEL2_TAR);
2144 FPT_scsel(p_port);
2145 FPT_scasid(p_card, p_port);
2147 FPT_scbusf(p_port);
2149 WRW_HARPOON((p_port + hp_intstat), SCAM_SEL);
2152 return 0x00;
2155 /*---------------------------------------------------------------------
2157 * Function: SccbMgrTableInit
2159 * Description: Initialize all Sccb manager data structures.
2161 *---------------------------------------------------------------------*/
2163 static void FPT_SccbMgrTableInitAll()
2165 unsigned char thisCard;
2167 for (thisCard = 0; thisCard < MAX_CARDS; thisCard++) {
2168 FPT_SccbMgrTableInitCard(&FPT_BL_Card[thisCard], thisCard);
2170 FPT_BL_Card[thisCard].ioPort = 0x00;
2171 FPT_BL_Card[thisCard].cardInfo = NULL;
2172 FPT_BL_Card[thisCard].cardIndex = 0xFF;
2173 FPT_BL_Card[thisCard].ourId = 0x00;
2174 FPT_BL_Card[thisCard].pNvRamInfo = NULL;
2178 /*---------------------------------------------------------------------
2180 * Function: SccbMgrTableInit
2182 * Description: Initialize all Sccb manager data structures.
2184 *---------------------------------------------------------------------*/
2186 static void FPT_SccbMgrTableInitCard(struct sccb_card *pCurrCard,
2187 unsigned char p_card)
2189 unsigned char scsiID, qtag;
2191 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
2192 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
2195 for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
2196 FPT_sccbMgrTbl[p_card][scsiID].TarStatus = 0;
2197 FPT_sccbMgrTbl[p_card][scsiID].TarEEValue = 0;
2198 FPT_SccbMgrTableInitTarget(p_card, scsiID);
2201 pCurrCard->scanIndex = 0x00;
2202 pCurrCard->currentSCCB = NULL;
2203 pCurrCard->globalFlags = 0x00;
2204 pCurrCard->cmdCounter = 0x00;
2205 pCurrCard->tagQ_Lst = 0x01;
2206 pCurrCard->discQCount = 0;
2210 /*---------------------------------------------------------------------
2212 * Function: SccbMgrTableInit
2214 * Description: Initialize all Sccb manager data structures.
2216 *---------------------------------------------------------------------*/
2218 static void FPT_SccbMgrTableInitTarget(unsigned char p_card,
2219 unsigned char target)
2222 unsigned char lun, qtag;
2223 struct sccb_mgr_tar_info *currTar_Info;
2225 currTar_Info = &FPT_sccbMgrTbl[p_card][target];
2227 currTar_Info->TarSelQ_Cnt = 0;
2228 currTar_Info->TarSyncCtrl = 0;
2230 currTar_Info->TarSelQ_Head = NULL;
2231 currTar_Info->TarSelQ_Tail = NULL;
2232 currTar_Info->TarTagQ_Cnt = 0;
2233 currTar_Info->TarLUN_CA = 0;
2235 for (lun = 0; lun < MAX_LUN; lun++) {
2236 currTar_Info->TarLUNBusy[lun] = 0;
2237 currTar_Info->LunDiscQ_Idx[lun] = 0;
2240 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
2241 if (FPT_BL_Card[p_card].discQ_Tbl[qtag] != NULL) {
2242 if (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
2243 target) {
2244 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
2245 FPT_BL_Card[p_card].discQCount--;
2251 /*---------------------------------------------------------------------
2253 * Function: sfetm
2255 * Description: Read in a message byte from the SCSI bus, and check
2256 * for a parity error.
2258 *---------------------------------------------------------------------*/
2260 static unsigned char FPT_sfm(unsigned long port, struct sccb *pCurrSCCB)
2262 unsigned char message;
2263 unsigned short TimeOutLoop;
2265 TimeOutLoop = 0;
2266 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2267 (TimeOutLoop++ < 20000)) {
2270 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
2272 message = RD_HARPOON(port + hp_scsidata_0);
2274 WR_HARPOON(port + hp_scsisig, SCSI_ACK + S_MSGI_PH);
2276 if (TimeOutLoop > 20000)
2277 message = 0x00; /* force message byte = 0 if Time Out on Req */
2279 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
2280 (RD_HARPOON(port + hp_addstat) & SCSI_PAR_ERR)) {
2281 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2282 WR_HARPOON(port + hp_xferstat, 0);
2283 WR_HARPOON(port + hp_fiforead, 0);
2284 WR_HARPOON(port + hp_fifowrite, 0);
2285 if (pCurrSCCB != NULL) {
2286 pCurrSCCB->Sccb_scsimsg = SMPARITY;
2288 message = 0x00;
2289 do {
2290 ACCEPT_MSG_ATN(port);
2291 TimeOutLoop = 0;
2292 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2293 (TimeOutLoop++ < 20000)) {
2295 if (TimeOutLoop > 20000) {
2296 WRW_HARPOON((port + hp_intstat), PARITY);
2297 return message;
2299 if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) !=
2300 S_MSGI_PH) {
2301 WRW_HARPOON((port + hp_intstat), PARITY);
2302 return message;
2304 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
2306 RD_HARPOON(port + hp_scsidata_0);
2308 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2310 } while (1);
2313 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2314 WR_HARPOON(port + hp_xferstat, 0);
2315 WR_HARPOON(port + hp_fiforead, 0);
2316 WR_HARPOON(port + hp_fifowrite, 0);
2317 return message;
2320 /*---------------------------------------------------------------------
2322 * Function: FPT_ssel
2324 * Description: Load up automation and select target device.
2326 *---------------------------------------------------------------------*/
2328 static void FPT_ssel(unsigned long port, unsigned char p_card)
2331 unsigned char auto_loaded, i, target, *theCCB;
2333 unsigned long cdb_reg;
2334 struct sccb_card *CurrCard;
2335 struct sccb *currSCCB;
2336 struct sccb_mgr_tar_info *currTar_Info;
2337 unsigned char lastTag, lun;
2339 CurrCard = &FPT_BL_Card[p_card];
2340 currSCCB = CurrCard->currentSCCB;
2341 target = currSCCB->TargID;
2342 currTar_Info = &FPT_sccbMgrTbl[p_card][target];
2343 lastTag = CurrCard->tagQ_Lst;
2345 ARAM_ACCESS(port);
2347 if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
2348 currSCCB->ControlByte &= ~F_USE_CMD_Q;
2350 if (((CurrCard->globalFlags & F_CONLUN_IO) &&
2351 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING)))
2353 lun = currSCCB->Lun;
2354 else
2355 lun = 0;
2357 if (CurrCard->globalFlags & F_TAG_STARTED) {
2358 if (!(currSCCB->ControlByte & F_USE_CMD_Q)) {
2359 if ((currTar_Info->TarLUN_CA == 0)
2360 && ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
2361 == TAG_Q_TRYING)) {
2363 if (currTar_Info->TarTagQ_Cnt != 0) {
2364 currTar_Info->TarLUNBusy[lun] = 1;
2365 FPT_queueSelectFail(CurrCard, p_card);
2366 SGRAM_ACCESS(port);
2367 return;
2370 else {
2371 currTar_Info->TarLUNBusy[lun] = 1;
2375 /*End non-tagged */
2376 else {
2377 currTar_Info->TarLUNBusy[lun] = 1;
2381 /*!Use cmd Q Tagged */
2382 else {
2383 if (currTar_Info->TarLUN_CA == 1) {
2384 FPT_queueSelectFail(CurrCard, p_card);
2385 SGRAM_ACCESS(port);
2386 return;
2389 currTar_Info->TarLUNBusy[lun] = 1;
2391 } /*else use cmd Q tagged */
2394 /*if glob tagged started */
2395 else {
2396 currTar_Info->TarLUNBusy[lun] = 1;
2399 if ((((CurrCard->globalFlags & F_CONLUN_IO) &&
2400 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
2401 || (!(currSCCB->ControlByte & F_USE_CMD_Q)))) {
2402 if (CurrCard->discQCount >= QUEUE_DEPTH) {
2403 currTar_Info->TarLUNBusy[lun] = 1;
2404 FPT_queueSelectFail(CurrCard, p_card);
2405 SGRAM_ACCESS(port);
2406 return;
2408 for (i = 1; i < QUEUE_DEPTH; i++) {
2409 if (++lastTag >= QUEUE_DEPTH)
2410 lastTag = 1;
2411 if (CurrCard->discQ_Tbl[lastTag] == NULL) {
2412 CurrCard->tagQ_Lst = lastTag;
2413 currTar_Info->LunDiscQ_Idx[lun] = lastTag;
2414 CurrCard->discQ_Tbl[lastTag] = currSCCB;
2415 CurrCard->discQCount++;
2416 break;
2419 if (i == QUEUE_DEPTH) {
2420 currTar_Info->TarLUNBusy[lun] = 1;
2421 FPT_queueSelectFail(CurrCard, p_card);
2422 SGRAM_ACCESS(port);
2423 return;
2427 auto_loaded = 0;
2429 WR_HARPOON(port + hp_select_id, target);
2430 WR_HARPOON(port + hp_gp_reg_3, target); /* Use by new automation logic */
2432 if (currSCCB->OperationCode == RESET_COMMAND) {
2433 WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
2434 (currSCCB->
2435 Sccb_idmsg & ~DISC_PRIV)));
2437 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + NP);
2439 currSCCB->Sccb_scsimsg = SMDEV_RESET;
2441 WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
2442 auto_loaded = 1;
2443 currSCCB->Sccb_scsistat = SELECT_BDR_ST;
2445 if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
2446 currTar_Info->TarSyncCtrl = 0;
2447 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2450 if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
2451 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2454 FPT_sssyncv(port, target, NARROW_SCSI, currTar_Info);
2455 FPT_SccbMgrTableInitTarget(p_card, target);
2459 else if (currSCCB->Sccb_scsistat == ABORT_ST) {
2460 WRW_HARPOON((port + ID_MSG_STRT), (MPM_OP + AMSG_OUT +
2461 (currSCCB->
2462 Sccb_idmsg & ~DISC_PRIV)));
2464 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
2466 WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT +
2467 (((unsigned
2468 char)(currSCCB->
2469 ControlByte &
2470 TAG_TYPE_MASK)
2471 >> 6) | (unsigned char)
2472 0x20)));
2473 WRW_HARPOON((port + SYNC_MSGS + 2),
2474 (MPM_OP + AMSG_OUT + currSCCB->Sccb_tag));
2475 WRW_HARPOON((port + SYNC_MSGS + 4), (BRH_OP + ALWAYS + NP));
2477 WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
2478 auto_loaded = 1;
2482 else if (!(currTar_Info->TarStatus & WIDE_NEGOCIATED)) {
2483 auto_loaded = FPT_siwidn(port, p_card);
2484 currSCCB->Sccb_scsistat = SELECT_WN_ST;
2487 else if (!((currTar_Info->TarStatus & TAR_SYNC_MASK)
2488 == SYNC_SUPPORTED)) {
2489 auto_loaded = FPT_sisyncn(port, p_card, 0);
2490 currSCCB->Sccb_scsistat = SELECT_SN_ST;
2493 if (!auto_loaded) {
2495 if (currSCCB->ControlByte & F_USE_CMD_Q) {
2497 CurrCard->globalFlags |= F_TAG_STARTED;
2499 if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK)
2500 == TAG_Q_REJECT) {
2501 currSCCB->ControlByte &= ~F_USE_CMD_Q;
2503 /* Fix up the start instruction with a jump to
2504 Non-Tag-CMD handling */
2505 WRW_HARPOON((port + ID_MSG_STRT),
2506 BRH_OP + ALWAYS + NTCMD);
2508 WRW_HARPOON((port + NON_TAG_ID_MSG),
2509 (MPM_OP + AMSG_OUT +
2510 currSCCB->Sccb_idmsg));
2512 WR_HARPOON(port + hp_autostart_3,
2513 (SELECT + SELCHK_STRT));
2515 /* Setup our STATE so we know what happend when
2516 the wheels fall off. */
2517 currSCCB->Sccb_scsistat = SELECT_ST;
2519 currTar_Info->TarLUNBusy[lun] = 1;
2522 else {
2523 WRW_HARPOON((port + ID_MSG_STRT),
2524 (MPM_OP + AMSG_OUT +
2525 currSCCB->Sccb_idmsg));
2527 WRW_HARPOON((port + ID_MSG_STRT + 2),
2528 (MPM_OP + AMSG_OUT +
2529 (((unsigned char)(currSCCB->
2530 ControlByte &
2531 TAG_TYPE_MASK)
2532 >> 6) | (unsigned char)0x20)));
2534 for (i = 1; i < QUEUE_DEPTH; i++) {
2535 if (++lastTag >= QUEUE_DEPTH)
2536 lastTag = 1;
2537 if (CurrCard->discQ_Tbl[lastTag] ==
2538 NULL) {
2539 WRW_HARPOON((port +
2540 ID_MSG_STRT + 6),
2541 (MPM_OP + AMSG_OUT +
2542 lastTag));
2543 CurrCard->tagQ_Lst = lastTag;
2544 currSCCB->Sccb_tag = lastTag;
2545 CurrCard->discQ_Tbl[lastTag] =
2546 currSCCB;
2547 CurrCard->discQCount++;
2548 break;
2552 if (i == QUEUE_DEPTH) {
2553 currTar_Info->TarLUNBusy[lun] = 1;
2554 FPT_queueSelectFail(CurrCard, p_card);
2555 SGRAM_ACCESS(port);
2556 return;
2559 currSCCB->Sccb_scsistat = SELECT_Q_ST;
2561 WR_HARPOON(port + hp_autostart_3,
2562 (SELECT + SELCHK_STRT));
2566 else {
2568 WRW_HARPOON((port + ID_MSG_STRT),
2569 BRH_OP + ALWAYS + NTCMD);
2571 WRW_HARPOON((port + NON_TAG_ID_MSG),
2572 (MPM_OP + AMSG_OUT + currSCCB->Sccb_idmsg));
2574 currSCCB->Sccb_scsistat = SELECT_ST;
2576 WR_HARPOON(port + hp_autostart_3,
2577 (SELECT + SELCHK_STRT));
2580 theCCB = (unsigned char *)&currSCCB->Cdb[0];
2582 cdb_reg = port + CMD_STRT;
2584 for (i = 0; i < currSCCB->CdbLength; i++) {
2585 WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + *theCCB));
2586 cdb_reg += 2;
2587 theCCB++;
2590 if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
2591 WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
2594 /* auto_loaded */
2595 WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
2596 WR_HARPOON(port + hp_xferstat, 0x00);
2598 WRW_HARPOON((port + hp_intstat), (PROG_HLT | TIMEOUT | SEL | BUS_FREE));
2600 WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT));
2602 if (!(currSCCB->Sccb_MGRFlags & F_DEV_SELECTED)) {
2603 WR_HARPOON(port + hp_scsictrl_0,
2604 (SEL_TAR | ENA_ATN | ENA_RESEL | ENA_SCAM_SEL));
2605 } else {
2607 /* auto_loaded = (RD_HARPOON(port+hp_autostart_3) & (unsigned char)0x1F);
2608 auto_loaded |= AUTO_IMMED; */
2609 auto_loaded = AUTO_IMMED;
2611 DISABLE_AUTO(port);
2613 WR_HARPOON(port + hp_autostart_3, auto_loaded);
2616 SGRAM_ACCESS(port);
2619 /*---------------------------------------------------------------------
2621 * Function: FPT_sres
2623 * Description: Hookup the correct CCB and handle the incoming messages.
2625 *---------------------------------------------------------------------*/
2627 static void FPT_sres(unsigned long port, unsigned char p_card,
2628 struct sccb_card *pCurrCard)
2631 unsigned char our_target, message, lun = 0, tag, msgRetryCount;
2633 struct sccb_mgr_tar_info *currTar_Info;
2634 struct sccb *currSCCB;
2636 if (pCurrCard->currentSCCB != NULL) {
2637 currTar_Info =
2638 &FPT_sccbMgrTbl[p_card][pCurrCard->currentSCCB->TargID];
2639 DISABLE_AUTO(port);
2641 WR_HARPOON((port + hp_scsictrl_0), (ENA_RESEL | ENA_SCAM_SEL));
2643 currSCCB = pCurrCard->currentSCCB;
2644 if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
2645 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
2646 currSCCB->Sccb_scsistat = BUS_FREE_ST;
2648 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
2649 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
2650 currSCCB->Sccb_scsistat = BUS_FREE_ST;
2652 if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
2653 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
2654 TAG_Q_TRYING))) {
2655 currTar_Info->TarLUNBusy[currSCCB->Lun] = 0;
2656 if (currSCCB->Sccb_scsistat != ABORT_ST) {
2657 pCurrCard->discQCount--;
2658 pCurrCard->discQ_Tbl[currTar_Info->
2659 LunDiscQ_Idx[currSCCB->
2660 Lun]]
2661 = NULL;
2663 } else {
2664 currTar_Info->TarLUNBusy[0] = 0;
2665 if (currSCCB->Sccb_tag) {
2666 if (currSCCB->Sccb_scsistat != ABORT_ST) {
2667 pCurrCard->discQCount--;
2668 pCurrCard->discQ_Tbl[currSCCB->
2669 Sccb_tag] = NULL;
2671 } else {
2672 if (currSCCB->Sccb_scsistat != ABORT_ST) {
2673 pCurrCard->discQCount--;
2674 pCurrCard->discQ_Tbl[currTar_Info->
2675 LunDiscQ_Idx[0]] =
2676 NULL;
2681 FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
2684 WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
2686 our_target = (unsigned char)(RD_HARPOON(port + hp_select_id) >> 4);
2687 currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
2689 msgRetryCount = 0;
2690 do {
2692 currTar_Info = &FPT_sccbMgrTbl[p_card][our_target];
2693 tag = 0;
2695 while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
2696 if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
2698 WRW_HARPOON((port + hp_intstat), PHASE);
2699 return;
2703 WRW_HARPOON((port + hp_intstat), PHASE);
2704 if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGI_PH) {
2706 message = FPT_sfm(port, pCurrCard->currentSCCB);
2707 if (message) {
2709 if (message <= (0x80 | LUN_MASK)) {
2710 lun = message & (unsigned char)LUN_MASK;
2712 if ((currTar_Info->
2713 TarStatus & TAR_TAG_Q_MASK) ==
2714 TAG_Q_TRYING) {
2715 if (currTar_Info->TarTagQ_Cnt !=
2716 0) {
2718 if (!
2719 (currTar_Info->
2720 TarLUN_CA)) {
2721 ACCEPT_MSG(port); /*Release the ACK for ID msg. */
2723 message =
2724 FPT_sfm
2725 (port,
2726 pCurrCard->
2727 currentSCCB);
2728 if (message) {
2729 ACCEPT_MSG
2730 (port);
2733 else
2734 message
2735 = 0;
2737 if (message !=
2738 0) {
2739 tag =
2740 FPT_sfm
2741 (port,
2742 pCurrCard->
2743 currentSCCB);
2745 if (!
2746 (tag))
2747 message
2753 /*C.A. exists! */
2755 /*End Q cnt != 0 */
2757 /*End Tag cmds supported! */
2759 /*End valid ID message. */
2760 else {
2762 ACCEPT_MSG_ATN(port);
2766 /* End good id message. */
2767 else {
2769 message = 0;
2771 } else {
2772 ACCEPT_MSG_ATN(port);
2774 while (!
2775 (RDW_HARPOON((port + hp_intstat)) &
2776 (PHASE | RESET))
2777 && !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
2778 && (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
2780 return;
2783 if (message == 0) {
2784 msgRetryCount++;
2785 if (msgRetryCount == 1) {
2786 FPT_SendMsg(port, SMPARITY);
2787 } else {
2788 FPT_SendMsg(port, SMDEV_RESET);
2790 FPT_sssyncv(port, our_target, NARROW_SCSI,
2791 currTar_Info);
2793 if (FPT_sccbMgrTbl[p_card][our_target].
2794 TarEEValue & EE_SYNC_MASK) {
2796 FPT_sccbMgrTbl[p_card][our_target].
2797 TarStatus &= ~TAR_SYNC_MASK;
2801 if (FPT_sccbMgrTbl[p_card][our_target].
2802 TarEEValue & EE_WIDE_SCSI) {
2804 FPT_sccbMgrTbl[p_card][our_target].
2805 TarStatus &= ~TAR_WIDE_MASK;
2808 FPT_queueFlushTargSccb(p_card, our_target,
2809 SCCB_COMPLETE);
2810 FPT_SccbMgrTableInitTarget(p_card, our_target);
2811 return;
2814 } while (message == 0);
2816 if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
2817 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
2818 currTar_Info->TarLUNBusy[lun] = 1;
2819 pCurrCard->currentSCCB =
2820 pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[lun]];
2821 if (pCurrCard->currentSCCB != NULL) {
2822 ACCEPT_MSG(port);
2823 } else {
2824 ACCEPT_MSG_ATN(port);
2826 } else {
2827 currTar_Info->TarLUNBusy[0] = 1;
2829 if (tag) {
2830 if (pCurrCard->discQ_Tbl[tag] != NULL) {
2831 pCurrCard->currentSCCB =
2832 pCurrCard->discQ_Tbl[tag];
2833 currTar_Info->TarTagQ_Cnt--;
2834 ACCEPT_MSG(port);
2835 } else {
2836 ACCEPT_MSG_ATN(port);
2838 } else {
2839 pCurrCard->currentSCCB =
2840 pCurrCard->discQ_Tbl[currTar_Info->LunDiscQ_Idx[0]];
2841 if (pCurrCard->currentSCCB != NULL) {
2842 ACCEPT_MSG(port);
2843 } else {
2844 ACCEPT_MSG_ATN(port);
2849 if (pCurrCard->currentSCCB != NULL) {
2850 if (pCurrCard->currentSCCB->Sccb_scsistat == ABORT_ST) {
2851 /* During Abort Tag command, the target could have got re-selected
2852 and completed the command. Check the select Q and remove the CCB
2853 if it is in the Select Q */
2854 FPT_queueFindSccb(pCurrCard->currentSCCB, p_card);
2858 while (!(RDW_HARPOON((port + hp_intstat)) & (PHASE | RESET)) &&
2859 !(RD_HARPOON(port + hp_scsisig) & SCSI_REQ) &&
2860 (RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ;
2863 static void FPT_SendMsg(unsigned long port, unsigned char message)
2865 while (!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) {
2866 if (!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) {
2868 WRW_HARPOON((port + hp_intstat), PHASE);
2869 return;
2873 WRW_HARPOON((port + hp_intstat), PHASE);
2874 if ((RD_HARPOON(port + hp_scsisig) & S_SCSI_PHZ) == S_MSGO_PH) {
2875 WRW_HARPOON((port + hp_intstat),
2876 (BUS_FREE | PHASE | XFER_CNT_0));
2878 WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
2880 WR_HARPOON(port + hp_scsidata_0, message);
2882 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
2884 ACCEPT_MSG(port);
2886 WR_HARPOON(port + hp_portctrl_0, 0x00);
2888 if ((message == SMABORT) || (message == SMDEV_RESET) ||
2889 (message == SMABORT_TAG)) {
2890 while (!
2891 (RDW_HARPOON((port + hp_intstat)) &
2892 (BUS_FREE | PHASE))) {
2895 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
2896 WRW_HARPOON((port + hp_intstat), BUS_FREE);
2902 /*---------------------------------------------------------------------
2904 * Function: FPT_sdecm
2906 * Description: Determine the proper responce to the message from the
2907 * target device.
2909 *---------------------------------------------------------------------*/
2910 static void FPT_sdecm(unsigned char message, unsigned long port,
2911 unsigned char p_card)
2913 struct sccb *currSCCB;
2914 struct sccb_card *CurrCard;
2915 struct sccb_mgr_tar_info *currTar_Info;
2917 CurrCard = &FPT_BL_Card[p_card];
2918 currSCCB = CurrCard->currentSCCB;
2920 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
2922 if (message == SMREST_DATA_PTR) {
2923 if (!(currSCCB->Sccb_XferState & F_NO_DATA_YET)) {
2924 currSCCB->Sccb_ATC = currSCCB->Sccb_savedATC;
2926 FPT_hostDataXferRestart(currSCCB);
2929 ACCEPT_MSG(port);
2930 WR_HARPOON(port + hp_autostart_1,
2931 (AUTO_IMMED + DISCONNECT_START));
2934 else if (message == SMCMD_COMP) {
2936 if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
2937 currTar_Info->TarStatus &=
2938 ~(unsigned char)TAR_TAG_Q_MASK;
2939 currTar_Info->TarStatus |= (unsigned char)TAG_Q_REJECT;
2942 ACCEPT_MSG(port);
2946 else if ((message == SMNO_OP) || (message >= SMIDENT)
2947 || (message == SMINIT_RECOVERY) || (message == SMREL_RECOVERY)) {
2949 ACCEPT_MSG(port);
2950 WR_HARPOON(port + hp_autostart_1,
2951 (AUTO_IMMED + DISCONNECT_START));
2954 else if (message == SMREJECT) {
2956 if ((currSCCB->Sccb_scsistat == SELECT_SN_ST) ||
2957 (currSCCB->Sccb_scsistat == SELECT_WN_ST) ||
2958 ((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)
2959 || ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) ==
2960 TAG_Q_TRYING))
2962 WRW_HARPOON((port + hp_intstat), BUS_FREE);
2964 ACCEPT_MSG(port);
2966 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
2967 (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
2971 if (currSCCB->Lun == 0x00) {
2972 if ((currSCCB->Sccb_scsistat == SELECT_SN_ST)) {
2974 currTar_Info->TarStatus |=
2975 (unsigned char)SYNC_SUPPORTED;
2977 currTar_Info->TarEEValue &=
2978 ~EE_SYNC_MASK;
2981 else if ((currSCCB->Sccb_scsistat ==
2982 SELECT_WN_ST)) {
2984 currTar_Info->TarStatus =
2985 (currTar_Info->
2986 TarStatus & ~WIDE_ENABLED) |
2987 WIDE_NEGOCIATED;
2989 currTar_Info->TarEEValue &=
2990 ~EE_WIDE_SCSI;
2994 else if ((currTar_Info->
2995 TarStatus & TAR_TAG_Q_MASK) ==
2996 TAG_Q_TRYING) {
2997 currTar_Info->TarStatus =
2998 (currTar_Info->
2999 TarStatus & ~(unsigned char)
3000 TAR_TAG_Q_MASK) | TAG_Q_REJECT;
3002 currSCCB->ControlByte &= ~F_USE_CMD_Q;
3003 CurrCard->discQCount--;
3004 CurrCard->discQ_Tbl[currSCCB->
3005 Sccb_tag] = NULL;
3006 currSCCB->Sccb_tag = 0x00;
3011 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
3013 if (currSCCB->Lun == 0x00) {
3014 WRW_HARPOON((port + hp_intstat),
3015 BUS_FREE);
3016 CurrCard->globalFlags |= F_NEW_SCCB_CMD;
3020 else {
3022 if ((CurrCard->globalFlags & F_CONLUN_IO) &&
3023 ((currTar_Info->
3024 TarStatus & TAR_TAG_Q_MASK) !=
3025 TAG_Q_TRYING))
3026 currTar_Info->TarLUNBusy[currSCCB->
3027 Lun] = 1;
3028 else
3029 currTar_Info->TarLUNBusy[0] = 1;
3031 currSCCB->ControlByte &=
3032 ~(unsigned char)F_USE_CMD_Q;
3034 WR_HARPOON(port + hp_autostart_1,
3035 (AUTO_IMMED + DISCONNECT_START));
3040 else {
3041 ACCEPT_MSG(port);
3043 while ((!(RD_HARPOON(port + hp_scsisig) & SCSI_REQ)) &&
3044 (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)))
3048 if (!(RDW_HARPOON((port + hp_intstat)) & BUS_FREE)) {
3049 WR_HARPOON(port + hp_autostart_1,
3050 (AUTO_IMMED + DISCONNECT_START));
3055 else if (message == SMEXT) {
3057 ACCEPT_MSG(port);
3058 FPT_shandem(port, p_card, currSCCB);
3061 else if (message == SMIGNORWR) {
3063 ACCEPT_MSG(port); /* ACK the RESIDUE MSG */
3065 message = FPT_sfm(port, currSCCB);
3067 if (currSCCB->Sccb_scsimsg != SMPARITY)
3068 ACCEPT_MSG(port);
3069 WR_HARPOON(port + hp_autostart_1,
3070 (AUTO_IMMED + DISCONNECT_START));
3073 else {
3075 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
3076 currSCCB->Sccb_scsimsg = SMREJECT;
3078 ACCEPT_MSG_ATN(port);
3079 WR_HARPOON(port + hp_autostart_1,
3080 (AUTO_IMMED + DISCONNECT_START));
3084 /*---------------------------------------------------------------------
3086 * Function: FPT_shandem
3088 * Description: Decide what to do with the extended message.
3090 *---------------------------------------------------------------------*/
3091 static void FPT_shandem(unsigned long port, unsigned char p_card,
3092 struct sccb *pCurrSCCB)
3094 unsigned char length, message;
3096 length = FPT_sfm(port, pCurrSCCB);
3097 if (length) {
3099 ACCEPT_MSG(port);
3100 message = FPT_sfm(port, pCurrSCCB);
3101 if (message) {
3103 if (message == SMSYNC) {
3105 if (length == 0x03) {
3107 ACCEPT_MSG(port);
3108 FPT_stsyncn(port, p_card);
3109 } else {
3111 pCurrSCCB->Sccb_scsimsg = SMREJECT;
3112 ACCEPT_MSG_ATN(port);
3114 } else if (message == SMWDTR) {
3116 if (length == 0x02) {
3118 ACCEPT_MSG(port);
3119 FPT_stwidn(port, p_card);
3120 } else {
3122 pCurrSCCB->Sccb_scsimsg = SMREJECT;
3123 ACCEPT_MSG_ATN(port);
3125 WR_HARPOON(port + hp_autostart_1,
3126 (AUTO_IMMED +
3127 DISCONNECT_START));
3129 } else {
3131 pCurrSCCB->Sccb_scsimsg = SMREJECT;
3132 ACCEPT_MSG_ATN(port);
3134 WR_HARPOON(port + hp_autostart_1,
3135 (AUTO_IMMED + DISCONNECT_START));
3137 } else {
3138 if (pCurrSCCB->Sccb_scsimsg != SMPARITY)
3139 ACCEPT_MSG(port);
3140 WR_HARPOON(port + hp_autostart_1,
3141 (AUTO_IMMED + DISCONNECT_START));
3143 } else {
3144 if (pCurrSCCB->Sccb_scsimsg == SMPARITY)
3145 WR_HARPOON(port + hp_autostart_1,
3146 (AUTO_IMMED + DISCONNECT_START));
3150 /*---------------------------------------------------------------------
3152 * Function: FPT_sisyncn
3154 * Description: Read in a message byte from the SCSI bus, and check
3155 * for a parity error.
3157 *---------------------------------------------------------------------*/
3159 static unsigned char FPT_sisyncn(unsigned long port, unsigned char p_card,
3160 unsigned char syncFlag)
3162 struct sccb *currSCCB;
3163 struct sccb_mgr_tar_info *currTar_Info;
3165 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3166 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
3168 if (!((currTar_Info->TarStatus & TAR_SYNC_MASK) == SYNC_TRYING)) {
3170 WRW_HARPOON((port + ID_MSG_STRT),
3171 (MPM_OP + AMSG_OUT +
3172 (currSCCB->
3173 Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
3175 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
3177 WRW_HARPOON((port + SYNC_MSGS + 0),
3178 (MPM_OP + AMSG_OUT + SMEXT));
3179 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
3180 WRW_HARPOON((port + SYNC_MSGS + 4),
3181 (MPM_OP + AMSG_OUT + SMSYNC));
3183 if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
3185 WRW_HARPOON((port + SYNC_MSGS + 6),
3186 (MPM_OP + AMSG_OUT + 12));
3188 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
3189 EE_SYNC_10MB)
3191 WRW_HARPOON((port + SYNC_MSGS + 6),
3192 (MPM_OP + AMSG_OUT + 25));
3194 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) ==
3195 EE_SYNC_5MB)
3197 WRW_HARPOON((port + SYNC_MSGS + 6),
3198 (MPM_OP + AMSG_OUT + 50));
3200 else
3201 WRW_HARPOON((port + SYNC_MSGS + 6),
3202 (MPM_OP + AMSG_OUT + 00));
3204 WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
3205 WRW_HARPOON((port + SYNC_MSGS + 10),
3206 (MPM_OP + AMSG_OUT + DEFAULT_OFFSET));
3207 WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
3209 if (syncFlag == 0) {
3210 WR_HARPOON(port + hp_autostart_3,
3211 (SELECT + SELCHK_STRT));
3212 currTar_Info->TarStatus =
3213 ((currTar_Info->
3214 TarStatus & ~(unsigned char)TAR_SYNC_MASK) |
3215 (unsigned char)SYNC_TRYING);
3216 } else {
3217 WR_HARPOON(port + hp_autostart_3,
3218 (AUTO_IMMED + CMD_ONLY_STRT));
3221 return 1;
3224 else {
3226 currTar_Info->TarStatus |= (unsigned char)SYNC_SUPPORTED;
3227 currTar_Info->TarEEValue &= ~EE_SYNC_MASK;
3228 return 0;
3232 /*---------------------------------------------------------------------
3234 * Function: FPT_stsyncn
3236 * Description: The has sent us a Sync Nego message so handle it as
3237 * necessary.
3239 *---------------------------------------------------------------------*/
3240 static void FPT_stsyncn(unsigned long port, unsigned char p_card)
3242 unsigned char sync_msg, offset, sync_reg, our_sync_msg;
3243 struct sccb *currSCCB;
3244 struct sccb_mgr_tar_info *currTar_Info;
3246 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3247 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
3249 sync_msg = FPT_sfm(port, currSCCB);
3251 if ((sync_msg == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3252 WR_HARPOON(port + hp_autostart_1,
3253 (AUTO_IMMED + DISCONNECT_START));
3254 return;
3257 ACCEPT_MSG(port);
3259 offset = FPT_sfm(port, currSCCB);
3261 if ((offset == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3262 WR_HARPOON(port + hp_autostart_1,
3263 (AUTO_IMMED + DISCONNECT_START));
3264 return;
3267 if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_20MB)
3269 our_sync_msg = 12; /* Setup our Message to 20mb/s */
3271 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_10MB)
3273 our_sync_msg = 25; /* Setup our Message to 10mb/s */
3275 else if ((currTar_Info->TarEEValue & EE_SYNC_MASK) == EE_SYNC_5MB)
3277 our_sync_msg = 50; /* Setup our Message to 5mb/s */
3278 else
3280 our_sync_msg = 0; /* Message = Async */
3282 if (sync_msg < our_sync_msg) {
3283 sync_msg = our_sync_msg; /*if faster, then set to max. */
3286 if (offset == ASYNC)
3287 sync_msg = ASYNC;
3289 if (offset > MAX_OFFSET)
3290 offset = MAX_OFFSET;
3292 sync_reg = 0x00;
3294 if (sync_msg > 12)
3296 sync_reg = 0x20; /* Use 10MB/s */
3298 if (sync_msg > 25)
3300 sync_reg = 0x40; /* Use 6.6MB/s */
3302 if (sync_msg > 38)
3304 sync_reg = 0x60; /* Use 5MB/s */
3306 if (sync_msg > 50)
3308 sync_reg = 0x80; /* Use 4MB/s */
3310 if (sync_msg > 62)
3312 sync_reg = 0xA0; /* Use 3.33MB/s */
3314 if (sync_msg > 75)
3316 sync_reg = 0xC0; /* Use 2.85MB/s */
3318 if (sync_msg > 87)
3320 sync_reg = 0xE0; /* Use 2.5MB/s */
3322 if (sync_msg > 100) {
3324 sync_reg = 0x00; /* Use ASYNC */
3325 offset = 0x00;
3328 if (currTar_Info->TarStatus & WIDE_ENABLED)
3330 sync_reg |= offset;
3332 else
3334 sync_reg |= (offset | NARROW_SCSI);
3336 FPT_sssyncv(port, currSCCB->TargID, sync_reg, currTar_Info);
3338 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
3340 ACCEPT_MSG(port);
3342 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3343 ~(unsigned char)TAR_SYNC_MASK) |
3344 (unsigned char)SYNC_SUPPORTED);
3346 WR_HARPOON(port + hp_autostart_1,
3347 (AUTO_IMMED + DISCONNECT_START));
3350 else {
3352 ACCEPT_MSG_ATN(port);
3354 FPT_sisyncr(port, sync_msg, offset);
3356 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3357 ~(unsigned char)TAR_SYNC_MASK) |
3358 (unsigned char)SYNC_SUPPORTED);
3362 /*---------------------------------------------------------------------
3364 * Function: FPT_sisyncr
3366 * Description: Answer the targets sync message.
3368 *---------------------------------------------------------------------*/
3369 static void FPT_sisyncr(unsigned long port, unsigned char sync_pulse,
3370 unsigned char offset)
3372 ARAM_ACCESS(port);
3373 WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT));
3374 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x03));
3375 WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMSYNC));
3376 WRW_HARPOON((port + SYNC_MSGS + 6), (MPM_OP + AMSG_OUT + sync_pulse));
3377 WRW_HARPOON((port + SYNC_MSGS + 8), (RAT_OP));
3378 WRW_HARPOON((port + SYNC_MSGS + 10), (MPM_OP + AMSG_OUT + offset));
3379 WRW_HARPOON((port + SYNC_MSGS + 12), (BRH_OP + ALWAYS + NP));
3380 SGRAM_ACCESS(port);
3382 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3383 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
3385 WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
3387 while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
3391 /*---------------------------------------------------------------------
3393 * Function: FPT_siwidn
3395 * Description: Read in a message byte from the SCSI bus, and check
3396 * for a parity error.
3398 *---------------------------------------------------------------------*/
3400 static unsigned char FPT_siwidn(unsigned long port, unsigned char p_card)
3402 struct sccb *currSCCB;
3403 struct sccb_mgr_tar_info *currTar_Info;
3405 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3406 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
3408 if (!((currTar_Info->TarStatus & TAR_WIDE_MASK) == WIDE_NEGOCIATED)) {
3410 WRW_HARPOON((port + ID_MSG_STRT),
3411 (MPM_OP + AMSG_OUT +
3412 (currSCCB->
3413 Sccb_idmsg & ~(unsigned char)DISC_PRIV)));
3415 WRW_HARPOON((port + ID_MSG_STRT + 2), BRH_OP + ALWAYS + CMDPZ);
3417 WRW_HARPOON((port + SYNC_MSGS + 0),
3418 (MPM_OP + AMSG_OUT + SMEXT));
3419 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
3420 WRW_HARPOON((port + SYNC_MSGS + 4),
3421 (MPM_OP + AMSG_OUT + SMWDTR));
3422 WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
3423 WRW_HARPOON((port + SYNC_MSGS + 8),
3424 (MPM_OP + AMSG_OUT + SM16BIT));
3425 WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
3427 WR_HARPOON(port + hp_autostart_3, (SELECT + SELCHK_STRT));
3429 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3430 ~(unsigned char)TAR_WIDE_MASK) |
3431 (unsigned char)WIDE_ENABLED);
3433 return 1;
3436 else {
3438 currTar_Info->TarStatus = ((currTar_Info->TarStatus &
3439 ~(unsigned char)TAR_WIDE_MASK) |
3440 WIDE_NEGOCIATED);
3442 currTar_Info->TarEEValue &= ~EE_WIDE_SCSI;
3443 return 0;
3447 /*---------------------------------------------------------------------
3449 * Function: FPT_stwidn
3451 * Description: The has sent us a Wide Nego message so handle it as
3452 * necessary.
3454 *---------------------------------------------------------------------*/
3455 static void FPT_stwidn(unsigned long port, unsigned char p_card)
3457 unsigned char width;
3458 struct sccb *currSCCB;
3459 struct sccb_mgr_tar_info *currTar_Info;
3461 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3462 currTar_Info = &FPT_sccbMgrTbl[p_card][currSCCB->TargID];
3464 width = FPT_sfm(port, currSCCB);
3466 if ((width == 0x00) && (currSCCB->Sccb_scsimsg == SMPARITY)) {
3467 WR_HARPOON(port + hp_autostart_1,
3468 (AUTO_IMMED + DISCONNECT_START));
3469 return;
3472 if (!(currTar_Info->TarEEValue & EE_WIDE_SCSI))
3473 width = 0;
3475 if (width) {
3476 currTar_Info->TarStatus |= WIDE_ENABLED;
3477 width = 0;
3478 } else {
3479 width = NARROW_SCSI;
3480 currTar_Info->TarStatus &= ~WIDE_ENABLED;
3483 FPT_sssyncv(port, currSCCB->TargID, width, currTar_Info);
3485 if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
3487 currTar_Info->TarStatus |= WIDE_NEGOCIATED;
3489 if (!
3490 ((currTar_Info->TarStatus & TAR_SYNC_MASK) ==
3491 SYNC_SUPPORTED)) {
3492 ACCEPT_MSG_ATN(port);
3493 ARAM_ACCESS(port);
3494 FPT_sisyncn(port, p_card, 1);
3495 currSCCB->Sccb_scsistat = SELECT_SN_ST;
3496 SGRAM_ACCESS(port);
3497 } else {
3498 ACCEPT_MSG(port);
3499 WR_HARPOON(port + hp_autostart_1,
3500 (AUTO_IMMED + DISCONNECT_START));
3504 else {
3506 ACCEPT_MSG_ATN(port);
3508 if (currTar_Info->TarEEValue & EE_WIDE_SCSI)
3509 width = SM16BIT;
3510 else
3511 width = SM8BIT;
3513 FPT_siwidr(port, width);
3515 currTar_Info->TarStatus |= (WIDE_NEGOCIATED | WIDE_ENABLED);
3519 /*---------------------------------------------------------------------
3521 * Function: FPT_siwidr
3523 * Description: Answer the targets Wide nego message.
3525 *---------------------------------------------------------------------*/
3526 static void FPT_siwidr(unsigned long port, unsigned char width)
3528 ARAM_ACCESS(port);
3529 WRW_HARPOON((port + SYNC_MSGS + 0), (MPM_OP + AMSG_OUT + SMEXT));
3530 WRW_HARPOON((port + SYNC_MSGS + 2), (MPM_OP + AMSG_OUT + 0x02));
3531 WRW_HARPOON((port + SYNC_MSGS + 4), (MPM_OP + AMSG_OUT + SMWDTR));
3532 WRW_HARPOON((port + SYNC_MSGS + 6), (RAT_OP));
3533 WRW_HARPOON((port + SYNC_MSGS + 8), (MPM_OP + AMSG_OUT + width));
3534 WRW_HARPOON((port + SYNC_MSGS + 10), (BRH_OP + ALWAYS + NP));
3535 SGRAM_ACCESS(port);
3537 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3538 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT_1);
3540 WR_HARPOON(port + hp_autostart_3, (AUTO_IMMED + CMD_ONLY_STRT));
3542 while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | AUTO_INT))) {
3546 /*---------------------------------------------------------------------
3548 * Function: FPT_sssyncv
3550 * Description: Write the desired value to the Sync Register for the
3551 * ID specified.
3553 *---------------------------------------------------------------------*/
3554 static void FPT_sssyncv(unsigned long p_port, unsigned char p_id,
3555 unsigned char p_sync_value,
3556 struct sccb_mgr_tar_info *currTar_Info)
3558 unsigned char index;
3560 index = p_id;
3562 switch (index) {
3564 case 0:
3565 index = 12; /* hp_synctarg_0 */
3566 break;
3567 case 1:
3568 index = 13; /* hp_synctarg_1 */
3569 break;
3570 case 2:
3571 index = 14; /* hp_synctarg_2 */
3572 break;
3573 case 3:
3574 index = 15; /* hp_synctarg_3 */
3575 break;
3576 case 4:
3577 index = 8; /* hp_synctarg_4 */
3578 break;
3579 case 5:
3580 index = 9; /* hp_synctarg_5 */
3581 break;
3582 case 6:
3583 index = 10; /* hp_synctarg_6 */
3584 break;
3585 case 7:
3586 index = 11; /* hp_synctarg_7 */
3587 break;
3588 case 8:
3589 index = 4; /* hp_synctarg_8 */
3590 break;
3591 case 9:
3592 index = 5; /* hp_synctarg_9 */
3593 break;
3594 case 10:
3595 index = 6; /* hp_synctarg_10 */
3596 break;
3597 case 11:
3598 index = 7; /* hp_synctarg_11 */
3599 break;
3600 case 12:
3601 index = 0; /* hp_synctarg_12 */
3602 break;
3603 case 13:
3604 index = 1; /* hp_synctarg_13 */
3605 break;
3606 case 14:
3607 index = 2; /* hp_synctarg_14 */
3608 break;
3609 case 15:
3610 index = 3; /* hp_synctarg_15 */
3614 WR_HARPOON(p_port + hp_synctarg_base + index, p_sync_value);
3616 currTar_Info->TarSyncCtrl = p_sync_value;
3619 /*---------------------------------------------------------------------
3621 * Function: FPT_sresb
3623 * Description: Reset the desired card's SCSI bus.
3625 *---------------------------------------------------------------------*/
3626 static void FPT_sresb(unsigned long port, unsigned char p_card)
3628 unsigned char scsiID, i;
3630 struct sccb_mgr_tar_info *currTar_Info;
3632 WR_HARPOON(port + hp_page_ctrl,
3633 (RD_HARPOON(port + hp_page_ctrl) | G_INT_DISABLE));
3634 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
3636 WR_HARPOON(port + hp_scsictrl_0, SCSI_RST);
3638 scsiID = RD_HARPOON(port + hp_seltimeout);
3639 WR_HARPOON(port + hp_seltimeout, TO_5ms);
3640 WRW_HARPOON((port + hp_intstat), TIMEOUT);
3642 WR_HARPOON(port + hp_portctrl_0, (SCSI_PORT | START_TO));
3644 while (!(RDW_HARPOON((port + hp_intstat)) & TIMEOUT)) {
3647 WR_HARPOON(port + hp_seltimeout, scsiID);
3649 WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
3651 FPT_Wait(port, TO_5ms);
3653 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
3655 WR_HARPOON(port + hp_int_mask, (RD_HARPOON(port + hp_int_mask) | 0x00));
3657 for (scsiID = 0; scsiID < MAX_SCSI_TAR; scsiID++) {
3658 currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
3660 if (currTar_Info->TarEEValue & EE_SYNC_MASK) {
3661 currTar_Info->TarSyncCtrl = 0;
3662 currTar_Info->TarStatus &= ~TAR_SYNC_MASK;
3665 if (currTar_Info->TarEEValue & EE_WIDE_SCSI) {
3666 currTar_Info->TarStatus &= ~TAR_WIDE_MASK;
3669 FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
3671 FPT_SccbMgrTableInitTarget(p_card, scsiID);
3674 FPT_BL_Card[p_card].scanIndex = 0x00;
3675 FPT_BL_Card[p_card].currentSCCB = NULL;
3676 FPT_BL_Card[p_card].globalFlags &= ~(F_TAG_STARTED | F_HOST_XFER_ACT
3677 | F_NEW_SCCB_CMD);
3678 FPT_BL_Card[p_card].cmdCounter = 0x00;
3679 FPT_BL_Card[p_card].discQCount = 0x00;
3680 FPT_BL_Card[p_card].tagQ_Lst = 0x01;
3682 for (i = 0; i < QUEUE_DEPTH; i++)
3683 FPT_BL_Card[p_card].discQ_Tbl[i] = NULL;
3685 WR_HARPOON(port + hp_page_ctrl,
3686 (RD_HARPOON(port + hp_page_ctrl) & ~G_INT_DISABLE));
3690 /*---------------------------------------------------------------------
3692 * Function: FPT_ssenss
3694 * Description: Setup for the Auto Sense command.
3696 *---------------------------------------------------------------------*/
3697 static void FPT_ssenss(struct sccb_card *pCurrCard)
3699 unsigned char i;
3700 struct sccb *currSCCB;
3702 currSCCB = pCurrCard->currentSCCB;
3704 currSCCB->Save_CdbLen = currSCCB->CdbLength;
3706 for (i = 0; i < 6; i++) {
3708 currSCCB->Save_Cdb[i] = currSCCB->Cdb[i];
3711 currSCCB->CdbLength = SIX_BYTE_CMD;
3712 currSCCB->Cdb[0] = SCSI_REQUEST_SENSE;
3713 currSCCB->Cdb[1] = currSCCB->Cdb[1] & (unsigned char)0xE0; /*Keep LUN. */
3714 currSCCB->Cdb[2] = 0x00;
3715 currSCCB->Cdb[3] = 0x00;
3716 currSCCB->Cdb[4] = currSCCB->RequestSenseLength;
3717 currSCCB->Cdb[5] = 0x00;
3719 currSCCB->Sccb_XferCnt = (unsigned long)currSCCB->RequestSenseLength;
3721 currSCCB->Sccb_ATC = 0x00;
3723 currSCCB->Sccb_XferState |= F_AUTO_SENSE;
3725 currSCCB->Sccb_XferState &= ~F_SG_XFER;
3727 currSCCB->Sccb_idmsg = currSCCB->Sccb_idmsg & ~(unsigned char)DISC_PRIV;
3729 currSCCB->ControlByte = 0x00;
3731 currSCCB->Sccb_MGRFlags &= F_STATUSLOADED;
3734 /*---------------------------------------------------------------------
3736 * Function: FPT_sxfrp
3738 * Description: Transfer data into the bit bucket until the device
3739 * decides to switch phase.
3741 *---------------------------------------------------------------------*/
3743 static void FPT_sxfrp(unsigned long p_port, unsigned char p_card)
3745 unsigned char curr_phz;
3747 DISABLE_AUTO(p_port);
3749 if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
3751 FPT_hostDataXferAbort(p_port, p_card,
3752 FPT_BL_Card[p_card].currentSCCB);
3756 /* If the Automation handled the end of the transfer then do not
3757 match the phase or we will get out of sync with the ISR. */
3759 if (RDW_HARPOON((p_port + hp_intstat)) &
3760 (BUS_FREE | XFER_CNT_0 | AUTO_INT))
3761 return;
3763 WR_HARPOON(p_port + hp_xfercnt_0, 0x00);
3765 curr_phz = RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ;
3767 WRW_HARPOON((p_port + hp_intstat), XFER_CNT_0);
3769 WR_HARPOON(p_port + hp_scsisig, curr_phz);
3771 while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET)) &&
3772 (curr_phz ==
3773 (RD_HARPOON(p_port + hp_scsisig) & (unsigned char)S_SCSI_PHZ)))
3775 if (curr_phz & (unsigned char)SCSI_IOBIT) {
3776 WR_HARPOON(p_port + hp_portctrl_0,
3777 (SCSI_PORT | HOST_PORT | SCSI_INBIT));
3779 if (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
3780 RD_HARPOON(p_port + hp_fifodata_0);
3782 } else {
3783 WR_HARPOON(p_port + hp_portctrl_0,
3784 (SCSI_PORT | HOST_PORT | HOST_WRT));
3785 if (RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY) {
3786 WR_HARPOON(p_port + hp_fifodata_0, 0xFA);
3789 } /* End of While loop for padding data I/O phase */
3791 while (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
3792 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ)
3793 break;
3796 WR_HARPOON(p_port + hp_portctrl_0,
3797 (SCSI_PORT | HOST_PORT | SCSI_INBIT));
3798 while (!(RD_HARPOON(p_port + hp_xferstat) & FIFO_EMPTY)) {
3799 RD_HARPOON(p_port + hp_fifodata_0);
3802 if (!(RDW_HARPOON((p_port + hp_intstat)) & (BUS_FREE | RESET))) {
3803 WR_HARPOON(p_port + hp_autostart_0,
3804 (AUTO_IMMED + DISCONNECT_START));
3805 while (!(RDW_HARPOON((p_port + hp_intstat)) & AUTO_INT)) {
3808 if (RDW_HARPOON((p_port + hp_intstat)) &
3809 (ICMD_COMP | ITAR_DISC))
3810 while (!
3811 (RDW_HARPOON((p_port + hp_intstat)) &
3812 (BUS_FREE | RSEL))) ;
3816 /*---------------------------------------------------------------------
3818 * Function: FPT_schkdd
3820 * Description: Make sure data has been flushed from both FIFOs and abort
3821 * the operations if necessary.
3823 *---------------------------------------------------------------------*/
3825 static void FPT_schkdd(unsigned long port, unsigned char p_card)
3827 unsigned short TimeOutLoop;
3828 unsigned char sPhase;
3830 struct sccb *currSCCB;
3832 currSCCB = FPT_BL_Card[p_card].currentSCCB;
3834 if ((currSCCB->Sccb_scsistat != DATA_OUT_ST) &&
3835 (currSCCB->Sccb_scsistat != DATA_IN_ST)) {
3836 return;
3839 if (currSCCB->Sccb_XferState & F_ODD_BALL_CNT) {
3841 currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - 1);
3843 currSCCB->Sccb_XferCnt = 1;
3845 currSCCB->Sccb_XferState &= ~F_ODD_BALL_CNT;
3846 WRW_HARPOON((port + hp_fiforead), (unsigned short)0x00);
3847 WR_HARPOON(port + hp_xferstat, 0x00);
3850 else {
3852 currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
3854 currSCCB->Sccb_XferCnt = 0;
3857 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
3858 (currSCCB->HostStatus == SCCB_COMPLETE)) {
3860 currSCCB->HostStatus = SCCB_PARITY_ERR;
3861 WRW_HARPOON((port + hp_intstat), PARITY);
3864 FPT_hostDataXferAbort(port, p_card, currSCCB);
3866 while (RD_HARPOON(port + hp_scsisig) & SCSI_ACK) {
3869 TimeOutLoop = 0;
3871 while (RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY) {
3872 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
3873 return;
3875 if (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) {
3876 break;
3878 if (RDW_HARPOON((port + hp_intstat)) & RESET) {
3879 return;
3881 if ((RD_HARPOON(port + hp_scsisig) & SCSI_REQ)
3882 || (TimeOutLoop++ > 0x3000))
3883 break;
3886 sPhase = RD_HARPOON(port + hp_scsisig) & (SCSI_BSY | S_SCSI_PHZ);
3887 if ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) ||
3888 (RD_HARPOON(port + hp_offsetctr) & (unsigned char)0x1F) ||
3889 (sPhase == (SCSI_BSY | S_DATAO_PH)) ||
3890 (sPhase == (SCSI_BSY | S_DATAI_PH))) {
3892 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
3894 if (!(currSCCB->Sccb_XferState & F_ALL_XFERRED)) {
3895 if (currSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
3896 FPT_phaseDataIn(port, p_card);
3899 else {
3900 FPT_phaseDataOut(port, p_card);
3902 } else {
3903 FPT_sxfrp(port, p_card);
3904 if (!(RDW_HARPOON((port + hp_intstat)) &
3905 (BUS_FREE | ICMD_COMP | ITAR_DISC | RESET))) {
3906 WRW_HARPOON((port + hp_intstat), AUTO_INT);
3907 FPT_phaseDecode(port, p_card);
3913 else {
3914 WR_HARPOON(port + hp_portctrl_0, 0x00);
3918 /*---------------------------------------------------------------------
3920 * Function: FPT_sinits
3922 * Description: Setup SCCB manager fields in this SCCB.
3924 *---------------------------------------------------------------------*/
3926 static void FPT_sinits(struct sccb *p_sccb, unsigned char p_card)
3928 struct sccb_mgr_tar_info *currTar_Info;
3930 if ((p_sccb->TargID > MAX_SCSI_TAR) || (p_sccb->Lun > MAX_LUN)) {
3931 return;
3933 currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
3935 p_sccb->Sccb_XferState = 0x00;
3936 p_sccb->Sccb_XferCnt = p_sccb->DataLength;
3938 if ((p_sccb->OperationCode == SCATTER_GATHER_COMMAND) ||
3939 (p_sccb->OperationCode == RESIDUAL_SG_COMMAND)) {
3941 p_sccb->Sccb_SGoffset = 0;
3942 p_sccb->Sccb_XferState = F_SG_XFER;
3943 p_sccb->Sccb_XferCnt = 0x00;
3946 if (p_sccb->DataLength == 0x00)
3948 p_sccb->Sccb_XferState |= F_ALL_XFERRED;
3950 if (p_sccb->ControlByte & F_USE_CMD_Q) {
3951 if ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) == TAG_Q_REJECT)
3952 p_sccb->ControlByte &= ~F_USE_CMD_Q;
3954 else
3955 currTar_Info->TarStatus |= TAG_Q_TRYING;
3958 /* For !single SCSI device in system & device allow Disconnect
3959 or command is tag_q type then send Cmd with Disconnect Enable
3960 else send Cmd with Disconnect Disable */
3963 if (((!(FPT_BL_Card[p_card].globalFlags & F_SINGLE_DEVICE)) &&
3964 (currTar_Info->TarStatus & TAR_ALLOW_DISC)) ||
3965 (currTar_Info->TarStatus & TAG_Q_TRYING)) {
3967 if ((currTar_Info->TarStatus & TAR_ALLOW_DISC) ||
3968 (currTar_Info->TarStatus & TAG_Q_TRYING)) {
3969 p_sccb->Sccb_idmsg =
3970 (unsigned char)(SMIDENT | DISC_PRIV) | p_sccb->Lun;
3973 else {
3975 p_sccb->Sccb_idmsg = (unsigned char)SMIDENT | p_sccb->Lun;
3978 p_sccb->HostStatus = 0x00;
3979 p_sccb->TargetStatus = 0x00;
3980 p_sccb->Sccb_tag = 0x00;
3981 p_sccb->Sccb_MGRFlags = 0x00;
3982 p_sccb->Sccb_sgseg = 0x00;
3983 p_sccb->Sccb_ATC = 0x00;
3984 p_sccb->Sccb_savedATC = 0x00;
3986 p_sccb->SccbVirtDataPtr = 0x00;
3987 p_sccb->Sccb_forwardlink = NULL;
3988 p_sccb->Sccb_backlink = NULL;
3990 p_sccb->Sccb_scsistat = BUS_FREE_ST;
3991 p_sccb->SccbStatus = SCCB_IN_PROCESS;
3992 p_sccb->Sccb_scsimsg = SMNO_OP;
3996 /*---------------------------------------------------------------------
3998 * Function: Phase Decode
4000 * Description: Determine the phase and call the appropriate function.
4002 *---------------------------------------------------------------------*/
4004 static void FPT_phaseDecode(unsigned long p_port, unsigned char p_card)
4006 unsigned char phase_ref;
4007 void (*phase) (unsigned long, unsigned char);
4009 DISABLE_AUTO(p_port);
4011 phase_ref =
4012 (unsigned char)(RD_HARPOON(p_port + hp_scsisig) & S_SCSI_PHZ);
4014 phase = FPT_s_PhaseTbl[phase_ref];
4016 (*phase) (p_port, p_card); /* Call the correct phase func */
4019 /*---------------------------------------------------------------------
4021 * Function: Data Out Phase
4023 * Description: Start up both the BusMaster and Xbow.
4025 *---------------------------------------------------------------------*/
4027 static void FPT_phaseDataOut(unsigned long port, unsigned char p_card)
4030 struct sccb *currSCCB;
4032 currSCCB = FPT_BL_Card[p_card].currentSCCB;
4033 if (currSCCB == NULL) {
4034 return; /* Exit if No SCCB record */
4037 currSCCB->Sccb_scsistat = DATA_OUT_ST;
4038 currSCCB->Sccb_XferState &= ~(F_HOST_XFER_DIR | F_NO_DATA_YET);
4040 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
4042 WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
4044 WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
4046 FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
4048 if (currSCCB->Sccb_XferCnt == 0) {
4050 if ((currSCCB->ControlByte & SCCB_DATA_XFER_OUT) &&
4051 (currSCCB->HostStatus == SCCB_COMPLETE))
4052 currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
4054 FPT_sxfrp(port, p_card);
4055 if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
4056 FPT_phaseDecode(port, p_card);
4060 /*---------------------------------------------------------------------
4062 * Function: Data In Phase
4064 * Description: Startup the BusMaster and the XBOW.
4066 *---------------------------------------------------------------------*/
4068 static void FPT_phaseDataIn(unsigned long port, unsigned char p_card)
4071 struct sccb *currSCCB;
4073 currSCCB = FPT_BL_Card[p_card].currentSCCB;
4075 if (currSCCB == NULL) {
4076 return; /* Exit if No SCCB record */
4079 currSCCB->Sccb_scsistat = DATA_IN_ST;
4080 currSCCB->Sccb_XferState |= F_HOST_XFER_DIR;
4081 currSCCB->Sccb_XferState &= ~F_NO_DATA_YET;
4083 WR_HARPOON(port + hp_portctrl_0, SCSI_PORT);
4085 WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
4087 WR_HARPOON(port + hp_autostart_0, (END_DATA + END_DATA_START));
4089 FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
4091 if (currSCCB->Sccb_XferCnt == 0) {
4093 if ((currSCCB->ControlByte & SCCB_DATA_XFER_IN) &&
4094 (currSCCB->HostStatus == SCCB_COMPLETE))
4095 currSCCB->HostStatus = SCCB_DATA_OVER_RUN;
4097 FPT_sxfrp(port, p_card);
4098 if (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | RESET)))
4099 FPT_phaseDecode(port, p_card);
4104 /*---------------------------------------------------------------------
4106 * Function: Command Phase
4108 * Description: Load the CDB into the automation and start it up.
4110 *---------------------------------------------------------------------*/
4112 static void FPT_phaseCommand(unsigned long p_port, unsigned char p_card)
4114 struct sccb *currSCCB;
4115 unsigned long cdb_reg;
4116 unsigned char i;
4118 currSCCB = FPT_BL_Card[p_card].currentSCCB;
4120 if (currSCCB->OperationCode == RESET_COMMAND) {
4122 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4123 currSCCB->CdbLength = SIX_BYTE_CMD;
4126 WR_HARPOON(p_port + hp_scsisig, 0x00);
4128 ARAM_ACCESS(p_port);
4130 cdb_reg = p_port + CMD_STRT;
4132 for (i = 0; i < currSCCB->CdbLength; i++) {
4134 if (currSCCB->OperationCode == RESET_COMMAND)
4136 WRW_HARPOON(cdb_reg, (MPM_OP + ACOMMAND + 0x00));
4138 else
4139 WRW_HARPOON(cdb_reg,
4140 (MPM_OP + ACOMMAND + currSCCB->Cdb[i]));
4141 cdb_reg += 2;
4144 if (currSCCB->CdbLength != TWELVE_BYTE_CMD)
4145 WRW_HARPOON(cdb_reg, (BRH_OP + ALWAYS + NP));
4147 WR_HARPOON(p_port + hp_portctrl_0, (SCSI_PORT));
4149 currSCCB->Sccb_scsistat = COMMAND_ST;
4151 WR_HARPOON(p_port + hp_autostart_3, (AUTO_IMMED | CMD_ONLY_STRT));
4152 SGRAM_ACCESS(p_port);
4155 /*---------------------------------------------------------------------
4157 * Function: Status phase
4159 * Description: Bring in the status and command complete message bytes
4161 *---------------------------------------------------------------------*/
4163 static void FPT_phaseStatus(unsigned long port, unsigned char p_card)
4165 /* Start-up the automation to finish off this command and let the
4166 isr handle the interrupt for command complete when it comes in.
4167 We could wait here for the interrupt to be generated?
4170 WR_HARPOON(port + hp_scsisig, 0x00);
4172 WR_HARPOON(port + hp_autostart_0, (AUTO_IMMED + END_DATA_START));
4175 /*---------------------------------------------------------------------
4177 * Function: Phase Message Out
4179 * Description: Send out our message (if we have one) and handle whatever
4180 * else is involed.
4182 *---------------------------------------------------------------------*/
4184 static void FPT_phaseMsgOut(unsigned long port, unsigned char p_card)
4186 unsigned char message, scsiID;
4187 struct sccb *currSCCB;
4188 struct sccb_mgr_tar_info *currTar_Info;
4190 currSCCB = FPT_BL_Card[p_card].currentSCCB;
4192 if (currSCCB != NULL) {
4194 message = currSCCB->Sccb_scsimsg;
4195 scsiID = currSCCB->TargID;
4197 if (message == SMDEV_RESET) {
4199 currTar_Info = &FPT_sccbMgrTbl[p_card][scsiID];
4200 currTar_Info->TarSyncCtrl = 0;
4201 FPT_sssyncv(port, scsiID, NARROW_SCSI, currTar_Info);
4203 if (FPT_sccbMgrTbl[p_card][scsiID].
4204 TarEEValue & EE_SYNC_MASK) {
4206 FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
4207 ~TAR_SYNC_MASK;
4211 if (FPT_sccbMgrTbl[p_card][scsiID].
4212 TarEEValue & EE_WIDE_SCSI) {
4214 FPT_sccbMgrTbl[p_card][scsiID].TarStatus &=
4215 ~TAR_WIDE_MASK;
4218 FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
4219 FPT_SccbMgrTableInitTarget(p_card, scsiID);
4220 } else if (currSCCB->Sccb_scsistat == ABORT_ST) {
4221 currSCCB->HostStatus = SCCB_COMPLETE;
4222 if (FPT_BL_Card[p_card].discQ_Tbl[currSCCB->Sccb_tag] !=
4223 NULL) {
4224 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4225 Sccb_tag] = NULL;
4226 FPT_sccbMgrTbl[p_card][scsiID].TarTagQ_Cnt--;
4231 else if (currSCCB->Sccb_scsistat < COMMAND_ST) {
4233 if (message == SMNO_OP) {
4234 currSCCB->Sccb_MGRFlags |= F_DEV_SELECTED;
4236 FPT_ssel(port, p_card);
4237 return;
4239 } else {
4241 if (message == SMABORT)
4243 FPT_queueFlushSccb(p_card, SCCB_COMPLETE);
4246 } else {
4247 message = SMABORT;
4250 WRW_HARPOON((port + hp_intstat), (BUS_FREE | PHASE | XFER_CNT_0));
4252 WR_HARPOON(port + hp_portctrl_0, SCSI_BUS_EN);
4254 WR_HARPOON(port + hp_scsidata_0, message);
4256 WR_HARPOON(port + hp_scsisig, (SCSI_ACK + S_ILL_PH));
4258 ACCEPT_MSG(port);
4260 WR_HARPOON(port + hp_portctrl_0, 0x00);
4262 if ((message == SMABORT) || (message == SMDEV_RESET) ||
4263 (message == SMABORT_TAG)) {
4265 while (!(RDW_HARPOON((port + hp_intstat)) & (BUS_FREE | PHASE))) {
4268 if (RDW_HARPOON((port + hp_intstat)) & BUS_FREE) {
4269 WRW_HARPOON((port + hp_intstat), BUS_FREE);
4271 if (currSCCB != NULL) {
4273 if ((FPT_BL_Card[p_card].
4274 globalFlags & F_CONLUN_IO)
4276 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4277 TarStatus & TAR_TAG_Q_MASK) !=
4278 TAG_Q_TRYING))
4279 FPT_sccbMgrTbl[p_card][currSCCB->
4280 TargID].
4281 TarLUNBusy[currSCCB->Lun] = 0;
4282 else
4283 FPT_sccbMgrTbl[p_card][currSCCB->
4284 TargID].
4285 TarLUNBusy[0] = 0;
4287 FPT_queueCmdComplete(&FPT_BL_Card[p_card],
4288 currSCCB, p_card);
4291 else {
4292 FPT_BL_Card[p_card].globalFlags |=
4293 F_NEW_SCCB_CMD;
4297 else {
4299 FPT_sxfrp(port, p_card);
4303 else {
4305 if (message == SMPARITY) {
4306 currSCCB->Sccb_scsimsg = SMNO_OP;
4307 WR_HARPOON(port + hp_autostart_1,
4308 (AUTO_IMMED + DISCONNECT_START));
4309 } else {
4310 FPT_sxfrp(port, p_card);
4315 /*---------------------------------------------------------------------
4317 * Function: Message In phase
4319 * Description: Bring in the message and determine what to do with it.
4321 *---------------------------------------------------------------------*/
4323 static void FPT_phaseMsgIn(unsigned long port, unsigned char p_card)
4325 unsigned char message;
4326 struct sccb *currSCCB;
4328 currSCCB = FPT_BL_Card[p_card].currentSCCB;
4330 if (FPT_BL_Card[p_card].globalFlags & F_HOST_XFER_ACT) {
4332 FPT_phaseChkFifo(port, p_card);
4335 message = RD_HARPOON(port + hp_scsidata_0);
4336 if ((message == SMDISC) || (message == SMSAVE_DATA_PTR)) {
4338 WR_HARPOON(port + hp_autostart_1,
4339 (AUTO_IMMED + END_DATA_START));
4343 else {
4345 message = FPT_sfm(port, currSCCB);
4346 if (message) {
4348 FPT_sdecm(message, port, p_card);
4350 } else {
4351 if (currSCCB->Sccb_scsimsg != SMPARITY)
4352 ACCEPT_MSG(port);
4353 WR_HARPOON(port + hp_autostart_1,
4354 (AUTO_IMMED + DISCONNECT_START));
4360 /*---------------------------------------------------------------------
4362 * Function: Illegal phase
4364 * Description: Target switched to some illegal phase, so all we can do
4365 * is report an error back to the host (if that is possible)
4366 * and send an ABORT message to the misbehaving target.
4368 *---------------------------------------------------------------------*/
4370 static void FPT_phaseIllegal(unsigned long port, unsigned char p_card)
4372 struct sccb *currSCCB;
4374 currSCCB = FPT_BL_Card[p_card].currentSCCB;
4376 WR_HARPOON(port + hp_scsisig, RD_HARPOON(port + hp_scsisig));
4377 if (currSCCB != NULL) {
4379 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4380 currSCCB->Sccb_scsistat = ABORT_ST;
4381 currSCCB->Sccb_scsimsg = SMABORT;
4384 ACCEPT_MSG_ATN(port);
4387 /*---------------------------------------------------------------------
4389 * Function: Phase Check FIFO
4391 * Description: Make sure data has been flushed from both FIFOs and abort
4392 * the operations if necessary.
4394 *---------------------------------------------------------------------*/
4396 static void FPT_phaseChkFifo(unsigned long port, unsigned char p_card)
4398 unsigned long xfercnt;
4399 struct sccb *currSCCB;
4401 currSCCB = FPT_BL_Card[p_card].currentSCCB;
4403 if (currSCCB->Sccb_scsistat == DATA_IN_ST) {
4405 while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) &&
4406 (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)) {
4409 if (!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY)) {
4410 currSCCB->Sccb_ATC += currSCCB->Sccb_XferCnt;
4412 currSCCB->Sccb_XferCnt = 0;
4414 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
4415 (currSCCB->HostStatus == SCCB_COMPLETE)) {
4416 currSCCB->HostStatus = SCCB_PARITY_ERR;
4417 WRW_HARPOON((port + hp_intstat), PARITY);
4420 FPT_hostDataXferAbort(port, p_card, currSCCB);
4422 FPT_dataXferProcessor(port, &FPT_BL_Card[p_card]);
4424 while ((!(RD_HARPOON(port + hp_xferstat) & FIFO_EMPTY))
4425 && (RD_HARPOON(port + hp_ext_status) &
4426 BM_CMD_BUSY)) {
4432 /*End Data In specific code. */
4433 GET_XFER_CNT(port, xfercnt);
4435 WR_HARPOON(port + hp_xfercnt_0, 0x00);
4437 WR_HARPOON(port + hp_portctrl_0, 0x00);
4439 currSCCB->Sccb_ATC += (currSCCB->Sccb_XferCnt - xfercnt);
4441 currSCCB->Sccb_XferCnt = xfercnt;
4443 if ((RDW_HARPOON((port + hp_intstat)) & PARITY) &&
4444 (currSCCB->HostStatus == SCCB_COMPLETE)) {
4446 currSCCB->HostStatus = SCCB_PARITY_ERR;
4447 WRW_HARPOON((port + hp_intstat), PARITY);
4450 FPT_hostDataXferAbort(port, p_card, currSCCB);
4452 WR_HARPOON(port + hp_fifowrite, 0x00);
4453 WR_HARPOON(port + hp_fiforead, 0x00);
4454 WR_HARPOON(port + hp_xferstat, 0x00);
4456 WRW_HARPOON((port + hp_intstat), XFER_CNT_0);
4459 /*---------------------------------------------------------------------
4461 * Function: Phase Bus Free
4463 * Description: We just went bus free so figure out if it was
4464 * because of command complete or from a disconnect.
4466 *---------------------------------------------------------------------*/
4467 static void FPT_phaseBusFree(unsigned long port, unsigned char p_card)
4469 struct sccb *currSCCB;
4471 currSCCB = FPT_BL_Card[p_card].currentSCCB;
4473 if (currSCCB != NULL) {
4475 DISABLE_AUTO(port);
4477 if (currSCCB->OperationCode == RESET_COMMAND) {
4479 if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4480 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4481 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4482 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4483 TarLUNBusy[currSCCB->Lun] = 0;
4484 else
4485 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4486 TarLUNBusy[0] = 0;
4488 FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
4489 p_card);
4491 FPT_queueSearchSelect(&FPT_BL_Card[p_card], p_card);
4495 else if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
4496 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4497 (unsigned char)SYNC_SUPPORTED;
4498 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4499 ~EE_SYNC_MASK;
4502 else if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
4503 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
4504 (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4505 TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
4507 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4508 ~EE_WIDE_SCSI;
4511 else if (currSCCB->Sccb_scsistat == SELECT_Q_ST) {
4512 /* Make sure this is not a phony BUS_FREE. If we were
4513 reselected or if BUSY is NOT on then this is a
4514 valid BUS FREE. SRR Wednesday, 5/10/1995. */
4516 if ((!(RD_HARPOON(port + hp_scsisig) & SCSI_BSY)) ||
4517 (RDW_HARPOON((port + hp_intstat)) & RSEL)) {
4518 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4519 TarStatus &= ~TAR_TAG_Q_MASK;
4520 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4521 TarStatus |= TAG_Q_REJECT;
4524 else {
4525 return;
4529 else {
4531 currSCCB->Sccb_scsistat = BUS_FREE_ST;
4533 if (!currSCCB->HostStatus) {
4534 currSCCB->HostStatus = SCCB_PHASE_SEQUENCE_FAIL;
4537 if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4538 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4539 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4540 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4541 TarLUNBusy[currSCCB->Lun] = 0;
4542 else
4543 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4544 TarLUNBusy[0] = 0;
4546 FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB,
4547 p_card);
4548 return;
4551 FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
4553 } /*end if !=null */
4556 /*---------------------------------------------------------------------
4558 * Function: Auto Load Default Map
4560 * Description: Load the Automation RAM with the defualt map values.
4562 *---------------------------------------------------------------------*/
4563 static void FPT_autoLoadDefaultMap(unsigned long p_port)
4565 unsigned long map_addr;
4567 ARAM_ACCESS(p_port);
4568 map_addr = p_port + hp_aramBase;
4570 WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0xC0)); /*ID MESSAGE */
4571 map_addr += 2;
4572 WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x20)); /*SIMPLE TAG QUEUEING MSG */
4573 map_addr += 2;
4574 WRW_HARPOON(map_addr, RAT_OP); /*RESET ATTENTION */
4575 map_addr += 2;
4576 WRW_HARPOON(map_addr, (MPM_OP + AMSG_OUT + 0x00)); /*TAG ID MSG */
4577 map_addr += 2;
4578 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 0 */
4579 map_addr += 2;
4580 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 1 */
4581 map_addr += 2;
4582 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 2 */
4583 map_addr += 2;
4584 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 3 */
4585 map_addr += 2;
4586 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 4 */
4587 map_addr += 2;
4588 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 5 */
4589 map_addr += 2;
4590 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 6 */
4591 map_addr += 2;
4592 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 7 */
4593 map_addr += 2;
4594 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 8 */
4595 map_addr += 2;
4596 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 9 */
4597 map_addr += 2;
4598 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 10 */
4599 map_addr += 2;
4600 WRW_HARPOON(map_addr, (MPM_OP + ACOMMAND + 0x00)); /*CDB BYTE 11 */
4601 map_addr += 2;
4602 WRW_HARPOON(map_addr, (CPE_OP + ADATA_OUT + DINT)); /*JUMP IF DATA OUT */
4603 map_addr += 2;
4604 WRW_HARPOON(map_addr, (TCB_OP + FIFO_0 + DI)); /*JUMP IF NO DATA IN FIFO */
4605 map_addr += 2; /*This means AYNC DATA IN */
4606 WRW_HARPOON(map_addr, (SSI_OP + SSI_IDO_STRT)); /*STOP AND INTERRUPT */
4607 map_addr += 2;
4608 WRW_HARPOON(map_addr, (CPE_OP + ADATA_IN + DINT)); /*JUMP IF NOT DATA IN PHZ */
4609 map_addr += 2;
4610 WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST)); /*IF NOT MSG IN CHECK 4 DATA IN */
4611 map_addr += 2;
4612 WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x02)); /*SAVE DATA PTR MSG? */
4613 map_addr += 2;
4614 WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + DC)); /*GO CHECK FOR DISCONNECT MSG */
4615 map_addr += 2;
4616 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR1)); /*SAVE DATA PTRS MSG */
4617 map_addr += 2;
4618 WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + ST)); /*IF NOT MSG IN CHECK DATA IN */
4619 map_addr += 2;
4620 WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x04)); /*DISCONNECT MSG? */
4621 map_addr += 2;
4622 WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + UNKNWN)); /*UKNKNOWN MSG */
4623 map_addr += 2;
4624 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET)); /*XFER DISCONNECT MSG */
4625 map_addr += 2;
4626 WRW_HARPOON(map_addr, (SSI_OP + SSI_ITAR_DISC)); /*STOP AND INTERRUPT */
4627 map_addr += 2;
4628 WRW_HARPOON(map_addr, (CPN_OP + ASTATUS + UNKNWN)); /*JUMP IF NOT STATUS PHZ. */
4629 map_addr += 2;
4630 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_AR0)); /*GET STATUS BYTE */
4631 map_addr += 2;
4632 WRW_HARPOON(map_addr, (CPN_OP + AMSG_IN + CC)); /*ERROR IF NOT MSG IN PHZ */
4633 map_addr += 2;
4634 WRW_HARPOON(map_addr, (CRD_OP + SDATA + 0x00)); /*CHECK FOR CMD COMPLETE MSG. */
4635 map_addr += 2;
4636 WRW_HARPOON(map_addr, (BRH_OP + NOT_EQ + CC)); /*ERROR IF NOT CMD COMPLETE MSG. */
4637 map_addr += 2;
4638 WRW_HARPOON(map_addr, (MRR_OP + SDATA + D_BUCKET)); /*GET CMD COMPLETE MSG */
4639 map_addr += 2;
4640 WRW_HARPOON(map_addr, (SSI_OP + SSI_ICMD_COMP)); /*END OF COMMAND */
4641 map_addr += 2;
4643 WRW_HARPOON(map_addr, (SSI_OP + SSI_IUNKWN)); /*RECEIVED UNKNOWN MSG BYTE */
4644 map_addr += 2;
4645 WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */
4646 map_addr += 2;
4647 WRW_HARPOON(map_addr, (SSI_OP + SSI_ITICKLE)); /*BIOS Tickled the Mgr */
4648 map_addr += 2;
4649 WRW_HARPOON(map_addr, (SSI_OP + SSI_IRFAIL)); /*EXPECTED ID/TAG MESSAGES AND */
4650 map_addr += 2; /* DIDN'T GET ONE */
4651 WRW_HARPOON(map_addr, (CRR_OP + AR3 + S_IDREG)); /* comp SCSI SEL ID & AR3 */
4652 map_addr += 2;
4653 WRW_HARPOON(map_addr, (BRH_OP + EQUAL + 0x00)); /*SEL ID OK then Conti. */
4654 map_addr += 2;
4655 WRW_HARPOON(map_addr, (SSI_OP + SSI_INO_CC)); /*NO COMMAND COMPLETE AFTER STATUS */
4657 SGRAM_ACCESS(p_port);
4660 /*---------------------------------------------------------------------
4662 * Function: Auto Command Complete
4664 * Description: Post command back to host and find another command
4665 * to execute.
4667 *---------------------------------------------------------------------*/
4669 static void FPT_autoCmdCmplt(unsigned long p_port, unsigned char p_card)
4671 struct sccb *currSCCB;
4672 unsigned char status_byte;
4674 currSCCB = FPT_BL_Card[p_card].currentSCCB;
4676 status_byte = RD_HARPOON(p_port + hp_gp_reg_0);
4678 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUN_CA = 0;
4680 if (status_byte != SSGOOD) {
4682 if (status_byte == SSQ_FULL) {
4684 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4685 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4686 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4687 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4688 TarLUNBusy[currSCCB->Lun] = 1;
4689 if (FPT_BL_Card[p_card].discQCount != 0)
4690 FPT_BL_Card[p_card].discQCount--;
4691 FPT_BL_Card[p_card].
4692 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4693 [currSCCB->TargID].
4694 LunDiscQ_Idx[currSCCB->Lun]] =
4695 NULL;
4696 } else {
4697 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4698 TarLUNBusy[0] = 1;
4699 if (currSCCB->Sccb_tag) {
4700 if (FPT_BL_Card[p_card].discQCount != 0)
4701 FPT_BL_Card[p_card].
4702 discQCount--;
4703 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4704 Sccb_tag]
4705 = NULL;
4706 } else {
4707 if (FPT_BL_Card[p_card].discQCount != 0)
4708 FPT_BL_Card[p_card].
4709 discQCount--;
4710 FPT_BL_Card[p_card].
4711 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4712 [currSCCB->TargID].
4713 LunDiscQ_Idx[0]] = NULL;
4717 currSCCB->Sccb_MGRFlags |= F_STATUSLOADED;
4719 FPT_queueSelectFail(&FPT_BL_Card[p_card], p_card);
4721 return;
4724 if (currSCCB->Sccb_scsistat == SELECT_SN_ST) {
4725 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus |=
4726 (unsigned char)SYNC_SUPPORTED;
4728 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4729 ~EE_SYNC_MASK;
4730 FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
4732 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4733 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4734 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4735 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4736 TarLUNBusy[currSCCB->Lun] = 1;
4737 if (FPT_BL_Card[p_card].discQCount != 0)
4738 FPT_BL_Card[p_card].discQCount--;
4739 FPT_BL_Card[p_card].
4740 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4741 [currSCCB->TargID].
4742 LunDiscQ_Idx[currSCCB->Lun]] =
4743 NULL;
4744 } else {
4745 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4746 TarLUNBusy[0] = 1;
4747 if (currSCCB->Sccb_tag) {
4748 if (FPT_BL_Card[p_card].discQCount != 0)
4749 FPT_BL_Card[p_card].
4750 discQCount--;
4751 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4752 Sccb_tag]
4753 = NULL;
4754 } else {
4755 if (FPT_BL_Card[p_card].discQCount != 0)
4756 FPT_BL_Card[p_card].
4757 discQCount--;
4758 FPT_BL_Card[p_card].
4759 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4760 [currSCCB->TargID].
4761 LunDiscQ_Idx[0]] = NULL;
4764 return;
4768 if (currSCCB->Sccb_scsistat == SELECT_WN_ST) {
4770 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarStatus =
4771 (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4772 TarStatus & ~WIDE_ENABLED) | WIDE_NEGOCIATED;
4774 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarEEValue &=
4775 ~EE_WIDE_SCSI;
4776 FPT_BL_Card[p_card].globalFlags |= F_NEW_SCCB_CMD;
4778 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4779 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4780 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
4781 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4782 TarLUNBusy[currSCCB->Lun] = 1;
4783 if (FPT_BL_Card[p_card].discQCount != 0)
4784 FPT_BL_Card[p_card].discQCount--;
4785 FPT_BL_Card[p_card].
4786 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4787 [currSCCB->TargID].
4788 LunDiscQ_Idx[currSCCB->Lun]] =
4789 NULL;
4790 } else {
4791 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4792 TarLUNBusy[0] = 1;
4793 if (currSCCB->Sccb_tag) {
4794 if (FPT_BL_Card[p_card].discQCount != 0)
4795 FPT_BL_Card[p_card].
4796 discQCount--;
4797 FPT_BL_Card[p_card].discQ_Tbl[currSCCB->
4798 Sccb_tag]
4799 = NULL;
4800 } else {
4801 if (FPT_BL_Card[p_card].discQCount != 0)
4802 FPT_BL_Card[p_card].
4803 discQCount--;
4804 FPT_BL_Card[p_card].
4805 discQ_Tbl[FPT_sccbMgrTbl[p_card]
4806 [currSCCB->TargID].
4807 LunDiscQ_Idx[0]] = NULL;
4810 return;
4814 if (status_byte == SSCHECK) {
4815 if (FPT_BL_Card[p_card].globalFlags & F_DO_RENEGO) {
4816 if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4817 TarEEValue & EE_SYNC_MASK) {
4818 FPT_sccbMgrTbl[p_card][currSCCB->
4819 TargID].
4820 TarStatus &= ~TAR_SYNC_MASK;
4822 if (FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4823 TarEEValue & EE_WIDE_SCSI) {
4824 FPT_sccbMgrTbl[p_card][currSCCB->
4825 TargID].
4826 TarStatus &= ~TAR_WIDE_MASK;
4831 if (!(currSCCB->Sccb_XferState & F_AUTO_SENSE)) {
4833 currSCCB->SccbStatus = SCCB_ERROR;
4834 currSCCB->TargetStatus = status_byte;
4836 if (status_byte == SSCHECK) {
4838 FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4839 TarLUN_CA = 1;
4841 if (currSCCB->RequestSenseLength !=
4842 NO_AUTO_REQUEST_SENSE) {
4844 if (currSCCB->RequestSenseLength == 0)
4845 currSCCB->RequestSenseLength =
4848 FPT_ssenss(&FPT_BL_Card[p_card]);
4849 FPT_BL_Card[p_card].globalFlags |=
4850 F_NEW_SCCB_CMD;
4852 if (((FPT_BL_Card[p_card].
4853 globalFlags & F_CONLUN_IO)
4855 ((FPT_sccbMgrTbl[p_card]
4856 [currSCCB->TargID].
4857 TarStatus & TAR_TAG_Q_MASK) !=
4858 TAG_Q_TRYING))) {
4859 FPT_sccbMgrTbl[p_card]
4860 [currSCCB->TargID].
4861 TarLUNBusy[currSCCB->Lun] =
4863 if (FPT_BL_Card[p_card].
4864 discQCount != 0)
4865 FPT_BL_Card[p_card].
4866 discQCount--;
4867 FPT_BL_Card[p_card].
4868 discQ_Tbl[FPT_sccbMgrTbl
4869 [p_card]
4870 [currSCCB->
4871 TargID].
4872 LunDiscQ_Idx
4873 [currSCCB->Lun]] =
4874 NULL;
4875 } else {
4876 FPT_sccbMgrTbl[p_card]
4877 [currSCCB->TargID].
4878 TarLUNBusy[0] = 1;
4879 if (currSCCB->Sccb_tag) {
4880 if (FPT_BL_Card[p_card].
4881 discQCount != 0)
4882 FPT_BL_Card
4883 [p_card].
4884 discQCount--;
4885 FPT_BL_Card[p_card].
4886 discQ_Tbl[currSCCB->
4887 Sccb_tag]
4888 = NULL;
4889 } else {
4890 if (FPT_BL_Card[p_card].
4891 discQCount != 0)
4892 FPT_BL_Card
4893 [p_card].
4894 discQCount--;
4895 FPT_BL_Card[p_card].
4896 discQ_Tbl
4897 [FPT_sccbMgrTbl
4898 [p_card][currSCCB->
4899 TargID].
4900 LunDiscQ_Idx[0]] =
4901 NULL;
4904 return;
4910 if ((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
4911 ((FPT_sccbMgrTbl[p_card][currSCCB->TargID].
4912 TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))
4913 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[currSCCB->
4914 Lun] = 0;
4915 else
4916 FPT_sccbMgrTbl[p_card][currSCCB->TargID].TarLUNBusy[0] = 0;
4918 FPT_queueCmdComplete(&FPT_BL_Card[p_card], currSCCB, p_card);
4921 #define SHORT_WAIT 0x0000000F
4922 #define LONG_WAIT 0x0000FFFFL
4924 /*---------------------------------------------------------------------
4926 * Function: Data Transfer Processor
4928 * Description: This routine performs two tasks.
4929 * (1) Start data transfer by calling HOST_DATA_XFER_START
4930 * function. Once data transfer is started, (2) Depends
4931 * on the type of data transfer mode Scatter/Gather mode
4932 * or NON Scatter/Gather mode. In NON Scatter/Gather mode,
4933 * this routine checks Sccb_MGRFlag (F_HOST_XFER_ACT bit) for
4934 * data transfer done. In Scatter/Gather mode, this routine
4935 * checks bus master command complete and dual rank busy
4936 * bit to keep chaining SC transfer command. Similarly,
4937 * in Scatter/Gather mode, it checks Sccb_MGRFlag
4938 * (F_HOST_XFER_ACT bit) for data transfer done.
4940 *---------------------------------------------------------------------*/
4942 static void FPT_dataXferProcessor(unsigned long port,
4943 struct sccb_card *pCurrCard)
4945 struct sccb *currSCCB;
4947 currSCCB = pCurrCard->currentSCCB;
4949 if (currSCCB->Sccb_XferState & F_SG_XFER) {
4950 if (pCurrCard->globalFlags & F_HOST_XFER_ACT)
4952 currSCCB->Sccb_sgseg += (unsigned char)SG_BUF_CNT;
4953 currSCCB->Sccb_SGoffset = 0x00;
4955 pCurrCard->globalFlags |= F_HOST_XFER_ACT;
4957 FPT_busMstrSGDataXferStart(port, currSCCB);
4960 else {
4961 if (!(pCurrCard->globalFlags & F_HOST_XFER_ACT)) {
4962 pCurrCard->globalFlags |= F_HOST_XFER_ACT;
4964 FPT_busMstrDataXferStart(port, currSCCB);
4969 /*---------------------------------------------------------------------
4971 * Function: BusMaster Scatter Gather Data Transfer Start
4973 * Description:
4975 *---------------------------------------------------------------------*/
4976 static void FPT_busMstrSGDataXferStart(unsigned long p_port,
4977 struct sccb *pcurrSCCB)
4979 unsigned long count, addr, tmpSGCnt;
4980 unsigned int sg_index;
4981 unsigned char sg_count, i;
4982 unsigned long reg_offset;
4984 if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
4986 count = ((unsigned long)HOST_RD_CMD) << 24;
4989 else {
4990 count = ((unsigned long)HOST_WRT_CMD) << 24;
4993 sg_count = 0;
4994 tmpSGCnt = 0;
4995 sg_index = pcurrSCCB->Sccb_sgseg;
4996 reg_offset = hp_aramBase;
4998 i = (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
4999 ~(SGRAM_ARAM | SCATTER_EN));
5001 WR_HARPOON(p_port + hp_page_ctrl, i);
5003 while ((sg_count < (unsigned char)SG_BUF_CNT) &&
5004 ((unsigned long)(sg_index * (unsigned int)SG_ELEMENT_SIZE) <
5005 pcurrSCCB->DataLength)) {
5007 tmpSGCnt += *(((unsigned long *)pcurrSCCB->DataPointer) +
5008 (sg_index * 2));
5010 count |= *(((unsigned long *)pcurrSCCB->DataPointer) +
5011 (sg_index * 2));
5013 addr = *(((unsigned long *)pcurrSCCB->DataPointer) +
5014 ((sg_index * 2) + 1));
5016 if ((!sg_count) && (pcurrSCCB->Sccb_SGoffset)) {
5018 addr +=
5019 ((count & 0x00FFFFFFL) - pcurrSCCB->Sccb_SGoffset);
5020 count =
5021 (count & 0xFF000000L) | pcurrSCCB->Sccb_SGoffset;
5023 tmpSGCnt = count & 0x00FFFFFFL;
5026 WR_HARP32(p_port, reg_offset, addr);
5027 reg_offset += 4;
5029 WR_HARP32(p_port, reg_offset, count);
5030 reg_offset += 4;
5032 count &= 0xFF000000L;
5033 sg_index++;
5034 sg_count++;
5036 } /*End While */
5038 pcurrSCCB->Sccb_XferCnt = tmpSGCnt;
5040 WR_HARPOON(p_port + hp_sg_addr, (sg_count << 4));
5042 if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
5044 WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
5046 WR_HARPOON(p_port + hp_portctrl_0,
5047 (DMA_PORT | SCSI_PORT | SCSI_INBIT));
5048 WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
5051 else {
5053 if ((!(RD_HARPOON(p_port + hp_synctarg_0) & NARROW_SCSI)) &&
5054 (tmpSGCnt & 0x000000001)) {
5056 pcurrSCCB->Sccb_XferState |= F_ODD_BALL_CNT;
5057 tmpSGCnt--;
5060 WR_HARP32(p_port, hp_xfercnt_0, tmpSGCnt);
5062 WR_HARPOON(p_port + hp_portctrl_0,
5063 (SCSI_PORT | DMA_PORT | DMA_RD));
5064 WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
5067 WR_HARPOON(p_port + hp_page_ctrl, (unsigned char)(i | SCATTER_EN));
5071 /*---------------------------------------------------------------------
5073 * Function: BusMaster Data Transfer Start
5075 * Description:
5077 *---------------------------------------------------------------------*/
5078 static void FPT_busMstrDataXferStart(unsigned long p_port,
5079 struct sccb *pcurrSCCB)
5081 unsigned long addr, count;
5083 if (!(pcurrSCCB->Sccb_XferState & F_AUTO_SENSE)) {
5085 count = pcurrSCCB->Sccb_XferCnt;
5087 addr =
5088 (unsigned long)pcurrSCCB->DataPointer + pcurrSCCB->Sccb_ATC;
5091 else {
5092 addr = pcurrSCCB->SensePointer;
5093 count = pcurrSCCB->RequestSenseLength;
5097 HP_SETUP_ADDR_CNT(p_port, addr, count);
5099 if (pcurrSCCB->Sccb_XferState & F_HOST_XFER_DIR) {
5101 WR_HARPOON(p_port + hp_portctrl_0,
5102 (DMA_PORT | SCSI_PORT | SCSI_INBIT));
5103 WR_HARPOON(p_port + hp_scsisig, S_DATAI_PH);
5105 WR_HARPOON(p_port + hp_xfer_cmd,
5106 (XFER_DMA_HOST | XFER_HOST_AUTO | XFER_DMA_8BIT));
5109 else {
5111 WR_HARPOON(p_port + hp_portctrl_0,
5112 (SCSI_PORT | DMA_PORT | DMA_RD));
5113 WR_HARPOON(p_port + hp_scsisig, S_DATAO_PH);
5115 WR_HARPOON(p_port + hp_xfer_cmd,
5116 (XFER_HOST_DMA | XFER_HOST_AUTO | XFER_DMA_8BIT));
5121 /*---------------------------------------------------------------------
5123 * Function: BusMaster Timeout Handler
5125 * Description: This function is called after a bus master command busy time
5126 * out is detected. This routines issue halt state machine
5127 * with a software time out for command busy. If command busy
5128 * is still asserted at the end of the time out, it issues
5129 * hard abort with another software time out. It hard abort
5130 * command busy is also time out, it'll just give up.
5132 *---------------------------------------------------------------------*/
5133 static unsigned char FPT_busMstrTimeOut(unsigned long p_port)
5135 unsigned long timeout;
5137 timeout = LONG_WAIT;
5139 WR_HARPOON(p_port + hp_sys_ctrl, HALT_MACH);
5141 while ((!(RD_HARPOON(p_port + hp_ext_status) & CMD_ABORTED))
5142 && timeout--) {
5145 if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
5146 WR_HARPOON(p_port + hp_sys_ctrl, HARD_ABORT);
5148 timeout = LONG_WAIT;
5149 while ((RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY)
5150 && timeout--) {
5154 RD_HARPOON(p_port + hp_int_status); /*Clear command complete */
5156 if (RD_HARPOON(p_port + hp_ext_status) & BM_CMD_BUSY) {
5157 return 1;
5160 else {
5161 return 0;
5165 /*---------------------------------------------------------------------
5167 * Function: Host Data Transfer Abort
5169 * Description: Abort any in progress transfer.
5171 *---------------------------------------------------------------------*/
5172 static void FPT_hostDataXferAbort(unsigned long port, unsigned char p_card,
5173 struct sccb *pCurrSCCB)
5176 unsigned long timeout;
5177 unsigned long remain_cnt;
5178 unsigned int sg_ptr;
5180 FPT_BL_Card[p_card].globalFlags &= ~F_HOST_XFER_ACT;
5182 if (pCurrSCCB->Sccb_XferState & F_AUTO_SENSE) {
5184 if (!(RD_HARPOON(port + hp_int_status) & INT_CMD_COMPL)) {
5186 WR_HARPOON(port + hp_bm_ctrl,
5187 (RD_HARPOON(port + hp_bm_ctrl) |
5188 FLUSH_XFER_CNTR));
5189 timeout = LONG_WAIT;
5191 while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
5192 && timeout--) {
5195 WR_HARPOON(port + hp_bm_ctrl,
5196 (RD_HARPOON(port + hp_bm_ctrl) &
5197 ~FLUSH_XFER_CNTR));
5199 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
5201 if (FPT_busMstrTimeOut(port)) {
5203 if (pCurrSCCB->HostStatus == 0x00)
5205 pCurrSCCB->HostStatus =
5206 SCCB_BM_ERR;
5210 if (RD_HARPOON(port + hp_int_status) &
5211 INT_EXT_STATUS)
5213 if (RD_HARPOON(port + hp_ext_status) &
5214 BAD_EXT_STATUS)
5216 if (pCurrSCCB->HostStatus ==
5217 0x00)
5219 pCurrSCCB->HostStatus =
5220 SCCB_BM_ERR;
5226 else if (pCurrSCCB->Sccb_XferCnt) {
5228 if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
5230 WR_HARPOON(port + hp_page_ctrl,
5231 (RD_HARPOON(port + hp_page_ctrl) &
5232 ~SCATTER_EN));
5234 WR_HARPOON(port + hp_sg_addr, 0x00);
5236 sg_ptr = pCurrSCCB->Sccb_sgseg + SG_BUF_CNT;
5238 if (sg_ptr >
5239 (unsigned int)(pCurrSCCB->DataLength /
5240 SG_ELEMENT_SIZE)) {
5242 sg_ptr =
5243 (unsigned int)(pCurrSCCB->DataLength /
5244 SG_ELEMENT_SIZE);
5247 remain_cnt = pCurrSCCB->Sccb_XferCnt;
5249 while (remain_cnt < 0x01000000L) {
5251 sg_ptr--;
5253 if (remain_cnt >
5254 (unsigned
5255 long)(*(((unsigned long *)pCurrSCCB->
5256 DataPointer) + (sg_ptr * 2)))) {
5258 remain_cnt -=
5259 (unsigned
5260 long)(*(((unsigned long *)
5261 pCurrSCCB->DataPointer) +
5262 (sg_ptr * 2)));
5265 else {
5267 break;
5271 if (remain_cnt < 0x01000000L) {
5273 pCurrSCCB->Sccb_SGoffset = remain_cnt;
5275 pCurrSCCB->Sccb_sgseg = (unsigned short)sg_ptr;
5277 if ((unsigned long)(sg_ptr * SG_ELEMENT_SIZE) ==
5278 pCurrSCCB->DataLength && (remain_cnt == 0))
5280 pCurrSCCB->Sccb_XferState |=
5281 F_ALL_XFERRED;
5284 else {
5286 if (pCurrSCCB->HostStatus == 0x00) {
5288 pCurrSCCB->HostStatus =
5289 SCCB_GROSS_FW_ERR;
5294 if (!(pCurrSCCB->Sccb_XferState & F_HOST_XFER_DIR)) {
5296 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
5298 FPT_busMstrTimeOut(port);
5301 else {
5303 if (RD_HARPOON(port + hp_int_status) &
5304 INT_EXT_STATUS) {
5306 if (RD_HARPOON(port + hp_ext_status) &
5307 BAD_EXT_STATUS) {
5309 if (pCurrSCCB->HostStatus ==
5310 0x00) {
5312 pCurrSCCB->HostStatus =
5313 SCCB_BM_ERR;
5321 else {
5323 if ((RD_HARPOON(port + hp_fifo_cnt)) >= BM_THRESHOLD) {
5325 timeout = SHORT_WAIT;
5327 while ((RD_HARPOON(port + hp_ext_status) &
5328 BM_CMD_BUSY)
5329 && ((RD_HARPOON(port + hp_fifo_cnt)) >=
5330 BM_THRESHOLD) && timeout--) {
5334 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
5336 WR_HARPOON(port + hp_bm_ctrl,
5337 (RD_HARPOON(port + hp_bm_ctrl) |
5338 FLUSH_XFER_CNTR));
5340 timeout = LONG_WAIT;
5342 while ((RD_HARPOON(port + hp_ext_status) &
5343 BM_CMD_BUSY) && timeout--) {
5346 WR_HARPOON(port + hp_bm_ctrl,
5347 (RD_HARPOON(port + hp_bm_ctrl) &
5348 ~FLUSH_XFER_CNTR));
5350 if (RD_HARPOON(port + hp_ext_status) &
5351 BM_CMD_BUSY) {
5353 if (pCurrSCCB->HostStatus == 0x00) {
5355 pCurrSCCB->HostStatus =
5356 SCCB_BM_ERR;
5359 FPT_busMstrTimeOut(port);
5363 if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
5365 if (RD_HARPOON(port + hp_ext_status) &
5366 BAD_EXT_STATUS) {
5368 if (pCurrSCCB->HostStatus == 0x00) {
5370 pCurrSCCB->HostStatus =
5371 SCCB_BM_ERR;
5379 else {
5381 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
5383 timeout = LONG_WAIT;
5385 while ((RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY)
5386 && timeout--) {
5389 if (RD_HARPOON(port + hp_ext_status) & BM_CMD_BUSY) {
5391 if (pCurrSCCB->HostStatus == 0x00) {
5393 pCurrSCCB->HostStatus = SCCB_BM_ERR;
5396 FPT_busMstrTimeOut(port);
5400 if (RD_HARPOON(port + hp_int_status) & INT_EXT_STATUS) {
5402 if (RD_HARPOON(port + hp_ext_status) & BAD_EXT_STATUS) {
5404 if (pCurrSCCB->HostStatus == 0x00) {
5406 pCurrSCCB->HostStatus = SCCB_BM_ERR;
5412 if (pCurrSCCB->Sccb_XferState & F_SG_XFER) {
5414 WR_HARPOON(port + hp_page_ctrl,
5415 (RD_HARPOON(port + hp_page_ctrl) &
5416 ~SCATTER_EN));
5418 WR_HARPOON(port + hp_sg_addr, 0x00);
5420 pCurrSCCB->Sccb_sgseg += SG_BUF_CNT;
5422 pCurrSCCB->Sccb_SGoffset = 0x00;
5424 if ((unsigned long)(pCurrSCCB->Sccb_sgseg *
5425 SG_ELEMENT_SIZE) >=
5426 pCurrSCCB->DataLength) {
5428 pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
5430 pCurrSCCB->Sccb_sgseg =
5431 (unsigned short)(pCurrSCCB->DataLength /
5432 SG_ELEMENT_SIZE);
5437 else {
5439 if (!(pCurrSCCB->Sccb_XferState & F_AUTO_SENSE))
5441 pCurrSCCB->Sccb_XferState |= F_ALL_XFERRED;
5445 WR_HARPOON(port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
5448 /*---------------------------------------------------------------------
5450 * Function: Host Data Transfer Restart
5452 * Description: Reset the available count due to a restore data
5453 * pointers message.
5455 *---------------------------------------------------------------------*/
5456 static void FPT_hostDataXferRestart(struct sccb *currSCCB)
5458 unsigned long data_count;
5459 unsigned int sg_index;
5460 unsigned long *sg_ptr;
5462 if (currSCCB->Sccb_XferState & F_SG_XFER) {
5464 currSCCB->Sccb_XferCnt = 0;
5466 sg_index = 0xffff; /*Index by long words into sg list. */
5467 data_count = 0; /*Running count of SG xfer counts. */
5469 sg_ptr = (unsigned long *)currSCCB->DataPointer;
5471 while (data_count < currSCCB->Sccb_ATC) {
5473 sg_index++;
5474 data_count += *(sg_ptr + (sg_index * 2));
5477 if (data_count == currSCCB->Sccb_ATC) {
5479 currSCCB->Sccb_SGoffset = 0;
5480 sg_index++;
5483 else {
5484 currSCCB->Sccb_SGoffset =
5485 data_count - currSCCB->Sccb_ATC;
5488 currSCCB->Sccb_sgseg = (unsigned short)sg_index;
5491 else {
5492 currSCCB->Sccb_XferCnt =
5493 currSCCB->DataLength - currSCCB->Sccb_ATC;
5497 /*---------------------------------------------------------------------
5499 * Function: FPT_scini
5501 * Description: Setup all data structures necessary for SCAM selection.
5503 *---------------------------------------------------------------------*/
5505 static void FPT_scini(unsigned char p_card, unsigned char p_our_id,
5506 unsigned char p_power_up)
5509 unsigned char loser, assigned_id;
5510 unsigned long p_port;
5512 unsigned char i, k, ScamFlg;
5513 struct sccb_card *currCard;
5514 struct nvram_info *pCurrNvRam;
5516 currCard = &FPT_BL_Card[p_card];
5517 p_port = currCard->ioPort;
5518 pCurrNvRam = currCard->pNvRamInfo;
5520 if (pCurrNvRam) {
5521 ScamFlg = pCurrNvRam->niScamConf;
5522 i = pCurrNvRam->niSysConf;
5523 } else {
5524 ScamFlg =
5525 (unsigned char)FPT_utilEERead(p_port, SCAM_CONFIG / 2);
5526 i = (unsigned
5527 char)(FPT_utilEERead(p_port, (SYSTEM_CONFIG / 2)));
5529 if (!(i & 0x02)) /* check if reset bus in AutoSCSI parameter set */
5530 return;
5532 FPT_inisci(p_card, p_port, p_our_id);
5534 /* Force to wait 1 sec after SCSI bus reset. Some SCAM device FW
5535 too slow to return to SCAM selection */
5537 /* if (p_power_up)
5538 FPT_Wait1Second(p_port);
5539 else
5540 FPT_Wait(p_port, TO_250ms); */
5542 FPT_Wait1Second(p_port);
5544 if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2)) {
5545 while (!(FPT_scarb(p_port, INIT_SELTD))) {
5548 FPT_scsel(p_port);
5550 do {
5551 FPT_scxferc(p_port, SYNC_PTRN);
5552 FPT_scxferc(p_port, DOM_MSTR);
5553 loser =
5554 FPT_scsendi(p_port,
5555 &FPT_scamInfo[p_our_id].id_string[0]);
5556 } while (loser == 0xFF);
5558 FPT_scbusf(p_port);
5560 if ((p_power_up) && (!loser)) {
5561 FPT_sresb(p_port, p_card);
5562 FPT_Wait(p_port, TO_250ms);
5564 while (!(FPT_scarb(p_port, INIT_SELTD))) {
5567 FPT_scsel(p_port);
5569 do {
5570 FPT_scxferc(p_port, SYNC_PTRN);
5571 FPT_scxferc(p_port, DOM_MSTR);
5572 loser =
5573 FPT_scsendi(p_port,
5574 &FPT_scamInfo[p_our_id].
5575 id_string[0]);
5576 } while (loser == 0xFF);
5578 FPT_scbusf(p_port);
5582 else {
5583 loser = 0;
5586 if (!loser) {
5588 FPT_scamInfo[p_our_id].state = ID_ASSIGNED;
5590 if (ScamFlg & SCAM_ENABLED) {
5592 for (i = 0; i < MAX_SCSI_TAR; i++) {
5593 if ((FPT_scamInfo[i].state == ID_UNASSIGNED) ||
5594 (FPT_scamInfo[i].state == ID_UNUSED)) {
5595 if (FPT_scsell(p_port, i)) {
5596 FPT_scamInfo[i].state = LEGACY;
5597 if ((FPT_scamInfo[i].
5598 id_string[0] != 0xFF)
5599 || (FPT_scamInfo[i].
5600 id_string[1] != 0xFA)) {
5602 FPT_scamInfo[i].
5603 id_string[0] = 0xFF;
5604 FPT_scamInfo[i].
5605 id_string[1] = 0xFA;
5606 if (pCurrNvRam == NULL)
5607 currCard->
5608 globalFlags
5610 F_UPDATE_EEPROM;
5616 FPT_sresb(p_port, p_card);
5617 FPT_Wait1Second(p_port);
5618 while (!(FPT_scarb(p_port, INIT_SELTD))) {
5620 FPT_scsel(p_port);
5621 FPT_scasid(p_card, p_port);
5626 else if ((loser) && (ScamFlg & SCAM_ENABLED)) {
5627 FPT_scamInfo[p_our_id].id_string[0] = SLV_TYPE_CODE0;
5628 assigned_id = 0;
5629 FPT_scwtsel(p_port);
5631 do {
5632 while (FPT_scxferc(p_port, 0x00) != SYNC_PTRN) {
5635 i = FPT_scxferc(p_port, 0x00);
5636 if (i == ASSIGN_ID) {
5637 if (!
5638 (FPT_scsendi
5639 (p_port,
5640 &FPT_scamInfo[p_our_id].id_string[0]))) {
5641 i = FPT_scxferc(p_port, 0x00);
5642 if (FPT_scvalq(i)) {
5643 k = FPT_scxferc(p_port, 0x00);
5645 if (FPT_scvalq(k)) {
5646 currCard->ourId =
5647 ((unsigned char)(i
5651 (k &
5652 (unsigned char)7))
5653 & (unsigned char)
5654 0x3F;
5655 FPT_inisci(p_card,
5656 p_port,
5657 p_our_id);
5658 FPT_scamInfo[currCard->
5659 ourId].
5660 state = ID_ASSIGNED;
5661 FPT_scamInfo[currCard->
5662 ourId].
5663 id_string[0]
5664 = SLV_TYPE_CODE0;
5665 assigned_id = 1;
5671 else if (i == SET_P_FLAG) {
5672 if (!(FPT_scsendi(p_port,
5673 &FPT_scamInfo[p_our_id].
5674 id_string[0])))
5675 FPT_scamInfo[p_our_id].id_string[0] |=
5676 0x80;
5678 } while (!assigned_id);
5680 while (FPT_scxferc(p_port, 0x00) != CFG_CMPLT) {
5684 if (ScamFlg & SCAM_ENABLED) {
5685 FPT_scbusf(p_port);
5686 if (currCard->globalFlags & F_UPDATE_EEPROM) {
5687 FPT_scsavdi(p_card, p_port);
5688 currCard->globalFlags &= ~F_UPDATE_EEPROM;
5693 for (i=0,k=0; i < MAX_SCSI_TAR; i++)
5695 if ((FPT_scamInfo[i].state == ID_ASSIGNED) ||
5696 (FPT_scamInfo[i].state == LEGACY))
5697 k++;
5700 if (k==2)
5701 currCard->globalFlags |= F_SINGLE_DEVICE;
5702 else
5703 currCard->globalFlags &= ~F_SINGLE_DEVICE;
5707 /*---------------------------------------------------------------------
5709 * Function: FPT_scarb
5711 * Description: Gain control of the bus and wait SCAM select time (250ms)
5713 *---------------------------------------------------------------------*/
5715 static int FPT_scarb(unsigned long p_port, unsigned char p_sel_type)
5717 if (p_sel_type == INIT_SELTD) {
5719 while (RD_HARPOON(p_port + hp_scsisig) & (SCSI_SEL | SCSI_BSY)) {
5722 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL)
5723 return 0;
5725 if (RD_HARPOON(p_port + hp_scsidata_0) != 00)
5726 return 0;
5728 WR_HARPOON(p_port + hp_scsisig,
5729 (RD_HARPOON(p_port + hp_scsisig) | SCSI_BSY));
5731 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_SEL) {
5733 WR_HARPOON(p_port + hp_scsisig,
5734 (RD_HARPOON(p_port + hp_scsisig) &
5735 ~SCSI_BSY));
5736 return 0;
5739 WR_HARPOON(p_port + hp_scsisig,
5740 (RD_HARPOON(p_port + hp_scsisig) | SCSI_SEL));
5742 if (RD_HARPOON(p_port + hp_scsidata_0) != 00) {
5744 WR_HARPOON(p_port + hp_scsisig,
5745 (RD_HARPOON(p_port + hp_scsisig) &
5746 ~(SCSI_BSY | SCSI_SEL)));
5747 return 0;
5751 WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
5752 & ~ACTdeassert));
5753 WR_HARPOON(p_port + hp_scsireset, SCAM_EN);
5754 WR_HARPOON(p_port + hp_scsidata_0, 0x00);
5755 WR_HARPOON(p_port + hp_scsidata_1, 0x00);
5756 WR_HARPOON(p_port + hp_portctrl_0, SCSI_BUS_EN);
5758 WR_HARPOON(p_port + hp_scsisig,
5759 (RD_HARPOON(p_port + hp_scsisig) | SCSI_MSG));
5761 WR_HARPOON(p_port + hp_scsisig, (RD_HARPOON(p_port + hp_scsisig)
5762 & ~SCSI_BSY));
5764 FPT_Wait(p_port, TO_250ms);
5766 return 1;
5769 /*---------------------------------------------------------------------
5771 * Function: FPT_scbusf
5773 * Description: Release the SCSI bus and disable SCAM selection.
5775 *---------------------------------------------------------------------*/
5777 static void FPT_scbusf(unsigned long p_port)
5779 WR_HARPOON(p_port + hp_page_ctrl,
5780 (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
5782 WR_HARPOON(p_port + hp_scsidata_0, 0x00);
5784 WR_HARPOON(p_port + hp_portctrl_0, (RD_HARPOON(p_port + hp_portctrl_0)
5785 & ~SCSI_BUS_EN));
5787 WR_HARPOON(p_port + hp_scsisig, 0x00);
5789 WR_HARPOON(p_port + hp_scsireset, (RD_HARPOON(p_port + hp_scsireset)
5790 & ~SCAM_EN));
5792 WR_HARPOON(p_port + hp_clkctrl_0, (RD_HARPOON(p_port + hp_clkctrl_0)
5793 | ACTdeassert));
5795 WRW_HARPOON((p_port + hp_intstat), (BUS_FREE | AUTO_INT | SCAM_SEL));
5797 WR_HARPOON(p_port + hp_page_ctrl,
5798 (RD_HARPOON(p_port + hp_page_ctrl) & ~G_INT_DISABLE));
5801 /*---------------------------------------------------------------------
5803 * Function: FPT_scasid
5805 * Description: Assign an ID to all the SCAM devices.
5807 *---------------------------------------------------------------------*/
5809 static void FPT_scasid(unsigned char p_card, unsigned long p_port)
5811 unsigned char temp_id_string[ID_STRING_LENGTH];
5813 unsigned char i, k, scam_id;
5814 unsigned char crcBytes[3];
5815 struct nvram_info *pCurrNvRam;
5816 unsigned short *pCrcBytes;
5818 pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
5820 i = 0;
5822 while (!i) {
5824 for (k = 0; k < ID_STRING_LENGTH; k++) {
5825 temp_id_string[k] = (unsigned char)0x00;
5828 FPT_scxferc(p_port, SYNC_PTRN);
5829 FPT_scxferc(p_port, ASSIGN_ID);
5831 if (!(FPT_sciso(p_port, &temp_id_string[0]))) {
5832 if (pCurrNvRam) {
5833 pCrcBytes = (unsigned short *)&crcBytes[0];
5834 *pCrcBytes = FPT_CalcCrc16(&temp_id_string[0]);
5835 crcBytes[2] = FPT_CalcLrc(&temp_id_string[0]);
5836 temp_id_string[1] = crcBytes[2];
5837 temp_id_string[2] = crcBytes[0];
5838 temp_id_string[3] = crcBytes[1];
5839 for (k = 4; k < ID_STRING_LENGTH; k++)
5840 temp_id_string[k] = (unsigned char)0x00;
5842 i = FPT_scmachid(p_card, temp_id_string);
5844 if (i == CLR_PRIORITY) {
5845 FPT_scxferc(p_port, MISC_CODE);
5846 FPT_scxferc(p_port, CLR_P_FLAG);
5847 i = 0; /*Not the last ID yet. */
5850 else if (i != NO_ID_AVAIL) {
5851 if (i < 8)
5852 FPT_scxferc(p_port, ID_0_7);
5853 else
5854 FPT_scxferc(p_port, ID_8_F);
5856 scam_id = (i & (unsigned char)0x07);
5858 for (k = 1; k < 0x08; k <<= 1)
5859 if (!(k & i))
5860 scam_id += 0x08; /*Count number of zeros in DB0-3. */
5862 FPT_scxferc(p_port, scam_id);
5864 i = 0; /*Not the last ID yet. */
5868 else {
5869 i = 1;
5872 } /*End while */
5874 FPT_scxferc(p_port, SYNC_PTRN);
5875 FPT_scxferc(p_port, CFG_CMPLT);
5878 /*---------------------------------------------------------------------
5880 * Function: FPT_scsel
5882 * Description: Select all the SCAM devices.
5884 *---------------------------------------------------------------------*/
5886 static void FPT_scsel(unsigned long p_port)
5889 WR_HARPOON(p_port + hp_scsisig, SCSI_SEL);
5890 FPT_scwiros(p_port, SCSI_MSG);
5892 WR_HARPOON(p_port + hp_scsisig, (SCSI_SEL | SCSI_BSY));
5894 WR_HARPOON(p_port + hp_scsisig,
5895 (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5896 WR_HARPOON(p_port + hp_scsidata_0,
5897 (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) |
5898 (unsigned char)(BIT(7) + BIT(6))));
5900 WR_HARPOON(p_port + hp_scsisig, (SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5901 FPT_scwiros(p_port, SCSI_SEL);
5903 WR_HARPOON(p_port + hp_scsidata_0,
5904 (unsigned char)(RD_HARPOON(p_port + hp_scsidata_0) &
5905 ~(unsigned char)BIT(6)));
5906 FPT_scwirod(p_port, BIT(6));
5908 WR_HARPOON(p_port + hp_scsisig,
5909 (SCSI_SEL | SCSI_BSY | SCSI_IOBIT | SCSI_CD));
5912 /*---------------------------------------------------------------------
5914 * Function: FPT_scxferc
5916 * Description: Handshake the p_data (DB4-0) across the bus.
5918 *---------------------------------------------------------------------*/
5920 static unsigned char FPT_scxferc(unsigned long p_port, unsigned char p_data)
5922 unsigned char curr_data, ret_data;
5924 curr_data = p_data | BIT(7) | BIT(5); /*Start with DB7 & DB5 asserted. */
5926 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5928 curr_data &= ~BIT(7);
5930 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5932 FPT_scwirod(p_port, BIT(7)); /*Wait for DB7 to be released. */
5933 while (!(RD_HARPOON(p_port + hp_scsidata_0) & BIT(5))) ;
5935 ret_data = (RD_HARPOON(p_port + hp_scsidata_0) & (unsigned char)0x1F);
5937 curr_data |= BIT(6);
5939 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5941 curr_data &= ~BIT(5);
5943 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5945 FPT_scwirod(p_port, BIT(5)); /*Wait for DB5 to be released. */
5947 curr_data &= ~(BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0)); /*Release data bits */
5948 curr_data |= BIT(7);
5950 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5952 curr_data &= ~BIT(6);
5954 WR_HARPOON(p_port + hp_scsidata_0, curr_data);
5956 FPT_scwirod(p_port, BIT(6)); /*Wait for DB6 to be released. */
5958 return ret_data;
5961 /*---------------------------------------------------------------------
5963 * Function: FPT_scsendi
5965 * Description: Transfer our Identification string to determine if we
5966 * will be the dominant master.
5968 *---------------------------------------------------------------------*/
5970 static unsigned char FPT_scsendi(unsigned long p_port,
5971 unsigned char p_id_string[])
5973 unsigned char ret_data, byte_cnt, bit_cnt, defer;
5975 defer = 0;
5977 for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
5979 for (bit_cnt = 0x80; bit_cnt != 0; bit_cnt >>= 1) {
5981 if (defer)
5982 ret_data = FPT_scxferc(p_port, 00);
5984 else if (p_id_string[byte_cnt] & bit_cnt)
5986 ret_data = FPT_scxferc(p_port, 02);
5988 else {
5990 ret_data = FPT_scxferc(p_port, 01);
5991 if (ret_data & 02)
5992 defer = 1;
5995 if ((ret_data & 0x1C) == 0x10)
5996 return 0x00; /*End of isolation stage, we won! */
5998 if (ret_data & 0x1C)
5999 return 0xFF;
6001 if ((defer) && (!(ret_data & 0x1F)))
6002 return 0x01; /*End of isolation stage, we lost. */
6004 } /*bit loop */
6006 } /*byte loop */
6008 if (defer)
6009 return 0x01; /*We lost */
6010 else
6011 return 0; /*We WON! Yeeessss! */
6014 /*---------------------------------------------------------------------
6016 * Function: FPT_sciso
6018 * Description: Transfer the Identification string.
6020 *---------------------------------------------------------------------*/
6022 static unsigned char FPT_sciso(unsigned long p_port,
6023 unsigned char p_id_string[])
6025 unsigned char ret_data, the_data, byte_cnt, bit_cnt;
6027 the_data = 0;
6029 for (byte_cnt = 0; byte_cnt < ID_STRING_LENGTH; byte_cnt++) {
6031 for (bit_cnt = 0; bit_cnt < 8; bit_cnt++) {
6033 ret_data = FPT_scxferc(p_port, 0);
6035 if (ret_data & 0xFC)
6036 return 0xFF;
6038 else {
6040 the_data <<= 1;
6041 if (ret_data & BIT(1)) {
6042 the_data |= 1;
6046 if ((ret_data & 0x1F) == 0) {
6048 if(bit_cnt != 0 || bit_cnt != 8)
6050 byte_cnt = 0;
6051 bit_cnt = 0;
6052 FPT_scxferc(p_port, SYNC_PTRN);
6053 FPT_scxferc(p_port, ASSIGN_ID);
6054 continue;
6057 if (byte_cnt)
6058 return 0x00;
6059 else
6060 return 0xFF;
6063 } /*bit loop */
6065 p_id_string[byte_cnt] = the_data;
6067 } /*byte loop */
6069 return 0;
6072 /*---------------------------------------------------------------------
6074 * Function: FPT_scwirod
6076 * Description: Sample the SCSI data bus making sure the signal has been
6077 * deasserted for the correct number of consecutive samples.
6079 *---------------------------------------------------------------------*/
6081 static void FPT_scwirod(unsigned long p_port, unsigned char p_data_bit)
6083 unsigned char i;
6085 i = 0;
6086 while (i < MAX_SCSI_TAR) {
6088 if (RD_HARPOON(p_port + hp_scsidata_0) & p_data_bit)
6090 i = 0;
6092 else
6094 i++;
6099 /*---------------------------------------------------------------------
6101 * Function: FPT_scwiros
6103 * Description: Sample the SCSI Signal lines making sure the signal has been
6104 * deasserted for the correct number of consecutive samples.
6106 *---------------------------------------------------------------------*/
6108 static void FPT_scwiros(unsigned long p_port, unsigned char p_data_bit)
6110 unsigned char i;
6112 i = 0;
6113 while (i < MAX_SCSI_TAR) {
6115 if (RD_HARPOON(p_port + hp_scsisig) & p_data_bit)
6117 i = 0;
6119 else
6121 i++;
6126 /*---------------------------------------------------------------------
6128 * Function: FPT_scvalq
6130 * Description: Make sure we received a valid data byte.
6132 *---------------------------------------------------------------------*/
6134 static unsigned char FPT_scvalq(unsigned char p_quintet)
6136 unsigned char count;
6138 for (count = 1; count < 0x08; count <<= 1) {
6139 if (!(p_quintet & count))
6140 p_quintet -= 0x80;
6143 if (p_quintet & 0x18)
6144 return 0;
6146 else
6147 return 1;
6150 /*---------------------------------------------------------------------
6152 * Function: FPT_scsell
6154 * Description: Select the specified device ID using a selection timeout
6155 * less than 4ms. If somebody responds then it is a legacy
6156 * drive and this ID must be marked as such.
6158 *---------------------------------------------------------------------*/
6160 static unsigned char FPT_scsell(unsigned long p_port, unsigned char targ_id)
6162 unsigned long i;
6164 WR_HARPOON(p_port + hp_page_ctrl,
6165 (RD_HARPOON(p_port + hp_page_ctrl) | G_INT_DISABLE));
6167 ARAM_ACCESS(p_port);
6169 WR_HARPOON(p_port + hp_addstat,
6170 (RD_HARPOON(p_port + hp_addstat) | SCAM_TIMER));
6171 WR_HARPOON(p_port + hp_seltimeout, TO_4ms);
6173 for (i = p_port + CMD_STRT; i < p_port + CMD_STRT + 12; i += 2) {
6174 WRW_HARPOON(i, (MPM_OP + ACOMMAND));
6176 WRW_HARPOON(i, (BRH_OP + ALWAYS + NP));
6178 WRW_HARPOON((p_port + hp_intstat),
6179 (RESET | TIMEOUT | SEL | BUS_FREE | AUTO_INT));
6181 WR_HARPOON(p_port + hp_select_id, targ_id);
6183 WR_HARPOON(p_port + hp_portctrl_0, SCSI_PORT);
6184 WR_HARPOON(p_port + hp_autostart_3, (SELECT | CMD_ONLY_STRT));
6185 WR_HARPOON(p_port + hp_scsictrl_0, (SEL_TAR | ENA_RESEL));
6187 while (!(RDW_HARPOON((p_port + hp_intstat)) &
6188 (RESET | PROG_HLT | TIMEOUT | AUTO_INT))) {
6191 if (RDW_HARPOON((p_port + hp_intstat)) & RESET)
6192 FPT_Wait(p_port, TO_250ms);
6194 DISABLE_AUTO(p_port);
6196 WR_HARPOON(p_port + hp_addstat,
6197 (RD_HARPOON(p_port + hp_addstat) & ~SCAM_TIMER));
6198 WR_HARPOON(p_port + hp_seltimeout, TO_290ms);
6200 SGRAM_ACCESS(p_port);
6202 if (RDW_HARPOON((p_port + hp_intstat)) & (RESET | TIMEOUT)) {
6204 WRW_HARPOON((p_port + hp_intstat),
6205 (RESET | TIMEOUT | SEL | BUS_FREE | PHASE));
6207 WR_HARPOON(p_port + hp_page_ctrl,
6208 (RD_HARPOON(p_port + hp_page_ctrl) &
6209 ~G_INT_DISABLE));
6211 return 0; /*No legacy device */
6214 else {
6216 while (!(RDW_HARPOON((p_port + hp_intstat)) & BUS_FREE)) {
6217 if (RD_HARPOON(p_port + hp_scsisig) & SCSI_REQ) {
6218 WR_HARPOON(p_port + hp_scsisig,
6219 (SCSI_ACK + S_ILL_PH));
6220 ACCEPT_MSG(p_port);
6224 WRW_HARPOON((p_port + hp_intstat), CLR_ALL_INT_1);
6226 WR_HARPOON(p_port + hp_page_ctrl,
6227 (RD_HARPOON(p_port + hp_page_ctrl) &
6228 ~G_INT_DISABLE));
6230 return 1; /*Found one of them oldies! */
6234 /*---------------------------------------------------------------------
6236 * Function: FPT_scwtsel
6238 * Description: Wait to be selected by another SCAM initiator.
6240 *---------------------------------------------------------------------*/
6242 static void FPT_scwtsel(unsigned long p_port)
6244 while (!(RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL)) {
6248 /*---------------------------------------------------------------------
6250 * Function: FPT_inisci
6252 * Description: Setup the data Structure with the info from the EEPROM.
6254 *---------------------------------------------------------------------*/
6256 static void FPT_inisci(unsigned char p_card, unsigned long p_port,
6257 unsigned char p_our_id)
6259 unsigned char i, k, max_id;
6260 unsigned short ee_data;
6261 struct nvram_info *pCurrNvRam;
6263 pCurrNvRam = FPT_BL_Card[p_card].pNvRamInfo;
6265 if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6266 max_id = 0x08;
6268 else
6269 max_id = 0x10;
6271 if (pCurrNvRam) {
6272 for (i = 0; i < max_id; i++) {
6274 for (k = 0; k < 4; k++)
6275 FPT_scamInfo[i].id_string[k] =
6276 pCurrNvRam->niScamTbl[i][k];
6277 for (k = 4; k < ID_STRING_LENGTH; k++)
6278 FPT_scamInfo[i].id_string[k] =
6279 (unsigned char)0x00;
6281 if (FPT_scamInfo[i].id_string[0] == 0x00)
6282 FPT_scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */
6283 else
6284 FPT_scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */
6287 } else {
6288 for (i = 0; i < max_id; i++) {
6289 for (k = 0; k < ID_STRING_LENGTH; k += 2) {
6290 ee_data =
6291 FPT_utilEERead(p_port,
6292 (unsigned
6293 short)((EE_SCAMBASE / 2) +
6294 (unsigned short)(i *
6295 ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
6296 FPT_scamInfo[i].id_string[k] =
6297 (unsigned char)ee_data;
6298 ee_data >>= 8;
6299 FPT_scamInfo[i].id_string[k + 1] =
6300 (unsigned char)ee_data;
6303 if ((FPT_scamInfo[i].id_string[0] == 0x00) ||
6304 (FPT_scamInfo[i].id_string[0] == 0xFF))
6306 FPT_scamInfo[i].state = ID_UNUSED; /*Default to unused ID. */
6308 else
6309 FPT_scamInfo[i].state = ID_UNASSIGNED; /*Default to unassigned ID. */
6313 for (k = 0; k < ID_STRING_LENGTH; k++)
6314 FPT_scamInfo[p_our_id].id_string[k] = FPT_scamHAString[k];
6318 /*---------------------------------------------------------------------
6320 * Function: FPT_scmachid
6322 * Description: Match the Device ID string with our values stored in
6323 * the EEPROM.
6325 *---------------------------------------------------------------------*/
6327 static unsigned char FPT_scmachid(unsigned char p_card,
6328 unsigned char p_id_string[])
6331 unsigned char i, k, match;
6333 for (i = 0; i < MAX_SCSI_TAR; i++) {
6335 match = 1;
6337 for (k = 0; k < ID_STRING_LENGTH; k++) {
6338 if (p_id_string[k] != FPT_scamInfo[i].id_string[k])
6339 match = 0;
6342 if (match) {
6343 FPT_scamInfo[i].state = ID_ASSIGNED;
6344 return i;
6349 if (p_id_string[0] & BIT(5))
6350 i = 8;
6351 else
6352 i = MAX_SCSI_TAR;
6354 if (((p_id_string[0] & 0x06) == 0x02)
6355 || ((p_id_string[0] & 0x06) == 0x04))
6356 match = p_id_string[1] & (unsigned char)0x1F;
6357 else
6358 match = 7;
6360 while (i > 0) {
6361 i--;
6363 if (FPT_scamInfo[match].state == ID_UNUSED) {
6364 for (k = 0; k < ID_STRING_LENGTH; k++) {
6365 FPT_scamInfo[match].id_string[k] =
6366 p_id_string[k];
6369 FPT_scamInfo[match].state = ID_ASSIGNED;
6371 if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
6372 FPT_BL_Card[p_card].globalFlags |=
6373 F_UPDATE_EEPROM;
6374 return match;
6378 match--;
6380 if (match == 0xFF) {
6381 if (p_id_string[0] & BIT(5))
6382 match = 7;
6383 else
6384 match = MAX_SCSI_TAR - 1;
6388 if (p_id_string[0] & BIT(7)) {
6389 return CLR_PRIORITY;
6392 if (p_id_string[0] & BIT(5))
6393 i = 8;
6394 else
6395 i = MAX_SCSI_TAR;
6397 if (((p_id_string[0] & 0x06) == 0x02)
6398 || ((p_id_string[0] & 0x06) == 0x04))
6399 match = p_id_string[1] & (unsigned char)0x1F;
6400 else
6401 match = 7;
6403 while (i > 0) {
6405 i--;
6407 if (FPT_scamInfo[match].state == ID_UNASSIGNED) {
6408 for (k = 0; k < ID_STRING_LENGTH; k++) {
6409 FPT_scamInfo[match].id_string[k] =
6410 p_id_string[k];
6413 FPT_scamInfo[match].id_string[0] |= BIT(7);
6414 FPT_scamInfo[match].state = ID_ASSIGNED;
6415 if (FPT_BL_Card[p_card].pNvRamInfo == NULL)
6416 FPT_BL_Card[p_card].globalFlags |=
6417 F_UPDATE_EEPROM;
6418 return match;
6422 match--;
6424 if (match == 0xFF) {
6425 if (p_id_string[0] & BIT(5))
6426 match = 7;
6427 else
6428 match = MAX_SCSI_TAR - 1;
6432 return NO_ID_AVAIL;
6435 /*---------------------------------------------------------------------
6437 * Function: FPT_scsavdi
6439 * Description: Save off the device SCAM ID strings.
6441 *---------------------------------------------------------------------*/
6443 static void FPT_scsavdi(unsigned char p_card, unsigned long p_port)
6445 unsigned char i, k, max_id;
6446 unsigned short ee_data, sum_data;
6448 sum_data = 0x0000;
6450 for (i = 1; i < EE_SCAMBASE / 2; i++) {
6451 sum_data += FPT_utilEERead(p_port, i);
6454 FPT_utilEEWriteOnOff(p_port, 1); /* Enable write access to the EEPROM */
6456 if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6457 max_id = 0x08;
6459 else
6460 max_id = 0x10;
6462 for (i = 0; i < max_id; i++) {
6464 for (k = 0; k < ID_STRING_LENGTH; k += 2) {
6465 ee_data = FPT_scamInfo[i].id_string[k + 1];
6466 ee_data <<= 8;
6467 ee_data |= FPT_scamInfo[i].id_string[k];
6468 sum_data += ee_data;
6469 FPT_utilEEWrite(p_port, ee_data,
6470 (unsigned short)((EE_SCAMBASE / 2) +
6471 (unsigned short)(i *
6472 ((unsigned short)ID_STRING_LENGTH / 2)) + (unsigned short)(k / 2)));
6476 FPT_utilEEWrite(p_port, sum_data, EEPROM_CHECK_SUM / 2);
6477 FPT_utilEEWriteOnOff(p_port, 0); /* Turn off write access */
6480 /*---------------------------------------------------------------------
6482 * Function: FPT_XbowInit
6484 * Description: Setup the Xbow for normal operation.
6486 *---------------------------------------------------------------------*/
6488 static void FPT_XbowInit(unsigned long port, unsigned char ScamFlg)
6490 unsigned char i;
6492 i = RD_HARPOON(port + hp_page_ctrl);
6493 WR_HARPOON(port + hp_page_ctrl, (unsigned char)(i | G_INT_DISABLE));
6495 WR_HARPOON(port + hp_scsireset, 0x00);
6496 WR_HARPOON(port + hp_portctrl_1, HOST_MODE8);
6498 WR_HARPOON(port + hp_scsireset, (DMA_RESET | HPSCSI_RESET | PROG_RESET |
6499 FIFO_CLR));
6501 WR_HARPOON(port + hp_scsireset, SCSI_INI);
6503 WR_HARPOON(port + hp_clkctrl_0, CLKCTRL_DEFAULT);
6505 WR_HARPOON(port + hp_scsisig, 0x00); /* Clear any signals we might */
6506 WR_HARPOON(port + hp_scsictrl_0, ENA_SCAM_SEL);
6508 WRW_HARPOON((port + hp_intstat), CLR_ALL_INT);
6510 FPT_default_intena = RESET | RSEL | PROG_HLT | TIMEOUT |
6511 BUS_FREE | XFER_CNT_0 | AUTO_INT;
6513 if ((ScamFlg & SCAM_ENABLED) && (ScamFlg & SCAM_LEVEL2))
6514 FPT_default_intena |= SCAM_SEL;
6516 WRW_HARPOON((port + hp_intena), FPT_default_intena);
6518 WR_HARPOON(port + hp_seltimeout, TO_290ms);
6520 /* Turn on SCSI_MODE8 for narrow cards to fix the
6521 strapping issue with the DUAL CHANNEL card */
6522 if (RD_HARPOON(port + hp_page_ctrl) & NARROW_SCSI_CARD)
6523 WR_HARPOON(port + hp_addstat, SCSI_MODE8);
6525 WR_HARPOON(port + hp_page_ctrl, i);
6529 /*---------------------------------------------------------------------
6531 * Function: FPT_BusMasterInit
6533 * Description: Initialize the BusMaster for normal operations.
6535 *---------------------------------------------------------------------*/
6537 static void FPT_BusMasterInit(unsigned long p_port)
6540 WR_HARPOON(p_port + hp_sys_ctrl, DRVR_RST);
6541 WR_HARPOON(p_port + hp_sys_ctrl, 0x00);
6543 WR_HARPOON(p_port + hp_host_blk_cnt, XFER_BLK64);
6545 WR_HARPOON(p_port + hp_bm_ctrl, (BMCTRL_DEFAULT));
6547 WR_HARPOON(p_port + hp_ee_ctrl, (SCSI_TERM_ENA_H));
6549 RD_HARPOON(p_port + hp_int_status); /*Clear interrupts. */
6550 WR_HARPOON(p_port + hp_int_mask, (INT_CMD_COMPL | SCSI_INTERRUPT));
6551 WR_HARPOON(p_port + hp_page_ctrl, (RD_HARPOON(p_port + hp_page_ctrl) &
6552 ~SCATTER_EN));
6555 /*---------------------------------------------------------------------
6557 * Function: FPT_DiagEEPROM
6559 * Description: Verfiy checksum and 'Key' and initialize the EEPROM if
6560 * necessary.
6562 *---------------------------------------------------------------------*/
6564 static void FPT_DiagEEPROM(unsigned long p_port)
6566 unsigned short index, temp, max_wd_cnt;
6568 if (RD_HARPOON(p_port + hp_page_ctrl) & NARROW_SCSI_CARD)
6569 max_wd_cnt = EEPROM_WD_CNT;
6570 else
6571 max_wd_cnt = EEPROM_WD_CNT * 2;
6573 temp = FPT_utilEERead(p_port, FW_SIGNATURE / 2);
6575 if (temp == 0x4641) {
6577 for (index = 2; index < max_wd_cnt; index++) {
6579 temp += FPT_utilEERead(p_port, index);
6583 if (temp == FPT_utilEERead(p_port, EEPROM_CHECK_SUM / 2)) {
6585 return; /*EEPROM is Okay so return now! */
6589 FPT_utilEEWriteOnOff(p_port, (unsigned char)1);
6591 for (index = 0; index < max_wd_cnt; index++) {
6593 FPT_utilEEWrite(p_port, 0x0000, index);
6596 temp = 0;
6598 FPT_utilEEWrite(p_port, 0x4641, FW_SIGNATURE / 2);
6599 temp += 0x4641;
6600 FPT_utilEEWrite(p_port, 0x3920, MODEL_NUMB_0 / 2);
6601 temp += 0x3920;
6602 FPT_utilEEWrite(p_port, 0x3033, MODEL_NUMB_2 / 2);
6603 temp += 0x3033;
6604 FPT_utilEEWrite(p_port, 0x2020, MODEL_NUMB_4 / 2);
6605 temp += 0x2020;
6606 FPT_utilEEWrite(p_port, 0x70D3, SYSTEM_CONFIG / 2);
6607 temp += 0x70D3;
6608 FPT_utilEEWrite(p_port, 0x0010, BIOS_CONFIG / 2);
6609 temp += 0x0010;
6610 FPT_utilEEWrite(p_port, 0x0003, SCAM_CONFIG / 2);
6611 temp += 0x0003;
6612 FPT_utilEEWrite(p_port, 0x0007, ADAPTER_SCSI_ID / 2);
6613 temp += 0x0007;
6615 FPT_utilEEWrite(p_port, 0x0000, IGNORE_B_SCAN / 2);
6616 temp += 0x0000;
6617 FPT_utilEEWrite(p_port, 0x0000, SEND_START_ENA / 2);
6618 temp += 0x0000;
6619 FPT_utilEEWrite(p_port, 0x0000, DEVICE_ENABLE / 2);
6620 temp += 0x0000;
6622 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL01 / 2);
6623 temp += 0x4242;
6624 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL23 / 2);
6625 temp += 0x4242;
6626 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL45 / 2);
6627 temp += 0x4242;
6628 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL67 / 2);
6629 temp += 0x4242;
6630 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBL89 / 2);
6631 temp += 0x4242;
6632 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLab / 2);
6633 temp += 0x4242;
6634 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLcd / 2);
6635 temp += 0x4242;
6636 FPT_utilEEWrite(p_port, 0x4242, SYNC_RATE_TBLef / 2);
6637 temp += 0x4242;
6639 FPT_utilEEWrite(p_port, 0x6C46, 64 / 2); /*PRODUCT ID */
6640 temp += 0x6C46;
6641 FPT_utilEEWrite(p_port, 0x7361, 66 / 2); /* FlashPoint LT */
6642 temp += 0x7361;
6643 FPT_utilEEWrite(p_port, 0x5068, 68 / 2);
6644 temp += 0x5068;
6645 FPT_utilEEWrite(p_port, 0x696F, 70 / 2);
6646 temp += 0x696F;
6647 FPT_utilEEWrite(p_port, 0x746E, 72 / 2);
6648 temp += 0x746E;
6649 FPT_utilEEWrite(p_port, 0x4C20, 74 / 2);
6650 temp += 0x4C20;
6651 FPT_utilEEWrite(p_port, 0x2054, 76 / 2);
6652 temp += 0x2054;
6653 FPT_utilEEWrite(p_port, 0x2020, 78 / 2);
6654 temp += 0x2020;
6656 index = ((EE_SCAMBASE / 2) + (7 * 16));
6657 FPT_utilEEWrite(p_port, (0x0700 + TYPE_CODE0), index);
6658 temp += (0x0700 + TYPE_CODE0);
6659 index++;
6660 FPT_utilEEWrite(p_port, 0x5542, index); /*Vendor ID code */
6661 temp += 0x5542; /* BUSLOGIC */
6662 index++;
6663 FPT_utilEEWrite(p_port, 0x4C53, index);
6664 temp += 0x4C53;
6665 index++;
6666 FPT_utilEEWrite(p_port, 0x474F, index);
6667 temp += 0x474F;
6668 index++;
6669 FPT_utilEEWrite(p_port, 0x4349, index);
6670 temp += 0x4349;
6671 index++;
6672 FPT_utilEEWrite(p_port, 0x5442, index); /*Vendor unique code */
6673 temp += 0x5442; /* BT- 930 */
6674 index++;
6675 FPT_utilEEWrite(p_port, 0x202D, index);
6676 temp += 0x202D;
6677 index++;
6678 FPT_utilEEWrite(p_port, 0x3339, index);
6679 temp += 0x3339;
6680 index++; /*Serial # */
6681 FPT_utilEEWrite(p_port, 0x2030, index); /* 01234567 */
6682 temp += 0x2030;
6683 index++;
6684 FPT_utilEEWrite(p_port, 0x5453, index);
6685 temp += 0x5453;
6686 index++;
6687 FPT_utilEEWrite(p_port, 0x5645, index);
6688 temp += 0x5645;
6689 index++;
6690 FPT_utilEEWrite(p_port, 0x2045, index);
6691 temp += 0x2045;
6692 index++;
6693 FPT_utilEEWrite(p_port, 0x202F, index);
6694 temp += 0x202F;
6695 index++;
6696 FPT_utilEEWrite(p_port, 0x4F4A, index);
6697 temp += 0x4F4A;
6698 index++;
6699 FPT_utilEEWrite(p_port, 0x204E, index);
6700 temp += 0x204E;
6701 index++;
6702 FPT_utilEEWrite(p_port, 0x3539, index);
6703 temp += 0x3539;
6705 FPT_utilEEWrite(p_port, temp, EEPROM_CHECK_SUM / 2);
6707 FPT_utilEEWriteOnOff(p_port, (unsigned char)0);
6711 /*---------------------------------------------------------------------
6713 * Function: Queue Search Select
6715 * Description: Try to find a new command to execute.
6717 *---------------------------------------------------------------------*/
6719 static void FPT_queueSearchSelect(struct sccb_card *pCurrCard,
6720 unsigned char p_card)
6722 unsigned char scan_ptr, lun;
6723 struct sccb_mgr_tar_info *currTar_Info;
6724 struct sccb *pOldSccb;
6726 scan_ptr = pCurrCard->scanIndex;
6727 do {
6728 currTar_Info = &FPT_sccbMgrTbl[p_card][scan_ptr];
6729 if ((pCurrCard->globalFlags & F_CONLUN_IO) &&
6730 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
6731 TAG_Q_TRYING)) {
6732 if (currTar_Info->TarSelQ_Cnt != 0) {
6734 scan_ptr++;
6735 if (scan_ptr == MAX_SCSI_TAR)
6736 scan_ptr = 0;
6738 for (lun = 0; lun < MAX_LUN; lun++) {
6739 if (currTar_Info->TarLUNBusy[lun] == 0) {
6741 pCurrCard->currentSCCB =
6742 currTar_Info->TarSelQ_Head;
6743 pOldSccb = NULL;
6745 while ((pCurrCard->
6746 currentSCCB != NULL)
6747 && (lun !=
6748 pCurrCard->
6749 currentSCCB->Lun)) {
6750 pOldSccb =
6751 pCurrCard->
6752 currentSCCB;
6753 pCurrCard->currentSCCB =
6754 (struct sccb
6755 *)(pCurrCard->
6756 currentSCCB)->
6757 Sccb_forwardlink;
6759 if (pCurrCard->currentSCCB ==
6760 NULL)
6761 continue;
6762 if (pOldSccb != NULL) {
6763 pOldSccb->
6764 Sccb_forwardlink =
6765 (struct sccb
6766 *)(pCurrCard->
6767 currentSCCB)->
6768 Sccb_forwardlink;
6769 pOldSccb->
6770 Sccb_backlink =
6771 (struct sccb
6772 *)(pCurrCard->
6773 currentSCCB)->
6774 Sccb_backlink;
6775 currTar_Info->
6776 TarSelQ_Cnt--;
6777 } else {
6778 currTar_Info->
6779 TarSelQ_Head =
6780 (struct sccb
6781 *)(pCurrCard->
6782 currentSCCB)->
6783 Sccb_forwardlink;
6785 if (currTar_Info->
6786 TarSelQ_Head ==
6787 NULL) {
6788 currTar_Info->
6789 TarSelQ_Tail
6790 = NULL;
6791 currTar_Info->
6792 TarSelQ_Cnt
6793 = 0;
6794 } else {
6795 currTar_Info->
6796 TarSelQ_Cnt--;
6797 currTar_Info->
6798 TarSelQ_Head->
6799 Sccb_backlink
6801 (struct sccb
6802 *)NULL;
6805 pCurrCard->scanIndex = scan_ptr;
6807 pCurrCard->globalFlags |=
6808 F_NEW_SCCB_CMD;
6810 break;
6815 else {
6816 scan_ptr++;
6817 if (scan_ptr == MAX_SCSI_TAR) {
6818 scan_ptr = 0;
6822 } else {
6823 if ((currTar_Info->TarSelQ_Cnt != 0) &&
6824 (currTar_Info->TarLUNBusy[0] == 0)) {
6826 pCurrCard->currentSCCB =
6827 currTar_Info->TarSelQ_Head;
6829 currTar_Info->TarSelQ_Head =
6830 (struct sccb *)(pCurrCard->currentSCCB)->
6831 Sccb_forwardlink;
6833 if (currTar_Info->TarSelQ_Head == NULL) {
6834 currTar_Info->TarSelQ_Tail = NULL;
6835 currTar_Info->TarSelQ_Cnt = 0;
6836 } else {
6837 currTar_Info->TarSelQ_Cnt--;
6838 currTar_Info->TarSelQ_Head->
6839 Sccb_backlink = (struct sccb *)NULL;
6842 scan_ptr++;
6843 if (scan_ptr == MAX_SCSI_TAR)
6844 scan_ptr = 0;
6846 pCurrCard->scanIndex = scan_ptr;
6848 pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
6850 break;
6853 else {
6854 scan_ptr++;
6855 if (scan_ptr == MAX_SCSI_TAR) {
6856 scan_ptr = 0;
6860 } while (scan_ptr != pCurrCard->scanIndex);
6863 /*---------------------------------------------------------------------
6865 * Function: Queue Select Fail
6867 * Description: Add the current SCCB to the head of the Queue.
6869 *---------------------------------------------------------------------*/
6871 static void FPT_queueSelectFail(struct sccb_card *pCurrCard,
6872 unsigned char p_card)
6874 unsigned char thisTarg;
6875 struct sccb_mgr_tar_info *currTar_Info;
6877 if (pCurrCard->currentSCCB != NULL) {
6878 thisTarg =
6879 (unsigned char)(((struct sccb *)(pCurrCard->currentSCCB))->
6880 TargID);
6881 currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
6883 pCurrCard->currentSCCB->Sccb_backlink = (struct sccb *)NULL;
6885 pCurrCard->currentSCCB->Sccb_forwardlink =
6886 currTar_Info->TarSelQ_Head;
6888 if (currTar_Info->TarSelQ_Cnt == 0) {
6889 currTar_Info->TarSelQ_Tail = pCurrCard->currentSCCB;
6892 else {
6893 currTar_Info->TarSelQ_Head->Sccb_backlink =
6894 pCurrCard->currentSCCB;
6897 currTar_Info->TarSelQ_Head = pCurrCard->currentSCCB;
6899 pCurrCard->currentSCCB = NULL;
6900 currTar_Info->TarSelQ_Cnt++;
6904 /*---------------------------------------------------------------------
6906 * Function: Queue Command Complete
6908 * Description: Call the callback function with the current SCCB.
6910 *---------------------------------------------------------------------*/
6912 static void FPT_queueCmdComplete(struct sccb_card *pCurrCard,
6913 struct sccb *p_sccb, unsigned char p_card)
6916 unsigned char i, SCSIcmd;
6917 CALL_BK_FN callback;
6918 struct sccb_mgr_tar_info *currTar_Info;
6920 SCSIcmd = p_sccb->Cdb[0];
6922 if (!(p_sccb->Sccb_XferState & F_ALL_XFERRED)) {
6924 if ((p_sccb->
6925 ControlByte & (SCCB_DATA_XFER_OUT | SCCB_DATA_XFER_IN))
6926 && (p_sccb->HostStatus == SCCB_COMPLETE)
6927 && (p_sccb->TargetStatus != SSCHECK))
6929 if ((SCSIcmd == SCSI_READ) ||
6930 (SCSIcmd == SCSI_WRITE) ||
6931 (SCSIcmd == SCSI_READ_EXTENDED) ||
6932 (SCSIcmd == SCSI_WRITE_EXTENDED) ||
6933 (SCSIcmd == SCSI_WRITE_AND_VERIFY) ||
6934 (SCSIcmd == SCSI_START_STOP_UNIT) ||
6935 (pCurrCard->globalFlags & F_NO_FILTER)
6937 p_sccb->HostStatus = SCCB_DATA_UNDER_RUN;
6940 if (p_sccb->SccbStatus == SCCB_IN_PROCESS) {
6941 if (p_sccb->HostStatus || p_sccb->TargetStatus)
6942 p_sccb->SccbStatus = SCCB_ERROR;
6943 else
6944 p_sccb->SccbStatus = SCCB_SUCCESS;
6947 if (p_sccb->Sccb_XferState & F_AUTO_SENSE) {
6949 p_sccb->CdbLength = p_sccb->Save_CdbLen;
6950 for (i = 0; i < 6; i++) {
6951 p_sccb->Cdb[i] = p_sccb->Save_Cdb[i];
6955 if ((p_sccb->OperationCode == RESIDUAL_SG_COMMAND) ||
6956 (p_sccb->OperationCode == RESIDUAL_COMMAND)) {
6958 FPT_utilUpdateResidual(p_sccb);
6961 pCurrCard->cmdCounter--;
6962 if (!pCurrCard->cmdCounter) {
6964 if (pCurrCard->globalFlags & F_GREEN_PC) {
6965 WR_HARPOON(pCurrCard->ioPort + hp_clkctrl_0,
6966 (PWR_DWN | CLKCTRL_DEFAULT));
6967 WR_HARPOON(pCurrCard->ioPort + hp_sys_ctrl, STOP_CLK);
6970 WR_HARPOON(pCurrCard->ioPort + hp_semaphore,
6971 (RD_HARPOON(pCurrCard->ioPort + hp_semaphore) &
6972 ~SCCB_MGR_ACTIVE));
6976 if (pCurrCard->discQCount != 0) {
6977 currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
6978 if (((pCurrCard->globalFlags & F_CONLUN_IO) &&
6979 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) !=
6980 TAG_Q_TRYING))) {
6981 pCurrCard->discQCount--;
6982 pCurrCard->discQ_Tbl[currTar_Info->
6983 LunDiscQ_Idx[p_sccb->Lun]] = NULL;
6984 } else {
6985 if (p_sccb->Sccb_tag) {
6986 pCurrCard->discQCount--;
6987 pCurrCard->discQ_Tbl[p_sccb->Sccb_tag] = NULL;
6988 } else {
6989 pCurrCard->discQCount--;
6990 pCurrCard->discQ_Tbl[currTar_Info->
6991 LunDiscQ_Idx[0]] = NULL;
6997 callback = (CALL_BK_FN) p_sccb->SccbCallback;
6998 callback(p_sccb);
6999 pCurrCard->globalFlags |= F_NEW_SCCB_CMD;
7000 pCurrCard->currentSCCB = NULL;
7003 /*---------------------------------------------------------------------
7005 * Function: Queue Disconnect
7007 * Description: Add SCCB to our disconnect array.
7009 *---------------------------------------------------------------------*/
7010 static void FPT_queueDisconnect(struct sccb *p_sccb, unsigned char p_card)
7012 struct sccb_mgr_tar_info *currTar_Info;
7014 currTar_Info = &FPT_sccbMgrTbl[p_card][p_sccb->TargID];
7016 if (((FPT_BL_Card[p_card].globalFlags & F_CONLUN_IO) &&
7017 ((currTar_Info->TarStatus & TAR_TAG_Q_MASK) != TAG_Q_TRYING))) {
7018 FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
7019 LunDiscQ_Idx[p_sccb->Lun]] =
7020 p_sccb;
7021 } else {
7022 if (p_sccb->Sccb_tag) {
7023 FPT_BL_Card[p_card].discQ_Tbl[p_sccb->Sccb_tag] =
7024 p_sccb;
7025 FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarLUNBusy[0] =
7027 FPT_sccbMgrTbl[p_card][p_sccb->TargID].TarTagQ_Cnt++;
7028 } else {
7029 FPT_BL_Card[p_card].discQ_Tbl[currTar_Info->
7030 LunDiscQ_Idx[0]] = p_sccb;
7033 FPT_BL_Card[p_card].currentSCCB = NULL;
7036 /*---------------------------------------------------------------------
7038 * Function: Queue Flush SCCB
7040 * Description: Flush all SCCB's back to the host driver for this target.
7042 *---------------------------------------------------------------------*/
7044 static void FPT_queueFlushSccb(unsigned char p_card, unsigned char error_code)
7046 unsigned char qtag, thisTarg;
7047 struct sccb *currSCCB;
7048 struct sccb_mgr_tar_info *currTar_Info;
7050 currSCCB = FPT_BL_Card[p_card].currentSCCB;
7051 if (currSCCB != NULL) {
7052 thisTarg = (unsigned char)currSCCB->TargID;
7053 currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
7055 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
7057 if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
7058 (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID ==
7059 thisTarg)) {
7061 FPT_BL_Card[p_card].discQ_Tbl[qtag]->
7062 HostStatus = (unsigned char)error_code;
7064 FPT_queueCmdComplete(&FPT_BL_Card[p_card],
7065 FPT_BL_Card[p_card].
7066 discQ_Tbl[qtag], p_card);
7068 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
7069 currTar_Info->TarTagQ_Cnt--;
7077 /*---------------------------------------------------------------------
7079 * Function: Queue Flush Target SCCB
7081 * Description: Flush all SCCB's back to the host driver for this target.
7083 *---------------------------------------------------------------------*/
7085 static void FPT_queueFlushTargSccb(unsigned char p_card, unsigned char thisTarg,
7086 unsigned char error_code)
7088 unsigned char qtag;
7089 struct sccb_mgr_tar_info *currTar_Info;
7091 currTar_Info = &FPT_sccbMgrTbl[p_card][thisTarg];
7093 for (qtag = 0; qtag < QUEUE_DEPTH; qtag++) {
7095 if (FPT_BL_Card[p_card].discQ_Tbl[qtag] &&
7096 (FPT_BL_Card[p_card].discQ_Tbl[qtag]->TargID == thisTarg)) {
7098 FPT_BL_Card[p_card].discQ_Tbl[qtag]->HostStatus =
7099 (unsigned char)error_code;
7101 FPT_queueCmdComplete(&FPT_BL_Card[p_card],
7102 FPT_BL_Card[p_card].
7103 discQ_Tbl[qtag], p_card);
7105 FPT_BL_Card[p_card].discQ_Tbl[qtag] = NULL;
7106 currTar_Info->TarTagQ_Cnt--;
7113 static void FPT_queueAddSccb(struct sccb *p_SCCB, unsigned char p_card)
7115 struct sccb_mgr_tar_info *currTar_Info;
7116 currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
7118 p_SCCB->Sccb_forwardlink = NULL;
7120 p_SCCB->Sccb_backlink = currTar_Info->TarSelQ_Tail;
7122 if (currTar_Info->TarSelQ_Cnt == 0) {
7124 currTar_Info->TarSelQ_Head = p_SCCB;
7127 else {
7129 currTar_Info->TarSelQ_Tail->Sccb_forwardlink = p_SCCB;
7132 currTar_Info->TarSelQ_Tail = p_SCCB;
7133 currTar_Info->TarSelQ_Cnt++;
7136 /*---------------------------------------------------------------------
7138 * Function: Queue Find SCCB
7140 * Description: Search the target select Queue for this SCCB, and
7141 * remove it if found.
7143 *---------------------------------------------------------------------*/
7145 static unsigned char FPT_queueFindSccb(struct sccb *p_SCCB,
7146 unsigned char p_card)
7148 struct sccb *q_ptr;
7149 struct sccb_mgr_tar_info *currTar_Info;
7151 currTar_Info = &FPT_sccbMgrTbl[p_card][p_SCCB->TargID];
7153 q_ptr = currTar_Info->TarSelQ_Head;
7155 while (q_ptr != NULL) {
7157 if (q_ptr == p_SCCB) {
7159 if (currTar_Info->TarSelQ_Head == q_ptr) {
7161 currTar_Info->TarSelQ_Head =
7162 q_ptr->Sccb_forwardlink;
7165 if (currTar_Info->TarSelQ_Tail == q_ptr) {
7167 currTar_Info->TarSelQ_Tail =
7168 q_ptr->Sccb_backlink;
7171 if (q_ptr->Sccb_forwardlink != NULL) {
7172 q_ptr->Sccb_forwardlink->Sccb_backlink =
7173 q_ptr->Sccb_backlink;
7176 if (q_ptr->Sccb_backlink != NULL) {
7177 q_ptr->Sccb_backlink->Sccb_forwardlink =
7178 q_ptr->Sccb_forwardlink;
7181 currTar_Info->TarSelQ_Cnt--;
7183 return 1;
7186 else {
7187 q_ptr = q_ptr->Sccb_forwardlink;
7191 return 0;
7195 /*---------------------------------------------------------------------
7197 * Function: Utility Update Residual Count
7199 * Description: Update the XferCnt to the remaining byte count.
7200 * If we transferred all the data then just write zero.
7201 * If Non-SG transfer then report Total Cnt - Actual Transfer
7202 * Cnt. For SG transfers add the count fields of all
7203 * remaining SG elements, as well as any partial remaining
7204 * element.
7206 *---------------------------------------------------------------------*/
7208 static void FPT_utilUpdateResidual(struct sccb *p_SCCB)
7210 unsigned long partial_cnt;
7211 unsigned int sg_index;
7212 unsigned long *sg_ptr;
7214 if (p_SCCB->Sccb_XferState & F_ALL_XFERRED) {
7216 p_SCCB->DataLength = 0x0000;
7219 else if (p_SCCB->Sccb_XferState & F_SG_XFER) {
7221 partial_cnt = 0x0000;
7223 sg_index = p_SCCB->Sccb_sgseg;
7225 sg_ptr = (unsigned long *)p_SCCB->DataPointer;
7227 if (p_SCCB->Sccb_SGoffset) {
7229 partial_cnt = p_SCCB->Sccb_SGoffset;
7230 sg_index++;
7233 while (((unsigned long)sg_index *
7234 (unsigned long)SG_ELEMENT_SIZE) < p_SCCB->DataLength) {
7236 partial_cnt += *(sg_ptr + (sg_index * 2));
7237 sg_index++;
7240 p_SCCB->DataLength = partial_cnt;
7243 else {
7245 p_SCCB->DataLength -= p_SCCB->Sccb_ATC;
7249 /*---------------------------------------------------------------------
7251 * Function: Wait 1 Second
7253 * Description: Wait for 1 second.
7255 *---------------------------------------------------------------------*/
7257 static void FPT_Wait1Second(unsigned long p_port)
7259 unsigned char i;
7261 for (i = 0; i < 4; i++) {
7263 FPT_Wait(p_port, TO_250ms);
7265 if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
7266 break;
7268 if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
7269 break;
7273 /*---------------------------------------------------------------------
7275 * Function: FPT_Wait
7277 * Description: Wait the desired delay.
7279 *---------------------------------------------------------------------*/
7281 static void FPT_Wait(unsigned long p_port, unsigned char p_delay)
7283 unsigned char old_timer;
7284 unsigned char green_flag;
7286 old_timer = RD_HARPOON(p_port + hp_seltimeout);
7288 green_flag = RD_HARPOON(p_port + hp_clkctrl_0);
7289 WR_HARPOON(p_port + hp_clkctrl_0, CLKCTRL_DEFAULT);
7291 WR_HARPOON(p_port + hp_seltimeout, p_delay);
7292 WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
7293 WRW_HARPOON((p_port + hp_intena), (FPT_default_intena & ~TIMEOUT));
7295 WR_HARPOON(p_port + hp_portctrl_0,
7296 (RD_HARPOON(p_port + hp_portctrl_0) | START_TO));
7298 while (!(RDW_HARPOON((p_port + hp_intstat)) & TIMEOUT)) {
7300 if ((RD_HARPOON(p_port + hp_scsictrl_0) & SCSI_RST))
7301 break;
7303 if ((RDW_HARPOON((p_port + hp_intstat)) & SCAM_SEL))
7304 break;
7307 WR_HARPOON(p_port + hp_portctrl_0,
7308 (RD_HARPOON(p_port + hp_portctrl_0) & ~START_TO));
7310 WRW_HARPOON((p_port + hp_intstat), TIMEOUT);
7311 WRW_HARPOON((p_port + hp_intena), FPT_default_intena);
7313 WR_HARPOON(p_port + hp_clkctrl_0, green_flag);
7315 WR_HARPOON(p_port + hp_seltimeout, old_timer);
7318 /*---------------------------------------------------------------------
7320 * Function: Enable/Disable Write to EEPROM
7322 * Description: The EEPROM must first be enabled for writes
7323 * A total of 9 clocks are needed.
7325 *---------------------------------------------------------------------*/
7327 static void FPT_utilEEWriteOnOff(unsigned long p_port, unsigned char p_mode)
7329 unsigned char ee_value;
7331 ee_value =
7332 (unsigned char)(RD_HARPOON(p_port + hp_ee_ctrl) &
7333 (EXT_ARB_ACK | SCSI_TERM_ENA_H));
7335 if (p_mode)
7337 FPT_utilEESendCmdAddr(p_port, EWEN, EWEN_ADDR);
7339 else
7341 FPT_utilEESendCmdAddr(p_port, EWDS, EWDS_ADDR);
7343 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */
7344 WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /*Turn off Master Select */
7347 /*---------------------------------------------------------------------
7349 * Function: Write EEPROM
7351 * Description: Write a word to the EEPROM at the specified
7352 * address.
7354 *---------------------------------------------------------------------*/
7356 static void FPT_utilEEWrite(unsigned long p_port, unsigned short ee_data,
7357 unsigned short ee_addr)
7360 unsigned char ee_value;
7361 unsigned short i;
7363 ee_value =
7364 (unsigned
7365 char)((RD_HARPOON(p_port + hp_ee_ctrl) &
7366 (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
7368 FPT_utilEESendCmdAddr(p_port, EE_WRITE, ee_addr);
7370 ee_value |= (SEE_MS + SEE_CS);
7372 for (i = 0x8000; i != 0; i >>= 1) {
7374 if (i & ee_data)
7375 ee_value |= SEE_DO;
7376 else
7377 ee_value &= ~SEE_DO;
7379 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7380 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7381 ee_value |= SEE_CLK; /* Clock data! */
7382 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7383 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7384 ee_value &= ~SEE_CLK;
7385 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7386 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7388 ee_value &= (EXT_ARB_ACK | SCSI_TERM_ENA_H);
7389 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS));
7391 FPT_Wait(p_port, TO_10ms);
7393 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS | SEE_CS)); /* Set CS to EEPROM */
7394 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /* Turn off CS */
7395 WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /* Turn off Master Select */
7398 /*---------------------------------------------------------------------
7400 * Function: Read EEPROM
7402 * Description: Read a word from the EEPROM at the desired
7403 * address.
7405 *---------------------------------------------------------------------*/
7407 static unsigned short FPT_utilEERead(unsigned long p_port,
7408 unsigned short ee_addr)
7410 unsigned short i, ee_data1, ee_data2;
7412 i = 0;
7413 ee_data1 = FPT_utilEEReadOrg(p_port, ee_addr);
7414 do {
7415 ee_data2 = FPT_utilEEReadOrg(p_port, ee_addr);
7417 if (ee_data1 == ee_data2)
7418 return ee_data1;
7420 ee_data1 = ee_data2;
7421 i++;
7423 } while (i < 4);
7425 return ee_data1;
7428 /*---------------------------------------------------------------------
7430 * Function: Read EEPROM Original
7432 * Description: Read a word from the EEPROM at the desired
7433 * address.
7435 *---------------------------------------------------------------------*/
7437 static unsigned short FPT_utilEEReadOrg(unsigned long p_port,
7438 unsigned short ee_addr)
7441 unsigned char ee_value;
7442 unsigned short i, ee_data;
7444 ee_value =
7445 (unsigned
7446 char)((RD_HARPOON(p_port + hp_ee_ctrl) &
7447 (EXT_ARB_ACK | SCSI_TERM_ENA_H)) | (SEE_MS | SEE_CS));
7449 FPT_utilEESendCmdAddr(p_port, EE_READ, ee_addr);
7451 ee_value |= (SEE_MS + SEE_CS);
7452 ee_data = 0;
7454 for (i = 1; i <= 16; i++) {
7456 ee_value |= SEE_CLK; /* Clock data! */
7457 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7458 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7459 ee_value &= ~SEE_CLK;
7460 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7461 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7463 ee_data <<= 1;
7465 if (RD_HARPOON(p_port + hp_ee_ctrl) & SEE_DI)
7466 ee_data |= 1;
7469 ee_value &= ~(SEE_MS + SEE_CS);
7470 WR_HARPOON(p_port + hp_ee_ctrl, (ee_value | SEE_MS)); /*Turn off CS */
7471 WR_HARPOON(p_port + hp_ee_ctrl, ee_value); /*Turn off Master Select */
7473 return ee_data;
7476 /*---------------------------------------------------------------------
7478 * Function: Send EE command and Address to the EEPROM
7480 * Description: Transfers the correct command and sends the address
7481 * to the eeprom.
7483 *---------------------------------------------------------------------*/
7485 static void FPT_utilEESendCmdAddr(unsigned long p_port, unsigned char ee_cmd,
7486 unsigned short ee_addr)
7488 unsigned char ee_value;
7489 unsigned char narrow_flg;
7491 unsigned short i;
7493 narrow_flg =
7494 (unsigned char)(RD_HARPOON(p_port + hp_page_ctrl) &
7495 NARROW_SCSI_CARD);
7497 ee_value = SEE_MS;
7498 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7500 ee_value |= SEE_CS; /* Set CS to EEPROM */
7501 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7503 for (i = 0x04; i != 0; i >>= 1) {
7505 if (i & ee_cmd)
7506 ee_value |= SEE_DO;
7507 else
7508 ee_value &= ~SEE_DO;
7510 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7511 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7512 ee_value |= SEE_CLK; /* Clock data! */
7513 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7514 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7515 ee_value &= ~SEE_CLK;
7516 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7517 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7520 if (narrow_flg)
7521 i = 0x0080;
7523 else
7524 i = 0x0200;
7526 while (i != 0) {
7528 if (i & ee_addr)
7529 ee_value |= SEE_DO;
7530 else
7531 ee_value &= ~SEE_DO;
7533 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7534 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7535 ee_value |= SEE_CLK; /* Clock data! */
7536 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7537 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7538 ee_value &= ~SEE_CLK;
7539 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7540 WR_HARPOON(p_port + hp_ee_ctrl, ee_value);
7542 i >>= 1;
7546 static unsigned short FPT_CalcCrc16(unsigned char buffer[])
7548 unsigned short crc = 0;
7549 int i, j;
7550 unsigned short ch;
7551 for (i = 0; i < ID_STRING_LENGTH; i++) {
7552 ch = (unsigned short)buffer[i];
7553 for (j = 0; j < 8; j++) {
7554 if ((crc ^ ch) & 1)
7555 crc = (crc >> 1) ^ CRCMASK;
7556 else
7557 crc >>= 1;
7558 ch >>= 1;
7561 return crc;
7564 static unsigned char FPT_CalcLrc(unsigned char buffer[])
7566 int i;
7567 unsigned char lrc;
7568 lrc = 0;
7569 for (i = 0; i < ID_STRING_LENGTH; i++)
7570 lrc ^= buffer[i];
7571 return lrc;
7575 The following inline definitions avoid type conflicts.
7578 static inline unsigned char
7579 FlashPoint__ProbeHostAdapter(struct FlashPoint_Info *FlashPointInfo)
7581 return FlashPoint_ProbeHostAdapter((struct sccb_mgr_info *)
7582 FlashPointInfo);
7585 static inline FlashPoint_CardHandle_T
7586 FlashPoint__HardwareResetHostAdapter(struct FlashPoint_Info *FlashPointInfo)
7588 return FlashPoint_HardwareResetHostAdapter((struct sccb_mgr_info *)
7589 FlashPointInfo);
7592 static inline void
7593 FlashPoint__ReleaseHostAdapter(FlashPoint_CardHandle_T CardHandle)
7595 FlashPoint_ReleaseHostAdapter(CardHandle);
7598 static inline void
7599 FlashPoint__StartCCB(FlashPoint_CardHandle_T CardHandle,
7600 struct BusLogic_CCB *CCB)
7602 FlashPoint_StartCCB(CardHandle, (struct sccb *)CCB);
7605 static inline void
7606 FlashPoint__AbortCCB(FlashPoint_CardHandle_T CardHandle,
7607 struct BusLogic_CCB *CCB)
7609 FlashPoint_AbortCCB(CardHandle, (struct sccb *)CCB);
7612 static inline bool
7613 FlashPoint__InterruptPending(FlashPoint_CardHandle_T CardHandle)
7615 return FlashPoint_InterruptPending(CardHandle);
7618 static inline int
7619 FlashPoint__HandleInterrupt(FlashPoint_CardHandle_T CardHandle)
7621 return FlashPoint_HandleInterrupt(CardHandle);
7624 #define FlashPoint_ProbeHostAdapter FlashPoint__ProbeHostAdapter
7625 #define FlashPoint_HardwareResetHostAdapter FlashPoint__HardwareResetHostAdapter
7626 #define FlashPoint_ReleaseHostAdapter FlashPoint__ReleaseHostAdapter
7627 #define FlashPoint_StartCCB FlashPoint__StartCCB
7628 #define FlashPoint_AbortCCB FlashPoint__AbortCCB
7629 #define FlashPoint_InterruptPending FlashPoint__InterruptPending
7630 #define FlashPoint_HandleInterrupt FlashPoint__HandleInterrupt
7632 #else /* CONFIG_SCSI_OMIT_FLASHPOINT */
7635 Define prototypes for the FlashPoint SCCB Manager Functions.
7638 extern unsigned char FlashPoint_ProbeHostAdapter(struct FlashPoint_Info *);
7639 extern FlashPoint_CardHandle_T
7640 FlashPoint_HardwareResetHostAdapter(struct FlashPoint_Info *);
7641 extern void FlashPoint_StartCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *);
7642 extern int FlashPoint_AbortCCB(FlashPoint_CardHandle_T, struct BusLogic_CCB *);
7643 extern bool FlashPoint_InterruptPending(FlashPoint_CardHandle_T);
7644 extern int FlashPoint_HandleInterrupt(FlashPoint_CardHandle_T);
7645 extern void FlashPoint_ReleaseHostAdapter(FlashPoint_CardHandle_T);
7647 #endif /* CONFIG_SCSI_OMIT_FLASHPOINT */