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