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