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 General 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
82 #include <linux/jiffies.h>
83 #include <linux/delay.h>
84 #include <linux/blkdev.h>
89 /*--- external functions --*/
90 static void tul_se2_wait(void);
92 /*--- forward refrence ---*/
93 static SCB
*tul_find_busy_scb(HCS
* pCurHcb
, WORD tarlun
);
94 static SCB
*tul_find_done_scb(HCS
* pCurHcb
);
96 static int tulip_main(HCS
* pCurHcb
);
98 static int tul_next_state(HCS
* pCurHcb
);
99 static int tul_state_1(HCS
* pCurHcb
);
100 static int tul_state_2(HCS
* pCurHcb
);
101 static int tul_state_3(HCS
* pCurHcb
);
102 static int tul_state_4(HCS
* pCurHcb
);
103 static int tul_state_5(HCS
* pCurHcb
);
104 static int tul_state_6(HCS
* pCurHcb
);
105 static int tul_state_7(HCS
* pCurHcb
);
106 static int tul_xfer_data_in(HCS
* pCurHcb
);
107 static int tul_xfer_data_out(HCS
* pCurHcb
);
108 static int tul_xpad_in(HCS
* pCurHcb
);
109 static int tul_xpad_out(HCS
* pCurHcb
);
110 static int tul_status_msg(HCS
* pCurHcb
);
112 static int tul_msgin(HCS
* pCurHcb
);
113 static int tul_msgin_sync(HCS
* pCurHcb
);
114 static int tul_msgin_accept(HCS
* pCurHcb
);
115 static int tul_msgout_reject(HCS
* pCurHcb
);
116 static int tul_msgin_extend(HCS
* pCurHcb
);
118 static int tul_msgout_ide(HCS
* pCurHcb
);
119 static int tul_msgout_abort_targ(HCS
* pCurHcb
);
120 static int tul_msgout_abort_tag(HCS
* pCurHcb
);
122 static int tul_bus_device_reset(HCS
* pCurHcb
);
123 static void tul_select_atn(HCS
* pCurHcb
, SCB
* pCurScb
);
124 static void tul_select_atn3(HCS
* pCurHcb
, SCB
* pCurScb
);
125 static void tul_select_atn_stop(HCS
* pCurHcb
, SCB
* pCurScb
);
126 static int int_tul_busfree(HCS
* pCurHcb
);
127 int int_tul_scsi_rst(HCS
* pCurHcb
);
128 static int int_tul_bad_seq(HCS
* pCurHcb
);
129 static int int_tul_resel(HCS
* pCurHcb
);
130 static int tul_sync_done(HCS
* pCurHcb
);
131 static int wdtr_done(HCS
* pCurHcb
);
132 static int wait_tulip(HCS
* pCurHcb
);
133 static int tul_wait_done_disc(HCS
* pCurHcb
);
134 static int tul_wait_disc(HCS
* pCurHcb
);
135 static void tulip_scsi(HCS
* pCurHcb
);
136 static int tul_post_scsi_rst(HCS
* pCurHcb
);
138 static void tul_se2_ew_en(WORD CurBase
);
139 static void tul_se2_ew_ds(WORD CurBase
);
140 static int tul_se2_rd_all(WORD CurBase
);
141 static void tul_se2_update_all(WORD CurBase
); /* setup default pattern */
142 static void tul_read_eeprom(WORD CurBase
);
144 /* ---- EXTERNAL VARIABLES ---- */
145 HCS tul_hcs
[MAX_SUPPORTED_ADAPTERS
];
146 /* ---- INTERNAL VARIABLES ---- */
147 static INI_ADPT_STRUCT i91u_adpt
[MAX_SUPPORTED_ADAPTERS
];
149 /*NVRAM nvram, *nvramp = &nvram; */
150 static NVRAM i91unvram
;
151 static NVRAM
*i91unvramp
;
155 static UCHAR i91udftNvRam
[64] =
157 /*----------- header -----------*/
158 0x25, 0xc9, /* Signature */
161 /* -- Host Adapter Structure -- */
162 0x95, /* ModelByte0 */
163 0x00, /* ModelByte1 */
164 0x00, /* ModelInfo */
166 NBC1_DEFAULT
, /* BIOSConfig1 */
170 /* SCSI channel 0 and target Structure */
172 NCC1_DEFAULT
, /* SCSIconfig1 */
174 0x10, /* NumSCSItarget */
176 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
177 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
178 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
179 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
181 /* SCSI channel 1 and target Structure */
183 NCC1_DEFAULT
, /* SCSIconfig1 */
185 0x10, /* NumSCSItarget */
187 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
188 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
189 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
190 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
191 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
192 0, 0}; /* - CheckSum - */
195 static UCHAR tul_rate_tbl
[8] = /* fast 20 */
197 /* nanosecond devide by 4 */
199 18, /* 75ns, 13.3M */
202 37, /* 150ns, 6.6M */
203 43, /* 175ns, 5.7M */
208 extern int tul_num_ch
;
211 static void tul_do_pause(unsigned amount
)
212 { /* Pause for amount jiffies */
213 unsigned long the_time
= jiffies
+ amount
;
215 while (time_before_eq(jiffies
, the_time
));
218 /*-- forward reference --*/
220 /*******************************************************************
221 Use memeory refresh time ~ 15us * 2
222 ********************************************************************/
230 readByte
= TUL_RD(0, 0x61);
231 if ((readByte
& 0x10) == 0x10) {
233 readByte
= TUL_RD(0, 0x61);
234 if ((readByte
& 0x10) == 0x10)
238 readByte
= TUL_RD(0, 0x61);
239 if ((readByte
& 0x10) != 0x10)
244 readByte
= TUL_RD(0, 0x61);
245 if ((readByte
& 0x10) == 0x10)
249 readByte
= TUL_RD(0, 0x61);
250 if ((readByte
& 0x10) != 0x10)
258 /******************************************************************
259 Input: instruction for Serial E2PROM
261 EX: se2_rd(0 call se2_instr() to send address and read command
263 StartBit OP_Code Address Data
264 --------- -------- ------------------ -------
265 1 1 , 0 A5,A4,A3,A2,A1,A0 D15-D0
267 +-----------------------------------------------------
270 +--+ +--+ +--+ +--+ +--+
273 CLK -------+ +--+ +--+ +--+ +--+ +--
274 (leading edge trigger)
278 DI ----+ +--0------------------
279 (address and cmd sent to nvram)
281 -------------------------------------------+
284 (data sent from nvram)
287 ******************************************************************/
288 void tul_se2_instr(WORD CurBase
, UCHAR instr
)
293 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2DO
); /* cs+start bit */
295 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2CLK
| SE2DO
); /* +CLK */
298 for (i
= 0; i
< 8; i
++) {
300 b
= SE2CS
| SE2DO
; /* -CLK+dataBit */
302 b
= SE2CS
; /* -CLK */
303 TUL_WR(CurBase
+ TUL_NVRAM
, b
);
305 TUL_WR(CurBase
+ TUL_NVRAM
, b
| SE2CLK
); /* +CLK */
309 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* -CLK */
315 /******************************************************************
316 Function name : tul_se2_ew_en
317 Description : Enable erase/write state of serial EEPROM
318 ******************************************************************/
319 void tul_se2_ew_en(WORD CurBase
)
321 tul_se2_instr(CurBase
, 0x30); /* EWEN */
322 TUL_WR(CurBase
+ TUL_NVRAM
, 0); /* -CS */
328 /************************************************************************
329 Disable erase/write state of serial EEPROM
330 *************************************************************************/
331 void tul_se2_ew_ds(WORD CurBase
)
333 tul_se2_instr(CurBase
, 0); /* EWDS */
334 TUL_WR(CurBase
+ TUL_NVRAM
, 0); /* -CS */
340 /******************************************************************
341 Input :address of Serial E2PROM
342 Output :value stored in Serial E2PROM
343 *******************************************************************/
344 USHORT
tul_se2_rd(WORD CurBase
, ULONG adr
)
346 UCHAR instr
, readByte
;
350 instr
= (UCHAR
) (adr
| 0x80);
351 tul_se2_instr(CurBase
, instr
); /* READ INSTR */
354 for (i
= 15; i
>= 0; i
--) {
355 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2CLK
); /* +CLK */
357 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* -CLK */
359 /* sample data after the following edge of clock */
360 readByte
= TUL_RD(CurBase
, TUL_NVRAM
);
362 readWord
+= (readByte
<< i
);
363 tul_se2_wait(); /* 6/20/95 */
366 TUL_WR(CurBase
+ TUL_NVRAM
, 0); /* no chip select */
372 /******************************************************************
373 Input: new value in Serial E2PROM, address of Serial E2PROM
374 *******************************************************************/
375 void tul_se2_wr(WORD CurBase
, UCHAR adr
, USHORT writeWord
)
381 instr
= (UCHAR
) (adr
| 0x40);
382 tul_se2_instr(CurBase
, instr
); /* WRITE INSTR */
383 for (i
= 15; i
>= 0; i
--) {
384 if (writeWord
& 0x8000)
385 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2DO
); /* -CLK+dataBit 1 */
387 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* -CLK+dataBit 0 */
389 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2CLK
); /* +CLK */
393 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* -CLK */
395 TUL_WR(CurBase
+ TUL_NVRAM
, 0); /* -CS */
398 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* +CS */
402 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2CLK
); /* +CLK */
404 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* -CLK */
406 if ((readByte
= TUL_RD(CurBase
, TUL_NVRAM
)) & SE2DI
)
407 break; /* write complete */
409 TUL_WR(CurBase
+ TUL_NVRAM
, 0); /* -CS */
414 /***********************************************************************
415 Read SCSI H/A configuration parameters from serial EEPROM
416 ************************************************************************/
417 int tul_se2_rd_all(WORD CurBase
)
423 i91unvramp
= &i91unvram
;
424 np
= (USHORT
*) i91unvramp
;
425 for (i
= 0; i
< 32; i
++) {
426 *np
++ = tul_se2_rd(CurBase
, i
);
429 /*--------------------Is signature "ini" ok ? ----------------*/
430 if (i91unvramp
->NVM_Signature
!= INI_SIGNATURE
)
432 /*---------------------- Is ckecksum ok ? ----------------------*/
433 np
= (USHORT
*) i91unvramp
;
434 for (i
= 0; i
< 31; i
++)
436 if (i91unvramp
->NVM_CheckSum
!= (USHORT
) chksum
)
442 /***********************************************************************
443 Update SCSI H/A configuration parameters from serial EEPROM
444 ************************************************************************/
445 void tul_se2_update_all(WORD CurBase
)
446 { /* setup default pattern */
451 i91unvramp
= &i91unvram
;
452 /* Calculate checksum first */
453 np
= (USHORT
*) i91udftNvRam
;
454 for (i
= 0; i
< 31; i
++)
456 *np
= (USHORT
) chksum
;
457 tul_se2_ew_en(CurBase
); /* Enable write */
459 np
= (USHORT
*) i91udftNvRam
;
460 np1
= (USHORT
*) i91unvramp
;
461 for (i
= 0; i
< 32; i
++, np
++, np1
++) {
463 tul_se2_wr(CurBase
, i
, *np
);
467 tul_se2_ew_ds(CurBase
); /* Disable write */
471 /*************************************************************************
472 Function name : read_eeprom
473 **************************************************************************/
474 void tul_read_eeprom(WORD CurBase
)
478 i91unvramp
= &i91unvram
;
479 /*------Enable EEProm programming ---*/
480 gctrl
= TUL_RD(CurBase
, TUL_GCTRL
);
481 TUL_WR(CurBase
+ TUL_GCTRL
, gctrl
| TUL_GCTRL_EEPROM_BIT
);
482 if (tul_se2_rd_all(CurBase
) != 1) {
483 tul_se2_update_all(CurBase
); /* setup default pattern */
484 tul_se2_rd_all(CurBase
); /* load again */
486 /*------ Disable EEProm programming ---*/
487 gctrl
= TUL_RD(CurBase
, TUL_GCTRL
);
488 TUL_WR(CurBase
+ TUL_GCTRL
, gctrl
& ~TUL_GCTRL_EEPROM_BIT
);
491 int Addi91u_into_Adapter_table(WORD wBIOS
, WORD wBASE
, BYTE bInterrupt
,
492 BYTE bBus
, BYTE bDevice
)
496 for (i
= 0; i
< MAX_SUPPORTED_ADAPTERS
; i
++) {
497 if (i91u_adpt
[i
].ADPT_BIOS
< wBIOS
)
499 if (i91u_adpt
[i
].ADPT_BIOS
== wBIOS
) {
500 if (i91u_adpt
[i
].ADPT_BASE
== wBASE
) {
501 if (i91u_adpt
[i
].ADPT_Bus
!= 0xFF)
503 } else if (i91u_adpt
[i
].ADPT_BASE
< wBASE
)
506 for (j
= MAX_SUPPORTED_ADAPTERS
- 1; j
> i
; j
--) {
507 i91u_adpt
[j
].ADPT_BASE
= i91u_adpt
[j
- 1].ADPT_BASE
;
508 i91u_adpt
[j
].ADPT_INTR
= i91u_adpt
[j
- 1].ADPT_INTR
;
509 i91u_adpt
[j
].ADPT_BIOS
= i91u_adpt
[j
- 1].ADPT_BIOS
;
510 i91u_adpt
[j
].ADPT_Bus
= i91u_adpt
[j
- 1].ADPT_Bus
;
511 i91u_adpt
[j
].ADPT_Device
= i91u_adpt
[j
- 1].ADPT_Device
;
513 i91u_adpt
[i
].ADPT_BASE
= wBASE
;
514 i91u_adpt
[i
].ADPT_INTR
= bInterrupt
;
515 i91u_adpt
[i
].ADPT_BIOS
= wBIOS
;
516 i91u_adpt
[i
].ADPT_Bus
= bBus
;
517 i91u_adpt
[i
].ADPT_Device
= bDevice
;
523 void init_i91uAdapter_table(void)
527 for (i
= 0; i
< MAX_SUPPORTED_ADAPTERS
; i
++) { /* Initialize adapter structure */
528 i91u_adpt
[i
].ADPT_BIOS
= 0xffff;
529 i91u_adpt
[i
].ADPT_BASE
= 0xffff;
530 i91u_adpt
[i
].ADPT_INTR
= 0xff;
531 i91u_adpt
[i
].ADPT_Bus
= 0xff;
532 i91u_adpt
[i
].ADPT_Device
= 0xff;
537 void tul_stop_bm(HCS
* pCurHcb
)
540 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_XStatus
) & XPEND
) { /* if DMA xfer is pending, abort DMA xfer */
541 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_X_ABT
| TAX_X_CLR_FIFO
);
542 /* wait Abort DMA xfer done */
543 while ((TUL_RD(pCurHcb
->HCS_Base
, TUL_Int
) & XABT
) == 0);
545 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
548 /***************************************************************************/
549 void get_tulipPCIConfig(HCS
* pCurHcb
, int ch_idx
)
551 pCurHcb
->HCS_Base
= i91u_adpt
[ch_idx
].ADPT_BASE
; /* Supply base address */
552 pCurHcb
->HCS_BIOS
= i91u_adpt
[ch_idx
].ADPT_BIOS
; /* Supply BIOS address */
553 pCurHcb
->HCS_Intr
= i91u_adpt
[ch_idx
].ADPT_INTR
; /* Supply interrupt line */
557 /***************************************************************************/
558 int tul_reset_scsi(HCS
* pCurHcb
, int seconds
)
560 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_RST_BUS
);
562 while (!((pCurHcb
->HCS_JSInt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
)) & TSS_SCSIRST_INT
));
563 /* reset tulip chip */
565 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, 0);
567 /* Stall for a while, wait for target's firmware ready,make it 2 sec ! */
568 /* SONY 5200 tape drive won't work if only stall for 1 sec */
569 tul_do_pause(seconds
* HZ
);
571 TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
);
573 return (SCSI_RESET_SUCCESS
);
576 /***************************************************************************/
577 int init_tulip(HCS
* pCurHcb
, SCB
* scbp
, int tul_num_scb
, BYTE
* pbBiosAdr
, int seconds
)
582 SCB
*pTmpScb
, *pPrevScb
= NULL
;
584 pCurHcb
->HCS_NumScbs
= tul_num_scb
;
585 pCurHcb
->HCS_Semaph
= 1;
586 pCurHcb
->HCS_SemaphLock
= SPIN_LOCK_UNLOCKED
;
587 pCurHcb
->HCS_JSStatus0
= 0;
588 pCurHcb
->HCS_Scb
= scbp
;
589 pCurHcb
->HCS_NxtPend
= scbp
;
590 pCurHcb
->HCS_NxtAvail
= scbp
;
591 for (i
= 0, pTmpScb
= scbp
; i
< tul_num_scb
; i
++, pTmpScb
++) {
592 pTmpScb
->SCB_TagId
= i
;
594 pPrevScb
->SCB_NxtScb
= pTmpScb
;
597 pPrevScb
->SCB_NxtScb
= NULL
;
598 pCurHcb
->HCS_ScbEnd
= pTmpScb
;
599 pCurHcb
->HCS_FirstAvail
= scbp
;
600 pCurHcb
->HCS_LastAvail
= pPrevScb
;
601 pCurHcb
->HCS_AvailLock
= SPIN_LOCK_UNLOCKED
;
602 pCurHcb
->HCS_FirstPend
= NULL
;
603 pCurHcb
->HCS_LastPend
= NULL
;
604 pCurHcb
->HCS_FirstBusy
= NULL
;
605 pCurHcb
->HCS_LastBusy
= NULL
;
606 pCurHcb
->HCS_FirstDone
= NULL
;
607 pCurHcb
->HCS_LastDone
= NULL
;
608 pCurHcb
->HCS_ActScb
= NULL
;
609 pCurHcb
->HCS_ActTcs
= NULL
;
611 tul_read_eeprom(pCurHcb
->HCS_Base
);
612 /*---------- get H/A configuration -------------*/
613 if (i91unvramp
->NVM_SCSIInfo
[0].NVM_NumOfTarg
== 8)
614 pCurHcb
->HCS_MaxTar
= 8;
616 pCurHcb
->HCS_MaxTar
= 16;
618 pCurHcb
->HCS_Config
= i91unvramp
->NVM_SCSIInfo
[0].NVM_ChConfig1
;
620 pCurHcb
->HCS_SCSI_ID
= i91unvramp
->NVM_SCSIInfo
[0].NVM_ChSCSIID
;
621 pCurHcb
->HCS_IdMask
= ~(1 << pCurHcb
->HCS_SCSI_ID
);
624 /* Enable parity error response */
625 TUL_WR(pCurHcb
->HCS_Base
+ TUL_PCMD
, TUL_RD(pCurHcb
->HCS_Base
, TUL_PCMD
) | 0x40);
628 /* Mask all the interrupt */
629 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
631 tul_stop_bm(pCurHcb
);
632 /* --- Initialize the tulip --- */
633 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_RST_CHIP
);
635 /* program HBA's SCSI ID */
636 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SScsiId
, pCurHcb
->HCS_SCSI_ID
<< 4);
638 /* Enable Initiator Mode ,phase latch,alternate sync period mode,
639 disable SCSI reset */
640 if (pCurHcb
->HCS_Config
& HCC_EN_PAR
)
641 pCurHcb
->HCS_SConf1
= (TSC_INITDEFAULT
| TSC_EN_SCSI_PAR
);
643 pCurHcb
->HCS_SConf1
= (TSC_INITDEFAULT
);
644 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurHcb
->HCS_SConf1
);
646 /* Enable HW reselect */
647 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
);
649 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SPeriod
, 0);
651 /* selection time out = 250 ms */
652 TUL_WR(pCurHcb
->HCS_Base
+ TUL_STimeOut
, 153);
654 /*--------- Enable SCSI terminator -----*/
655 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCtrl
, (pCurHcb
->HCS_Config
& (HCC_ACT_TERM1
| HCC_ACT_TERM2
)));
656 TUL_WR(pCurHcb
->HCS_Base
+ TUL_GCTRL1
,
657 ((pCurHcb
->HCS_Config
& HCC_AUTO_TERM
) >> 4) | (TUL_RD(pCurHcb
->HCS_Base
, TUL_GCTRL1
) & 0xFE));
660 pwFlags
= & (i91unvramp
->NVM_SCSIInfo
[0].NVM_Targ0Config
),
661 pbHeads
= pbBiosAdr
+ 0x180;
662 i
< pCurHcb
->HCS_MaxTar
;
664 pCurHcb
->HCS_Tcs
[i
].TCS_Flags
= *pwFlags
& ~(TCF_SYNC_DONE
| TCF_WDTR_DONE
);
665 if (pCurHcb
->HCS_Tcs
[i
].TCS_Flags
& TCF_EN_255
)
666 pCurHcb
->HCS_Tcs
[i
].TCS_DrvFlags
= TCF_DRV_255_63
;
668 pCurHcb
->HCS_Tcs
[i
].TCS_DrvFlags
= 0;
669 pCurHcb
->HCS_Tcs
[i
].TCS_JS_Period
= 0;
670 pCurHcb
->HCS_Tcs
[i
].TCS_SConfig0
= pCurHcb
->HCS_SConf1
;
671 pCurHcb
->HCS_Tcs
[i
].TCS_DrvHead
= *pbHeads
++;
672 if (pCurHcb
->HCS_Tcs
[i
].TCS_DrvHead
== 255)
673 pCurHcb
->HCS_Tcs
[i
].TCS_DrvFlags
= TCF_DRV_255_63
;
675 pCurHcb
->HCS_Tcs
[i
].TCS_DrvFlags
= 0;
676 pCurHcb
->HCS_Tcs
[i
].TCS_DrvSector
= *pbHeads
++;
677 pCurHcb
->HCS_Tcs
[i
].TCS_Flags
&= ~TCF_BUSY
;
678 pCurHcb
->HCS_ActTags
[i
] = 0;
679 pCurHcb
->HCS_MaxTags
[i
] = 0xFF;
681 printk("i91u: PCI Base=0x%04X, IRQ=%d, BIOS=0x%04X0, SCSI ID=%d\n",
682 pCurHcb
->HCS_Base
, pCurHcb
->HCS_Intr
,
683 pCurHcb
->HCS_BIOS
, pCurHcb
->HCS_SCSI_ID
);
684 /*------------------- reset SCSI Bus ---------------------------*/
685 if (pCurHcb
->HCS_Config
& HCC_SCSI_RESET
) {
686 printk("i91u: Reset SCSI Bus ... \n");
687 tul_reset_scsi(pCurHcb
, seconds
);
689 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCFG1
, 0x17);
690 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SIntEnable
, 0xE9);
694 /***************************************************************************/
695 SCB
*tul_alloc_scb(HCS
* hcsp
)
699 spin_lock_irqsave(&(hcsp
->HCS_AvailLock
), flags
);
700 if ((pTmpScb
= hcsp
->HCS_FirstAvail
) != NULL
) {
702 printk("find scb at %08lx\n", (ULONG
) pTmpScb
);
704 if ((hcsp
->HCS_FirstAvail
= pTmpScb
->SCB_NxtScb
) == NULL
)
705 hcsp
->HCS_LastAvail
= NULL
;
706 pTmpScb
->SCB_NxtScb
= NULL
;
707 pTmpScb
->SCB_Status
= SCB_RENT
;
709 spin_unlock_irqrestore(&(hcsp
->HCS_AvailLock
), flags
);
713 /***************************************************************************/
714 void tul_release_scb(HCS
* hcsp
, SCB
* scbp
)
719 printk("Release SCB %lx; ", (ULONG
) scbp
);
721 spin_lock_irqsave(&(hcsp
->HCS_AvailLock
), flags
);
723 scbp
->SCB_Status
= 0;
724 scbp
->SCB_NxtScb
= NULL
;
725 if (hcsp
->HCS_LastAvail
!= NULL
) {
726 hcsp
->HCS_LastAvail
->SCB_NxtScb
= scbp
;
727 hcsp
->HCS_LastAvail
= scbp
;
729 hcsp
->HCS_FirstAvail
= scbp
;
730 hcsp
->HCS_LastAvail
= scbp
;
732 spin_unlock_irqrestore(&(hcsp
->HCS_AvailLock
), flags
);
735 /***************************************************************************/
736 void tul_append_pend_scb(HCS
* pCurHcb
, SCB
* scbp
)
740 printk("Append pend SCB %lx; ", (ULONG
) scbp
);
742 scbp
->SCB_Status
= SCB_PEND
;
743 scbp
->SCB_NxtScb
= NULL
;
744 if (pCurHcb
->HCS_LastPend
!= NULL
) {
745 pCurHcb
->HCS_LastPend
->SCB_NxtScb
= scbp
;
746 pCurHcb
->HCS_LastPend
= scbp
;
748 pCurHcb
->HCS_FirstPend
= scbp
;
749 pCurHcb
->HCS_LastPend
= scbp
;
753 /***************************************************************************/
754 void tul_push_pend_scb(HCS
* pCurHcb
, SCB
* scbp
)
758 printk("Push pend SCB %lx; ", (ULONG
) scbp
);
760 scbp
->SCB_Status
= SCB_PEND
;
761 if ((scbp
->SCB_NxtScb
= pCurHcb
->HCS_FirstPend
) != NULL
) {
762 pCurHcb
->HCS_FirstPend
= scbp
;
764 pCurHcb
->HCS_FirstPend
= scbp
;
765 pCurHcb
->HCS_LastPend
= scbp
;
769 /***************************************************************************/
770 SCB
*tul_find_first_pend_scb(HCS
* pCurHcb
)
775 pFirstPend
= pCurHcb
->HCS_FirstPend
;
776 while (pFirstPend
!= NULL
) {
777 if (pFirstPend
->SCB_Opcode
!= ExecSCSI
) {
780 if (pFirstPend
->SCB_TagMsg
== 0) {
781 if ((pCurHcb
->HCS_ActTags
[pFirstPend
->SCB_Target
] == 0) &&
782 !(pCurHcb
->HCS_Tcs
[pFirstPend
->SCB_Target
].TCS_Flags
& TCF_BUSY
)) {
786 if ((pCurHcb
->HCS_ActTags
[pFirstPend
->SCB_Target
] >=
787 pCurHcb
->HCS_MaxTags
[pFirstPend
->SCB_Target
]) |
788 (pCurHcb
->HCS_Tcs
[pFirstPend
->SCB_Target
].TCS_Flags
& TCF_BUSY
)) {
789 pFirstPend
= pFirstPend
->SCB_NxtScb
;
794 pFirstPend
= pFirstPend
->SCB_NxtScb
;
800 /***************************************************************************/
801 SCB
*tul_pop_pend_scb(HCS
* pCurHcb
)
805 if ((pTmpScb
= pCurHcb
->HCS_FirstPend
) != NULL
) {
806 if ((pCurHcb
->HCS_FirstPend
= pTmpScb
->SCB_NxtScb
) == NULL
)
807 pCurHcb
->HCS_LastPend
= NULL
;
808 pTmpScb
->SCB_NxtScb
= NULL
;
811 printk("Pop pend SCB %lx; ", (ULONG
) pTmpScb
);
817 /***************************************************************************/
818 void tul_unlink_pend_scb(HCS
* pCurHcb
, SCB
* pCurScb
)
820 SCB
*pTmpScb
, *pPrevScb
;
823 printk("unlink pend SCB %lx; ", (ULONG
) pCurScb
);
826 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstPend
;
827 while (pTmpScb
!= NULL
) {
828 if (pCurScb
== pTmpScb
) { /* Unlink this SCB */
829 if (pTmpScb
== pCurHcb
->HCS_FirstPend
) {
830 if ((pCurHcb
->HCS_FirstPend
= pTmpScb
->SCB_NxtScb
) == NULL
)
831 pCurHcb
->HCS_LastPend
= NULL
;
833 pPrevScb
->SCB_NxtScb
= pTmpScb
->SCB_NxtScb
;
834 if (pTmpScb
== pCurHcb
->HCS_LastPend
)
835 pCurHcb
->HCS_LastPend
= pPrevScb
;
837 pTmpScb
->SCB_NxtScb
= NULL
;
841 pTmpScb
= pTmpScb
->SCB_NxtScb
;
845 /***************************************************************************/
846 void tul_append_busy_scb(HCS
* pCurHcb
, SCB
* scbp
)
850 printk("append busy SCB %lx; ", (ULONG
) scbp
);
852 if (scbp
->SCB_TagMsg
)
853 pCurHcb
->HCS_ActTags
[scbp
->SCB_Target
]++;
855 pCurHcb
->HCS_Tcs
[scbp
->SCB_Target
].TCS_Flags
|= TCF_BUSY
;
856 scbp
->SCB_Status
= SCB_BUSY
;
857 scbp
->SCB_NxtScb
= NULL
;
858 if (pCurHcb
->HCS_LastBusy
!= NULL
) {
859 pCurHcb
->HCS_LastBusy
->SCB_NxtScb
= scbp
;
860 pCurHcb
->HCS_LastBusy
= scbp
;
862 pCurHcb
->HCS_FirstBusy
= scbp
;
863 pCurHcb
->HCS_LastBusy
= scbp
;
867 /***************************************************************************/
868 SCB
*tul_pop_busy_scb(HCS
* pCurHcb
)
873 if ((pTmpScb
= pCurHcb
->HCS_FirstBusy
) != NULL
) {
874 if ((pCurHcb
->HCS_FirstBusy
= pTmpScb
->SCB_NxtScb
) == NULL
)
875 pCurHcb
->HCS_LastBusy
= NULL
;
876 pTmpScb
->SCB_NxtScb
= NULL
;
877 if (pTmpScb
->SCB_TagMsg
)
878 pCurHcb
->HCS_ActTags
[pTmpScb
->SCB_Target
]--;
880 pCurHcb
->HCS_Tcs
[pTmpScb
->SCB_Target
].TCS_Flags
&= ~TCF_BUSY
;
883 printk("Pop busy SCB %lx; ", (ULONG
) pTmpScb
);
888 /***************************************************************************/
889 void tul_unlink_busy_scb(HCS
* pCurHcb
, SCB
* pCurScb
)
891 SCB
*pTmpScb
, *pPrevScb
;
894 printk("unlink busy SCB %lx; ", (ULONG
) pCurScb
);
897 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstBusy
;
898 while (pTmpScb
!= NULL
) {
899 if (pCurScb
== pTmpScb
) { /* Unlink this SCB */
900 if (pTmpScb
== pCurHcb
->HCS_FirstBusy
) {
901 if ((pCurHcb
->HCS_FirstBusy
= pTmpScb
->SCB_NxtScb
) == NULL
)
902 pCurHcb
->HCS_LastBusy
= NULL
;
904 pPrevScb
->SCB_NxtScb
= pTmpScb
->SCB_NxtScb
;
905 if (pTmpScb
== pCurHcb
->HCS_LastBusy
)
906 pCurHcb
->HCS_LastBusy
= pPrevScb
;
908 pTmpScb
->SCB_NxtScb
= NULL
;
909 if (pTmpScb
->SCB_TagMsg
)
910 pCurHcb
->HCS_ActTags
[pTmpScb
->SCB_Target
]--;
912 pCurHcb
->HCS_Tcs
[pTmpScb
->SCB_Target
].TCS_Flags
&= ~TCF_BUSY
;
916 pTmpScb
= pTmpScb
->SCB_NxtScb
;
921 /***************************************************************************/
922 SCB
*tul_find_busy_scb(HCS
* pCurHcb
, WORD tarlun
)
924 SCB
*pTmpScb
, *pPrevScb
;
928 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstBusy
;
929 while (pTmpScb
!= NULL
) {
930 scbp_tarlun
= (pTmpScb
->SCB_Lun
<< 8) | (pTmpScb
->SCB_Target
);
931 if (scbp_tarlun
== tarlun
) { /* Unlink this SCB */
935 pTmpScb
= pTmpScb
->SCB_NxtScb
;
938 printk("find busy SCB %lx; ", (ULONG
) pTmpScb
);
943 /***************************************************************************/
944 void tul_append_done_scb(HCS
* pCurHcb
, SCB
* scbp
)
948 printk("append done SCB %lx; ", (ULONG
) scbp
);
951 scbp
->SCB_Status
= SCB_DONE
;
952 scbp
->SCB_NxtScb
= NULL
;
953 if (pCurHcb
->HCS_LastDone
!= NULL
) {
954 pCurHcb
->HCS_LastDone
->SCB_NxtScb
= scbp
;
955 pCurHcb
->HCS_LastDone
= scbp
;
957 pCurHcb
->HCS_FirstDone
= scbp
;
958 pCurHcb
->HCS_LastDone
= scbp
;
962 /***************************************************************************/
963 SCB
*tul_find_done_scb(HCS
* pCurHcb
)
968 if ((pTmpScb
= pCurHcb
->HCS_FirstDone
) != NULL
) {
969 if ((pCurHcb
->HCS_FirstDone
= pTmpScb
->SCB_NxtScb
) == NULL
)
970 pCurHcb
->HCS_LastDone
= NULL
;
971 pTmpScb
->SCB_NxtScb
= NULL
;
974 printk("find done SCB %lx; ", (ULONG
) pTmpScb
);
979 /***************************************************************************/
980 int tul_abort_srb(HCS
* pCurHcb
, ULONG srbp
)
983 SCB
*pTmpScb
, *pPrevScb
;
985 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
987 if ((pCurHcb
->HCS_Semaph
== 0) && (pCurHcb
->HCS_ActScb
== NULL
)) {
988 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
989 /* disable Jasmin SCSI Int */
991 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
995 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
997 pCurHcb
->HCS_Semaph
= 1;
998 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1000 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1002 return SCSI_ABORT_SNOOZE
;
1004 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstPend
; /* Check Pend queue */
1005 while (pTmpScb
!= NULL
) {
1007 if (pTmpScb
->SCB_Srb
== (unsigned char *) srbp
) {
1008 if (pTmpScb
== pCurHcb
->HCS_ActScb
) {
1009 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1010 return SCSI_ABORT_BUSY
;
1011 } else if (pTmpScb
== pCurHcb
->HCS_FirstPend
) {
1012 if ((pCurHcb
->HCS_FirstPend
= pTmpScb
->SCB_NxtScb
) == NULL
)
1013 pCurHcb
->HCS_LastPend
= NULL
;
1015 pPrevScb
->SCB_NxtScb
= pTmpScb
->SCB_NxtScb
;
1016 if (pTmpScb
== pCurHcb
->HCS_LastPend
)
1017 pCurHcb
->HCS_LastPend
= pPrevScb
;
1019 pTmpScb
->SCB_HaStat
= HOST_ABORTED
;
1020 pTmpScb
->SCB_Flags
|= SCF_DONE
;
1021 if (pTmpScb
->SCB_Flags
& SCF_POST
)
1022 (*pTmpScb
->SCB_Post
) ((BYTE
*) pCurHcb
, (BYTE
*) pTmpScb
);
1023 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1024 return SCSI_ABORT_SUCCESS
;
1027 pTmpScb
= pTmpScb
->SCB_NxtScb
;
1030 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstBusy
; /* Check Busy queue */
1031 while (pTmpScb
!= NULL
) {
1033 if (pTmpScb
->SCB_Srb
== (unsigned char *) srbp
) {
1035 if (pTmpScb
== pCurHcb
->HCS_ActScb
) {
1036 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1037 return SCSI_ABORT_BUSY
;
1038 } else if (pTmpScb
->SCB_TagMsg
== 0) {
1039 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1040 return SCSI_ABORT_BUSY
;
1042 pCurHcb
->HCS_ActTags
[pTmpScb
->SCB_Target
]--;
1043 if (pTmpScb
== pCurHcb
->HCS_FirstBusy
) {
1044 if ((pCurHcb
->HCS_FirstBusy
= pTmpScb
->SCB_NxtScb
) == NULL
)
1045 pCurHcb
->HCS_LastBusy
= NULL
;
1047 pPrevScb
->SCB_NxtScb
= pTmpScb
->SCB_NxtScb
;
1048 if (pTmpScb
== pCurHcb
->HCS_LastBusy
)
1049 pCurHcb
->HCS_LastBusy
= pPrevScb
;
1051 pTmpScb
->SCB_NxtScb
= NULL
;
1054 pTmpScb
->SCB_HaStat
= HOST_ABORTED
;
1055 pTmpScb
->SCB_Flags
|= SCF_DONE
;
1056 if (pTmpScb
->SCB_Flags
& SCF_POST
)
1057 (*pTmpScb
->SCB_Post
) ((BYTE
*) pCurHcb
, (BYTE
*) pTmpScb
);
1058 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1059 return SCSI_ABORT_SUCCESS
;
1063 pTmpScb
= pTmpScb
->SCB_NxtScb
;
1065 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1066 return (SCSI_ABORT_NOT_RUNNING
);
1069 /***************************************************************************/
1070 int tul_bad_seq(HCS
* pCurHcb
)
1074 printk("tul_bad_seg c=%d\n", pCurHcb
->HCS_Index
);
1076 if ((pCurScb
= pCurHcb
->HCS_ActScb
) != NULL
) {
1077 tul_unlink_busy_scb(pCurHcb
, pCurScb
);
1078 pCurScb
->SCB_HaStat
= HOST_BAD_PHAS
;
1079 pCurScb
->SCB_TaStat
= 0;
1080 tul_append_done_scb(pCurHcb
, pCurScb
);
1082 tul_stop_bm(pCurHcb
);
1084 tul_reset_scsi(pCurHcb
, 8); /* 7/29/98 */
1086 return (tul_post_scsi_rst(pCurHcb
));
1089 /************************************************************************/
1090 int tul_device_reset(HCS
* pCurHcb
, ULONG pSrb
, unsigned int target
, unsigned int ResetFlags
)
1094 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1096 if (ResetFlags
& SCSI_RESET_ASYNCHRONOUS
) {
1098 if ((pCurHcb
->HCS_Semaph
== 0) && (pCurHcb
->HCS_ActScb
== NULL
)) {
1099 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1100 /* disable Jasmin SCSI Int */
1102 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1104 tulip_main(pCurHcb
);
1106 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1108 pCurHcb
->HCS_Semaph
= 1;
1109 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1111 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1113 return SCSI_RESET_SNOOZE
;
1115 pScb
= pCurHcb
->HCS_FirstBusy
; /* Check Busy queue */
1116 while (pScb
!= NULL
) {
1117 if (pScb
->SCB_Srb
== (unsigned char *) pSrb
)
1119 pScb
= pScb
->SCB_NxtScb
;
1122 printk("Unable to Reset - No SCB Found\n");
1124 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1125 return SCSI_RESET_NOT_RUNNING
;
1128 if ((pScb
= tul_alloc_scb(pCurHcb
)) == NULL
) {
1129 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1130 return SCSI_RESET_NOT_RUNNING
;
1132 pScb
->SCB_Opcode
= BusDevRst
;
1133 pScb
->SCB_Flags
= SCF_POST
;
1134 pScb
->SCB_Target
= target
;
1138 if (ResetFlags
& SCSI_RESET_SYNCHRONOUS
) {
1139 pScb
->SCB_Srb
= (unsigned char *) pSrb
;
1141 tul_push_pend_scb(pCurHcb
, pScb
); /* push this SCB to Pending queue */
1143 if (pCurHcb
->HCS_Semaph
== 1) {
1144 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1145 /* disable Jasmin SCSI Int */
1146 pCurHcb
->HCS_Semaph
= 0;
1148 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1150 tulip_main(pCurHcb
);
1152 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1154 pCurHcb
->HCS_Semaph
= 1;
1155 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1157 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1158 return SCSI_RESET_PENDING
;
1161 int tul_reset_scsi_bus(HCS
* pCurHcb
)
1165 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1166 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1167 pCurHcb
->HCS_Semaph
= 0;
1169 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1171 tul_stop_bm(pCurHcb
);
1173 tul_reset_scsi(pCurHcb
, 2); /* 7/29/98 */
1175 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1176 tul_post_scsi_rst(pCurHcb
);
1178 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1180 tulip_main(pCurHcb
);
1182 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1184 pCurHcb
->HCS_Semaph
= 1;
1185 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1186 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1187 return (SCSI_RESET_SUCCESS
| SCSI_RESET_HOST_RESET
);
1190 /************************************************************************/
1191 void tul_exec_scb(HCS
* pCurHcb
, SCB
* pCurScb
)
1195 pCurScb
->SCB_Mode
= 0;
1197 pCurScb
->SCB_SGIdx
= 0;
1198 pCurScb
->SCB_SGMax
= pCurScb
->SCB_SGLen
;
1200 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1202 tul_append_pend_scb(pCurHcb
, pCurScb
); /* Append this SCB to Pending queue */
1204 /* VVVVV 07/21/98 */
1205 if (pCurHcb
->HCS_Semaph
== 1) {
1206 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1207 /* disable Jasmin SCSI Int */
1208 pCurHcb
->HCS_Semaph
= 0;
1210 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1212 tulip_main(pCurHcb
);
1214 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1216 pCurHcb
->HCS_Semaph
= 1;
1217 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1219 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1223 /***************************************************************************/
1224 int tul_isr(HCS
* pCurHcb
)
1226 /* Enter critical section */
1228 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_Int
) & TSS_INT_PENDING
) {
1229 if (pCurHcb
->HCS_Semaph
== 1) {
1230 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1231 /* Disable Tulip SCSI Int */
1232 pCurHcb
->HCS_Semaph
= 0;
1234 tulip_main(pCurHcb
);
1236 pCurHcb
->HCS_Semaph
= 1;
1237 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1244 /***************************************************************************/
1245 int tulip_main(HCS
* pCurHcb
)
1251 tulip_scsi(pCurHcb
); /* Call tulip_scsi */
1253 while ((pCurScb
= tul_find_done_scb(pCurHcb
)) != NULL
) { /* find done entry */
1254 if (pCurScb
->SCB_TaStat
== QUEUE_FULL
) {
1255 pCurHcb
->HCS_MaxTags
[pCurScb
->SCB_Target
] =
1256 pCurHcb
->HCS_ActTags
[pCurScb
->SCB_Target
] - 1;
1257 pCurScb
->SCB_TaStat
= 0;
1258 tul_append_pend_scb(pCurHcb
, pCurScb
);
1261 if (!(pCurScb
->SCB_Mode
& SCM_RSENS
)) { /* not in auto req. sense mode */
1262 if (pCurScb
->SCB_TaStat
== 2) {
1264 /* clr sync. nego flag */
1266 if (pCurScb
->SCB_Flags
& SCF_SENSE
) {
1268 len
= pCurScb
->SCB_SenseLen
;
1271 pCurScb
->SCB_BufLen
= pCurScb
->SCB_SenseLen
;
1272 pCurScb
->SCB_BufPtr
= pCurScb
->SCB_SensePtr
;
1273 pCurScb
->SCB_Flags
&= ~(SCF_SG
| SCF_DIR
); /* for xfer_data_in */
1274 /* pCurScb->SCB_Flags |= SCF_NO_DCHK; */
1275 /* so, we won't report worng direction in xfer_data_in,
1276 and won't report HOST_DO_DU in state_6 */
1277 pCurScb
->SCB_Mode
= SCM_RSENS
;
1278 pCurScb
->SCB_Ident
&= 0xBF; /* Disable Disconnect */
1279 pCurScb
->SCB_TagMsg
= 0;
1280 pCurScb
->SCB_TaStat
= 0;
1281 pCurScb
->SCB_CDBLen
= 6;
1282 pCurScb
->SCB_CDB
[0] = SCSICMD_RequestSense
;
1283 pCurScb
->SCB_CDB
[1] = 0;
1284 pCurScb
->SCB_CDB
[2] = 0;
1285 pCurScb
->SCB_CDB
[3] = 0;
1286 pCurScb
->SCB_CDB
[4] = len
;
1287 pCurScb
->SCB_CDB
[5] = 0;
1288 tul_push_pend_scb(pCurHcb
, pCurScb
);
1292 } else { /* in request sense mode */
1294 if (pCurScb
->SCB_TaStat
== 2) { /* check contition status again after sending
1295 requset sense cmd 0x3 */
1296 pCurScb
->SCB_HaStat
= HOST_BAD_PHAS
;
1298 pCurScb
->SCB_TaStat
= 2;
1300 pCurScb
->SCB_Flags
|= SCF_DONE
;
1301 if (pCurScb
->SCB_Flags
& SCF_POST
) {
1302 (*pCurScb
->SCB_Post
) ((BYTE
*) pCurHcb
, (BYTE
*) pCurScb
);
1307 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus0
) & TSS_INT_PENDING
)
1310 if (pCurHcb
->HCS_ActScb
) { /* return to OS and wait for xfer_done_ISR/Selected_ISR */
1311 return 1; /* return to OS, enable interrupt */
1313 /* Check pending SCB */
1314 if (tul_find_first_pend_scb(pCurHcb
) == NULL
) {
1315 return 1; /* return to OS, enable interrupt */
1317 } /* End of for loop */
1318 /* statement won't reach here */
1324 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
1325 /***************************************************************************/
1326 /***************************************************************************/
1327 /***************************************************************************/
1328 /***************************************************************************/
1330 /***************************************************************************/
1331 void tulip_scsi(HCS
* pCurHcb
)
1336 /* make sure to service interrupt asap */
1338 if ((pCurHcb
->HCS_JSStatus0
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus0
)) & TSS_INT_PENDING
) {
1340 pCurHcb
->HCS_Phase
= pCurHcb
->HCS_JSStatus0
& TSS_PH_MASK
;
1341 pCurHcb
->HCS_JSStatus1
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus1
);
1342 pCurHcb
->HCS_JSInt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
);
1343 if (pCurHcb
->HCS_JSInt
& TSS_SCSIRST_INT
) { /* SCSI bus reset detected */
1344 int_tul_scsi_rst(pCurHcb
);
1347 if (pCurHcb
->HCS_JSInt
& TSS_RESEL_INT
) { /* if selected/reselected interrupt */
1348 if (int_tul_resel(pCurHcb
) == 0)
1349 tul_next_state(pCurHcb
);
1352 if (pCurHcb
->HCS_JSInt
& TSS_SEL_TIMEOUT
) {
1353 int_tul_busfree(pCurHcb
);
1356 if (pCurHcb
->HCS_JSInt
& TSS_DISC_INT
) { /* BUS disconnection */
1357 int_tul_busfree(pCurHcb
); /* unexpected bus free or sel timeout */
1360 if (pCurHcb
->HCS_JSInt
& (TSS_FUNC_COMP
| TSS_BUS_SERV
)) { /* func complete or Bus service */
1361 if ((pCurScb
= pCurHcb
->HCS_ActScb
) != NULL
)
1362 tul_next_state(pCurHcb
);
1366 if (pCurHcb
->HCS_ActScb
!= NULL
)
1369 if ((pCurScb
= tul_find_first_pend_scb(pCurHcb
)) == NULL
)
1372 /* program HBA's SCSI ID & target SCSI ID */
1373 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SScsiId
,
1374 (pCurHcb
->HCS_SCSI_ID
<< 4) | (pCurScb
->SCB_Target
& 0x0F));
1375 if (pCurScb
->SCB_Opcode
== ExecSCSI
) {
1376 pCurTcb
= &pCurHcb
->HCS_Tcs
[pCurScb
->SCB_Target
];
1378 if (pCurScb
->SCB_TagMsg
)
1379 pCurTcb
->TCS_DrvFlags
|= TCF_DRV_EN_TAG
;
1381 pCurTcb
->TCS_DrvFlags
&= ~TCF_DRV_EN_TAG
;
1383 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SPeriod
, pCurTcb
->TCS_JS_Period
);
1384 if ((pCurTcb
->TCS_Flags
& (TCF_WDTR_DONE
| TCF_NO_WDTR
)) == 0) { /* do wdtr negotiation */
1385 tul_select_atn_stop(pCurHcb
, pCurScb
);
1387 if ((pCurTcb
->TCS_Flags
& (TCF_SYNC_DONE
| TCF_NO_SYNC_NEGO
)) == 0) { /* do sync negotiation */
1388 tul_select_atn_stop(pCurHcb
, pCurScb
);
1390 if (pCurScb
->SCB_TagMsg
)
1391 tul_select_atn3(pCurHcb
, pCurScb
);
1393 tul_select_atn(pCurHcb
, pCurScb
);
1396 if (pCurScb
->SCB_Flags
& SCF_POLL
) {
1397 while (wait_tulip(pCurHcb
) != -1) {
1398 if (tul_next_state(pCurHcb
) == -1)
1402 } else if (pCurScb
->SCB_Opcode
== BusDevRst
) {
1403 tul_select_atn_stop(pCurHcb
, pCurScb
);
1404 pCurScb
->SCB_NxtStat
= 8;
1405 if (pCurScb
->SCB_Flags
& SCF_POLL
) {
1406 while (wait_tulip(pCurHcb
) != -1) {
1407 if (tul_next_state(pCurHcb
) == -1)
1411 } else if (pCurScb
->SCB_Opcode
== AbortCmd
) {
1414 srbp
= (ULONG
) pCurScb
->SCB_Srb
;
1416 if (tul_abort_srb(pCurHcb
, srbp
) != 0) {
1419 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
1421 tul_release_scb(pCurHcb
, pCurScb
);
1423 pCurScb
->SCB_Opcode
= BusDevRst
;
1424 tul_select_atn_stop(pCurHcb
, pCurScb
);
1425 pCurScb
->SCB_NxtStat
= 8;
1430 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
1431 pCurScb
->SCB_HaStat
= 0x16; /* bad command */
1432 tul_append_done_scb(pCurHcb
, pCurScb
);
1438 /***************************************************************************/
1439 int tul_next_state(HCS
* pCurHcb
)
1443 next
= pCurHcb
->HCS_ActScb
->SCB_NxtStat
;
1447 next
= tul_state_1(pCurHcb
);
1450 next
= tul_state_2(pCurHcb
);
1453 next
= tul_state_3(pCurHcb
);
1456 next
= tul_state_4(pCurHcb
);
1459 next
= tul_state_5(pCurHcb
);
1462 next
= tul_state_6(pCurHcb
);
1465 next
= tul_state_7(pCurHcb
);
1468 return (tul_bus_device_reset(pCurHcb
));
1470 return (tul_bad_seq(pCurHcb
));
1478 /***************************************************************************/
1479 /* sTate after selection with attention & stop */
1480 int tul_state_1(HCS
* pCurHcb
)
1482 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1483 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
1488 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
1489 tul_append_busy_scb(pCurHcb
, pCurScb
);
1491 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurTcb
->TCS_SConfig0
);
1493 if (pCurHcb
->HCS_Phase
== MSG_OUT
) {
1495 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, (TSC_EN_BUS_IN
| TSC_HW_RESELECT
));
1497 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_Ident
);
1499 if (pCurScb
->SCB_TagMsg
) {
1500 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_TagMsg
);
1501 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_TagId
);
1503 if ((pCurTcb
->TCS_Flags
& (TCF_WDTR_DONE
| TCF_NO_WDTR
)) == 0) {
1505 pCurTcb
->TCS_Flags
|= TCF_WDTR_DONE
;
1507 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_EXTEND
);
1508 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 2); /* Extended msg length */
1509 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 3); /* Sync request */
1510 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 1); /* Start from 16 bits */
1511 } else if ((pCurTcb
->TCS_Flags
& (TCF_SYNC_DONE
| TCF_NO_SYNC_NEGO
)) == 0) {
1513 pCurTcb
->TCS_Flags
|= TCF_SYNC_DONE
;
1515 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_EXTEND
);
1516 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 3); /* extended msg length */
1517 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 1); /* sync request */
1518 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, tul_rate_tbl
[pCurTcb
->TCS_Flags
& TCF_SCSI_RATE
]);
1519 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MAX_OFFSET
); /* REQ/ACK offset */
1521 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1522 if (wait_tulip(pCurHcb
) == -1)
1525 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1526 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, (TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)));
1531 /***************************************************************************/
1532 /* state after selection with attention */
1533 /* state after selection with attention3 */
1534 int tul_state_2(HCS
* pCurHcb
)
1536 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1537 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
1542 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
1543 tul_append_busy_scb(pCurHcb
, pCurScb
);
1545 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurTcb
->TCS_SConfig0
);
1547 if (pCurHcb
->HCS_JSStatus1
& TSS_CMD_PH_CMP
) {
1550 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1551 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, (TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)));
1555 /***************************************************************************/
1556 /* state before CDB xfer is done */
1557 int tul_state_3(HCS
* pCurHcb
)
1559 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1560 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
1567 switch (pCurHcb
->HCS_Phase
) {
1568 case CMD_OUT
: /* Command out phase */
1569 for (i
= 0; i
< (int) pCurScb
->SCB_CDBLen
; i
++)
1570 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_CDB
[i
]);
1571 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1572 if (wait_tulip(pCurHcb
) == -1)
1574 if (pCurHcb
->HCS_Phase
== CMD_OUT
) {
1575 return (tul_bad_seq(pCurHcb
));
1579 case MSG_IN
: /* Message in phase */
1580 pCurScb
->SCB_NxtStat
= 3;
1581 if (tul_msgin(pCurHcb
) == -1)
1585 case STATUS_IN
: /* Status phase */
1586 if (tul_status_msg(pCurHcb
) == -1)
1590 case MSG_OUT
: /* Message out phase */
1591 if (pCurTcb
->TCS_Flags
& (TCF_SYNC_DONE
| TCF_NO_SYNC_NEGO
)) {
1593 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_NOP
); /* msg nop */
1594 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1595 if (wait_tulip(pCurHcb
) == -1)
1599 pCurTcb
->TCS_Flags
|= TCF_SYNC_DONE
;
1601 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_EXTEND
);
1602 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 3); /* ext. msg len */
1603 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 1); /* sync request */
1604 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, tul_rate_tbl
[pCurTcb
->TCS_Flags
& TCF_SCSI_RATE
]);
1605 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MAX_OFFSET
); /* REQ/ACK offset */
1606 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1607 if (wait_tulip(pCurHcb
) == -1)
1609 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1610 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7));
1616 return (tul_bad_seq(pCurHcb
));
1622 /***************************************************************************/
1623 int tul_state_4(HCS
* pCurHcb
)
1625 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1630 if ((pCurScb
->SCB_Flags
& SCF_DIR
) == SCF_NO_XF
) {
1631 return (6); /* Go to state 6 */
1634 if (pCurScb
->SCB_BufLen
== 0)
1635 return (6); /* Go to state 6 */
1637 switch (pCurHcb
->HCS_Phase
) {
1639 case STATUS_IN
: /* Status phase */
1640 if ((pCurScb
->SCB_Flags
& SCF_DIR
) != 0) { /* if direction bit set then report data underrun */
1641 pCurScb
->SCB_HaStat
= HOST_DO_DU
;
1643 if ((tul_status_msg(pCurHcb
)) == -1)
1647 case MSG_IN
: /* Message in phase */
1648 pCurScb
->SCB_NxtStat
= 0x4;
1649 if (tul_msgin(pCurHcb
) == -1)
1653 case MSG_OUT
: /* Message out phase */
1654 if (pCurHcb
->HCS_JSStatus0
& TSS_PAR_ERROR
) {
1655 pCurScb
->SCB_BufLen
= 0;
1656 pCurScb
->SCB_HaStat
= HOST_DO_DU
;
1657 if (tul_msgout_ide(pCurHcb
) == -1)
1659 return (6); /* Go to state 6 */
1661 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_NOP
); /* msg nop */
1662 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1663 if (wait_tulip(pCurHcb
) == -1)
1668 case DATA_IN
: /* Data in phase */
1669 return (tul_xfer_data_in(pCurHcb
));
1671 case DATA_OUT
: /* Data out phase */
1672 return (tul_xfer_data_out(pCurHcb
));
1675 return (tul_bad_seq(pCurHcb
));
1681 /***************************************************************************/
1682 /* state after dma xfer done or phase change before xfer done */
1683 int tul_state_5(HCS
* pCurHcb
)
1685 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1686 long cnt
, xcnt
; /* cannot use unsigned !! code: if (xcnt < 0) */
1691 /*------ get remaining count -------*/
1693 cnt
= TUL_RDLONG(pCurHcb
->HCS_Base
, TUL_SCnt0
) & 0x0FFFFFF;
1695 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_XCmd
) & 0x20) {
1696 /* ----------------------- DATA_IN ----------------------------- */
1697 /* check scsi parity error */
1698 if (pCurHcb
->HCS_JSStatus0
& TSS_PAR_ERROR
) {
1699 pCurScb
->SCB_HaStat
= HOST_DO_DU
;
1701 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_XStatus
) & XPEND
) { /* DMA xfer pending, Send STOP */
1702 /* tell Hardware scsi xfer has been terminated */
1703 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCtrl
, TUL_RD(pCurHcb
->HCS_Base
, TUL_XCtrl
) | 0x80);
1704 /* wait until DMA xfer not pending */
1705 while (TUL_RD(pCurHcb
->HCS_Base
, TUL_XStatus
) & XPEND
);
1708 /*-------- DATA OUT -----------*/
1709 if ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus1
) & TSS_XFER_CMP
) == 0) {
1710 if (pCurHcb
->HCS_ActTcs
->TCS_JS_Period
& TSC_WIDE_SCSI
)
1711 cnt
+= (TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifoCnt
) & 0x1F) << 1;
1713 cnt
+= (TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifoCnt
) & 0x1F);
1715 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_XStatus
) & XPEND
) { /* if DMA xfer is pending, abort DMA xfer */
1716 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_X_ABT
);
1717 /* wait Abort DMA xfer done */
1718 while ((TUL_RD(pCurHcb
->HCS_Base
, TUL_Int
) & XABT
) == 0);
1720 if ((cnt
== 1) && (pCurHcb
->HCS_Phase
== DATA_OUT
)) {
1721 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1722 if (wait_tulip(pCurHcb
) == -1) {
1727 if ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus1
) & TSS_XFER_CMP
) == 0)
1728 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1733 pCurScb
->SCB_BufLen
= 0;
1734 return (6); /* Go to state 6 */
1736 /* Update active data pointer */
1737 xcnt
= (long) pCurScb
->SCB_BufLen
- cnt
; /* xcnt== bytes already xferred */
1738 pCurScb
->SCB_BufLen
= (U32
) cnt
; /* cnt == bytes left to be xferred */
1739 if (pCurScb
->SCB_Flags
& SCF_SG
) {
1743 sgp
= &pCurScb
->SCB_SGList
[pCurScb
->SCB_SGIdx
];
1744 for (i
= pCurScb
->SCB_SGIdx
; i
< pCurScb
->SCB_SGMax
; sgp
++, i
++) {
1745 xcnt
-= (long) sgp
->SG_Len
;
1746 if (xcnt
< 0) { /* this sgp xfer half done */
1747 xcnt
+= (long) sgp
->SG_Len
; /* xcnt == bytes xferred in this sgp */
1748 sgp
->SG_Ptr
+= (U32
) xcnt
; /* new ptr to be xfer */
1749 sgp
->SG_Len
-= (U32
) xcnt
; /* new len to be xfer */
1750 pCurScb
->SCB_BufPtr
+= ((U32
) (i
- pCurScb
->SCB_SGIdx
) << 3);
1751 /* new SG table ptr */
1752 pCurScb
->SCB_SGLen
= (BYTE
) (pCurScb
->SCB_SGMax
- i
);
1753 /* new SG table len */
1754 pCurScb
->SCB_SGIdx
= (WORD
) i
;
1755 /* for next disc and come in this loop */
1756 return (4); /* Go to state 4 */
1758 /* else (xcnt >= 0 , i.e. this sgp already xferred */
1760 return (6); /* Go to state 6 */
1762 pCurScb
->SCB_BufPtr
+= (U32
) xcnt
;
1764 return (4); /* Go to state 4 */
1767 /***************************************************************************/
1768 /* state after Data phase */
1769 int tul_state_6(HCS
* pCurHcb
)
1771 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1777 switch (pCurHcb
->HCS_Phase
) {
1778 case STATUS_IN
: /* Status phase */
1779 if ((tul_status_msg(pCurHcb
)) == -1)
1783 case MSG_IN
: /* Message in phase */
1784 pCurScb
->SCB_NxtStat
= 6;
1785 if ((tul_msgin(pCurHcb
)) == -1)
1789 case MSG_OUT
: /* Message out phase */
1790 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_NOP
); /* msg nop */
1791 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1792 if (wait_tulip(pCurHcb
) == -1)
1796 case DATA_IN
: /* Data in phase */
1797 return (tul_xpad_in(pCurHcb
));
1799 case DATA_OUT
: /* Data out phase */
1800 return (tul_xpad_out(pCurHcb
));
1803 return (tul_bad_seq(pCurHcb
));
1808 /***************************************************************************/
1809 int tul_state_7(HCS
* pCurHcb
)
1816 /* flush SCSI FIFO */
1817 cnt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifoCnt
) & 0x1F;
1819 for (i
= 0; i
< cnt
; i
++)
1820 TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
1822 switch (pCurHcb
->HCS_Phase
) {
1823 case DATA_IN
: /* Data in phase */
1824 case DATA_OUT
: /* Data out phase */
1825 return (tul_bad_seq(pCurHcb
));
1827 return (6); /* Go to state 6 */
1831 /***************************************************************************/
1832 int tul_xfer_data_in(HCS
* pCurHcb
)
1834 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1836 if ((pCurScb
->SCB_Flags
& SCF_DIR
) == SCF_DOUT
) {
1837 return (6); /* wrong direction */
1839 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, pCurScb
->SCB_BufLen
);
1841 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_DMA_IN
); /* 7/25/95 */
1843 if (pCurScb
->SCB_Flags
& SCF_SG
) { /* S/G xfer */
1844 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XCntH
, ((ULONG
) pCurScb
->SCB_SGLen
) << 3);
1845 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XAddH
, pCurScb
->SCB_BufPtr
);
1846 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_SG_IN
);
1848 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XCntH
, pCurScb
->SCB_BufLen
);
1849 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XAddH
, pCurScb
->SCB_BufPtr
);
1850 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_X_IN
);
1852 pCurScb
->SCB_NxtStat
= 0x5;
1853 return (0); /* return to OS, wait xfer done , let jas_isr come in */
1857 /***************************************************************************/
1858 int tul_xfer_data_out(HCS
* pCurHcb
)
1860 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1862 if ((pCurScb
->SCB_Flags
& SCF_DIR
) == SCF_DIN
) {
1863 return (6); /* wrong direction */
1865 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, pCurScb
->SCB_BufLen
);
1866 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_DMA_OUT
);
1868 if (pCurScb
->SCB_Flags
& SCF_SG
) { /* S/G xfer */
1869 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XCntH
, ((ULONG
) pCurScb
->SCB_SGLen
) << 3);
1870 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XAddH
, pCurScb
->SCB_BufPtr
);
1871 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_SG_OUT
);
1873 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XCntH
, pCurScb
->SCB_BufLen
);
1874 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XAddH
, pCurScb
->SCB_BufPtr
);
1875 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_X_OUT
);
1878 pCurScb
->SCB_NxtStat
= 0x5;
1879 return (0); /* return to OS, wait xfer done , let jas_isr come in */
1883 /***************************************************************************/
1884 int tul_xpad_in(HCS
* pCurHcb
)
1886 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1887 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
1889 if ((pCurScb
->SCB_Flags
& SCF_DIR
) != SCF_NO_DCHK
) {
1890 pCurScb
->SCB_HaStat
= HOST_DO_DU
; /* over run */
1893 if (pCurTcb
->TCS_JS_Period
& TSC_WIDE_SCSI
)
1894 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 2);
1896 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
1898 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
1899 if ((wait_tulip(pCurHcb
)) == -1) {
1902 if (pCurHcb
->HCS_Phase
!= DATA_IN
) {
1903 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1906 TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
1910 int tul_xpad_out(HCS
* pCurHcb
)
1912 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1913 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
1915 if ((pCurScb
->SCB_Flags
& SCF_DIR
) != SCF_NO_DCHK
) {
1916 pCurScb
->SCB_HaStat
= HOST_DO_DU
; /* over run */
1919 if (pCurTcb
->TCS_JS_Period
& TSC_WIDE_SCSI
)
1920 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 2);
1922 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
1924 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 0);
1925 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1926 if ((wait_tulip(pCurHcb
)) == -1) {
1929 if (pCurHcb
->HCS_Phase
!= DATA_OUT
) { /* Disable wide CPU to allow read 16 bits */
1930 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
);
1931 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1938 /***************************************************************************/
1939 int tul_status_msg(HCS
* pCurHcb
)
1940 { /* status & MSG_IN */
1941 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1944 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_CMD_COMP
);
1945 if ((wait_tulip(pCurHcb
)) == -1) {
1949 pCurScb
->SCB_TaStat
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
1951 if (pCurHcb
->HCS_Phase
== MSG_OUT
) {
1952 if (pCurHcb
->HCS_JSStatus0
& TSS_PAR_ERROR
) {
1953 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_PARITY
);
1955 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_NOP
);
1957 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1958 return (wait_tulip(pCurHcb
));
1960 if (pCurHcb
->HCS_Phase
== MSG_IN
) {
1961 msg
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
1962 if (pCurHcb
->HCS_JSStatus0
& TSS_PAR_ERROR
) { /* Parity error */
1963 if ((tul_msgin_accept(pCurHcb
)) == -1)
1965 if (pCurHcb
->HCS_Phase
!= MSG_OUT
)
1966 return (tul_bad_seq(pCurHcb
));
1967 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_PARITY
);
1968 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1969 return (wait_tulip(pCurHcb
));
1971 if (msg
== 0) { /* Command complete */
1973 if ((pCurScb
->SCB_TaStat
& 0x18) == 0x10) { /* No link support */
1974 return (tul_bad_seq(pCurHcb
));
1976 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1977 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_MSG_ACCEPT
);
1978 return tul_wait_done_disc(pCurHcb
);
1981 if ((msg
== MSG_LINK_COMP
) || (msg
== MSG_LINK_FLAG
)) {
1982 if ((pCurScb
->SCB_TaStat
& 0x18) == 0x10)
1983 return (tul_msgin_accept(pCurHcb
));
1986 return (tul_bad_seq(pCurHcb
));
1990 /***************************************************************************/
1992 int int_tul_busfree(HCS
* pCurHcb
)
1994 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1996 if (pCurScb
!= NULL
) {
1997 if (pCurScb
->SCB_Status
& SCB_SELECT
) { /* selection timeout */
1998 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
1999 pCurScb
->SCB_HaStat
= HOST_SEL_TOUT
;
2000 tul_append_done_scb(pCurHcb
, pCurScb
);
2001 } else { /* Unexpected bus free */
2002 tul_unlink_busy_scb(pCurHcb
, pCurScb
);
2003 pCurScb
->SCB_HaStat
= HOST_BUS_FREE
;
2004 tul_append_done_scb(pCurHcb
, pCurScb
);
2006 pCurHcb
->HCS_ActScb
= NULL
;
2007 pCurHcb
->HCS_ActTcs
= NULL
;
2009 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
); /* Flush SCSI FIFO */
2010 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, TSC_INITDEFAULT
);
2011 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
); /* Enable HW reselect */
2016 /***************************************************************************/
2017 /* scsi bus reset */
2018 int int_tul_scsi_rst(HCS
* pCurHcb
)
2023 /* if DMA xfer is pending, abort DMA xfer */
2024 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_XStatus
) & 0x01) {
2025 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_X_ABT
| TAX_X_CLR_FIFO
);
2026 /* wait Abort DMA xfer done */
2027 while ((TUL_RD(pCurHcb
->HCS_Base
, TUL_Int
) & 0x04) == 0);
2028 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2030 /* Abort all active & disconnected scb */
2031 while ((pCurScb
= tul_pop_busy_scb(pCurHcb
)) != NULL
) {
2032 pCurScb
->SCB_HaStat
= HOST_BAD_PHAS
;
2033 tul_append_done_scb(pCurHcb
, pCurScb
);
2035 pCurHcb
->HCS_ActScb
= NULL
;
2036 pCurHcb
->HCS_ActTcs
= NULL
;
2038 /* clr sync nego. done flag */
2039 for (i
= 0; i
< pCurHcb
->HCS_MaxTar
; i
++) {
2040 pCurHcb
->HCS_Tcs
[i
].TCS_Flags
&= ~(TCF_SYNC_DONE
| TCF_WDTR_DONE
);
2046 /***************************************************************************/
2047 /* scsi reselection */
2048 int int_tul_resel(HCS
* pCurHcb
)
2055 if ((pCurScb
= pCurHcb
->HCS_ActScb
) != NULL
) {
2056 if (pCurScb
->SCB_Status
& SCB_SELECT
) { /* if waiting for selection complete */
2057 pCurScb
->SCB_Status
&= ~SCB_SELECT
;
2059 pCurHcb
->HCS_ActScb
= NULL
;
2061 /* --------- get target id---------------------- */
2062 tar
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SBusId
);
2063 /* ------ get LUN from Identify message----------- */
2064 lun
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SIdent
) & 0x0F;
2065 /* 07/22/98 from 0x1F -> 0x0F */
2066 pCurTcb
= &pCurHcb
->HCS_Tcs
[tar
];
2067 pCurHcb
->HCS_ActTcs
= pCurTcb
;
2068 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurTcb
->TCS_SConfig0
);
2069 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SPeriod
, pCurTcb
->TCS_JS_Period
);
2072 /* ------------- tag queueing ? ------------------- */
2073 if (pCurTcb
->TCS_DrvFlags
& TCF_DRV_EN_TAG
) {
2074 if ((tul_msgin_accept(pCurHcb
)) == -1)
2076 if (pCurHcb
->HCS_Phase
!= MSG_IN
)
2078 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2079 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2080 if ((wait_tulip(pCurHcb
)) == -1)
2082 msg
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
); /* Read Tag Message */
2084 if ((msg
< MSG_STAG
) || (msg
> MSG_OTAG
)) /* Is simple Tag */
2087 if ((tul_msgin_accept(pCurHcb
)) == -1)
2090 if (pCurHcb
->HCS_Phase
!= MSG_IN
)
2093 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2094 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2095 if ((wait_tulip(pCurHcb
)) == -1)
2097 tag
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
); /* Read Tag ID */
2098 pCurScb
= pCurHcb
->HCS_Scb
+ tag
;
2099 if ((pCurScb
->SCB_Target
!= tar
) || (pCurScb
->SCB_Lun
!= lun
)) {
2100 return tul_msgout_abort_tag(pCurHcb
);
2102 if (pCurScb
->SCB_Status
!= SCB_BUSY
) { /* 03/24/95 */
2103 return tul_msgout_abort_tag(pCurHcb
);
2105 pCurHcb
->HCS_ActScb
= pCurScb
;
2106 if ((tul_msgin_accept(pCurHcb
)) == -1)
2108 } else { /* No tag */
2110 if ((pCurScb
= tul_find_busy_scb(pCurHcb
, tar
| (lun
<< 8))) == NULL
) {
2111 return tul_msgout_abort_targ(pCurHcb
);
2113 pCurHcb
->HCS_ActScb
= pCurScb
;
2114 if (!(pCurTcb
->TCS_DrvFlags
& TCF_DRV_EN_TAG
)) {
2115 if ((tul_msgin_accept(pCurHcb
)) == -1)
2123 /***************************************************************************/
2124 int int_tul_bad_seq(HCS
* pCurHcb
)
2125 { /* target wrong phase */
2129 tul_reset_scsi(pCurHcb
, 10);
2131 while ((pCurScb
= tul_pop_busy_scb(pCurHcb
)) != NULL
) {
2132 pCurScb
->SCB_HaStat
= HOST_BAD_PHAS
;
2133 tul_append_done_scb(pCurHcb
, pCurScb
);
2135 for (i
= 0; i
< pCurHcb
->HCS_MaxTar
; i
++) {
2136 pCurHcb
->HCS_Tcs
[i
].TCS_Flags
&= ~(TCF_SYNC_DONE
| TCF_WDTR_DONE
);
2142 /***************************************************************************/
2143 int tul_msgout_abort_targ(HCS
* pCurHcb
)
2146 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2147 if (tul_msgin_accept(pCurHcb
) == -1)
2149 if (pCurHcb
->HCS_Phase
!= MSG_OUT
)
2150 return (tul_bad_seq(pCurHcb
));
2152 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_ABORT
);
2153 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2155 return tul_wait_disc(pCurHcb
);
2158 /***************************************************************************/
2159 int tul_msgout_abort_tag(HCS
* pCurHcb
)
2162 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2163 if (tul_msgin_accept(pCurHcb
) == -1)
2165 if (pCurHcb
->HCS_Phase
!= MSG_OUT
)
2166 return (tul_bad_seq(pCurHcb
));
2168 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_ABORT_TAG
);
2169 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2171 return tul_wait_disc(pCurHcb
);
2175 /***************************************************************************/
2176 int tul_msgin(HCS
* pCurHcb
)
2182 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2184 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2185 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2186 if ((wait_tulip(pCurHcb
)) == -1)
2189 switch (TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
)) {
2190 case MSG_DISC
: /* Disconnect msg */
2191 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_MSG_ACCEPT
);
2193 return tul_wait_disc(pCurHcb
);
2198 tul_msgin_accept(pCurHcb
);
2201 case MSG_REJ
: /* Clear ATN first */
2202 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
,
2203 (TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)));
2204 pCurTcb
= pCurHcb
->HCS_ActTcs
;
2205 if ((pCurTcb
->TCS_Flags
& (TCF_SYNC_DONE
| TCF_NO_SYNC_NEGO
)) == 0) { /* do sync nego */
2206 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2208 tul_msgin_accept(pCurHcb
);
2211 case MSG_EXTEND
: /* extended msg */
2212 tul_msgin_extend(pCurHcb
);
2215 case MSG_IGNOREWIDE
:
2216 tul_msgin_accept(pCurHcb
);
2220 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2221 if (wait_tulip(pCurHcb
) == -1)
2224 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 0); /* put pad */
2225 TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
); /* get IGNORE field */
2226 TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
); /* get pad */
2228 tul_msgin_accept(pCurHcb
);
2233 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2234 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_MSG_ACCEPT
);
2235 return tul_wait_done_disc(pCurHcb
);
2238 tul_msgout_reject(pCurHcb
);
2241 if (pCurHcb
->HCS_Phase
!= MSG_IN
)
2242 return (pCurHcb
->HCS_Phase
);
2244 /* statement won't reach here */
2250 /***************************************************************************/
2251 int tul_msgout_reject(HCS
* pCurHcb
)
2254 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2256 if ((tul_msgin_accept(pCurHcb
)) == -1)
2259 if (pCurHcb
->HCS_Phase
== MSG_OUT
) {
2260 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_REJ
); /* Msg reject */
2261 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2262 return (wait_tulip(pCurHcb
));
2264 return (pCurHcb
->HCS_Phase
);
2269 /***************************************************************************/
2270 int tul_msgout_ide(HCS
* pCurHcb
)
2272 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_IDE
); /* Initiator Detected Error */
2273 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2274 return (wait_tulip(pCurHcb
));
2278 /***************************************************************************/
2279 int tul_msgin_extend(HCS
* pCurHcb
)
2283 if (tul_msgin_accept(pCurHcb
) != MSG_IN
)
2284 return (pCurHcb
->HCS_Phase
);
2286 /* Get extended msg length */
2287 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2288 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2289 if (wait_tulip(pCurHcb
) == -1)
2292 len
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
2293 pCurHcb
->HCS_Msg
[0] = len
;
2294 for (idx
= 1; len
!= 0; len
--) {
2296 if ((tul_msgin_accept(pCurHcb
)) != MSG_IN
)
2297 return (pCurHcb
->HCS_Phase
);
2298 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2299 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2300 if (wait_tulip(pCurHcb
) == -1)
2302 pCurHcb
->HCS_Msg
[idx
++] = TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
2304 if (pCurHcb
->HCS_Msg
[1] == 1) { /* if it's synchronous data transfer request */
2305 if (pCurHcb
->HCS_Msg
[0] != 3) /* if length is not right */
2306 return (tul_msgout_reject(pCurHcb
));
2307 if (pCurHcb
->HCS_ActTcs
->TCS_Flags
& TCF_NO_SYNC_NEGO
) { /* Set OFFSET=0 to do async, nego back */
2308 pCurHcb
->HCS_Msg
[3] = 0;
2310 if ((tul_msgin_sync(pCurHcb
) == 0) &&
2311 (pCurHcb
->HCS_ActTcs
->TCS_Flags
& TCF_SYNC_DONE
)) {
2312 tul_sync_done(pCurHcb
);
2313 return (tul_msgin_accept(pCurHcb
));
2317 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2318 if ((tul_msgin_accept(pCurHcb
)) != MSG_OUT
)
2319 return (pCurHcb
->HCS_Phase
);
2321 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2323 tul_sync_done(pCurHcb
);
2325 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_EXTEND
);
2326 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 3);
2327 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 1);
2328 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurHcb
->HCS_Msg
[2]);
2329 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurHcb
->HCS_Msg
[3]);
2331 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2332 return (wait_tulip(pCurHcb
));
2334 if ((pCurHcb
->HCS_Msg
[0] != 2) || (pCurHcb
->HCS_Msg
[1] != 3))
2335 return (tul_msgout_reject(pCurHcb
));
2336 /* if it's WIDE DATA XFER REQ */
2337 if (pCurHcb
->HCS_ActTcs
->TCS_Flags
& TCF_NO_WDTR
) {
2338 pCurHcb
->HCS_Msg
[2] = 0;
2340 if (pCurHcb
->HCS_Msg
[2] > 2) /* > 32 bits */
2341 return (tul_msgout_reject(pCurHcb
));
2342 if (pCurHcb
->HCS_Msg
[2] == 2) { /* == 32 */
2343 pCurHcb
->HCS_Msg
[2] = 1;
2345 if ((pCurHcb
->HCS_ActTcs
->TCS_Flags
& TCF_NO_WDTR
) == 0) {
2347 if ((pCurHcb
->HCS_ActTcs
->TCS_Flags
& (TCF_SYNC_DONE
| TCF_NO_SYNC_NEGO
)) == 0)
2348 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2349 return (tul_msgin_accept(pCurHcb
));
2353 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2355 if (tul_msgin_accept(pCurHcb
) != MSG_OUT
)
2356 return (pCurHcb
->HCS_Phase
);
2358 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_EXTEND
);
2359 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 2);
2360 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 3);
2361 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurHcb
->HCS_Msg
[2]);
2362 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2363 return (wait_tulip(pCurHcb
));
2366 /***************************************************************************/
2367 int tul_msgin_sync(HCS
* pCurHcb
)
2369 char default_period
;
2371 default_period
= tul_rate_tbl
[pCurHcb
->HCS_ActTcs
->TCS_Flags
& TCF_SCSI_RATE
];
2372 if (pCurHcb
->HCS_Msg
[3] > MAX_OFFSET
) {
2373 pCurHcb
->HCS_Msg
[3] = MAX_OFFSET
;
2374 if (pCurHcb
->HCS_Msg
[2] < default_period
) {
2375 pCurHcb
->HCS_Msg
[2] = default_period
;
2378 if (pCurHcb
->HCS_Msg
[2] >= 59) { /* Change to async */
2379 pCurHcb
->HCS_Msg
[3] = 0;
2383 /* offset requests asynchronous transfers ? */
2384 if (pCurHcb
->HCS_Msg
[3] == 0) {
2387 if (pCurHcb
->HCS_Msg
[2] < default_period
) {
2388 pCurHcb
->HCS_Msg
[2] = default_period
;
2391 if (pCurHcb
->HCS_Msg
[2] >= 59) {
2392 pCurHcb
->HCS_Msg
[3] = 0;
2399 /***************************************************************************/
2400 int wdtr_done(HCS
* pCurHcb
)
2402 pCurHcb
->HCS_ActTcs
->TCS_Flags
&= ~TCF_SYNC_DONE
;
2403 pCurHcb
->HCS_ActTcs
->TCS_Flags
|= TCF_WDTR_DONE
;
2405 pCurHcb
->HCS_ActTcs
->TCS_JS_Period
= 0;
2406 if (pCurHcb
->HCS_Msg
[2]) { /* if 16 bit */
2407 pCurHcb
->HCS_ActTcs
->TCS_JS_Period
|= TSC_WIDE_SCSI
;
2409 pCurHcb
->HCS_ActTcs
->TCS_SConfig0
&= ~TSC_ALT_PERIOD
;
2410 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurHcb
->HCS_ActTcs
->TCS_SConfig0
);
2411 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SPeriod
, pCurHcb
->HCS_ActTcs
->TCS_JS_Period
);
2416 /***************************************************************************/
2417 int tul_sync_done(HCS
* pCurHcb
)
2421 pCurHcb
->HCS_ActTcs
->TCS_Flags
|= TCF_SYNC_DONE
;
2423 if (pCurHcb
->HCS_Msg
[3]) {
2424 pCurHcb
->HCS_ActTcs
->TCS_JS_Period
|= pCurHcb
->HCS_Msg
[3];
2425 for (i
= 0; i
< 8; i
++) {
2426 if (tul_rate_tbl
[i
] >= pCurHcb
->HCS_Msg
[2]) /* pick the big one */
2429 pCurHcb
->HCS_ActTcs
->TCS_JS_Period
|= (i
<< 4);
2430 pCurHcb
->HCS_ActTcs
->TCS_SConfig0
|= TSC_ALT_PERIOD
;
2432 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurHcb
->HCS_ActTcs
->TCS_SConfig0
);
2433 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SPeriod
, pCurHcb
->HCS_ActTcs
->TCS_JS_Period
);
2439 int tul_post_scsi_rst(HCS
* pCurHcb
)
2445 pCurHcb
->HCS_ActScb
= 0;
2446 pCurHcb
->HCS_ActTcs
= 0;
2447 pCurHcb
->HCS_Flags
= 0;
2449 while ((pCurScb
= tul_pop_busy_scb(pCurHcb
)) != NULL
) {
2450 pCurScb
->SCB_HaStat
= HOST_BAD_PHAS
;
2451 tul_append_done_scb(pCurHcb
, pCurScb
);
2453 /* clear sync done flag */
2454 pCurTcb
= &pCurHcb
->HCS_Tcs
[0];
2455 for (i
= 0; i
< pCurHcb
->HCS_MaxTar
; pCurTcb
++, i
++) {
2456 pCurTcb
->TCS_Flags
&= ~(TCF_SYNC_DONE
| TCF_WDTR_DONE
);
2457 /* Initialize the sync. xfer register values to an asyn xfer */
2458 pCurTcb
->TCS_JS_Period
= 0;
2459 pCurTcb
->TCS_SConfig0
= pCurHcb
->HCS_SConf1
;
2460 pCurHcb
->HCS_ActTags
[0] = 0; /* 07/22/98 */
2461 pCurHcb
->HCS_Tcs
[i
].TCS_Flags
&= ~TCF_BUSY
; /* 07/22/98 */
2467 /***************************************************************************/
2468 void tul_select_atn_stop(HCS
* pCurHcb
, SCB
* pCurScb
)
2470 pCurScb
->SCB_Status
|= SCB_SELECT
;
2471 pCurScb
->SCB_NxtStat
= 0x1;
2472 pCurHcb
->HCS_ActScb
= pCurScb
;
2473 pCurHcb
->HCS_ActTcs
= &pCurHcb
->HCS_Tcs
[pCurScb
->SCB_Target
];
2474 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_SELATNSTOP
);
2479 /***************************************************************************/
2480 void tul_select_atn(HCS
* pCurHcb
, SCB
* pCurScb
)
2484 pCurScb
->SCB_Status
|= SCB_SELECT
;
2485 pCurScb
->SCB_NxtStat
= 0x2;
2487 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_Ident
);
2488 for (i
= 0; i
< (int) pCurScb
->SCB_CDBLen
; i
++)
2489 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_CDB
[i
]);
2490 pCurHcb
->HCS_ActTcs
= &pCurHcb
->HCS_Tcs
[pCurScb
->SCB_Target
];
2491 pCurHcb
->HCS_ActScb
= pCurScb
;
2492 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_SEL_ATN
);
2496 /***************************************************************************/
2497 void tul_select_atn3(HCS
* pCurHcb
, SCB
* pCurScb
)
2501 pCurScb
->SCB_Status
|= SCB_SELECT
;
2502 pCurScb
->SCB_NxtStat
= 0x2;
2504 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_Ident
);
2505 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_TagMsg
);
2506 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_TagId
);
2507 for (i
= 0; i
< (int) pCurScb
->SCB_CDBLen
; i
++)
2508 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_CDB
[i
]);
2509 pCurHcb
->HCS_ActTcs
= &pCurHcb
->HCS_Tcs
[pCurScb
->SCB_Target
];
2510 pCurHcb
->HCS_ActScb
= pCurScb
;
2511 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_SEL_ATN3
);
2515 /***************************************************************************/
2516 /* SCSI Bus Device Reset */
2517 int tul_bus_device_reset(HCS
* pCurHcb
)
2519 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
2520 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
2521 SCB
*pTmpScb
, *pPrevScb
;
2524 if (pCurHcb
->HCS_Phase
!= MSG_OUT
) {
2525 return (int_tul_bad_seq(pCurHcb
)); /* Unexpected phase */
2527 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
2528 tul_release_scb(pCurHcb
, pCurScb
);
2531 tar
= pCurScb
->SCB_Target
; /* target */
2532 pCurTcb
->TCS_Flags
&= ~(TCF_SYNC_DONE
| TCF_WDTR_DONE
| TCF_BUSY
);
2533 /* clr sync. nego & WDTR flags 07/22/98 */
2535 /* abort all SCB with same target */
2536 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstBusy
; /* Check Busy queue */
2537 while (pTmpScb
!= NULL
) {
2539 if (pTmpScb
->SCB_Target
== tar
) {
2541 if (pTmpScb
== pCurHcb
->HCS_FirstBusy
) {
2542 if ((pCurHcb
->HCS_FirstBusy
= pTmpScb
->SCB_NxtScb
) == NULL
)
2543 pCurHcb
->HCS_LastBusy
= NULL
;
2545 pPrevScb
->SCB_NxtScb
= pTmpScb
->SCB_NxtScb
;
2546 if (pTmpScb
== pCurHcb
->HCS_LastBusy
)
2547 pCurHcb
->HCS_LastBusy
= pPrevScb
;
2549 pTmpScb
->SCB_HaStat
= HOST_ABORTED
;
2550 tul_append_done_scb(pCurHcb
, pTmpScb
);
2552 /* Previous haven't change */
2556 pTmpScb
= pTmpScb
->SCB_NxtScb
;
2559 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_DEVRST
);
2560 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2562 return tul_wait_disc(pCurHcb
);
2566 /***************************************************************************/
2567 int tul_msgin_accept(HCS
* pCurHcb
)
2569 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_MSG_ACCEPT
);
2570 return (wait_tulip(pCurHcb
));
2573 /***************************************************************************/
2574 int wait_tulip(HCS
* pCurHcb
)
2577 while (!((pCurHcb
->HCS_JSStatus0
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus0
))
2578 & TSS_INT_PENDING
));
2580 pCurHcb
->HCS_JSInt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
);
2581 pCurHcb
->HCS_Phase
= pCurHcb
->HCS_JSStatus0
& TSS_PH_MASK
;
2582 pCurHcb
->HCS_JSStatus1
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus1
);
2584 if (pCurHcb
->HCS_JSInt
& TSS_RESEL_INT
) { /* if SCSI bus reset detected */
2585 return (int_tul_resel(pCurHcb
));
2587 if (pCurHcb
->HCS_JSInt
& TSS_SEL_TIMEOUT
) { /* if selected/reselected timeout interrupt */
2588 return (int_tul_busfree(pCurHcb
));
2590 if (pCurHcb
->HCS_JSInt
& TSS_SCSIRST_INT
) { /* if SCSI bus reset detected */
2591 return (int_tul_scsi_rst(pCurHcb
));
2593 if (pCurHcb
->HCS_JSInt
& TSS_DISC_INT
) { /* BUS disconnection */
2594 if (pCurHcb
->HCS_Flags
& HCF_EXPECT_DONE_DISC
) {
2595 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
); /* Flush SCSI FIFO */
2596 tul_unlink_busy_scb(pCurHcb
, pCurHcb
->HCS_ActScb
);
2597 pCurHcb
->HCS_ActScb
->SCB_HaStat
= 0;
2598 tul_append_done_scb(pCurHcb
, pCurHcb
->HCS_ActScb
);
2599 pCurHcb
->HCS_ActScb
= NULL
;
2600 pCurHcb
->HCS_ActTcs
= NULL
;
2601 pCurHcb
->HCS_Flags
&= ~HCF_EXPECT_DONE_DISC
;
2602 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, TSC_INITDEFAULT
);
2603 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
); /* Enable HW reselect */
2606 if (pCurHcb
->HCS_Flags
& HCF_EXPECT_DISC
) {
2607 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
); /* Flush SCSI FIFO */
2608 pCurHcb
->HCS_ActScb
= NULL
;
2609 pCurHcb
->HCS_ActTcs
= NULL
;
2610 pCurHcb
->HCS_Flags
&= ~HCF_EXPECT_DISC
;
2611 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, TSC_INITDEFAULT
);
2612 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
); /* Enable HW reselect */
2615 return (int_tul_busfree(pCurHcb
));
2617 if (pCurHcb
->HCS_JSInt
& (TSS_FUNC_COMP
| TSS_BUS_SERV
)) {
2618 return (pCurHcb
->HCS_Phase
);
2620 return (pCurHcb
->HCS_Phase
);
2622 /***************************************************************************/
2623 int tul_wait_disc(HCS
* pCurHcb
)
2626 while (!((pCurHcb
->HCS_JSStatus0
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus0
))
2627 & TSS_INT_PENDING
));
2630 pCurHcb
->HCS_JSInt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
);
2632 if (pCurHcb
->HCS_JSInt
& TSS_SCSIRST_INT
) { /* if SCSI bus reset detected */
2633 return (int_tul_scsi_rst(pCurHcb
));
2635 if (pCurHcb
->HCS_JSInt
& TSS_DISC_INT
) { /* BUS disconnection */
2636 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
); /* Flush SCSI FIFO */
2637 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, TSC_INITDEFAULT
);
2638 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
); /* Enable HW reselect */
2639 pCurHcb
->HCS_ActScb
= NULL
;
2642 return (tul_bad_seq(pCurHcb
));
2645 /***************************************************************************/
2646 int tul_wait_done_disc(HCS
* pCurHcb
)
2650 while (!((pCurHcb
->HCS_JSStatus0
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus0
))
2651 & TSS_INT_PENDING
));
2653 pCurHcb
->HCS_JSInt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
);
2656 if (pCurHcb
->HCS_JSInt
& TSS_SCSIRST_INT
) { /* if SCSI bus reset detected */
2657 return (int_tul_scsi_rst(pCurHcb
));
2659 if (pCurHcb
->HCS_JSInt
& TSS_DISC_INT
) { /* BUS disconnection */
2660 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
); /* Flush SCSI FIFO */
2661 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, TSC_INITDEFAULT
);
2662 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
); /* Enable HW reselect */
2663 tul_unlink_busy_scb(pCurHcb
, pCurHcb
->HCS_ActScb
);
2665 tul_append_done_scb(pCurHcb
, pCurHcb
->HCS_ActScb
);
2666 pCurHcb
->HCS_ActScb
= NULL
;
2669 return (tul_bad_seq(pCurHcb
));
2672 /**************************** EOF *********************************/