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