1 /**************************************************************************
2 * Initio 9100 device driver for Linux.
4 * Copyright (c) 1994-1998 Initio Corporation
5 * Copyright (c) 1998 Bas Vermeulen <bvermeul@blackstar.xs4all.nl>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; see the file COPYING. If not, write to
20 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
22 * --------------------------------------------------------------------------
24 * Redistribution and use in source and binary forms, with or without
25 * modification, are permitted provided that the following conditions
27 * 1. Redistributions of source code must retain the above copyright
28 * notice, this list of conditions, and the following disclaimer,
29 * without modification, immediately at the beginning of the file.
30 * 2. Redistributions in binary form must reproduce the above copyright
31 * notice, this list of conditions and the following disclaimer in the
32 * documentation and/or other materials provided with the distribution.
33 * 3. The name of the author may not be used to endorse or promote products
34 * derived from this software without specific prior written permission.
36 * Where this Software is combined with software released under the terms of
37 * the GNU Public License ("GPL") and the terms of the GPL would require the
38 * combined work to also be released under the terms of the GPL, the terms
39 * and conditions of this License will apply in addition to those of the
40 * GPL with the exception of any terms or conditions of this License that
41 * conflict with, or are expressly prohibited by, the GPL.
43 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
47 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 ************************************************************************
57 Description: PCI I/F for INI-910 SCSI Bus Master Controller
59 11/09/94 Tim Chen, Initiali Version 0.90A
60 01/17/95 TC, release ver 1.01
61 02/09/95 TC modify ReadPCIConfig, try both mechanisms;
62 02/15/95 TC add support for INI-9100W
63 06/04/96 HC, Change to fit LINUX from jaspci.c
64 11/18/96 HC, Port for tulip
65 07/08/98 hc, Support 0002134A
66 07/23/98 wh, Change the abort_srb routine.
67 09/16/98 hl, Support ALPHA, Rewrite the returnNumberAdapters <01>
68 12/09/98 bv, Removed unused code, changed tul_se2_wait to
69 use udelay(30) and tul_do_pause to enable
70 interrupts for >= 2.1.95
71 12/13/98 bv, Use spinlocks instead of cli() for serialized
72 access to HCS_Semaph, HCS_FirstAvail and HCS_LastAvail
73 members of the HCS structure.
74 01/09/98 bv, Fix a deadlock on SMP system.
75 **********************************************************************/
77 #define DEBUG_INTERRUPT 0
83 #ifndef CVT_LINUX_VERSION
84 #define CVT_LINUX_VERSION(V,P,S) (V * 65536 + P * 256 + S)
87 #ifndef LINUX_VERSION_CODE
88 #include <linux/version.h>
91 #include <linux/sched.h>
92 #include <linux/delay.h>
93 #include <linux/blk.h>
98 /*--- external functions --*/
99 static void tul_se2_wait(void);
101 /*--- forward refrence ---*/
102 static SCB
*tul_find_busy_scb(HCS
* pCurHcb
, WORD tarlun
);
103 static SCB
*tul_find_done_scb(HCS
* pCurHcb
);
105 static int tulip_main(HCS
* pCurHcb
);
107 static int tul_next_state(HCS
* pCurHcb
);
108 static int tul_state_1(HCS
* pCurHcb
);
109 static int tul_state_2(HCS
* pCurHcb
);
110 static int tul_state_3(HCS
* pCurHcb
);
111 static int tul_state_4(HCS
* pCurHcb
);
112 static int tul_state_5(HCS
* pCurHcb
);
113 static int tul_state_6(HCS
* pCurHcb
);
114 static int tul_state_7(HCS
* pCurHcb
);
115 static int tul_xfer_data_in(HCS
* pCurHcb
);
116 static int tul_xfer_data_out(HCS
* pCurHcb
);
117 static int tul_xpad_in(HCS
* pCurHcb
);
118 static int tul_xpad_out(HCS
* pCurHcb
);
119 static int tul_status_msg(HCS
* pCurHcb
);
121 static int tul_msgin(HCS
* pCurHcb
);
122 static int tul_msgin_sync(HCS
* pCurHcb
);
123 static int tul_msgin_accept(HCS
* pCurHcb
);
124 static int tul_msgout_reject(HCS
* pCurHcb
);
125 static int tul_msgin_extend(HCS
* pCurHcb
);
127 static int tul_msgout_ide(HCS
* pCurHcb
);
128 static int tul_msgout_abort_targ(HCS
* pCurHcb
);
129 static int tul_msgout_abort_tag(HCS
* pCurHcb
);
131 static int tul_bus_device_reset(HCS
* pCurHcb
);
132 static void tul_select_atn(HCS
* pCurHcb
, SCB
* pCurScb
);
133 static void tul_select_atn3(HCS
* pCurHcb
, SCB
* pCurScb
);
134 static void tul_select_atn_stop(HCS
* pCurHcb
, SCB
* pCurScb
);
135 static int int_tul_busfree(HCS
* pCurHcb
);
136 int int_tul_scsi_rst(HCS
* pCurHcb
);
137 static int int_tul_bad_seq(HCS
* pCurHcb
);
138 static int int_tul_resel(HCS
* pCurHcb
);
139 static int tul_sync_done(HCS
* pCurHcb
);
140 static int wdtr_done(HCS
* pCurHcb
);
141 static int wait_tulip(HCS
* pCurHcb
);
142 static int tul_wait_done_disc(HCS
* pCurHcb
);
143 static int tul_wait_disc(HCS
* pCurHcb
);
144 static void tulip_scsi(HCS
* pCurHcb
);
145 static int tul_post_scsi_rst(HCS
* pCurHcb
);
147 static void tul_se2_ew_en(WORD CurBase
);
148 static void tul_se2_ew_ds(WORD CurBase
);
149 static int tul_se2_rd_all(WORD CurBase
);
150 static void tul_se2_update_all(WORD CurBase
); /* setup default pattern */
151 static void tul_read_eeprom(WORD CurBase
);
153 /* ---- EXTERNAL VARIABLES ---- */
154 HCS tul_hcs
[MAX_SUPPORTED_ADAPTERS
];
155 /* ---- INTERNAL VARIABLES ---- */
156 static INI_ADPT_STRUCT i91u_adpt
[MAX_SUPPORTED_ADAPTERS
];
158 /*NVRAM nvram, *nvramp = &nvram; */
159 static NVRAM i91unvram
;
160 static NVRAM
*i91unvramp
;
164 static UCHAR i91udftNvRam
[64] =
166 /*----------- header -----------*/
167 0x25, 0xc9, /* Signature */
170 /* -- Host Adapter Structure -- */
171 0x95, /* ModelByte0 */
172 0x00, /* ModelByte1 */
173 0x00, /* ModelInfo */
175 NBC1_DEFAULT
, /* BIOSConfig1 */
179 /* SCSI channel 0 and target Structure */
181 NCC1_DEFAULT
, /* SCSIconfig1 */
183 0x10, /* NumSCSItarget */
185 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
186 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
187 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
188 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
190 /* SCSI channel 1 and target Structure */
192 NCC1_DEFAULT
, /* SCSIconfig1 */
194 0x10, /* NumSCSItarget */
196 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
197 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
198 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
199 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
200 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
201 0, 0}; /* - CheckSum - */
204 static UCHAR tul_rate_tbl
[8] = /* fast 20 */
206 /* nanosecond devide by 4 */
208 18, /* 75ns, 13.3M */
211 37, /* 150ns, 6.6M */
212 43, /* 175ns, 5.7M */
217 extern int tul_num_ch
;
220 static void tul_do_pause(unsigned amount
)
221 { /* Pause for amount jiffies */
222 unsigned long the_time
= jiffies
+ amount
;
224 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
225 while (time_before_eq(jiffies
, the_time
));
227 while (jiffies
< the_time
);
231 /*-- forward reference --*/
233 /*******************************************************************
234 Use memeory refresh time ~ 15us * 2
235 ********************************************************************/
243 readByte
= TUL_RD(0, 0x61);
244 if ((readByte
& 0x10) == 0x10) {
246 readByte
= TUL_RD(0, 0x61);
247 if ((readByte
& 0x10) == 0x10)
251 readByte
= TUL_RD(0, 0x61);
252 if ((readByte
& 0x10) != 0x10)
257 readByte
= TUL_RD(0, 0x61);
258 if ((readByte
& 0x10) == 0x10)
262 readByte
= TUL_RD(0, 0x61);
263 if ((readByte
& 0x10) != 0x10)
271 /******************************************************************
272 Input: instruction for Serial E2PROM
274 EX: se2_rd(0 call se2_instr() to send address and read command
276 StartBit OP_Code Address Data
277 --------- -------- ------------------ -------
278 1 1 , 0 A5,A4,A3,A2,A1,A0 D15-D0
280 +-----------------------------------------------------
283 +--+ +--+ +--+ +--+ +--+
286 CLK -------+ +--+ +--+ +--+ +--+ +--
287 (leading edge trigger)
291 DI ----+ +--0------------------
292 (address and cmd sent to nvram)
294 -------------------------------------------+
297 (data sent from nvram)
300 ******************************************************************/
301 void tul_se2_instr(WORD CurBase
, UCHAR instr
)
306 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2DO
); /* cs+start bit */
308 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2CLK
| SE2DO
); /* +CLK */
311 for (i
= 0; i
< 8; i
++) {
313 b
= SE2CS
| SE2DO
; /* -CLK+dataBit */
315 b
= SE2CS
; /* -CLK */
316 TUL_WR(CurBase
+ TUL_NVRAM
, b
);
318 TUL_WR(CurBase
+ TUL_NVRAM
, b
| SE2CLK
); /* +CLK */
322 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* -CLK */
328 /******************************************************************
329 Function name : tul_se2_ew_en
330 Description : Enable erase/write state of serial EEPROM
331 ******************************************************************/
332 void tul_se2_ew_en(WORD CurBase
)
334 tul_se2_instr(CurBase
, 0x30); /* EWEN */
335 TUL_WR(CurBase
+ TUL_NVRAM
, 0); /* -CS */
341 /************************************************************************
342 Disable erase/write state of serial EEPROM
343 *************************************************************************/
344 void tul_se2_ew_ds(WORD CurBase
)
346 tul_se2_instr(CurBase
, 0); /* EWDS */
347 TUL_WR(CurBase
+ TUL_NVRAM
, 0); /* -CS */
353 /******************************************************************
354 Input :address of Serial E2PROM
355 Output :value stored in Serial E2PROM
356 *******************************************************************/
357 USHORT
tul_se2_rd(WORD CurBase
, ULONG adr
)
359 UCHAR instr
, readByte
;
363 instr
= (UCHAR
) (adr
| 0x80);
364 tul_se2_instr(CurBase
, instr
); /* READ INSTR */
367 for (i
= 15; i
>= 0; i
--) {
368 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2CLK
); /* +CLK */
370 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* -CLK */
372 /* sample data after the following edge of clock */
373 readByte
= TUL_RD(CurBase
, TUL_NVRAM
);
375 readWord
+= (readByte
<< i
);
376 tul_se2_wait(); /* 6/20/95 */
379 TUL_WR(CurBase
+ TUL_NVRAM
, 0); /* no chip select */
385 /******************************************************************
386 Input: new value in Serial E2PROM, address of Serial E2PROM
387 *******************************************************************/
388 void tul_se2_wr(WORD CurBase
, UCHAR adr
, USHORT writeWord
)
394 instr
= (UCHAR
) (adr
| 0x40);
395 tul_se2_instr(CurBase
, instr
); /* WRITE INSTR */
396 for (i
= 15; i
>= 0; i
--) {
397 if (writeWord
& 0x8000)
398 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2DO
); /* -CLK+dataBit 1 */
400 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* -CLK+dataBit 0 */
402 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2CLK
); /* +CLK */
406 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* -CLK */
408 TUL_WR(CurBase
+ TUL_NVRAM
, 0); /* -CS */
411 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* +CS */
415 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2CLK
); /* +CLK */
417 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* -CLK */
419 if ((readByte
= TUL_RD(CurBase
, TUL_NVRAM
)) & SE2DI
)
420 break; /* write complete */
422 TUL_WR(CurBase
+ TUL_NVRAM
, 0); /* -CS */
427 /***********************************************************************
428 Read SCSI H/A configuration parameters from serial EEPROM
429 ************************************************************************/
430 int tul_se2_rd_all(WORD CurBase
)
436 i91unvramp
= &i91unvram
;
437 np
= (USHORT
*) i91unvramp
;
438 for (i
= 0; i
< 32; i
++) {
439 *np
++ = tul_se2_rd(CurBase
, i
);
442 /*--------------------Is signature "ini" ok ? ----------------*/
443 if (i91unvramp
->NVM_Signature
!= INI_SIGNATURE
)
445 /*---------------------- Is ckecksum ok ? ----------------------*/
446 np
= (USHORT
*) i91unvramp
;
447 for (i
= 0; i
< 31; i
++)
449 if (i91unvramp
->NVM_CheckSum
!= (USHORT
) chksum
)
455 /***********************************************************************
456 Update SCSI H/A configuration parameters from serial EEPROM
457 ************************************************************************/
458 void tul_se2_update_all(WORD CurBase
)
459 { /* setup default pattern */
464 i91unvramp
= &i91unvram
;
465 /* Calculate checksum first */
466 np
= (USHORT
*) i91udftNvRam
;
467 for (i
= 0; i
< 31; i
++)
469 *np
= (USHORT
) chksum
;
470 tul_se2_ew_en(CurBase
); /* Enable write */
472 np
= (USHORT
*) i91udftNvRam
;
473 np1
= (USHORT
*) i91unvramp
;
474 for (i
= 0; i
< 32; i
++, np
++, np1
++) {
476 tul_se2_wr(CurBase
, i
, *np
);
480 tul_se2_ew_ds(CurBase
); /* Disable write */
484 /*************************************************************************
485 Function name : read_eeprom
486 **************************************************************************/
487 void tul_read_eeprom(WORD CurBase
)
491 i91unvramp
= &i91unvram
;
492 /*------Enable EEProm programming ---*/
493 gctrl
= TUL_RD(CurBase
, TUL_GCTRL
);
494 TUL_WR(CurBase
+ TUL_GCTRL
, gctrl
| TUL_GCTRL_EEPROM_BIT
);
495 if (tul_se2_rd_all(CurBase
) != 1) {
496 tul_se2_update_all(CurBase
); /* setup default pattern */
497 tul_se2_rd_all(CurBase
); /* load again */
499 /*------ Disable EEProm programming ---*/
500 gctrl
= TUL_RD(CurBase
, TUL_GCTRL
);
501 TUL_WR(CurBase
+ TUL_GCTRL
, gctrl
& ~TUL_GCTRL_EEPROM_BIT
);
504 int Addi91u_into_Adapter_table(WORD wBIOS
, WORD wBASE
, BYTE bInterrupt
,
505 BYTE bBus
, BYTE bDevice
)
509 for (i
= 0; i
< MAX_SUPPORTED_ADAPTERS
; i
++) {
510 if (i91u_adpt
[i
].ADPT_BIOS
< wBIOS
)
512 if (i91u_adpt
[i
].ADPT_BIOS
== wBIOS
) {
513 if (i91u_adpt
[i
].ADPT_BASE
== wBASE
) {
514 if (i91u_adpt
[i
].ADPT_Bus
!= 0xFF)
516 } else if (i91u_adpt
[i
].ADPT_BASE
< wBASE
)
519 for (j
= MAX_SUPPORTED_ADAPTERS
- 1; j
> i
; j
--) {
520 i91u_adpt
[j
].ADPT_BASE
= i91u_adpt
[j
- 1].ADPT_BASE
;
521 i91u_adpt
[j
].ADPT_INTR
= i91u_adpt
[j
- 1].ADPT_INTR
;
522 i91u_adpt
[j
].ADPT_BIOS
= i91u_adpt
[j
- 1].ADPT_BIOS
;
523 i91u_adpt
[j
].ADPT_Bus
= i91u_adpt
[j
- 1].ADPT_Bus
;
524 i91u_adpt
[j
].ADPT_Device
= i91u_adpt
[j
- 1].ADPT_Device
;
526 i91u_adpt
[i
].ADPT_BASE
= wBASE
;
527 i91u_adpt
[i
].ADPT_INTR
= bInterrupt
;
528 i91u_adpt
[i
].ADPT_BIOS
= wBIOS
;
529 i91u_adpt
[i
].ADPT_Bus
= bBus
;
530 i91u_adpt
[i
].ADPT_Device
= bDevice
;
536 void init_i91uAdapter_table(void)
540 for (i
= 0; i
< MAX_SUPPORTED_ADAPTERS
; i
++) { /* Initialize adapter structure */
541 i91u_adpt
[i
].ADPT_BIOS
= 0xffff;
542 i91u_adpt
[i
].ADPT_BASE
= 0xffff;
543 i91u_adpt
[i
].ADPT_INTR
= 0xff;
544 i91u_adpt
[i
].ADPT_Bus
= 0xff;
545 i91u_adpt
[i
].ADPT_Device
= 0xff;
550 void tul_stop_bm(HCS
* pCurHcb
)
553 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_XStatus
) & XPEND
) { /* if DMA xfer is pending, abort DMA xfer */
554 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_X_ABT
| TAX_X_CLR_FIFO
);
555 /* wait Abort DMA xfer done */
556 while ((TUL_RD(pCurHcb
->HCS_Base
, TUL_Int
) & XABT
) == 0);
558 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
561 /***************************************************************************/
562 void get_tulipPCIConfig(HCS
* pCurHcb
, int ch_idx
)
564 pCurHcb
->HCS_Base
= i91u_adpt
[ch_idx
].ADPT_BASE
; /* Supply base address */
565 pCurHcb
->HCS_BIOS
= i91u_adpt
[ch_idx
].ADPT_BIOS
; /* Supply BIOS address */
566 pCurHcb
->HCS_Intr
= i91u_adpt
[ch_idx
].ADPT_INTR
; /* Supply interrupt line */
570 /***************************************************************************/
571 int tul_reset_scsi(HCS
* pCurHcb
, int seconds
)
573 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_RST_BUS
);
575 while (!((pCurHcb
->HCS_JSInt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
)) & TSS_SCSIRST_INT
));
576 /* reset tulip chip */
578 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, 0);
580 /* Stall for a while, wait for target's firmware ready,make it 2 sec ! */
581 /* SONY 5200 tape drive won't work if only stall for 1 sec */
582 tul_do_pause(seconds
* HZ
);
584 TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
);
586 return (SCSI_RESET_SUCCESS
);
589 /***************************************************************************/
590 int init_tulip(HCS
* pCurHcb
, SCB
* scbp
, int tul_num_scb
, BYTE
* pbBiosAdr
, int seconds
)
595 SCB
*pTmpScb
, *pPrevScb
= NULL
;
597 pCurHcb
->HCS_NumScbs
= tul_num_scb
;
598 pCurHcb
->HCS_Semaph
= 1;
599 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
600 pCurHcb
->HCS_SemaphLock
= SPIN_LOCK_UNLOCKED
;
602 pCurHcb
->HCS_JSStatus0
= 0;
603 pCurHcb
->HCS_Scb
= scbp
;
604 pCurHcb
->HCS_NxtPend
= scbp
;
605 pCurHcb
->HCS_NxtAvail
= scbp
;
606 for (i
= 0, pTmpScb
= scbp
; i
< tul_num_scb
; i
++, pTmpScb
++) {
607 pTmpScb
->SCB_TagId
= i
;
609 pPrevScb
->SCB_NxtScb
= pTmpScb
;
612 pPrevScb
->SCB_NxtScb
= NULL
;
613 pCurHcb
->HCS_ScbEnd
= pTmpScb
;
614 pCurHcb
->HCS_FirstAvail
= scbp
;
615 pCurHcb
->HCS_LastAvail
= pPrevScb
;
616 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
617 pCurHcb
->HCS_AvailLock
= SPIN_LOCK_UNLOCKED
;
619 pCurHcb
->HCS_FirstPend
= NULL
;
620 pCurHcb
->HCS_LastPend
= NULL
;
621 pCurHcb
->HCS_FirstBusy
= NULL
;
622 pCurHcb
->HCS_LastBusy
= NULL
;
623 pCurHcb
->HCS_FirstDone
= NULL
;
624 pCurHcb
->HCS_LastDone
= NULL
;
625 pCurHcb
->HCS_ActScb
= NULL
;
626 pCurHcb
->HCS_ActTcs
= NULL
;
628 tul_read_eeprom(pCurHcb
->HCS_Base
);
629 /*---------- get H/A configuration -------------*/
630 if (i91unvramp
->NVM_SCSIInfo
[0].NVM_NumOfTarg
== 8)
631 pCurHcb
->HCS_MaxTar
= 8;
633 pCurHcb
->HCS_MaxTar
= 16;
635 pCurHcb
->HCS_Config
= i91unvramp
->NVM_SCSIInfo
[0].NVM_ChConfig1
;
637 pCurHcb
->HCS_SCSI_ID
= i91unvramp
->NVM_SCSIInfo
[0].NVM_ChSCSIID
;
638 pCurHcb
->HCS_IdMask
= ~(1 << pCurHcb
->HCS_SCSI_ID
);
641 /* Enable parity error response */
642 TUL_WR(pCurHcb
->HCS_Base
+ TUL_PCMD
, TUL_RD(pCurHcb
->HCS_Base
, TUL_PCMD
) | 0x40);
645 /* Mask all the interrupt */
646 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
648 tul_stop_bm(pCurHcb
);
649 /* --- Initialize the tulip --- */
650 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_RST_CHIP
);
652 /* program HBA's SCSI ID */
653 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SScsiId
, pCurHcb
->HCS_SCSI_ID
<< 4);
655 /* Enable Initiator Mode ,phase latch,alternate sync period mode,
656 disable SCSI reset */
657 if (pCurHcb
->HCS_Config
& HCC_EN_PAR
)
658 pCurHcb
->HCS_SConf1
= (TSC_INITDEFAULT
| TSC_EN_SCSI_PAR
);
660 pCurHcb
->HCS_SConf1
= (TSC_INITDEFAULT
);
661 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurHcb
->HCS_SConf1
);
663 /* Enable HW reselect */
664 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
);
666 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SPeriod
, 0);
668 /* selection time out = 250 ms */
669 TUL_WR(pCurHcb
->HCS_Base
+ TUL_STimeOut
, 153);
671 /*--------- Enable SCSI terminator -----*/
672 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCtrl
, (pCurHcb
->HCS_Config
& (HCC_ACT_TERM1
| HCC_ACT_TERM2
)));
673 TUL_WR(pCurHcb
->HCS_Base
+ TUL_GCTRL1
,
674 ((pCurHcb
->HCS_Config
& HCC_AUTO_TERM
) >> 4) | (TUL_RD(pCurHcb
->HCS_Base
, TUL_GCTRL1
) & 0xFE));
677 pwFlags
= (WORD
*) & (i91unvramp
->NVM_SCSIInfo
[0].NVM_Targ0Config
),
678 pbHeads
= pbBiosAdr
+ 0x180;
679 i
< pCurHcb
->HCS_MaxTar
;
681 pCurHcb
->HCS_Tcs
[i
].TCS_Flags
= *pwFlags
& ~(TCF_SYNC_DONE
| TCF_WDTR_DONE
);
682 if (pCurHcb
->HCS_Tcs
[i
].TCS_Flags
& TCF_EN_255
)
683 pCurHcb
->HCS_Tcs
[i
].TCS_DrvFlags
= TCF_DRV_255_63
;
685 pCurHcb
->HCS_Tcs
[i
].TCS_DrvFlags
= 0;
686 pCurHcb
->HCS_Tcs
[i
].TCS_JS_Period
= 0;
687 pCurHcb
->HCS_Tcs
[i
].TCS_SConfig0
= pCurHcb
->HCS_SConf1
;
688 pCurHcb
->HCS_Tcs
[i
].TCS_DrvHead
= *pbHeads
++;
689 if (pCurHcb
->HCS_Tcs
[i
].TCS_DrvHead
== 255)
690 pCurHcb
->HCS_Tcs
[i
].TCS_DrvFlags
= TCF_DRV_255_63
;
692 pCurHcb
->HCS_Tcs
[i
].TCS_DrvFlags
= 0;
693 pCurHcb
->HCS_Tcs
[i
].TCS_DrvSector
= *pbHeads
++;
694 pCurHcb
->HCS_Tcs
[i
].TCS_Flags
&= ~TCF_BUSY
;
695 pCurHcb
->HCS_ActTags
[i
] = 0;
696 pCurHcb
->HCS_MaxTags
[i
] = 0xFF;
698 printk("i91u: PCI Base=0x%04X, IRQ=%d, BIOS=0x%04X0, SCSI ID=%d\n",
699 pCurHcb
->HCS_Base
, pCurHcb
->HCS_Intr
,
700 pCurHcb
->HCS_BIOS
, pCurHcb
->HCS_SCSI_ID
);
701 /*------------------- reset SCSI Bus ---------------------------*/
702 if (pCurHcb
->HCS_Config
& HCC_SCSI_RESET
) {
703 printk("i91u: Reset SCSI Bus ... \n");
704 tul_reset_scsi(pCurHcb
, seconds
);
706 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCFG1
, 0x17);
707 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SIntEnable
, 0xE9);
711 /***************************************************************************/
712 SCB
*tul_alloc_scb(HCS
* hcsp
)
716 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
717 spin_lock_irqsave(&(hcsp
->HCS_AvailLock
), flags
);
722 if ((pTmpScb
= hcsp
->HCS_FirstAvail
) != NULL
) {
724 printk("find scb at %08lx\n", (ULONG
) pTmpScb
);
726 if ((hcsp
->HCS_FirstAvail
= pTmpScb
->SCB_NxtScb
) == NULL
)
727 hcsp
->HCS_LastAvail
= NULL
;
728 pTmpScb
->SCB_NxtScb
= NULL
;
729 pTmpScb
->SCB_Status
= SCB_RENT
;
731 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
732 spin_unlock_irqrestore(&(hcsp
->HCS_AvailLock
), flags
);
734 restore_flags(flags
);
739 /***************************************************************************/
740 void tul_release_scb(HCS
* hcsp
, SCB
* scbp
)
745 printk("Release SCB %lx; ", (ULONG
) scbp
);
747 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
748 spin_lock_irqsave(&(hcsp
->HCS_AvailLock
), flags
);
754 scbp
->SCB_Status
= 0;
755 scbp
->SCB_NxtScb
= NULL
;
756 if (hcsp
->HCS_LastAvail
!= NULL
) {
757 hcsp
->HCS_LastAvail
->SCB_NxtScb
= scbp
;
758 hcsp
->HCS_LastAvail
= scbp
;
760 hcsp
->HCS_FirstAvail
= scbp
;
761 hcsp
->HCS_LastAvail
= scbp
;
763 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
764 spin_unlock_irqrestore(&(hcsp
->HCS_AvailLock
), flags
);
766 restore_flags(flags
);
770 /***************************************************************************/
771 void tul_append_pend_scb(HCS
* pCurHcb
, SCB
* scbp
)
775 printk("Append pend SCB %lx; ", (ULONG
) scbp
);
777 scbp
->SCB_Status
= SCB_PEND
;
778 scbp
->SCB_NxtScb
= NULL
;
779 if (pCurHcb
->HCS_LastPend
!= NULL
) {
780 pCurHcb
->HCS_LastPend
->SCB_NxtScb
= scbp
;
781 pCurHcb
->HCS_LastPend
= scbp
;
783 pCurHcb
->HCS_FirstPend
= scbp
;
784 pCurHcb
->HCS_LastPend
= scbp
;
788 /***************************************************************************/
789 void tul_push_pend_scb(HCS
* pCurHcb
, SCB
* scbp
)
793 printk("Push pend SCB %lx; ", (ULONG
) scbp
);
795 scbp
->SCB_Status
= SCB_PEND
;
796 if ((scbp
->SCB_NxtScb
= pCurHcb
->HCS_FirstPend
) != NULL
) {
797 pCurHcb
->HCS_FirstPend
= scbp
;
799 pCurHcb
->HCS_FirstPend
= scbp
;
800 pCurHcb
->HCS_LastPend
= scbp
;
804 /***************************************************************************/
805 SCB
*tul_find_first_pend_scb(HCS
* pCurHcb
)
810 pFirstPend
= pCurHcb
->HCS_FirstPend
;
811 while (pFirstPend
!= NULL
) {
812 if (pFirstPend
->SCB_Opcode
!= ExecSCSI
) {
815 if (pFirstPend
->SCB_TagMsg
== 0) {
816 if ((pCurHcb
->HCS_ActTags
[pFirstPend
->SCB_Target
] == 0) &&
817 !(pCurHcb
->HCS_Tcs
[pFirstPend
->SCB_Target
].TCS_Flags
& TCF_BUSY
)) {
821 if ((pCurHcb
->HCS_ActTags
[pFirstPend
->SCB_Target
] >=
822 pCurHcb
->HCS_MaxTags
[pFirstPend
->SCB_Target
]) |
823 (pCurHcb
->HCS_Tcs
[pFirstPend
->SCB_Target
].TCS_Flags
& TCF_BUSY
)) {
824 pFirstPend
= pFirstPend
->SCB_NxtScb
;
829 pFirstPend
= pFirstPend
->SCB_NxtScb
;
835 /***************************************************************************/
836 SCB
*tul_pop_pend_scb(HCS
* pCurHcb
)
840 if ((pTmpScb
= pCurHcb
->HCS_FirstPend
) != NULL
) {
841 if ((pCurHcb
->HCS_FirstPend
= pTmpScb
->SCB_NxtScb
) == NULL
)
842 pCurHcb
->HCS_LastPend
= NULL
;
843 pTmpScb
->SCB_NxtScb
= NULL
;
846 printk("Pop pend SCB %lx; ", (ULONG
) pTmpScb
);
852 /***************************************************************************/
853 void tul_unlink_pend_scb(HCS
* pCurHcb
, SCB
* pCurScb
)
855 SCB
*pTmpScb
, *pPrevScb
;
858 printk("unlink pend SCB %lx; ", (ULONG
) pCurScb
);
861 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstPend
;
862 while (pTmpScb
!= NULL
) {
863 if (pCurScb
== pTmpScb
) { /* Unlink this SCB */
864 if (pTmpScb
== pCurHcb
->HCS_FirstPend
) {
865 if ((pCurHcb
->HCS_FirstPend
= pTmpScb
->SCB_NxtScb
) == NULL
)
866 pCurHcb
->HCS_LastPend
= NULL
;
868 pPrevScb
->SCB_NxtScb
= pTmpScb
->SCB_NxtScb
;
869 if (pTmpScb
== pCurHcb
->HCS_LastPend
)
870 pCurHcb
->HCS_LastPend
= pPrevScb
;
872 pTmpScb
->SCB_NxtScb
= NULL
;
876 pTmpScb
= pTmpScb
->SCB_NxtScb
;
880 /***************************************************************************/
881 void tul_append_busy_scb(HCS
* pCurHcb
, SCB
* scbp
)
885 printk("append busy SCB %lx; ", (ULONG
) scbp
);
887 if (scbp
->SCB_TagMsg
)
888 pCurHcb
->HCS_ActTags
[scbp
->SCB_Target
]++;
890 pCurHcb
->HCS_Tcs
[scbp
->SCB_Target
].TCS_Flags
|= TCF_BUSY
;
891 scbp
->SCB_Status
= SCB_BUSY
;
892 scbp
->SCB_NxtScb
= NULL
;
893 if (pCurHcb
->HCS_LastBusy
!= NULL
) {
894 pCurHcb
->HCS_LastBusy
->SCB_NxtScb
= scbp
;
895 pCurHcb
->HCS_LastBusy
= scbp
;
897 pCurHcb
->HCS_FirstBusy
= scbp
;
898 pCurHcb
->HCS_LastBusy
= scbp
;
902 /***************************************************************************/
903 SCB
*tul_pop_busy_scb(HCS
* pCurHcb
)
908 if ((pTmpScb
= pCurHcb
->HCS_FirstBusy
) != NULL
) {
909 if ((pCurHcb
->HCS_FirstBusy
= pTmpScb
->SCB_NxtScb
) == NULL
)
910 pCurHcb
->HCS_LastBusy
= NULL
;
911 pTmpScb
->SCB_NxtScb
= NULL
;
912 if (pTmpScb
->SCB_TagMsg
)
913 pCurHcb
->HCS_ActTags
[pTmpScb
->SCB_Target
]--;
915 pCurHcb
->HCS_Tcs
[pTmpScb
->SCB_Target
].TCS_Flags
&= ~TCF_BUSY
;
918 printk("Pop busy SCB %lx; ", (ULONG
) pTmpScb
);
923 /***************************************************************************/
924 void tul_unlink_busy_scb(HCS
* pCurHcb
, SCB
* pCurScb
)
926 SCB
*pTmpScb
, *pPrevScb
;
929 printk("unlink busy SCB %lx; ", (ULONG
) pCurScb
);
932 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstBusy
;
933 while (pTmpScb
!= NULL
) {
934 if (pCurScb
== pTmpScb
) { /* Unlink this SCB */
935 if (pTmpScb
== pCurHcb
->HCS_FirstBusy
) {
936 if ((pCurHcb
->HCS_FirstBusy
= pTmpScb
->SCB_NxtScb
) == NULL
)
937 pCurHcb
->HCS_LastBusy
= NULL
;
939 pPrevScb
->SCB_NxtScb
= pTmpScb
->SCB_NxtScb
;
940 if (pTmpScb
== pCurHcb
->HCS_LastBusy
)
941 pCurHcb
->HCS_LastBusy
= pPrevScb
;
943 pTmpScb
->SCB_NxtScb
= NULL
;
944 if (pTmpScb
->SCB_TagMsg
)
945 pCurHcb
->HCS_ActTags
[pTmpScb
->SCB_Target
]--;
947 pCurHcb
->HCS_Tcs
[pTmpScb
->SCB_Target
].TCS_Flags
&= ~TCF_BUSY
;
951 pTmpScb
= pTmpScb
->SCB_NxtScb
;
956 /***************************************************************************/
957 SCB
*tul_find_busy_scb(HCS
* pCurHcb
, WORD tarlun
)
959 SCB
*pTmpScb
, *pPrevScb
;
963 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstBusy
;
964 while (pTmpScb
!= NULL
) {
965 scbp_tarlun
= (pTmpScb
->SCB_Lun
<< 8) | (pTmpScb
->SCB_Target
);
966 if (scbp_tarlun
== tarlun
) { /* Unlink this SCB */
970 pTmpScb
= pTmpScb
->SCB_NxtScb
;
973 printk("find busy SCB %lx; ", (ULONG
) pTmpScb
);
978 /***************************************************************************/
979 void tul_append_done_scb(HCS
* pCurHcb
, SCB
* scbp
)
983 printk("append done SCB %lx; ", (ULONG
) scbp
);
986 scbp
->SCB_Status
= SCB_DONE
;
987 scbp
->SCB_NxtScb
= NULL
;
988 if (pCurHcb
->HCS_LastDone
!= NULL
) {
989 pCurHcb
->HCS_LastDone
->SCB_NxtScb
= scbp
;
990 pCurHcb
->HCS_LastDone
= scbp
;
992 pCurHcb
->HCS_FirstDone
= scbp
;
993 pCurHcb
->HCS_LastDone
= scbp
;
997 /***************************************************************************/
998 SCB
*tul_find_done_scb(HCS
* pCurHcb
)
1003 if ((pTmpScb
= pCurHcb
->HCS_FirstDone
) != NULL
) {
1004 if ((pCurHcb
->HCS_FirstDone
= pTmpScb
->SCB_NxtScb
) == NULL
)
1005 pCurHcb
->HCS_LastDone
= NULL
;
1006 pTmpScb
->SCB_NxtScb
= NULL
;
1009 printk("find done SCB %lx; ", (ULONG
) pTmpScb
);
1014 /***************************************************************************/
1015 int tul_abort_srb(HCS
* pCurHcb
, ULONG srbp
)
1018 SCB
*pTmpScb
, *pPrevScb
;
1020 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1021 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1027 if ((pCurHcb
->HCS_Semaph
== 0) && (pCurHcb
->HCS_ActScb
== NULL
)) {
1028 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1029 /* disable Jasmin SCSI Int */
1031 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1032 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1035 tulip_main(pCurHcb
);
1037 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1038 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1041 pCurHcb
->HCS_Semaph
= 1;
1042 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1044 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1045 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1047 restore_flags(flags
);
1050 return SCSI_ABORT_SNOOZE
;
1052 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstPend
; /* Check Pend queue */
1053 while (pTmpScb
!= NULL
) {
1055 if (pTmpScb
->SCB_Srb
== (unsigned char *) srbp
) {
1056 if (pTmpScb
== pCurHcb
->HCS_ActScb
) {
1057 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1058 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1060 restore_flags(flags
);
1062 return SCSI_ABORT_BUSY
;
1063 } else if (pTmpScb
== pCurHcb
->HCS_FirstPend
) {
1064 if ((pCurHcb
->HCS_FirstPend
= pTmpScb
->SCB_NxtScb
) == NULL
)
1065 pCurHcb
->HCS_LastPend
= NULL
;
1067 pPrevScb
->SCB_NxtScb
= pTmpScb
->SCB_NxtScb
;
1068 if (pTmpScb
== pCurHcb
->HCS_LastPend
)
1069 pCurHcb
->HCS_LastPend
= pPrevScb
;
1071 pTmpScb
->SCB_HaStat
= HOST_ABORTED
;
1072 pTmpScb
->SCB_Flags
|= SCF_DONE
;
1073 if (pTmpScb
->SCB_Flags
& SCF_POST
)
1074 (*pTmpScb
->SCB_Post
) ((BYTE
*) pCurHcb
, (BYTE
*) pTmpScb
);
1075 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1076 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1078 restore_flags(flags
);
1080 return SCSI_ABORT_SUCCESS
;
1083 pTmpScb
= pTmpScb
->SCB_NxtScb
;
1086 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstBusy
; /* Check Busy queue */
1087 while (pTmpScb
!= NULL
) {
1089 if (pTmpScb
->SCB_Srb
== (unsigned char *) srbp
) {
1091 if (pTmpScb
== pCurHcb
->HCS_ActScb
) {
1092 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1093 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1095 restore_flags(flags
);
1097 return SCSI_ABORT_BUSY
;
1098 } else if (pTmpScb
->SCB_TagMsg
== 0) {
1099 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1100 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1102 restore_flags(flags
);
1104 return SCSI_ABORT_BUSY
;
1106 pCurHcb
->HCS_ActTags
[pTmpScb
->SCB_Target
]--;
1107 if (pTmpScb
== pCurHcb
->HCS_FirstBusy
) {
1108 if ((pCurHcb
->HCS_FirstBusy
= pTmpScb
->SCB_NxtScb
) == NULL
)
1109 pCurHcb
->HCS_LastBusy
= NULL
;
1111 pPrevScb
->SCB_NxtScb
= pTmpScb
->SCB_NxtScb
;
1112 if (pTmpScb
== pCurHcb
->HCS_LastBusy
)
1113 pCurHcb
->HCS_LastBusy
= pPrevScb
;
1115 pTmpScb
->SCB_NxtScb
= NULL
;
1118 pTmpScb
->SCB_HaStat
= HOST_ABORTED
;
1119 pTmpScb
->SCB_Flags
|= SCF_DONE
;
1120 if (pTmpScb
->SCB_Flags
& SCF_POST
)
1121 (*pTmpScb
->SCB_Post
) ((BYTE
*) pCurHcb
, (BYTE
*) pTmpScb
);
1122 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1123 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1125 restore_flags(flags
);
1127 return SCSI_ABORT_SUCCESS
;
1131 pTmpScb
= pTmpScb
->SCB_NxtScb
;
1133 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1134 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1136 restore_flags(flags
);
1138 return (SCSI_ABORT_NOT_RUNNING
);
1141 /***************************************************************************/
1142 int tul_bad_seq(HCS
* pCurHcb
)
1146 printk("tul_bad_seg c=%d\n", pCurHcb
->HCS_Index
);
1148 if ((pCurScb
= pCurHcb
->HCS_ActScb
) != NULL
) {
1149 tul_unlink_busy_scb(pCurHcb
, pCurScb
);
1150 pCurScb
->SCB_HaStat
= HOST_BAD_PHAS
;
1151 pCurScb
->SCB_TaStat
= 0;
1152 tul_append_done_scb(pCurHcb
, pCurScb
);
1154 tul_stop_bm(pCurHcb
);
1156 tul_reset_scsi(pCurHcb
, 8); /* 7/29/98 */
1158 return (tul_post_scsi_rst(pCurHcb
));
1161 /************************************************************************/
1162 int tul_device_reset(HCS
* pCurHcb
, ULONG pSrb
, unsigned int target
, unsigned int ResetFlags
)
1166 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1167 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1173 if (ResetFlags
& SCSI_RESET_ASYNCHRONOUS
) {
1175 if ((pCurHcb
->HCS_Semaph
== 0) && (pCurHcb
->HCS_ActScb
== NULL
)) {
1176 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1177 /* disable Jasmin SCSI Int */
1179 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1180 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1183 tulip_main(pCurHcb
);
1185 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1186 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1189 pCurHcb
->HCS_Semaph
= 1;
1190 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1192 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1193 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1195 restore_flags(flags
);
1198 return SCSI_RESET_SNOOZE
;
1200 pScb
= pCurHcb
->HCS_FirstBusy
; /* Check Busy queue */
1201 while (pScb
!= NULL
) {
1202 if (pScb
->SCB_Srb
== (unsigned char *) pSrb
)
1204 pScb
= pScb
->SCB_NxtScb
;
1207 printk("Unable to Reset - No SCB Found\n");
1209 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1210 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1212 restore_flags(flags
);
1214 return SCSI_RESET_NOT_RUNNING
;
1217 if ((pScb
= tul_alloc_scb(pCurHcb
)) == NULL
) {
1218 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1219 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1221 restore_flags(flags
);
1223 return SCSI_RESET_NOT_RUNNING
;
1225 pScb
->SCB_Opcode
= BusDevRst
;
1226 pScb
->SCB_Flags
= SCF_POST
;
1227 pScb
->SCB_Target
= target
;
1231 if (ResetFlags
& SCSI_RESET_SYNCHRONOUS
) {
1232 pScb
->SCB_Srb
= (unsigned char *) pSrb
;
1234 tul_push_pend_scb(pCurHcb
, pScb
); /* push this SCB to Pending queue */
1236 if (pCurHcb
->HCS_Semaph
== 1) {
1237 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1238 /* disable Jasmin SCSI Int */
1239 pCurHcb
->HCS_Semaph
= 0;
1241 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1242 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1245 tulip_main(pCurHcb
);
1247 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1248 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1251 pCurHcb
->HCS_Semaph
= 1;
1252 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1254 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1255 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1257 restore_flags(flags
);
1259 return SCSI_RESET_PENDING
;
1262 int tul_reset_scsi_bus(HCS
* pCurHcb
)
1266 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1267 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1272 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1273 pCurHcb
->HCS_Semaph
= 0;
1275 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1276 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1278 restore_flags(flags
);
1281 tul_stop_bm(pCurHcb
);
1283 tul_reset_scsi(pCurHcb
, 2); /* 7/29/98 */
1285 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1286 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1291 tul_post_scsi_rst(pCurHcb
);
1293 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1294 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1297 tulip_main(pCurHcb
);
1299 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1300 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1303 pCurHcb
->HCS_Semaph
= 1;
1304 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1305 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1306 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1308 restore_flags(flags
);
1310 return (SCSI_RESET_SUCCESS
| SCSI_RESET_HOST_RESET
);
1313 /************************************************************************/
1314 void tul_exec_scb(HCS
* pCurHcb
, SCB
* pCurScb
)
1318 pCurScb
->SCB_Mode
= 0;
1320 pCurScb
->SCB_SGIdx
= 0;
1321 pCurScb
->SCB_SGMax
= pCurScb
->SCB_SGLen
;
1323 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1324 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1330 tul_append_pend_scb(pCurHcb
, pCurScb
); /* Append this SCB to Pending queue */
1332 /* VVVVV 07/21/98 */
1333 if (pCurHcb
->HCS_Semaph
== 1) {
1334 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1335 /* disable Jasmin SCSI Int */
1336 pCurHcb
->HCS_Semaph
= 0;
1338 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1339 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1342 tulip_main(pCurHcb
);
1344 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1345 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1348 pCurHcb
->HCS_Semaph
= 1;
1349 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1351 #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1352 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1354 restore_flags(flags
);
1359 /***************************************************************************/
1360 int tul_isr(HCS
* pCurHcb
)
1362 /* Enter critical section */
1364 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_Int
) & TSS_INT_PENDING
) {
1365 if (pCurHcb
->HCS_Semaph
== 1) {
1366 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1367 /* Disable Tulip SCSI Int */
1368 pCurHcb
->HCS_Semaph
= 0;
1370 tulip_main(pCurHcb
);
1372 pCurHcb
->HCS_Semaph
= 1;
1373 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1380 /***************************************************************************/
1381 int tulip_main(HCS
* pCurHcb
)
1387 tulip_scsi(pCurHcb
); /* Call tulip_scsi */
1389 while ((pCurScb
= tul_find_done_scb(pCurHcb
)) != NULL
) { /* find done entry */
1390 if (pCurScb
->SCB_TaStat
== QUEUE_FULL
) {
1391 pCurHcb
->HCS_MaxTags
[pCurScb
->SCB_Target
] =
1392 pCurHcb
->HCS_ActTags
[pCurScb
->SCB_Target
] - 1;
1393 pCurScb
->SCB_TaStat
= 0;
1394 tul_append_pend_scb(pCurHcb
, pCurScb
);
1397 if (!(pCurScb
->SCB_Mode
& SCM_RSENS
)) { /* not in auto req. sense mode */
1398 if (pCurScb
->SCB_TaStat
== 2) {
1400 /* clr sync. nego flag */
1402 if (pCurScb
->SCB_Flags
& SCF_SENSE
) {
1404 len
= pCurScb
->SCB_SenseLen
;
1407 pCurScb
->SCB_BufLen
= pCurScb
->SCB_SenseLen
;
1408 pCurScb
->SCB_BufPtr
= pCurScb
->SCB_SensePtr
;
1409 pCurScb
->SCB_Flags
&= ~(SCF_SG
| SCF_DIR
); /* for xfer_data_in */
1410 /* pCurScb->SCB_Flags |= SCF_NO_DCHK; */
1411 /* so, we won't report worng direction in xfer_data_in,
1412 and won't report HOST_DO_DU in state_6 */
1413 pCurScb
->SCB_Mode
= SCM_RSENS
;
1414 pCurScb
->SCB_Ident
&= 0xBF; /* Disable Disconnect */
1415 pCurScb
->SCB_TagMsg
= 0;
1416 pCurScb
->SCB_TaStat
= 0;
1417 pCurScb
->SCB_CDBLen
= 6;
1418 pCurScb
->SCB_CDB
[0] = SCSICMD_RequestSense
;
1419 pCurScb
->SCB_CDB
[1] = 0;
1420 pCurScb
->SCB_CDB
[2] = 0;
1421 pCurScb
->SCB_CDB
[3] = 0;
1422 pCurScb
->SCB_CDB
[4] = len
;
1423 pCurScb
->SCB_CDB
[5] = 0;
1424 tul_push_pend_scb(pCurHcb
, pCurScb
);
1428 } else { /* in request sense mode */
1430 if (pCurScb
->SCB_TaStat
== 2) { /* check contition status again after sending
1431 requset sense cmd 0x3 */
1432 pCurScb
->SCB_HaStat
= HOST_BAD_PHAS
;
1434 pCurScb
->SCB_TaStat
= 2;
1436 pCurScb
->SCB_Flags
|= SCF_DONE
;
1437 if (pCurScb
->SCB_Flags
& SCF_POST
) {
1438 (*pCurScb
->SCB_Post
) ((BYTE
*) pCurHcb
, (BYTE
*) pCurScb
);
1443 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus0
) & TSS_INT_PENDING
)
1446 if (pCurHcb
->HCS_ActScb
) { /* return to OS and wait for xfer_done_ISR/Selected_ISR */
1447 return 1; /* return to OS, enable interrupt */
1449 /* Check pending SCB */
1450 if (tul_find_first_pend_scb(pCurHcb
) == NULL
) {
1451 return 1; /* return to OS, enable interrupt */
1453 } /* End of for loop */
1454 /* statement won't reach here */
1460 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
1461 /***************************************************************************/
1462 /***************************************************************************/
1463 /***************************************************************************/
1464 /***************************************************************************/
1466 /***************************************************************************/
1467 void tulip_scsi(HCS
* pCurHcb
)
1472 /* make sure to service interrupt asap */
1474 if ((pCurHcb
->HCS_JSStatus0
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus0
)) & TSS_INT_PENDING
) {
1476 pCurHcb
->HCS_Phase
= pCurHcb
->HCS_JSStatus0
& TSS_PH_MASK
;
1477 pCurHcb
->HCS_JSStatus1
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus1
);
1478 pCurHcb
->HCS_JSInt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
);
1479 if (pCurHcb
->HCS_JSInt
& TSS_SCSIRST_INT
) { /* SCSI bus reset detected */
1480 int_tul_scsi_rst(pCurHcb
);
1483 if (pCurHcb
->HCS_JSInt
& TSS_RESEL_INT
) { /* if selected/reselected interrupt */
1484 if (int_tul_resel(pCurHcb
) == 0)
1485 tul_next_state(pCurHcb
);
1488 if (pCurHcb
->HCS_JSInt
& TSS_SEL_TIMEOUT
) {
1489 int_tul_busfree(pCurHcb
);
1492 if (pCurHcb
->HCS_JSInt
& TSS_DISC_INT
) { /* BUS disconnection */
1493 int_tul_busfree(pCurHcb
); /* unexpected bus free or sel timeout */
1496 if (pCurHcb
->HCS_JSInt
& (TSS_FUNC_COMP
| TSS_BUS_SERV
)) { /* func complete or Bus service */
1497 if ((pCurScb
= pCurHcb
->HCS_ActScb
) != NULL
)
1498 tul_next_state(pCurHcb
);
1502 if (pCurHcb
->HCS_ActScb
!= NULL
)
1505 if ((pCurScb
= tul_find_first_pend_scb(pCurHcb
)) == NULL
)
1508 /* program HBA's SCSI ID & target SCSI ID */
1509 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SScsiId
,
1510 (pCurHcb
->HCS_SCSI_ID
<< 4) | (pCurScb
->SCB_Target
& 0x0F));
1511 if (pCurScb
->SCB_Opcode
== ExecSCSI
) {
1512 pCurTcb
= &pCurHcb
->HCS_Tcs
[pCurScb
->SCB_Target
];
1514 if (pCurScb
->SCB_TagMsg
)
1515 pCurTcb
->TCS_DrvFlags
|= TCF_DRV_EN_TAG
;
1517 pCurTcb
->TCS_DrvFlags
&= ~TCF_DRV_EN_TAG
;
1519 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SPeriod
, pCurTcb
->TCS_JS_Period
);
1520 if ((pCurTcb
->TCS_Flags
& (TCF_WDTR_DONE
| TCF_NO_WDTR
)) == 0) { /* do wdtr negotiation */
1521 tul_select_atn_stop(pCurHcb
, pCurScb
);
1523 if ((pCurTcb
->TCS_Flags
& (TCF_SYNC_DONE
| TCF_NO_SYNC_NEGO
)) == 0) { /* do sync negotiation */
1524 tul_select_atn_stop(pCurHcb
, pCurScb
);
1526 if (pCurScb
->SCB_TagMsg
)
1527 tul_select_atn3(pCurHcb
, pCurScb
);
1529 tul_select_atn(pCurHcb
, pCurScb
);
1532 if (pCurScb
->SCB_Flags
& SCF_POLL
) {
1533 while (wait_tulip(pCurHcb
) != -1) {
1534 if (tul_next_state(pCurHcb
) == -1)
1538 } else if (pCurScb
->SCB_Opcode
== BusDevRst
) {
1539 tul_select_atn_stop(pCurHcb
, pCurScb
);
1540 pCurScb
->SCB_NxtStat
= 8;
1541 if (pCurScb
->SCB_Flags
& SCF_POLL
) {
1542 while (wait_tulip(pCurHcb
) != -1) {
1543 if (tul_next_state(pCurHcb
) == -1)
1547 } else if (pCurScb
->SCB_Opcode
== AbortCmd
) {
1550 srbp
= (ULONG
) pCurScb
->SCB_Srb
;
1552 if (tul_abort_srb(pCurHcb
, srbp
) != 0) {
1555 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
1557 tul_release_scb(pCurHcb
, pCurScb
);
1559 pCurScb
->SCB_Opcode
= BusDevRst
;
1560 tul_select_atn_stop(pCurHcb
, pCurScb
);
1561 pCurScb
->SCB_NxtStat
= 8;
1566 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
1567 pCurScb
->SCB_HaStat
= 0x16; /* bad command */
1568 tul_append_done_scb(pCurHcb
, pCurScb
);
1574 /***************************************************************************/
1575 int tul_next_state(HCS
* pCurHcb
)
1579 next
= pCurHcb
->HCS_ActScb
->SCB_NxtStat
;
1583 next
= tul_state_1(pCurHcb
);
1586 next
= tul_state_2(pCurHcb
);
1589 next
= tul_state_3(pCurHcb
);
1592 next
= tul_state_4(pCurHcb
);
1595 next
= tul_state_5(pCurHcb
);
1598 next
= tul_state_6(pCurHcb
);
1601 next
= tul_state_7(pCurHcb
);
1604 return (tul_bus_device_reset(pCurHcb
));
1606 return (tul_bad_seq(pCurHcb
));
1614 /***************************************************************************/
1615 /* sTate after selection with attention & stop */
1616 int tul_state_1(HCS
* pCurHcb
)
1618 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1619 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
1624 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
1625 tul_append_busy_scb(pCurHcb
, pCurScb
);
1627 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurTcb
->TCS_SConfig0
);
1629 if (pCurHcb
->HCS_Phase
== MSG_OUT
) {
1631 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, (TSC_EN_BUS_IN
| TSC_HW_RESELECT
));
1633 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_Ident
);
1635 if (pCurScb
->SCB_TagMsg
) {
1636 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_TagMsg
);
1637 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_TagId
);
1639 if ((pCurTcb
->TCS_Flags
& (TCF_WDTR_DONE
| TCF_NO_WDTR
)) == 0) {
1641 pCurTcb
->TCS_Flags
|= TCF_WDTR_DONE
;
1643 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_EXTEND
);
1644 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 2); /* Extended msg length */
1645 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 3); /* Sync request */
1646 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 1); /* Start from 16 bits */
1647 } else if ((pCurTcb
->TCS_Flags
& (TCF_SYNC_DONE
| TCF_NO_SYNC_NEGO
)) == 0) {
1649 pCurTcb
->TCS_Flags
|= TCF_SYNC_DONE
;
1651 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_EXTEND
);
1652 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 3); /* extended msg length */
1653 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 1); /* sync request */
1654 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, tul_rate_tbl
[pCurTcb
->TCS_Flags
& TCF_SCSI_RATE
]);
1655 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MAX_OFFSET
); /* REQ/ACK offset */
1657 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1658 if (wait_tulip(pCurHcb
) == -1)
1661 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1662 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, (TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)));
1667 /***************************************************************************/
1668 /* state after selection with attention */
1669 /* state after selection with attention3 */
1670 int tul_state_2(HCS
* pCurHcb
)
1672 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1673 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
1678 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
1679 tul_append_busy_scb(pCurHcb
, pCurScb
);
1681 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurTcb
->TCS_SConfig0
);
1683 if (pCurHcb
->HCS_JSStatus1
& TSS_CMD_PH_CMP
) {
1686 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1687 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, (TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)));
1691 /***************************************************************************/
1692 /* state before CDB xfer is done */
1693 int tul_state_3(HCS
* pCurHcb
)
1695 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1696 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
1703 switch (pCurHcb
->HCS_Phase
) {
1704 case CMD_OUT
: /* Command out phase */
1705 for (i
= 0; i
< (int) pCurScb
->SCB_CDBLen
; i
++)
1706 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_CDB
[i
]);
1707 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1708 if (wait_tulip(pCurHcb
) == -1)
1710 if (pCurHcb
->HCS_Phase
== CMD_OUT
) {
1711 return (tul_bad_seq(pCurHcb
));
1715 case MSG_IN
: /* Message in phase */
1716 pCurScb
->SCB_NxtStat
= 3;
1717 if (tul_msgin(pCurHcb
) == -1)
1721 case STATUS_IN
: /* Status phase */
1722 if (tul_status_msg(pCurHcb
) == -1)
1726 case MSG_OUT
: /* Message out phase */
1727 if (pCurTcb
->TCS_Flags
& (TCF_SYNC_DONE
| TCF_NO_SYNC_NEGO
)) {
1729 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_NOP
); /* msg nop */
1730 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1731 if (wait_tulip(pCurHcb
) == -1)
1735 pCurTcb
->TCS_Flags
|= TCF_SYNC_DONE
;
1737 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_EXTEND
);
1738 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 3); /* ext. msg len */
1739 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 1); /* sync request */
1740 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, tul_rate_tbl
[pCurTcb
->TCS_Flags
& TCF_SCSI_RATE
]);
1741 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MAX_OFFSET
); /* REQ/ACK offset */
1742 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1743 if (wait_tulip(pCurHcb
) == -1)
1745 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1746 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7));
1752 return (tul_bad_seq(pCurHcb
));
1758 /***************************************************************************/
1759 int tul_state_4(HCS
* pCurHcb
)
1761 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1766 if ((pCurScb
->SCB_Flags
& SCF_DIR
) == SCF_NO_XF
) {
1767 return (6); /* Go to state 6 */
1770 if (pCurScb
->SCB_BufLen
== 0)
1771 return (6); /* Go to state 6 */
1773 switch (pCurHcb
->HCS_Phase
) {
1775 case STATUS_IN
: /* Status phase */
1776 if ((pCurScb
->SCB_Flags
& SCF_DIR
) != 0) { /* if direction bit set then report data underrun */
1777 pCurScb
->SCB_HaStat
= HOST_DO_DU
;
1779 if ((tul_status_msg(pCurHcb
)) == -1)
1783 case MSG_IN
: /* Message in phase */
1784 pCurScb
->SCB_NxtStat
= 0x4;
1785 if (tul_msgin(pCurHcb
) == -1)
1789 case MSG_OUT
: /* Message out phase */
1790 if (pCurHcb
->HCS_JSStatus0
& TSS_PAR_ERROR
) {
1791 pCurScb
->SCB_BufLen
= 0;
1792 pCurScb
->SCB_HaStat
= HOST_DO_DU
;
1793 if (tul_msgout_ide(pCurHcb
) == -1)
1795 return (6); /* Go to state 6 */
1797 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_NOP
); /* msg nop */
1798 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1799 if (wait_tulip(pCurHcb
) == -1)
1804 case DATA_IN
: /* Data in phase */
1805 return (tul_xfer_data_in(pCurHcb
));
1807 case DATA_OUT
: /* Data out phase */
1808 return (tul_xfer_data_out(pCurHcb
));
1811 return (tul_bad_seq(pCurHcb
));
1817 /***************************************************************************/
1818 /* state after dma xfer done or phase change before xfer done */
1819 int tul_state_5(HCS
* pCurHcb
)
1821 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1822 long cnt
, xcnt
; /* cannot use unsigned !! code: if (xcnt < 0) */
1827 /*------ get remaining count -------*/
1829 cnt
= TUL_RDLONG(pCurHcb
->HCS_Base
, TUL_SCnt0
) & 0x0FFFFFF;
1831 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_XCmd
) & 0x20) {
1832 /* ----------------------- DATA_IN ----------------------------- */
1833 /* check scsi parity error */
1834 if (pCurHcb
->HCS_JSStatus0
& TSS_PAR_ERROR
) {
1835 pCurScb
->SCB_HaStat
= HOST_DO_DU
;
1837 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_XStatus
) & XPEND
) { /* DMA xfer pending, Send STOP */
1838 /* tell Hardware scsi xfer has been terminated */
1839 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCtrl
, TUL_RD(pCurHcb
->HCS_Base
, TUL_XCtrl
) | 0x80);
1840 /* wait until DMA xfer not pending */
1841 while (TUL_RD(pCurHcb
->HCS_Base
, TUL_XStatus
) & XPEND
);
1844 /*-------- DATA OUT -----------*/
1845 if ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus1
) & TSS_XFER_CMP
) == 0) {
1846 if (pCurHcb
->HCS_ActTcs
->TCS_JS_Period
& TSC_WIDE_SCSI
)
1847 cnt
+= (TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifoCnt
) & 0x1F) << 1;
1849 cnt
+= (TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifoCnt
) & 0x1F);
1851 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_XStatus
) & XPEND
) { /* if DMA xfer is pending, abort DMA xfer */
1852 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_X_ABT
);
1853 /* wait Abort DMA xfer done */
1854 while ((TUL_RD(pCurHcb
->HCS_Base
, TUL_Int
) & XABT
) == 0);
1856 if ((cnt
== 1) && (pCurHcb
->HCS_Phase
== DATA_OUT
)) {
1857 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1858 if (wait_tulip(pCurHcb
) == -1) {
1863 if ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus1
) & TSS_XFER_CMP
) == 0)
1864 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1869 pCurScb
->SCB_BufLen
= 0;
1870 return (6); /* Go to state 6 */
1872 /* Update active data pointer */
1873 xcnt
= (long) pCurScb
->SCB_BufLen
- cnt
; /* xcnt== bytes already xferred */
1874 pCurScb
->SCB_BufLen
= (U32
) cnt
; /* cnt == bytes left to be xferred */
1875 if (pCurScb
->SCB_Flags
& SCF_SG
) {
1879 sgp
= &pCurScb
->SCB_SGList
[pCurScb
->SCB_SGIdx
];
1880 for (i
= pCurScb
->SCB_SGIdx
; i
< pCurScb
->SCB_SGMax
; sgp
++, i
++) {
1881 xcnt
-= (long) sgp
->SG_Len
;
1882 if (xcnt
< 0) { /* this sgp xfer half done */
1883 xcnt
+= (long) sgp
->SG_Len
; /* xcnt == bytes xferred in this sgp */
1884 sgp
->SG_Ptr
+= (U32
) xcnt
; /* new ptr to be xfer */
1885 sgp
->SG_Len
-= (U32
) xcnt
; /* new len to be xfer */
1886 pCurScb
->SCB_BufPtr
+= ((U32
) (i
- pCurScb
->SCB_SGIdx
) << 3);
1887 /* new SG table ptr */
1888 pCurScb
->SCB_SGLen
= (BYTE
) (pCurScb
->SCB_SGMax
- i
);
1889 /* new SG table len */
1890 pCurScb
->SCB_SGIdx
= (WORD
) i
;
1891 /* for next disc and come in this loop */
1892 return (4); /* Go to state 4 */
1894 /* else (xcnt >= 0 , i.e. this sgp already xferred */
1896 return (6); /* Go to state 6 */
1898 pCurScb
->SCB_BufPtr
+= (U32
) xcnt
;
1900 return (4); /* Go to state 4 */
1903 /***************************************************************************/
1904 /* state after Data phase */
1905 int tul_state_6(HCS
* pCurHcb
)
1907 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1913 switch (pCurHcb
->HCS_Phase
) {
1914 case STATUS_IN
: /* Status phase */
1915 if ((tul_status_msg(pCurHcb
)) == -1)
1919 case MSG_IN
: /* Message in phase */
1920 pCurScb
->SCB_NxtStat
= 6;
1921 if ((tul_msgin(pCurHcb
)) == -1)
1925 case MSG_OUT
: /* Message out phase */
1926 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_NOP
); /* msg nop */
1927 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1928 if (wait_tulip(pCurHcb
) == -1)
1932 case DATA_IN
: /* Data in phase */
1933 return (tul_xpad_in(pCurHcb
));
1935 case DATA_OUT
: /* Data out phase */
1936 return (tul_xpad_out(pCurHcb
));
1939 return (tul_bad_seq(pCurHcb
));
1944 /***************************************************************************/
1945 int tul_state_7(HCS
* pCurHcb
)
1952 /* flush SCSI FIFO */
1953 cnt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifoCnt
) & 0x1F;
1955 for (i
= 0; i
< cnt
; i
++)
1956 TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
1958 switch (pCurHcb
->HCS_Phase
) {
1959 case DATA_IN
: /* Data in phase */
1960 case DATA_OUT
: /* Data out phase */
1961 return (tul_bad_seq(pCurHcb
));
1963 return (6); /* Go to state 6 */
1967 /***************************************************************************/
1968 int tul_xfer_data_in(HCS
* pCurHcb
)
1970 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1972 if ((pCurScb
->SCB_Flags
& SCF_DIR
) == SCF_DOUT
) {
1973 return (6); /* wrong direction */
1975 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, pCurScb
->SCB_BufLen
);
1977 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_DMA_IN
); /* 7/25/95 */
1979 if (pCurScb
->SCB_Flags
& SCF_SG
) { /* S/G xfer */
1980 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XCntH
, ((ULONG
) pCurScb
->SCB_SGLen
) << 3);
1981 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XAddH
, pCurScb
->SCB_BufPtr
);
1982 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_SG_IN
);
1984 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XCntH
, pCurScb
->SCB_BufLen
);
1985 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XAddH
, pCurScb
->SCB_BufPtr
);
1986 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_X_IN
);
1988 pCurScb
->SCB_NxtStat
= 0x5;
1989 return (0); /* return to OS, wait xfer done , let jas_isr come in */
1993 /***************************************************************************/
1994 int tul_xfer_data_out(HCS
* pCurHcb
)
1996 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1998 if ((pCurScb
->SCB_Flags
& SCF_DIR
) == SCF_DIN
) {
1999 return (6); /* wrong direction */
2001 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, pCurScb
->SCB_BufLen
);
2002 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_DMA_OUT
);
2004 if (pCurScb
->SCB_Flags
& SCF_SG
) { /* S/G xfer */
2005 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XCntH
, ((ULONG
) pCurScb
->SCB_SGLen
) << 3);
2006 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XAddH
, pCurScb
->SCB_BufPtr
);
2007 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_SG_OUT
);
2009 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XCntH
, pCurScb
->SCB_BufLen
);
2010 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XAddH
, pCurScb
->SCB_BufPtr
);
2011 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_X_OUT
);
2014 pCurScb
->SCB_NxtStat
= 0x5;
2015 return (0); /* return to OS, wait xfer done , let jas_isr come in */
2019 /***************************************************************************/
2020 int tul_xpad_in(HCS
* pCurHcb
)
2022 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
2023 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
2025 if ((pCurScb
->SCB_Flags
& SCF_DIR
) != SCF_NO_DCHK
) {
2026 pCurScb
->SCB_HaStat
= HOST_DO_DU
; /* over run */
2029 if (pCurTcb
->TCS_JS_Period
& TSC_WIDE_SCSI
)
2030 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 2);
2032 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2034 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2035 if ((wait_tulip(pCurHcb
)) == -1) {
2038 if (pCurHcb
->HCS_Phase
!= DATA_IN
) {
2039 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2042 TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
2046 int tul_xpad_out(HCS
* pCurHcb
)
2048 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
2049 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
2051 if ((pCurScb
->SCB_Flags
& SCF_DIR
) != SCF_NO_DCHK
) {
2052 pCurScb
->SCB_HaStat
= HOST_DO_DU
; /* over run */
2055 if (pCurTcb
->TCS_JS_Period
& TSC_WIDE_SCSI
)
2056 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 2);
2058 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2060 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 0);
2061 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2062 if ((wait_tulip(pCurHcb
)) == -1) {
2065 if (pCurHcb
->HCS_Phase
!= DATA_OUT
) { /* Disable wide CPU to allow read 16 bits */
2066 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
);
2067 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2074 /***************************************************************************/
2075 int tul_status_msg(HCS
* pCurHcb
)
2076 { /* status & MSG_IN */
2077 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
2080 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_CMD_COMP
);
2081 if ((wait_tulip(pCurHcb
)) == -1) {
2085 pCurScb
->SCB_TaStat
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
2087 if (pCurHcb
->HCS_Phase
== MSG_OUT
) {
2088 if (pCurHcb
->HCS_JSStatus0
& TSS_PAR_ERROR
) {
2089 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_PARITY
);
2091 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_NOP
);
2093 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2094 return (wait_tulip(pCurHcb
));
2096 if (pCurHcb
->HCS_Phase
== MSG_IN
) {
2097 msg
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
2098 if (pCurHcb
->HCS_JSStatus0
& TSS_PAR_ERROR
) { /* Parity error */
2099 if ((tul_msgin_accept(pCurHcb
)) == -1)
2101 if (pCurHcb
->HCS_Phase
!= MSG_OUT
)
2102 return (tul_bad_seq(pCurHcb
));
2103 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_PARITY
);
2104 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2105 return (wait_tulip(pCurHcb
));
2107 if (msg
== 0) { /* Command complete */
2109 if ((pCurScb
->SCB_TaStat
& 0x18) == 0x10) { /* No link support */
2110 return (tul_bad_seq(pCurHcb
));
2112 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2113 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_MSG_ACCEPT
);
2114 return tul_wait_done_disc(pCurHcb
);
2117 if ((msg
== MSG_LINK_COMP
) || (msg
== MSG_LINK_FLAG
)) {
2118 if ((pCurScb
->SCB_TaStat
& 0x18) == 0x10)
2119 return (tul_msgin_accept(pCurHcb
));
2122 return (tul_bad_seq(pCurHcb
));
2126 /***************************************************************************/
2128 int int_tul_busfree(HCS
* pCurHcb
)
2130 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
2132 if (pCurScb
!= NULL
) {
2133 if (pCurScb
->SCB_Status
& SCB_SELECT
) { /* selection timeout */
2134 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
2135 pCurScb
->SCB_HaStat
= HOST_SEL_TOUT
;
2136 tul_append_done_scb(pCurHcb
, pCurScb
);
2137 } else { /* Unexpected bus free */
2138 tul_unlink_busy_scb(pCurHcb
, pCurScb
);
2139 pCurScb
->SCB_HaStat
= HOST_BUS_FREE
;
2140 tul_append_done_scb(pCurHcb
, pCurScb
);
2142 pCurHcb
->HCS_ActScb
= NULL
;
2143 pCurHcb
->HCS_ActTcs
= NULL
;
2145 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
); /* Flush SCSI FIFO */
2146 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, TSC_INITDEFAULT
);
2147 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
); /* Enable HW reselect */
2152 /***************************************************************************/
2153 /* scsi bus reset */
2154 int int_tul_scsi_rst(HCS
* pCurHcb
)
2159 /* if DMA xfer is pending, abort DMA xfer */
2160 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_XStatus
) & 0x01) {
2161 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_X_ABT
| TAX_X_CLR_FIFO
);
2162 /* wait Abort DMA xfer done */
2163 while ((TUL_RD(pCurHcb
->HCS_Base
, TUL_Int
) & 0x04) == 0);
2164 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2166 /* Abort all active & disconnected scb */
2167 while ((pCurScb
= tul_pop_busy_scb(pCurHcb
)) != NULL
) {
2168 pCurScb
->SCB_HaStat
= HOST_BAD_PHAS
;
2169 tul_append_done_scb(pCurHcb
, pCurScb
);
2171 pCurHcb
->HCS_ActScb
= NULL
;
2172 pCurHcb
->HCS_ActTcs
= NULL
;
2174 /* clr sync nego. done flag */
2175 for (i
= 0; i
< pCurHcb
->HCS_MaxTar
; i
++) {
2176 pCurHcb
->HCS_Tcs
[i
].TCS_Flags
&= ~(TCF_SYNC_DONE
| TCF_WDTR_DONE
);
2182 /***************************************************************************/
2183 /* scsi reselection */
2184 int int_tul_resel(HCS
* pCurHcb
)
2191 if ((pCurScb
= pCurHcb
->HCS_ActScb
) != NULL
) {
2192 if (pCurScb
->SCB_Status
& SCB_SELECT
) { /* if waiting for selection complete */
2193 pCurScb
->SCB_Status
&= ~SCB_SELECT
;
2195 pCurHcb
->HCS_ActScb
= NULL
;
2197 /* --------- get target id---------------------- */
2198 tar
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SBusId
);
2199 /* ------ get LUN from Identify message----------- */
2200 lun
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SIdent
) & 0x0F;
2201 /* 07/22/98 from 0x1F -> 0x0F */
2202 pCurTcb
= &pCurHcb
->HCS_Tcs
[tar
];
2203 pCurHcb
->HCS_ActTcs
= pCurTcb
;
2204 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurTcb
->TCS_SConfig0
);
2205 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SPeriod
, pCurTcb
->TCS_JS_Period
);
2208 /* ------------- tag queueing ? ------------------- */
2209 if (pCurTcb
->TCS_DrvFlags
& TCF_DRV_EN_TAG
) {
2210 if ((tul_msgin_accept(pCurHcb
)) == -1)
2212 if (pCurHcb
->HCS_Phase
!= MSG_IN
)
2214 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2215 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2216 if ((wait_tulip(pCurHcb
)) == -1)
2218 msg
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
); /* Read Tag Message */
2220 if ((msg
< MSG_STAG
) || (msg
> MSG_OTAG
)) /* Is simple Tag */
2223 if ((tul_msgin_accept(pCurHcb
)) == -1)
2226 if (pCurHcb
->HCS_Phase
!= MSG_IN
)
2229 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2230 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2231 if ((wait_tulip(pCurHcb
)) == -1)
2233 tag
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
); /* Read Tag ID */
2234 pCurScb
= pCurHcb
->HCS_Scb
+ tag
;
2235 if ((pCurScb
->SCB_Target
!= tar
) || (pCurScb
->SCB_Lun
!= lun
)) {
2236 return tul_msgout_abort_tag(pCurHcb
);
2238 if (pCurScb
->SCB_Status
!= SCB_BUSY
) { /* 03/24/95 */
2239 return tul_msgout_abort_tag(pCurHcb
);
2241 pCurHcb
->HCS_ActScb
= pCurScb
;
2242 if ((tul_msgin_accept(pCurHcb
)) == -1)
2244 } else { /* No tag */
2246 if ((pCurScb
= tul_find_busy_scb(pCurHcb
, tar
| (lun
<< 8))) == NULL
) {
2247 return tul_msgout_abort_targ(pCurHcb
);
2249 pCurHcb
->HCS_ActScb
= pCurScb
;
2250 if (!(pCurTcb
->TCS_DrvFlags
& TCF_DRV_EN_TAG
)) {
2251 if ((tul_msgin_accept(pCurHcb
)) == -1)
2259 /***************************************************************************/
2260 int int_tul_bad_seq(HCS
* pCurHcb
)
2261 { /* target wrong phase */
2265 tul_reset_scsi(pCurHcb
, 10);
2267 while ((pCurScb
= tul_pop_busy_scb(pCurHcb
)) != NULL
) {
2268 pCurScb
->SCB_HaStat
= HOST_BAD_PHAS
;
2269 tul_append_done_scb(pCurHcb
, pCurScb
);
2271 for (i
= 0; i
< pCurHcb
->HCS_MaxTar
; i
++) {
2272 pCurHcb
->HCS_Tcs
[i
].TCS_Flags
&= ~(TCF_SYNC_DONE
| TCF_WDTR_DONE
);;
2278 /***************************************************************************/
2279 int tul_msgout_abort_targ(HCS
* pCurHcb
)
2282 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2283 if (tul_msgin_accept(pCurHcb
) == -1)
2285 if (pCurHcb
->HCS_Phase
!= MSG_OUT
)
2286 return (tul_bad_seq(pCurHcb
));
2288 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_ABORT
);
2289 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2291 return tul_wait_disc(pCurHcb
);
2294 /***************************************************************************/
2295 int tul_msgout_abort_tag(HCS
* pCurHcb
)
2298 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2299 if (tul_msgin_accept(pCurHcb
) == -1)
2301 if (pCurHcb
->HCS_Phase
!= MSG_OUT
)
2302 return (tul_bad_seq(pCurHcb
));
2304 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_ABORT_TAG
);
2305 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2307 return tul_wait_disc(pCurHcb
);
2311 /***************************************************************************/
2312 int tul_msgin(HCS
* pCurHcb
)
2318 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2320 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2321 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2322 if ((wait_tulip(pCurHcb
)) == -1)
2325 switch (TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
)) {
2326 case MSG_DISC
: /* Disconnect msg */
2327 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_MSG_ACCEPT
);
2329 return tul_wait_disc(pCurHcb
);
2334 tul_msgin_accept(pCurHcb
);
2337 case MSG_REJ
: /* Clear ATN first */
2338 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
,
2339 (TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)));
2340 pCurTcb
= pCurHcb
->HCS_ActTcs
;
2341 if ((pCurTcb
->TCS_Flags
& (TCF_SYNC_DONE
| TCF_NO_SYNC_NEGO
)) == 0) { /* do sync nego */
2342 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2344 tul_msgin_accept(pCurHcb
);
2347 case MSG_EXTEND
: /* extended msg */
2348 tul_msgin_extend(pCurHcb
);
2351 case MSG_IGNOREWIDE
:
2352 tul_msgin_accept(pCurHcb
);
2356 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2357 if (wait_tulip(pCurHcb
) == -1)
2360 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 0); /* put pad */
2361 TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
); /* get IGNORE field */
2362 TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
); /* get pad */
2364 tul_msgin_accept(pCurHcb
);
2369 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2370 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_MSG_ACCEPT
);
2371 return tul_wait_done_disc(pCurHcb
);
2374 tul_msgout_reject(pCurHcb
);
2377 if (pCurHcb
->HCS_Phase
!= MSG_IN
)
2378 return (pCurHcb
->HCS_Phase
);
2380 /* statement won't reach here */
2386 /***************************************************************************/
2387 int tul_msgout_reject(HCS
* pCurHcb
)
2390 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2392 if ((tul_msgin_accept(pCurHcb
)) == -1)
2395 if (pCurHcb
->HCS_Phase
== MSG_OUT
) {
2396 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_REJ
); /* Msg reject */
2397 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2398 return (wait_tulip(pCurHcb
));
2400 return (pCurHcb
->HCS_Phase
);
2405 /***************************************************************************/
2406 int tul_msgout_ide(HCS
* pCurHcb
)
2408 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_IDE
); /* Initiator Detected Error */
2409 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2410 return (wait_tulip(pCurHcb
));
2414 /***************************************************************************/
2415 int tul_msgin_extend(HCS
* pCurHcb
)
2419 if (tul_msgin_accept(pCurHcb
) != MSG_IN
)
2420 return (pCurHcb
->HCS_Phase
);
2422 /* Get extended msg length */
2423 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2424 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2425 if (wait_tulip(pCurHcb
) == -1)
2428 len
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
2429 pCurHcb
->HCS_Msg
[0] = len
;
2430 for (idx
= 1; len
!= 0; len
--) {
2432 if ((tul_msgin_accept(pCurHcb
)) != MSG_IN
)
2433 return (pCurHcb
->HCS_Phase
);
2434 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2435 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2436 if (wait_tulip(pCurHcb
) == -1)
2438 pCurHcb
->HCS_Msg
[idx
++] = TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
2440 if (pCurHcb
->HCS_Msg
[1] == 1) { /* if it's synchronous data transfer request */
2441 if (pCurHcb
->HCS_Msg
[0] != 3) /* if length is not right */
2442 return (tul_msgout_reject(pCurHcb
));
2443 if (pCurHcb
->HCS_ActTcs
->TCS_Flags
& TCF_NO_SYNC_NEGO
) { /* Set OFFSET=0 to do async, nego back */
2444 pCurHcb
->HCS_Msg
[3] = 0;
2446 if ((tul_msgin_sync(pCurHcb
) == 0) &&
2447 (pCurHcb
->HCS_ActTcs
->TCS_Flags
& TCF_SYNC_DONE
)) {
2448 tul_sync_done(pCurHcb
);
2449 return (tul_msgin_accept(pCurHcb
));
2453 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2454 if ((tul_msgin_accept(pCurHcb
)) != MSG_OUT
)
2455 return (pCurHcb
->HCS_Phase
);
2457 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2459 tul_sync_done(pCurHcb
);
2461 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_EXTEND
);
2462 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 3);
2463 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 1);
2464 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurHcb
->HCS_Msg
[2]);
2465 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurHcb
->HCS_Msg
[3]);
2467 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2468 return (wait_tulip(pCurHcb
));
2470 if ((pCurHcb
->HCS_Msg
[0] != 2) || (pCurHcb
->HCS_Msg
[1] != 3))
2471 return (tul_msgout_reject(pCurHcb
));
2472 /* if it's WIDE DATA XFER REQ */
2473 if (pCurHcb
->HCS_ActTcs
->TCS_Flags
& TCF_NO_WDTR
) {
2474 pCurHcb
->HCS_Msg
[2] = 0;
2476 if (pCurHcb
->HCS_Msg
[2] > 2) /* > 32 bits */
2477 return (tul_msgout_reject(pCurHcb
));
2478 if (pCurHcb
->HCS_Msg
[2] == 2) { /* == 32 */
2479 pCurHcb
->HCS_Msg
[2] = 1;
2481 if ((pCurHcb
->HCS_ActTcs
->TCS_Flags
& TCF_NO_WDTR
) == 0) {
2483 if ((pCurHcb
->HCS_ActTcs
->TCS_Flags
& (TCF_SYNC_DONE
| TCF_NO_SYNC_NEGO
)) == 0)
2484 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2485 return (tul_msgin_accept(pCurHcb
));
2489 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2491 if (tul_msgin_accept(pCurHcb
) != MSG_OUT
)
2492 return (pCurHcb
->HCS_Phase
);
2494 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_EXTEND
);
2495 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 2);
2496 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 3);
2497 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurHcb
->HCS_Msg
[2]);
2498 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2499 return (wait_tulip(pCurHcb
));
2502 /***************************************************************************/
2503 int tul_msgin_sync(HCS
* pCurHcb
)
2505 char default_period
;
2507 default_period
= tul_rate_tbl
[pCurHcb
->HCS_ActTcs
->TCS_Flags
& TCF_SCSI_RATE
];
2508 if (pCurHcb
->HCS_Msg
[3] > MAX_OFFSET
) {
2509 pCurHcb
->HCS_Msg
[3] = MAX_OFFSET
;
2510 if (pCurHcb
->HCS_Msg
[2] < default_period
) {
2511 pCurHcb
->HCS_Msg
[2] = default_period
;
2514 if (pCurHcb
->HCS_Msg
[2] >= 59) { /* Change to async */
2515 pCurHcb
->HCS_Msg
[3] = 0;
2519 /* offset requests asynchronous transfers ? */
2520 if (pCurHcb
->HCS_Msg
[3] == 0) {
2523 if (pCurHcb
->HCS_Msg
[2] < default_period
) {
2524 pCurHcb
->HCS_Msg
[2] = default_period
;
2527 if (pCurHcb
->HCS_Msg
[2] >= 59) {
2528 pCurHcb
->HCS_Msg
[3] = 0;
2535 /***************************************************************************/
2536 int wdtr_done(HCS
* pCurHcb
)
2538 pCurHcb
->HCS_ActTcs
->TCS_Flags
&= ~TCF_SYNC_DONE
;
2539 pCurHcb
->HCS_ActTcs
->TCS_Flags
|= TCF_WDTR_DONE
;
2541 pCurHcb
->HCS_ActTcs
->TCS_JS_Period
= 0;
2542 if (pCurHcb
->HCS_Msg
[2]) { /* if 16 bit */
2543 pCurHcb
->HCS_ActTcs
->TCS_JS_Period
|= TSC_WIDE_SCSI
;
2545 pCurHcb
->HCS_ActTcs
->TCS_SConfig0
&= ~TSC_ALT_PERIOD
;
2546 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurHcb
->HCS_ActTcs
->TCS_SConfig0
);
2547 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SPeriod
, pCurHcb
->HCS_ActTcs
->TCS_JS_Period
);
2552 /***************************************************************************/
2553 int tul_sync_done(HCS
* pCurHcb
)
2557 pCurHcb
->HCS_ActTcs
->TCS_Flags
|= TCF_SYNC_DONE
;
2559 if (pCurHcb
->HCS_Msg
[3]) {
2560 pCurHcb
->HCS_ActTcs
->TCS_JS_Period
|= pCurHcb
->HCS_Msg
[3];
2561 for (i
= 0; i
< 8; i
++) {
2562 if (tul_rate_tbl
[i
] >= pCurHcb
->HCS_Msg
[2]) /* pick the big one */
2565 pCurHcb
->HCS_ActTcs
->TCS_JS_Period
|= (i
<< 4);
2566 pCurHcb
->HCS_ActTcs
->TCS_SConfig0
|= TSC_ALT_PERIOD
;
2568 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurHcb
->HCS_ActTcs
->TCS_SConfig0
);
2569 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SPeriod
, pCurHcb
->HCS_ActTcs
->TCS_JS_Period
);
2575 int tul_post_scsi_rst(HCS
* pCurHcb
)
2581 pCurHcb
->HCS_ActScb
= 0;
2582 pCurHcb
->HCS_ActTcs
= 0;
2583 pCurHcb
->HCS_Flags
= 0;
2585 while ((pCurScb
= tul_pop_busy_scb(pCurHcb
)) != NULL
) {
2586 pCurScb
->SCB_HaStat
= HOST_BAD_PHAS
;
2587 tul_append_done_scb(pCurHcb
, pCurScb
);
2589 /* clear sync done flag */
2590 pCurTcb
= &pCurHcb
->HCS_Tcs
[0];
2591 for (i
= 0; i
< pCurHcb
->HCS_MaxTar
; pCurTcb
++, i
++) {
2592 pCurTcb
->TCS_Flags
&= ~(TCF_SYNC_DONE
| TCF_WDTR_DONE
);
2593 /* Initialize the sync. xfer register values to an asyn xfer */
2594 pCurTcb
->TCS_JS_Period
= 0;
2595 pCurTcb
->TCS_SConfig0
= pCurHcb
->HCS_SConf1
;
2596 pCurHcb
->HCS_ActTags
[0] = 0; /* 07/22/98 */
2597 pCurHcb
->HCS_Tcs
[i
].TCS_Flags
&= ~TCF_BUSY
; /* 07/22/98 */
2603 /***************************************************************************/
2604 void tul_select_atn_stop(HCS
* pCurHcb
, SCB
* pCurScb
)
2606 pCurScb
->SCB_Status
|= SCB_SELECT
;
2607 pCurScb
->SCB_NxtStat
= 0x1;
2608 pCurHcb
->HCS_ActScb
= pCurScb
;
2609 pCurHcb
->HCS_ActTcs
= &pCurHcb
->HCS_Tcs
[pCurScb
->SCB_Target
];
2610 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_SELATNSTOP
);
2615 /***************************************************************************/
2616 void tul_select_atn(HCS
* pCurHcb
, SCB
* pCurScb
)
2620 pCurScb
->SCB_Status
|= SCB_SELECT
;
2621 pCurScb
->SCB_NxtStat
= 0x2;
2623 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_Ident
);
2624 for (i
= 0; i
< (int) pCurScb
->SCB_CDBLen
; i
++)
2625 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_CDB
[i
]);
2626 pCurHcb
->HCS_ActTcs
= &pCurHcb
->HCS_Tcs
[pCurScb
->SCB_Target
];
2627 pCurHcb
->HCS_ActScb
= pCurScb
;
2628 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_SEL_ATN
);
2632 /***************************************************************************/
2633 void tul_select_atn3(HCS
* pCurHcb
, SCB
* pCurScb
)
2637 pCurScb
->SCB_Status
|= SCB_SELECT
;
2638 pCurScb
->SCB_NxtStat
= 0x2;
2640 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_Ident
);
2641 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_TagMsg
);
2642 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_TagId
);
2643 for (i
= 0; i
< (int) pCurScb
->SCB_CDBLen
; i
++)
2644 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_CDB
[i
]);
2645 pCurHcb
->HCS_ActTcs
= &pCurHcb
->HCS_Tcs
[pCurScb
->SCB_Target
];
2646 pCurHcb
->HCS_ActScb
= pCurScb
;
2647 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_SEL_ATN3
);
2651 /***************************************************************************/
2652 /* SCSI Bus Device Reset */
2653 int tul_bus_device_reset(HCS
* pCurHcb
)
2655 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
2656 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
2657 SCB
*pTmpScb
, *pPrevScb
;
2660 if (pCurHcb
->HCS_Phase
!= MSG_OUT
) {
2661 return (int_tul_bad_seq(pCurHcb
)); /* Unexpected phase */
2663 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
2664 tul_release_scb(pCurHcb
, pCurScb
);
2667 tar
= pCurScb
->SCB_Target
; /* target */
2668 pCurTcb
->TCS_Flags
&= ~(TCF_SYNC_DONE
| TCF_WDTR_DONE
| TCF_BUSY
);
2669 /* clr sync. nego & WDTR flags 07/22/98 */
2671 /* abort all SCB with same target */
2672 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstBusy
; /* Check Busy queue */
2673 while (pTmpScb
!= NULL
) {
2675 if (pTmpScb
->SCB_Target
== tar
) {
2677 if (pTmpScb
== pCurHcb
->HCS_FirstBusy
) {
2678 if ((pCurHcb
->HCS_FirstBusy
= pTmpScb
->SCB_NxtScb
) == NULL
)
2679 pCurHcb
->HCS_LastBusy
= NULL
;
2681 pPrevScb
->SCB_NxtScb
= pTmpScb
->SCB_NxtScb
;
2682 if (pTmpScb
== pCurHcb
->HCS_LastBusy
)
2683 pCurHcb
->HCS_LastBusy
= pPrevScb
;
2685 pTmpScb
->SCB_HaStat
= HOST_ABORTED
;
2686 tul_append_done_scb(pCurHcb
, pTmpScb
);
2688 /* Previous haven't change */
2692 pTmpScb
= pTmpScb
->SCB_NxtScb
;
2695 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_DEVRST
);
2696 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2698 return tul_wait_disc(pCurHcb
);
2702 /***************************************************************************/
2703 int tul_msgin_accept(HCS
* pCurHcb
)
2705 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_MSG_ACCEPT
);
2706 return (wait_tulip(pCurHcb
));
2709 /***************************************************************************/
2710 int wait_tulip(HCS
* pCurHcb
)
2713 while (!((pCurHcb
->HCS_JSStatus0
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus0
))
2714 & TSS_INT_PENDING
));
2716 pCurHcb
->HCS_JSInt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
);
2717 pCurHcb
->HCS_Phase
= pCurHcb
->HCS_JSStatus0
& TSS_PH_MASK
;
2718 pCurHcb
->HCS_JSStatus1
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus1
);
2720 if (pCurHcb
->HCS_JSInt
& TSS_RESEL_INT
) { /* if SCSI bus reset detected */
2721 return (int_tul_resel(pCurHcb
));
2723 if (pCurHcb
->HCS_JSInt
& TSS_SEL_TIMEOUT
) { /* if selected/reselected timeout interrupt */
2724 return (int_tul_busfree(pCurHcb
));
2726 if (pCurHcb
->HCS_JSInt
& TSS_SCSIRST_INT
) { /* if SCSI bus reset detected */
2727 return (int_tul_scsi_rst(pCurHcb
));
2729 if (pCurHcb
->HCS_JSInt
& TSS_DISC_INT
) { /* BUS disconnection */
2730 if (pCurHcb
->HCS_Flags
& HCF_EXPECT_DONE_DISC
) {
2731 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
); /* Flush SCSI FIFO */
2732 tul_unlink_busy_scb(pCurHcb
, pCurHcb
->HCS_ActScb
);
2733 pCurHcb
->HCS_ActScb
->SCB_HaStat
= 0;
2734 tul_append_done_scb(pCurHcb
, pCurHcb
->HCS_ActScb
);
2735 pCurHcb
->HCS_ActScb
= NULL
;
2736 pCurHcb
->HCS_ActTcs
= NULL
;
2737 pCurHcb
->HCS_Flags
&= ~HCF_EXPECT_DONE_DISC
;
2738 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, TSC_INITDEFAULT
);
2739 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
); /* Enable HW reselect */
2742 if (pCurHcb
->HCS_Flags
& HCF_EXPECT_DISC
) {
2743 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
); /* Flush SCSI FIFO */
2744 pCurHcb
->HCS_ActScb
= NULL
;
2745 pCurHcb
->HCS_ActTcs
= NULL
;
2746 pCurHcb
->HCS_Flags
&= ~HCF_EXPECT_DISC
;
2747 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, TSC_INITDEFAULT
);
2748 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
); /* Enable HW reselect */
2751 return (int_tul_busfree(pCurHcb
));
2753 if (pCurHcb
->HCS_JSInt
& (TSS_FUNC_COMP
| TSS_BUS_SERV
)) {
2754 return (pCurHcb
->HCS_Phase
);
2756 return (pCurHcb
->HCS_Phase
);
2758 /***************************************************************************/
2759 int tul_wait_disc(HCS
* pCurHcb
)
2762 while (!((pCurHcb
->HCS_JSStatus0
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus0
))
2763 & TSS_INT_PENDING
));
2766 pCurHcb
->HCS_JSInt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
);
2768 if (pCurHcb
->HCS_JSInt
& TSS_SCSIRST_INT
) { /* if SCSI bus reset detected */
2769 return (int_tul_scsi_rst(pCurHcb
));
2771 if (pCurHcb
->HCS_JSInt
& TSS_DISC_INT
) { /* BUS disconnection */
2772 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
); /* Flush SCSI FIFO */
2773 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, TSC_INITDEFAULT
);
2774 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
); /* Enable HW reselect */
2775 pCurHcb
->HCS_ActScb
= NULL
;
2778 return (tul_bad_seq(pCurHcb
));
2781 /***************************************************************************/
2782 int tul_wait_done_disc(HCS
* pCurHcb
)
2786 while (!((pCurHcb
->HCS_JSStatus0
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus0
))
2787 & TSS_INT_PENDING
));
2789 pCurHcb
->HCS_JSInt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
);
2792 if (pCurHcb
->HCS_JSInt
& TSS_SCSIRST_INT
) { /* if SCSI bus reset detected */
2793 return (int_tul_scsi_rst(pCurHcb
));
2795 if (pCurHcb
->HCS_JSInt
& TSS_DISC_INT
) { /* BUS disconnection */
2796 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
); /* Flush SCSI FIFO */
2797 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, TSC_INITDEFAULT
);
2798 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
); /* Enable HW reselect */
2799 tul_unlink_busy_scb(pCurHcb
, pCurHcb
->HCS_ActScb
);
2801 tul_append_done_scb(pCurHcb
, pCurHcb
->HCS_ActScb
);
2802 pCurHcb
->HCS_ActScb
= NULL
;
2805 return (tul_bad_seq(pCurHcb
));
2808 /**************************** EOF *********************************/