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 *************************************************************************
59 * This is the Linux low-level SCSI driver for Initio INI-9X00U/UW SCSI host
62 * 08/06/97 hc - v1.01h
63 * - Support inic-940 and inic-935
64 * 09/26/97 hc - v1.01i
65 * - Make correction from J.W. Schultz suggestion
66 * 10/13/97 hc - Support reset function
67 * 10/21/97 hc - v1.01j
68 * - Support 32 LUN (SCSI 3)
69 * 01/14/98 hc - v1.01k
70 * - Fix memory allocation problem
71 * 03/04/98 hc - v1.01l
72 * - Fix tape rewind which will hang the system problem
73 * - Set can_queue to tul_num_scb
74 * 06/25/98 hc - v1.01m
75 * - Get it work for kernel version >= 2.1.75
76 * - Dynamic assign SCSI bus reset holding time in init_tulip()
77 * 07/02/98 hc - v1.01n
79 * 08/07/98 hc - v1.01o
80 * - Change the tul_abort_srb routine to use scsi_done. <01>
82 * - Change the INI9100U define and proc_dir_entry to
83 * reflect the newer Kernel 2.1.118, but the v1.o1o
84 * should work with Kernel 2.1.118.
85 * 09/20/98 wh - v1.02a
86 * - Support Abort command.
87 * - Handle reset routine.
90 * 12/09/98 bv - v1.03a
91 * - Removed unused code
92 * 12/13/98 bv - v1.03b
93 * - Remove cli() locking for kernels >= 2.1.95. This uses
94 * spinlocks to serialize access to the pSRB_head and
95 * pSRB_tail members of the HCS structure.
96 * 09/01/99 bv - v1.03d
97 * - Fixed a deadlock problem in SMP.
98 * 21/01/99 bv - v1.03e
99 * - Add support for the Domex 3192U PCI SCSI
100 * This is a slightly modified patch by
101 * Brian Macy <bmacy@sunshinecomputing.com>
102 * 22/02/99 bv - v1.03f
103 * - Didn't detect the INIC-950 in 2.0.x correctly.
105 * 05/07/99 bv - v1.03g
106 * - Changed the assumption that HZ = 100
107 * 10/17/03 mc - v1.04
108 * - added new DMA API support
109 * 06/01/04 jmd - v1.04a
110 * - Re-add reset_bus support
111 **************************************************************************/
113 #include <linux/module.h>
114 #include <linux/errno.h>
115 #include <linux/delay.h>
116 #include <linux/pci.h>
117 #include <linux/init.h>
118 #include <linux/blkdev.h>
119 #include <linux/spinlock.h>
120 #include <linux/stat.h>
121 #include <linux/kernel.h>
122 #include <linux/proc_fs.h>
123 #include <linux/string.h>
124 #include <linux/interrupt.h>
125 #include <linux/ioport.h>
126 #include <linux/slab.h>
127 #include <linux/jiffies.h>
128 #include <linux/dma-mapping.h>
131 #include <scsi/scsi.h>
132 #include <scsi/scsi_cmnd.h>
133 #include <scsi/scsi_device.h>
134 #include <scsi/scsi_host.h>
135 #include <scsi/scsi_tcq.h>
139 #define SENSE_SIZE 14
141 #define i91u_MAXQUEUE 2
142 #define i91u_REVID "Initio INI-9X00U/UW SCSI device driver; Revision: 1.04a"
144 #define I950_DEVICE_ID 0x9500 /* Initio's inic-950 product ID */
145 #define I940_DEVICE_ID 0x9400 /* Initio's inic-940 product ID */
146 #define I935_DEVICE_ID 0x9401 /* Initio's inic-935 product ID */
147 #define I920_DEVICE_ID 0x0002 /* Initio's other product ID */
150 static unsigned int i91u_debug
= DEBUG_DEFAULT
;
153 #define TUL_RDWORD(x,y) (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
155 typedef struct PCI_ID_Struc
{
156 unsigned short vendor_id
;
157 unsigned short device_id
;
160 static int tul_num_ch
= 4; /* Maximum 4 adapters */
161 static int tul_num_scb
;
162 static int tul_tag_enable
= 1;
166 static int setup_debug
= 0;
169 static void i91uSCBPost(BYTE
* pHcb
, BYTE
* pScb
);
171 /* PCI Devices supported by this driver */
172 static struct pci_device_id i91u_pci_devices
[] = {
173 { PCI_VENDOR_ID_INIT
, I950_DEVICE_ID
, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
174 { PCI_VENDOR_ID_INIT
, I940_DEVICE_ID
, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
175 { PCI_VENDOR_ID_INIT
, I935_DEVICE_ID
, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
176 { PCI_VENDOR_ID_INIT
, I920_DEVICE_ID
, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
177 { PCI_VENDOR_ID_DOMEX
, I920_DEVICE_ID
, PCI_ANY_ID
, PCI_ANY_ID
, 0, 0, 0},
180 MODULE_DEVICE_TABLE(pci
, i91u_pci_devices
);
182 #define DEBUG_INTERRUPT 0
183 #define DEBUG_QUEUE 0
184 #define DEBUG_STATE 0
187 /*--- external functions --*/
188 static void tul_se2_wait(void);
190 /*--- forward refrence ---*/
191 static SCB
*tul_find_busy_scb(HCS
* pCurHcb
, WORD tarlun
);
192 static SCB
*tul_find_done_scb(HCS
* pCurHcb
);
194 static int tulip_main(HCS
* pCurHcb
);
196 static int tul_next_state(HCS
* pCurHcb
);
197 static int tul_state_1(HCS
* pCurHcb
);
198 static int tul_state_2(HCS
* pCurHcb
);
199 static int tul_state_3(HCS
* pCurHcb
);
200 static int tul_state_4(HCS
* pCurHcb
);
201 static int tul_state_5(HCS
* pCurHcb
);
202 static int tul_state_6(HCS
* pCurHcb
);
203 static int tul_state_7(HCS
* pCurHcb
);
204 static int tul_xfer_data_in(HCS
* pCurHcb
);
205 static int tul_xfer_data_out(HCS
* pCurHcb
);
206 static int tul_xpad_in(HCS
* pCurHcb
);
207 static int tul_xpad_out(HCS
* pCurHcb
);
208 static int tul_status_msg(HCS
* pCurHcb
);
210 static int tul_msgin(HCS
* pCurHcb
);
211 static int tul_msgin_sync(HCS
* pCurHcb
);
212 static int tul_msgin_accept(HCS
* pCurHcb
);
213 static int tul_msgout_reject(HCS
* pCurHcb
);
214 static int tul_msgin_extend(HCS
* pCurHcb
);
216 static int tul_msgout_ide(HCS
* pCurHcb
);
217 static int tul_msgout_abort_targ(HCS
* pCurHcb
);
218 static int tul_msgout_abort_tag(HCS
* pCurHcb
);
220 static int tul_bus_device_reset(HCS
* pCurHcb
);
221 static void tul_select_atn(HCS
* pCurHcb
, SCB
* pCurScb
);
222 static void tul_select_atn3(HCS
* pCurHcb
, SCB
* pCurScb
);
223 static void tul_select_atn_stop(HCS
* pCurHcb
, SCB
* pCurScb
);
224 static int int_tul_busfree(HCS
* pCurHcb
);
225 static int int_tul_scsi_rst(HCS
* pCurHcb
);
226 static int int_tul_bad_seq(HCS
* pCurHcb
);
227 static int int_tul_resel(HCS
* pCurHcb
);
228 static int tul_sync_done(HCS
* pCurHcb
);
229 static int wdtr_done(HCS
* pCurHcb
);
230 static int wait_tulip(HCS
* pCurHcb
);
231 static int tul_wait_done_disc(HCS
* pCurHcb
);
232 static int tul_wait_disc(HCS
* pCurHcb
);
233 static void tulip_scsi(HCS
* pCurHcb
);
234 static int tul_post_scsi_rst(HCS
* pCurHcb
);
236 static void tul_se2_ew_en(WORD CurBase
);
237 static void tul_se2_ew_ds(WORD CurBase
);
238 static int tul_se2_rd_all(WORD CurBase
);
239 static void tul_se2_update_all(WORD CurBase
); /* setup default pattern */
240 static void tul_read_eeprom(WORD CurBase
);
242 /* ---- INTERNAL VARIABLES ---- */
243 static HCS tul_hcs
[MAX_SUPPORTED_ADAPTERS
];
244 static INI_ADPT_STRUCT i91u_adpt
[MAX_SUPPORTED_ADAPTERS
];
246 /*NVRAM nvram, *nvramp = &nvram; */
247 static NVRAM i91unvram
;
248 static NVRAM
*i91unvramp
;
252 static UCHAR i91udftNvRam
[64] =
254 /*----------- header -----------*/
255 0x25, 0xc9, /* Signature */
258 /* -- Host Adapter Structure -- */
259 0x95, /* ModelByte0 */
260 0x00, /* ModelByte1 */
261 0x00, /* ModelInfo */
263 NBC1_DEFAULT
, /* BIOSConfig1 */
267 /* SCSI channel 0 and target Structure */
269 NCC1_DEFAULT
, /* SCSIconfig1 */
271 0x10, /* NumSCSItarget */
273 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
274 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
275 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
276 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
278 /* SCSI channel 1 and target Structure */
280 NCC1_DEFAULT
, /* SCSIconfig1 */
282 0x10, /* NumSCSItarget */
284 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
285 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
286 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
287 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
288 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
289 0, 0}; /* - CheckSum - */
292 static UCHAR tul_rate_tbl
[8] = /* fast 20 */
294 /* nanosecond devide by 4 */
296 18, /* 75ns, 13.3M */
299 37, /* 150ns, 6.6M */
300 43, /* 175ns, 5.7M */
305 static void tul_do_pause(unsigned amount
)
306 { /* Pause for amount jiffies */
307 unsigned long the_time
= jiffies
+ amount
;
309 while (time_before_eq(jiffies
, the_time
));
312 /*-- forward reference --*/
314 /*******************************************************************
315 Use memeory refresh time ~ 15us * 2
316 ********************************************************************/
317 void tul_se2_wait(void)
324 readByte
= TUL_RD(0, 0x61);
325 if ((readByte
& 0x10) == 0x10) {
327 readByte
= TUL_RD(0, 0x61);
328 if ((readByte
& 0x10) == 0x10)
332 readByte
= TUL_RD(0, 0x61);
333 if ((readByte
& 0x10) != 0x10)
338 readByte
= TUL_RD(0, 0x61);
339 if ((readByte
& 0x10) == 0x10)
343 readByte
= TUL_RD(0, 0x61);
344 if ((readByte
& 0x10) != 0x10)
352 /******************************************************************
353 Input: instruction for Serial E2PROM
355 EX: se2_rd(0 call se2_instr() to send address and read command
357 StartBit OP_Code Address Data
358 --------- -------- ------------------ -------
359 1 1 , 0 A5,A4,A3,A2,A1,A0 D15-D0
361 +-----------------------------------------------------
364 +--+ +--+ +--+ +--+ +--+
367 CLK -------+ +--+ +--+ +--+ +--+ +--
368 (leading edge trigger)
372 DI ----+ +--0------------------
373 (address and cmd sent to nvram)
375 -------------------------------------------+
378 (data sent from nvram)
381 ******************************************************************/
382 static void tul_se2_instr(WORD CurBase
, UCHAR instr
)
387 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2DO
); /* cs+start bit */
389 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2CLK
| SE2DO
); /* +CLK */
392 for (i
= 0; i
< 8; i
++) {
394 b
= SE2CS
| SE2DO
; /* -CLK+dataBit */
396 b
= SE2CS
; /* -CLK */
397 TUL_WR(CurBase
+ TUL_NVRAM
, b
);
399 TUL_WR(CurBase
+ TUL_NVRAM
, b
| SE2CLK
); /* +CLK */
403 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* -CLK */
409 /******************************************************************
410 Function name : tul_se2_ew_en
411 Description : Enable erase/write state of serial EEPROM
412 ******************************************************************/
413 void tul_se2_ew_en(WORD CurBase
)
415 tul_se2_instr(CurBase
, 0x30); /* EWEN */
416 TUL_WR(CurBase
+ TUL_NVRAM
, 0); /* -CS */
422 /************************************************************************
423 Disable erase/write state of serial EEPROM
424 *************************************************************************/
425 void tul_se2_ew_ds(WORD CurBase
)
427 tul_se2_instr(CurBase
, 0); /* EWDS */
428 TUL_WR(CurBase
+ TUL_NVRAM
, 0); /* -CS */
434 /******************************************************************
435 Input :address of Serial E2PROM
436 Output :value stored in Serial E2PROM
437 *******************************************************************/
438 static USHORT
tul_se2_rd(WORD CurBase
, ULONG adr
)
440 UCHAR instr
, readByte
;
444 instr
= (UCHAR
) (adr
| 0x80);
445 tul_se2_instr(CurBase
, instr
); /* READ INSTR */
448 for (i
= 15; i
>= 0; i
--) {
449 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2CLK
); /* +CLK */
451 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* -CLK */
453 /* sample data after the following edge of clock */
454 readByte
= TUL_RD(CurBase
, TUL_NVRAM
);
456 readWord
+= (readByte
<< i
);
457 tul_se2_wait(); /* 6/20/95 */
460 TUL_WR(CurBase
+ TUL_NVRAM
, 0); /* no chip select */
466 /******************************************************************
467 Input: new value in Serial E2PROM, address of Serial E2PROM
468 *******************************************************************/
469 static void tul_se2_wr(WORD CurBase
, UCHAR adr
, USHORT writeWord
)
475 instr
= (UCHAR
) (adr
| 0x40);
476 tul_se2_instr(CurBase
, instr
); /* WRITE INSTR */
477 for (i
= 15; i
>= 0; i
--) {
478 if (writeWord
& 0x8000)
479 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2DO
); /* -CLK+dataBit 1 */
481 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* -CLK+dataBit 0 */
483 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2CLK
); /* +CLK */
487 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* -CLK */
489 TUL_WR(CurBase
+ TUL_NVRAM
, 0); /* -CS */
492 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* +CS */
496 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2CLK
); /* +CLK */
498 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* -CLK */
500 if ((readByte
= TUL_RD(CurBase
, TUL_NVRAM
)) & SE2DI
)
501 break; /* write complete */
503 TUL_WR(CurBase
+ TUL_NVRAM
, 0); /* -CS */
508 /***********************************************************************
509 Read SCSI H/A configuration parameters from serial EEPROM
510 ************************************************************************/
511 int tul_se2_rd_all(WORD CurBase
)
517 i91unvramp
= &i91unvram
;
518 np
= (USHORT
*) i91unvramp
;
519 for (i
= 0; i
< 32; i
++) {
520 *np
++ = tul_se2_rd(CurBase
, i
);
523 /*--------------------Is signature "ini" ok ? ----------------*/
524 if (i91unvramp
->NVM_Signature
!= INI_SIGNATURE
)
526 /*---------------------- Is ckecksum ok ? ----------------------*/
527 np
= (USHORT
*) i91unvramp
;
528 for (i
= 0; i
< 31; i
++)
530 if (i91unvramp
->NVM_CheckSum
!= (USHORT
) chksum
)
536 /***********************************************************************
537 Update SCSI H/A configuration parameters from serial EEPROM
538 ************************************************************************/
539 void tul_se2_update_all(WORD CurBase
)
540 { /* setup default pattern */
545 i91unvramp
= &i91unvram
;
546 /* Calculate checksum first */
547 np
= (USHORT
*) i91udftNvRam
;
548 for (i
= 0; i
< 31; i
++)
550 *np
= (USHORT
) chksum
;
551 tul_se2_ew_en(CurBase
); /* Enable write */
553 np
= (USHORT
*) i91udftNvRam
;
554 np1
= (USHORT
*) i91unvramp
;
555 for (i
= 0; i
< 32; i
++, np
++, np1
++) {
557 tul_se2_wr(CurBase
, i
, *np
);
561 tul_se2_ew_ds(CurBase
); /* Disable write */
565 /*************************************************************************
566 Function name : read_eeprom
567 **************************************************************************/
568 void tul_read_eeprom(WORD CurBase
)
572 i91unvramp
= &i91unvram
;
573 /*------Enable EEProm programming ---*/
574 gctrl
= TUL_RD(CurBase
, TUL_GCTRL
);
575 TUL_WR(CurBase
+ TUL_GCTRL
, gctrl
| TUL_GCTRL_EEPROM_BIT
);
576 if (tul_se2_rd_all(CurBase
) != 1) {
577 tul_se2_update_all(CurBase
); /* setup default pattern */
578 tul_se2_rd_all(CurBase
); /* load again */
580 /*------ Disable EEProm programming ---*/
581 gctrl
= TUL_RD(CurBase
, TUL_GCTRL
);
582 TUL_WR(CurBase
+ TUL_GCTRL
, gctrl
& ~TUL_GCTRL_EEPROM_BIT
);
585 static int Addi91u_into_Adapter_table(WORD wBIOS
, WORD wBASE
, BYTE bInterrupt
,
586 BYTE bBus
, BYTE bDevice
)
590 for (i
= 0; i
< MAX_SUPPORTED_ADAPTERS
; i
++) {
591 if (i91u_adpt
[i
].ADPT_BIOS
< wBIOS
)
593 if (i91u_adpt
[i
].ADPT_BIOS
== wBIOS
) {
594 if (i91u_adpt
[i
].ADPT_BASE
== wBASE
) {
595 if (i91u_adpt
[i
].ADPT_Bus
!= 0xFF)
597 } else if (i91u_adpt
[i
].ADPT_BASE
< wBASE
)
600 for (j
= MAX_SUPPORTED_ADAPTERS
- 1; j
> i
; j
--) {
601 i91u_adpt
[j
].ADPT_BASE
= i91u_adpt
[j
- 1].ADPT_BASE
;
602 i91u_adpt
[j
].ADPT_INTR
= i91u_adpt
[j
- 1].ADPT_INTR
;
603 i91u_adpt
[j
].ADPT_BIOS
= i91u_adpt
[j
- 1].ADPT_BIOS
;
604 i91u_adpt
[j
].ADPT_Bus
= i91u_adpt
[j
- 1].ADPT_Bus
;
605 i91u_adpt
[j
].ADPT_Device
= i91u_adpt
[j
- 1].ADPT_Device
;
607 i91u_adpt
[i
].ADPT_BASE
= wBASE
;
608 i91u_adpt
[i
].ADPT_INTR
= bInterrupt
;
609 i91u_adpt
[i
].ADPT_BIOS
= wBIOS
;
610 i91u_adpt
[i
].ADPT_Bus
= bBus
;
611 i91u_adpt
[i
].ADPT_Device
= bDevice
;
617 static void init_i91uAdapter_table(void)
621 for (i
= 0; i
< MAX_SUPPORTED_ADAPTERS
; i
++) { /* Initialize adapter structure */
622 i91u_adpt
[i
].ADPT_BIOS
= 0xffff;
623 i91u_adpt
[i
].ADPT_BASE
= 0xffff;
624 i91u_adpt
[i
].ADPT_INTR
= 0xff;
625 i91u_adpt
[i
].ADPT_Bus
= 0xff;
626 i91u_adpt
[i
].ADPT_Device
= 0xff;
631 static void tul_stop_bm(HCS
* pCurHcb
)
634 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_XStatus
) & XPEND
) { /* if DMA xfer is pending, abort DMA xfer */
635 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_X_ABT
| TAX_X_CLR_FIFO
);
636 /* wait Abort DMA xfer done */
637 while ((TUL_RD(pCurHcb
->HCS_Base
, TUL_Int
) & XABT
) == 0);
639 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
642 /***************************************************************************/
643 static void get_tulipPCIConfig(HCS
* pCurHcb
, int ch_idx
)
645 pCurHcb
->HCS_Base
= i91u_adpt
[ch_idx
].ADPT_BASE
; /* Supply base address */
646 pCurHcb
->HCS_BIOS
= i91u_adpt
[ch_idx
].ADPT_BIOS
; /* Supply BIOS address */
647 pCurHcb
->HCS_Intr
= i91u_adpt
[ch_idx
].ADPT_INTR
; /* Supply interrupt line */
651 /***************************************************************************/
652 static int tul_reset_scsi(HCS
* pCurHcb
, int seconds
)
654 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_RST_BUS
);
656 while (!((pCurHcb
->HCS_JSInt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
)) & TSS_SCSIRST_INT
));
657 /* reset tulip chip */
659 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, 0);
661 /* Stall for a while, wait for target's firmware ready,make it 2 sec ! */
662 /* SONY 5200 tape drive won't work if only stall for 1 sec */
663 tul_do_pause(seconds
* HZ
);
665 TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
);
667 return (SCSI_RESET_SUCCESS
);
670 /***************************************************************************/
671 static int init_tulip(HCS
* pCurHcb
, SCB
* scbp
, int tul_num_scb
,
672 BYTE
* pbBiosAdr
, int seconds
)
677 SCB
*pTmpScb
, *pPrevScb
= NULL
;
679 pCurHcb
->HCS_NumScbs
= tul_num_scb
;
680 pCurHcb
->HCS_Semaph
= 1;
681 spin_lock_init(&pCurHcb
->HCS_SemaphLock
);
682 pCurHcb
->HCS_JSStatus0
= 0;
683 pCurHcb
->HCS_Scb
= scbp
;
684 pCurHcb
->HCS_NxtPend
= scbp
;
685 pCurHcb
->HCS_NxtAvail
= scbp
;
686 for (i
= 0, pTmpScb
= scbp
; i
< tul_num_scb
; i
++, pTmpScb
++) {
687 pTmpScb
->SCB_TagId
= i
;
689 pPrevScb
->SCB_NxtScb
= pTmpScb
;
692 pPrevScb
->SCB_NxtScb
= NULL
;
693 pCurHcb
->HCS_ScbEnd
= pTmpScb
;
694 pCurHcb
->HCS_FirstAvail
= scbp
;
695 pCurHcb
->HCS_LastAvail
= pPrevScb
;
696 spin_lock_init(&pCurHcb
->HCS_AvailLock
);
697 pCurHcb
->HCS_FirstPend
= NULL
;
698 pCurHcb
->HCS_LastPend
= NULL
;
699 pCurHcb
->HCS_FirstBusy
= NULL
;
700 pCurHcb
->HCS_LastBusy
= NULL
;
701 pCurHcb
->HCS_FirstDone
= NULL
;
702 pCurHcb
->HCS_LastDone
= NULL
;
703 pCurHcb
->HCS_ActScb
= NULL
;
704 pCurHcb
->HCS_ActTcs
= NULL
;
706 tul_read_eeprom(pCurHcb
->HCS_Base
);
707 /*---------- get H/A configuration -------------*/
708 if (i91unvramp
->NVM_SCSIInfo
[0].NVM_NumOfTarg
== 8)
709 pCurHcb
->HCS_MaxTar
= 8;
711 pCurHcb
->HCS_MaxTar
= 16;
713 pCurHcb
->HCS_Config
= i91unvramp
->NVM_SCSIInfo
[0].NVM_ChConfig1
;
715 pCurHcb
->HCS_SCSI_ID
= i91unvramp
->NVM_SCSIInfo
[0].NVM_ChSCSIID
;
716 pCurHcb
->HCS_IdMask
= ~(1 << pCurHcb
->HCS_SCSI_ID
);
719 /* Enable parity error response */
720 TUL_WR(pCurHcb
->HCS_Base
+ TUL_PCMD
, TUL_RD(pCurHcb
->HCS_Base
, TUL_PCMD
) | 0x40);
723 /* Mask all the interrupt */
724 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
726 tul_stop_bm(pCurHcb
);
727 /* --- Initialize the tulip --- */
728 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_RST_CHIP
);
730 /* program HBA's SCSI ID */
731 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SScsiId
, pCurHcb
->HCS_SCSI_ID
<< 4);
733 /* Enable Initiator Mode ,phase latch,alternate sync period mode,
734 disable SCSI reset */
735 if (pCurHcb
->HCS_Config
& HCC_EN_PAR
)
736 pCurHcb
->HCS_SConf1
= (TSC_INITDEFAULT
| TSC_EN_SCSI_PAR
);
738 pCurHcb
->HCS_SConf1
= (TSC_INITDEFAULT
);
739 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurHcb
->HCS_SConf1
);
741 /* Enable HW reselect */
742 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
);
744 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SPeriod
, 0);
746 /* selection time out = 250 ms */
747 TUL_WR(pCurHcb
->HCS_Base
+ TUL_STimeOut
, 153);
749 /*--------- Enable SCSI terminator -----*/
750 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCtrl
, (pCurHcb
->HCS_Config
& (HCC_ACT_TERM1
| HCC_ACT_TERM2
)));
751 TUL_WR(pCurHcb
->HCS_Base
+ TUL_GCTRL1
,
752 ((pCurHcb
->HCS_Config
& HCC_AUTO_TERM
) >> 4) | (TUL_RD(pCurHcb
->HCS_Base
, TUL_GCTRL1
) & 0xFE));
755 pwFlags
= & (i91unvramp
->NVM_SCSIInfo
[0].NVM_Targ0Config
),
756 pbHeads
= pbBiosAdr
+ 0x180;
757 i
< pCurHcb
->HCS_MaxTar
;
759 pCurHcb
->HCS_Tcs
[i
].TCS_Flags
= *pwFlags
& ~(TCF_SYNC_DONE
| TCF_WDTR_DONE
);
760 if (pCurHcb
->HCS_Tcs
[i
].TCS_Flags
& TCF_EN_255
)
761 pCurHcb
->HCS_Tcs
[i
].TCS_DrvFlags
= TCF_DRV_255_63
;
763 pCurHcb
->HCS_Tcs
[i
].TCS_DrvFlags
= 0;
764 pCurHcb
->HCS_Tcs
[i
].TCS_JS_Period
= 0;
765 pCurHcb
->HCS_Tcs
[i
].TCS_SConfig0
= pCurHcb
->HCS_SConf1
;
766 pCurHcb
->HCS_Tcs
[i
].TCS_DrvHead
= *pbHeads
++;
767 if (pCurHcb
->HCS_Tcs
[i
].TCS_DrvHead
== 255)
768 pCurHcb
->HCS_Tcs
[i
].TCS_DrvFlags
= TCF_DRV_255_63
;
770 pCurHcb
->HCS_Tcs
[i
].TCS_DrvFlags
= 0;
771 pCurHcb
->HCS_Tcs
[i
].TCS_DrvSector
= *pbHeads
++;
772 pCurHcb
->HCS_Tcs
[i
].TCS_Flags
&= ~TCF_BUSY
;
773 pCurHcb
->HCS_ActTags
[i
] = 0;
774 pCurHcb
->HCS_MaxTags
[i
] = 0xFF;
776 printk("i91u: PCI Base=0x%04X, IRQ=%d, BIOS=0x%04X0, SCSI ID=%d\n",
777 pCurHcb
->HCS_Base
, pCurHcb
->HCS_Intr
,
778 pCurHcb
->HCS_BIOS
, pCurHcb
->HCS_SCSI_ID
);
779 /*------------------- reset SCSI Bus ---------------------------*/
780 if (pCurHcb
->HCS_Config
& HCC_SCSI_RESET
) {
781 printk("i91u: Reset SCSI Bus ... \n");
782 tul_reset_scsi(pCurHcb
, seconds
);
784 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCFG1
, 0x17);
785 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SIntEnable
, 0xE9);
789 /***************************************************************************/
790 static SCB
*tul_alloc_scb(HCS
* hcsp
)
794 spin_lock_irqsave(&(hcsp
->HCS_AvailLock
), flags
);
795 if ((pTmpScb
= hcsp
->HCS_FirstAvail
) != NULL
) {
797 printk("find scb at %08lx\n", (ULONG
) pTmpScb
);
799 if ((hcsp
->HCS_FirstAvail
= pTmpScb
->SCB_NxtScb
) == NULL
)
800 hcsp
->HCS_LastAvail
= NULL
;
801 pTmpScb
->SCB_NxtScb
= NULL
;
802 pTmpScb
->SCB_Status
= SCB_RENT
;
804 spin_unlock_irqrestore(&(hcsp
->HCS_AvailLock
), flags
);
808 /***************************************************************************/
809 static void tul_release_scb(HCS
* hcsp
, SCB
* scbp
)
814 printk("Release SCB %lx; ", (ULONG
) scbp
);
816 spin_lock_irqsave(&(hcsp
->HCS_AvailLock
), flags
);
817 scbp
->SCB_Srb
= NULL
;
818 scbp
->SCB_Status
= 0;
819 scbp
->SCB_NxtScb
= NULL
;
820 if (hcsp
->HCS_LastAvail
!= NULL
) {
821 hcsp
->HCS_LastAvail
->SCB_NxtScb
= scbp
;
822 hcsp
->HCS_LastAvail
= scbp
;
824 hcsp
->HCS_FirstAvail
= scbp
;
825 hcsp
->HCS_LastAvail
= scbp
;
827 spin_unlock_irqrestore(&(hcsp
->HCS_AvailLock
), flags
);
830 /***************************************************************************/
831 static void tul_append_pend_scb(HCS
* pCurHcb
, SCB
* scbp
)
835 printk("Append pend SCB %lx; ", (ULONG
) scbp
);
837 scbp
->SCB_Status
= SCB_PEND
;
838 scbp
->SCB_NxtScb
= NULL
;
839 if (pCurHcb
->HCS_LastPend
!= NULL
) {
840 pCurHcb
->HCS_LastPend
->SCB_NxtScb
= scbp
;
841 pCurHcb
->HCS_LastPend
= scbp
;
843 pCurHcb
->HCS_FirstPend
= scbp
;
844 pCurHcb
->HCS_LastPend
= scbp
;
848 /***************************************************************************/
849 static void tul_push_pend_scb(HCS
* pCurHcb
, SCB
* scbp
)
853 printk("Push pend SCB %lx; ", (ULONG
) scbp
);
855 scbp
->SCB_Status
= SCB_PEND
;
856 if ((scbp
->SCB_NxtScb
= pCurHcb
->HCS_FirstPend
) != NULL
) {
857 pCurHcb
->HCS_FirstPend
= scbp
;
859 pCurHcb
->HCS_FirstPend
= scbp
;
860 pCurHcb
->HCS_LastPend
= scbp
;
864 /***************************************************************************/
865 static SCB
*tul_find_first_pend_scb(HCS
* pCurHcb
)
870 pFirstPend
= pCurHcb
->HCS_FirstPend
;
871 while (pFirstPend
!= NULL
) {
872 if (pFirstPend
->SCB_Opcode
!= ExecSCSI
) {
875 if (pFirstPend
->SCB_TagMsg
== 0) {
876 if ((pCurHcb
->HCS_ActTags
[pFirstPend
->SCB_Target
] == 0) &&
877 !(pCurHcb
->HCS_Tcs
[pFirstPend
->SCB_Target
].TCS_Flags
& TCF_BUSY
)) {
881 if ((pCurHcb
->HCS_ActTags
[pFirstPend
->SCB_Target
] >=
882 pCurHcb
->HCS_MaxTags
[pFirstPend
->SCB_Target
]) |
883 (pCurHcb
->HCS_Tcs
[pFirstPend
->SCB_Target
].TCS_Flags
& TCF_BUSY
)) {
884 pFirstPend
= pFirstPend
->SCB_NxtScb
;
889 pFirstPend
= pFirstPend
->SCB_NxtScb
;
895 /***************************************************************************/
896 static void tul_unlink_pend_scb(HCS
* pCurHcb
, SCB
* pCurScb
)
898 SCB
*pTmpScb
, *pPrevScb
;
901 printk("unlink pend SCB %lx; ", (ULONG
) pCurScb
);
904 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstPend
;
905 while (pTmpScb
!= NULL
) {
906 if (pCurScb
== pTmpScb
) { /* Unlink this SCB */
907 if (pTmpScb
== pCurHcb
->HCS_FirstPend
) {
908 if ((pCurHcb
->HCS_FirstPend
= pTmpScb
->SCB_NxtScb
) == NULL
)
909 pCurHcb
->HCS_LastPend
= NULL
;
911 pPrevScb
->SCB_NxtScb
= pTmpScb
->SCB_NxtScb
;
912 if (pTmpScb
== pCurHcb
->HCS_LastPend
)
913 pCurHcb
->HCS_LastPend
= pPrevScb
;
915 pTmpScb
->SCB_NxtScb
= NULL
;
919 pTmpScb
= pTmpScb
->SCB_NxtScb
;
923 /***************************************************************************/
924 static void tul_append_busy_scb(HCS
* pCurHcb
, SCB
* scbp
)
928 printk("append busy SCB %lx; ", (ULONG
) scbp
);
930 if (scbp
->SCB_TagMsg
)
931 pCurHcb
->HCS_ActTags
[scbp
->SCB_Target
]++;
933 pCurHcb
->HCS_Tcs
[scbp
->SCB_Target
].TCS_Flags
|= TCF_BUSY
;
934 scbp
->SCB_Status
= SCB_BUSY
;
935 scbp
->SCB_NxtScb
= NULL
;
936 if (pCurHcb
->HCS_LastBusy
!= NULL
) {
937 pCurHcb
->HCS_LastBusy
->SCB_NxtScb
= scbp
;
938 pCurHcb
->HCS_LastBusy
= scbp
;
940 pCurHcb
->HCS_FirstBusy
= scbp
;
941 pCurHcb
->HCS_LastBusy
= scbp
;
945 /***************************************************************************/
946 static SCB
*tul_pop_busy_scb(HCS
* pCurHcb
)
951 if ((pTmpScb
= pCurHcb
->HCS_FirstBusy
) != NULL
) {
952 if ((pCurHcb
->HCS_FirstBusy
= pTmpScb
->SCB_NxtScb
) == NULL
)
953 pCurHcb
->HCS_LastBusy
= NULL
;
954 pTmpScb
->SCB_NxtScb
= NULL
;
955 if (pTmpScb
->SCB_TagMsg
)
956 pCurHcb
->HCS_ActTags
[pTmpScb
->SCB_Target
]--;
958 pCurHcb
->HCS_Tcs
[pTmpScb
->SCB_Target
].TCS_Flags
&= ~TCF_BUSY
;
961 printk("Pop busy SCB %lx; ", (ULONG
) pTmpScb
);
966 /***************************************************************************/
967 static void tul_unlink_busy_scb(HCS
* pCurHcb
, SCB
* pCurScb
)
969 SCB
*pTmpScb
, *pPrevScb
;
972 printk("unlink busy SCB %lx; ", (ULONG
) pCurScb
);
975 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstBusy
;
976 while (pTmpScb
!= NULL
) {
977 if (pCurScb
== pTmpScb
) { /* Unlink this SCB */
978 if (pTmpScb
== pCurHcb
->HCS_FirstBusy
) {
979 if ((pCurHcb
->HCS_FirstBusy
= pTmpScb
->SCB_NxtScb
) == NULL
)
980 pCurHcb
->HCS_LastBusy
= NULL
;
982 pPrevScb
->SCB_NxtScb
= pTmpScb
->SCB_NxtScb
;
983 if (pTmpScb
== pCurHcb
->HCS_LastBusy
)
984 pCurHcb
->HCS_LastBusy
= pPrevScb
;
986 pTmpScb
->SCB_NxtScb
= NULL
;
987 if (pTmpScb
->SCB_TagMsg
)
988 pCurHcb
->HCS_ActTags
[pTmpScb
->SCB_Target
]--;
990 pCurHcb
->HCS_Tcs
[pTmpScb
->SCB_Target
].TCS_Flags
&= ~TCF_BUSY
;
994 pTmpScb
= pTmpScb
->SCB_NxtScb
;
999 /***************************************************************************/
1000 SCB
*tul_find_busy_scb(HCS
* pCurHcb
, WORD tarlun
)
1002 SCB
*pTmpScb
, *pPrevScb
;
1006 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstBusy
;
1007 while (pTmpScb
!= NULL
) {
1008 scbp_tarlun
= (pTmpScb
->SCB_Lun
<< 8) | (pTmpScb
->SCB_Target
);
1009 if (scbp_tarlun
== tarlun
) { /* Unlink this SCB */
1013 pTmpScb
= pTmpScb
->SCB_NxtScb
;
1016 printk("find busy SCB %lx; ", (ULONG
) pTmpScb
);
1021 /***************************************************************************/
1022 static void tul_append_done_scb(HCS
* pCurHcb
, SCB
* scbp
)
1026 printk("append done SCB %lx; ", (ULONG
) scbp
);
1029 scbp
->SCB_Status
= SCB_DONE
;
1030 scbp
->SCB_NxtScb
= NULL
;
1031 if (pCurHcb
->HCS_LastDone
!= NULL
) {
1032 pCurHcb
->HCS_LastDone
->SCB_NxtScb
= scbp
;
1033 pCurHcb
->HCS_LastDone
= scbp
;
1035 pCurHcb
->HCS_FirstDone
= scbp
;
1036 pCurHcb
->HCS_LastDone
= scbp
;
1040 /***************************************************************************/
1041 SCB
*tul_find_done_scb(HCS
* pCurHcb
)
1046 if ((pTmpScb
= pCurHcb
->HCS_FirstDone
) != NULL
) {
1047 if ((pCurHcb
->HCS_FirstDone
= pTmpScb
->SCB_NxtScb
) == NULL
)
1048 pCurHcb
->HCS_LastDone
= NULL
;
1049 pTmpScb
->SCB_NxtScb
= NULL
;
1052 printk("find done SCB %lx; ", (ULONG
) pTmpScb
);
1057 /***************************************************************************/
1058 static int tul_abort_srb(HCS
* pCurHcb
, struct scsi_cmnd
*srbp
)
1061 SCB
*pTmpScb
, *pPrevScb
;
1063 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1065 if ((pCurHcb
->HCS_Semaph
== 0) && (pCurHcb
->HCS_ActScb
== NULL
)) {
1066 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1067 /* disable Jasmin SCSI Int */
1069 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1071 tulip_main(pCurHcb
);
1073 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1075 pCurHcb
->HCS_Semaph
= 1;
1076 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1078 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1080 return SCSI_ABORT_SNOOZE
;
1082 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstPend
; /* Check Pend queue */
1083 while (pTmpScb
!= NULL
) {
1085 if (pTmpScb
->SCB_Srb
== srbp
) {
1086 if (pTmpScb
== pCurHcb
->HCS_ActScb
) {
1087 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1088 return SCSI_ABORT_BUSY
;
1089 } else if (pTmpScb
== pCurHcb
->HCS_FirstPend
) {
1090 if ((pCurHcb
->HCS_FirstPend
= pTmpScb
->SCB_NxtScb
) == NULL
)
1091 pCurHcb
->HCS_LastPend
= NULL
;
1093 pPrevScb
->SCB_NxtScb
= pTmpScb
->SCB_NxtScb
;
1094 if (pTmpScb
== pCurHcb
->HCS_LastPend
)
1095 pCurHcb
->HCS_LastPend
= pPrevScb
;
1097 pTmpScb
->SCB_HaStat
= HOST_ABORTED
;
1098 pTmpScb
->SCB_Flags
|= SCF_DONE
;
1099 if (pTmpScb
->SCB_Flags
& SCF_POST
)
1100 (*pTmpScb
->SCB_Post
) ((BYTE
*) pCurHcb
, (BYTE
*) pTmpScb
);
1101 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1102 return SCSI_ABORT_SUCCESS
;
1105 pTmpScb
= pTmpScb
->SCB_NxtScb
;
1108 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstBusy
; /* Check Busy queue */
1109 while (pTmpScb
!= NULL
) {
1111 if (pTmpScb
->SCB_Srb
== srbp
) {
1113 if (pTmpScb
== pCurHcb
->HCS_ActScb
) {
1114 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1115 return SCSI_ABORT_BUSY
;
1116 } else if (pTmpScb
->SCB_TagMsg
== 0) {
1117 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1118 return SCSI_ABORT_BUSY
;
1120 pCurHcb
->HCS_ActTags
[pTmpScb
->SCB_Target
]--;
1121 if (pTmpScb
== pCurHcb
->HCS_FirstBusy
) {
1122 if ((pCurHcb
->HCS_FirstBusy
= pTmpScb
->SCB_NxtScb
) == NULL
)
1123 pCurHcb
->HCS_LastBusy
= NULL
;
1125 pPrevScb
->SCB_NxtScb
= pTmpScb
->SCB_NxtScb
;
1126 if (pTmpScb
== pCurHcb
->HCS_LastBusy
)
1127 pCurHcb
->HCS_LastBusy
= pPrevScb
;
1129 pTmpScb
->SCB_NxtScb
= NULL
;
1132 pTmpScb
->SCB_HaStat
= HOST_ABORTED
;
1133 pTmpScb
->SCB_Flags
|= SCF_DONE
;
1134 if (pTmpScb
->SCB_Flags
& SCF_POST
)
1135 (*pTmpScb
->SCB_Post
) ((BYTE
*) pCurHcb
, (BYTE
*) pTmpScb
);
1136 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1137 return SCSI_ABORT_SUCCESS
;
1141 pTmpScb
= pTmpScb
->SCB_NxtScb
;
1143 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1144 return (SCSI_ABORT_NOT_RUNNING
);
1147 /***************************************************************************/
1148 static int tul_bad_seq(HCS
* pCurHcb
)
1152 printk("tul_bad_seg c=%d\n", pCurHcb
->HCS_Index
);
1154 if ((pCurScb
= pCurHcb
->HCS_ActScb
) != NULL
) {
1155 tul_unlink_busy_scb(pCurHcb
, pCurScb
);
1156 pCurScb
->SCB_HaStat
= HOST_BAD_PHAS
;
1157 pCurScb
->SCB_TaStat
= 0;
1158 tul_append_done_scb(pCurHcb
, pCurScb
);
1160 tul_stop_bm(pCurHcb
);
1162 tul_reset_scsi(pCurHcb
, 8); /* 7/29/98 */
1164 return (tul_post_scsi_rst(pCurHcb
));
1169 /************************************************************************/
1170 static int tul_device_reset(HCS
* pCurHcb
, struct scsi_cmnd
*pSrb
,
1171 unsigned int target
, unsigned int ResetFlags
)
1175 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1177 if (ResetFlags
& SCSI_RESET_ASYNCHRONOUS
) {
1179 if ((pCurHcb
->HCS_Semaph
== 0) && (pCurHcb
->HCS_ActScb
== NULL
)) {
1180 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1181 /* disable Jasmin SCSI Int */
1183 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1185 tulip_main(pCurHcb
);
1187 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1189 pCurHcb
->HCS_Semaph
= 1;
1190 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1192 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1194 return SCSI_RESET_SNOOZE
;
1196 pScb
= pCurHcb
->HCS_FirstBusy
; /* Check Busy queue */
1197 while (pScb
!= NULL
) {
1198 if (pScb
->SCB_Srb
== pSrb
)
1200 pScb
= pScb
->SCB_NxtScb
;
1203 printk("Unable to Reset - No SCB Found\n");
1205 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1206 return SCSI_RESET_NOT_RUNNING
;
1209 if ((pScb
= tul_alloc_scb(pCurHcb
)) == NULL
) {
1210 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1211 return SCSI_RESET_NOT_RUNNING
;
1213 pScb
->SCB_Opcode
= BusDevRst
;
1214 pScb
->SCB_Flags
= SCF_POST
;
1215 pScb
->SCB_Target
= target
;
1218 pScb
->SCB_Srb
= NULL
;
1219 if (ResetFlags
& SCSI_RESET_SYNCHRONOUS
) {
1220 pScb
->SCB_Srb
= pSrb
;
1222 tul_push_pend_scb(pCurHcb
, pScb
); /* push this SCB to Pending queue */
1224 if (pCurHcb
->HCS_Semaph
== 1) {
1225 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1226 /* disable Jasmin SCSI Int */
1227 pCurHcb
->HCS_Semaph
= 0;
1229 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1231 tulip_main(pCurHcb
);
1233 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1235 pCurHcb
->HCS_Semaph
= 1;
1236 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1238 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1239 return SCSI_RESET_PENDING
;
1242 static int tul_reset_scsi_bus(HCS
* pCurHcb
)
1246 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1247 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1248 pCurHcb
->HCS_Semaph
= 0;
1250 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1252 tul_stop_bm(pCurHcb
);
1254 tul_reset_scsi(pCurHcb
, 2); /* 7/29/98 */
1256 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1257 tul_post_scsi_rst(pCurHcb
);
1259 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1261 tulip_main(pCurHcb
);
1263 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1265 pCurHcb
->HCS_Semaph
= 1;
1266 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1267 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1268 return (SCSI_RESET_SUCCESS
| SCSI_RESET_HOST_RESET
);
1273 /************************************************************************/
1274 static void tul_exec_scb(HCS
* pCurHcb
, SCB
* pCurScb
)
1278 pCurScb
->SCB_Mode
= 0;
1280 pCurScb
->SCB_SGIdx
= 0;
1281 pCurScb
->SCB_SGMax
= pCurScb
->SCB_SGLen
;
1283 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1285 tul_append_pend_scb(pCurHcb
, pCurScb
); /* Append this SCB to Pending queue */
1287 /* VVVVV 07/21/98 */
1288 if (pCurHcb
->HCS_Semaph
== 1) {
1289 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1290 /* disable Jasmin SCSI Int */
1291 pCurHcb
->HCS_Semaph
= 0;
1293 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1295 tulip_main(pCurHcb
);
1297 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1299 pCurHcb
->HCS_Semaph
= 1;
1300 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1302 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1306 /***************************************************************************/
1307 static int tul_isr(HCS
* pCurHcb
)
1309 /* Enter critical section */
1311 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_Int
) & TSS_INT_PENDING
) {
1312 if (pCurHcb
->HCS_Semaph
== 1) {
1313 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1314 /* Disable Tulip SCSI Int */
1315 pCurHcb
->HCS_Semaph
= 0;
1317 tulip_main(pCurHcb
);
1319 pCurHcb
->HCS_Semaph
= 1;
1320 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1327 /***************************************************************************/
1328 int tulip_main(HCS
* pCurHcb
)
1334 tulip_scsi(pCurHcb
); /* Call tulip_scsi */
1336 while ((pCurScb
= tul_find_done_scb(pCurHcb
)) != NULL
) { /* find done entry */
1337 if (pCurScb
->SCB_TaStat
== INI_QUEUE_FULL
) {
1338 pCurHcb
->HCS_MaxTags
[pCurScb
->SCB_Target
] =
1339 pCurHcb
->HCS_ActTags
[pCurScb
->SCB_Target
] - 1;
1340 pCurScb
->SCB_TaStat
= 0;
1341 tul_append_pend_scb(pCurHcb
, pCurScb
);
1344 if (!(pCurScb
->SCB_Mode
& SCM_RSENS
)) { /* not in auto req. sense mode */
1345 if (pCurScb
->SCB_TaStat
== 2) {
1347 /* clr sync. nego flag */
1349 if (pCurScb
->SCB_Flags
& SCF_SENSE
) {
1351 len
= pCurScb
->SCB_SenseLen
;
1354 pCurScb
->SCB_BufLen
= pCurScb
->SCB_SenseLen
;
1355 pCurScb
->SCB_BufPtr
= pCurScb
->SCB_SensePtr
;
1356 pCurScb
->SCB_Flags
&= ~(SCF_SG
| SCF_DIR
); /* for xfer_data_in */
1357 /* pCurScb->SCB_Flags |= SCF_NO_DCHK; */
1358 /* so, we won't report worng direction in xfer_data_in,
1359 and won't report HOST_DO_DU in state_6 */
1360 pCurScb
->SCB_Mode
= SCM_RSENS
;
1361 pCurScb
->SCB_Ident
&= 0xBF; /* Disable Disconnect */
1362 pCurScb
->SCB_TagMsg
= 0;
1363 pCurScb
->SCB_TaStat
= 0;
1364 pCurScb
->SCB_CDBLen
= 6;
1365 pCurScb
->SCB_CDB
[0] = SCSICMD_RequestSense
;
1366 pCurScb
->SCB_CDB
[1] = 0;
1367 pCurScb
->SCB_CDB
[2] = 0;
1368 pCurScb
->SCB_CDB
[3] = 0;
1369 pCurScb
->SCB_CDB
[4] = len
;
1370 pCurScb
->SCB_CDB
[5] = 0;
1371 tul_push_pend_scb(pCurHcb
, pCurScb
);
1375 } else { /* in request sense mode */
1377 if (pCurScb
->SCB_TaStat
== 2) { /* check contition status again after sending
1378 requset sense cmd 0x3 */
1379 pCurScb
->SCB_HaStat
= HOST_BAD_PHAS
;
1381 pCurScb
->SCB_TaStat
= 2;
1383 pCurScb
->SCB_Flags
|= SCF_DONE
;
1384 if (pCurScb
->SCB_Flags
& SCF_POST
) {
1385 (*pCurScb
->SCB_Post
) ((BYTE
*) pCurHcb
, (BYTE
*) pCurScb
);
1390 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus0
) & TSS_INT_PENDING
)
1393 if (pCurHcb
->HCS_ActScb
) { /* return to OS and wait for xfer_done_ISR/Selected_ISR */
1394 return 1; /* return to OS, enable interrupt */
1396 /* Check pending SCB */
1397 if (tul_find_first_pend_scb(pCurHcb
) == NULL
) {
1398 return 1; /* return to OS, enable interrupt */
1400 } /* End of for loop */
1401 /* statement won't reach here */
1407 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
1408 /***************************************************************************/
1409 /***************************************************************************/
1410 /***************************************************************************/
1411 /***************************************************************************/
1413 /***************************************************************************/
1414 void tulip_scsi(HCS
* pCurHcb
)
1419 /* make sure to service interrupt asap */
1421 if ((pCurHcb
->HCS_JSStatus0
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus0
)) & TSS_INT_PENDING
) {
1423 pCurHcb
->HCS_Phase
= pCurHcb
->HCS_JSStatus0
& TSS_PH_MASK
;
1424 pCurHcb
->HCS_JSStatus1
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus1
);
1425 pCurHcb
->HCS_JSInt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
);
1426 if (pCurHcb
->HCS_JSInt
& TSS_SCSIRST_INT
) { /* SCSI bus reset detected */
1427 int_tul_scsi_rst(pCurHcb
);
1430 if (pCurHcb
->HCS_JSInt
& TSS_RESEL_INT
) { /* if selected/reselected interrupt */
1431 if (int_tul_resel(pCurHcb
) == 0)
1432 tul_next_state(pCurHcb
);
1435 if (pCurHcb
->HCS_JSInt
& TSS_SEL_TIMEOUT
) {
1436 int_tul_busfree(pCurHcb
);
1439 if (pCurHcb
->HCS_JSInt
& TSS_DISC_INT
) { /* BUS disconnection */
1440 int_tul_busfree(pCurHcb
); /* unexpected bus free or sel timeout */
1443 if (pCurHcb
->HCS_JSInt
& (TSS_FUNC_COMP
| TSS_BUS_SERV
)) { /* func complete or Bus service */
1444 if ((pCurScb
= pCurHcb
->HCS_ActScb
) != NULL
)
1445 tul_next_state(pCurHcb
);
1449 if (pCurHcb
->HCS_ActScb
!= NULL
)
1452 if ((pCurScb
= tul_find_first_pend_scb(pCurHcb
)) == NULL
)
1455 /* program HBA's SCSI ID & target SCSI ID */
1456 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SScsiId
,
1457 (pCurHcb
->HCS_SCSI_ID
<< 4) | (pCurScb
->SCB_Target
& 0x0F));
1458 if (pCurScb
->SCB_Opcode
== ExecSCSI
) {
1459 pCurTcb
= &pCurHcb
->HCS_Tcs
[pCurScb
->SCB_Target
];
1461 if (pCurScb
->SCB_TagMsg
)
1462 pCurTcb
->TCS_DrvFlags
|= TCF_DRV_EN_TAG
;
1464 pCurTcb
->TCS_DrvFlags
&= ~TCF_DRV_EN_TAG
;
1466 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SPeriod
, pCurTcb
->TCS_JS_Period
);
1467 if ((pCurTcb
->TCS_Flags
& (TCF_WDTR_DONE
| TCF_NO_WDTR
)) == 0) { /* do wdtr negotiation */
1468 tul_select_atn_stop(pCurHcb
, pCurScb
);
1470 if ((pCurTcb
->TCS_Flags
& (TCF_SYNC_DONE
| TCF_NO_SYNC_NEGO
)) == 0) { /* do sync negotiation */
1471 tul_select_atn_stop(pCurHcb
, pCurScb
);
1473 if (pCurScb
->SCB_TagMsg
)
1474 tul_select_atn3(pCurHcb
, pCurScb
);
1476 tul_select_atn(pCurHcb
, pCurScb
);
1479 if (pCurScb
->SCB_Flags
& SCF_POLL
) {
1480 while (wait_tulip(pCurHcb
) != -1) {
1481 if (tul_next_state(pCurHcb
) == -1)
1485 } else if (pCurScb
->SCB_Opcode
== BusDevRst
) {
1486 tul_select_atn_stop(pCurHcb
, pCurScb
);
1487 pCurScb
->SCB_NxtStat
= 8;
1488 if (pCurScb
->SCB_Flags
& SCF_POLL
) {
1489 while (wait_tulip(pCurHcb
) != -1) {
1490 if (tul_next_state(pCurHcb
) == -1)
1494 } else if (pCurScb
->SCB_Opcode
== AbortCmd
) {
1495 if (tul_abort_srb(pCurHcb
, pCurScb
->SCB_Srb
) != 0) {
1498 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
1500 tul_release_scb(pCurHcb
, pCurScb
);
1502 pCurScb
->SCB_Opcode
= BusDevRst
;
1503 tul_select_atn_stop(pCurHcb
, pCurScb
);
1504 pCurScb
->SCB_NxtStat
= 8;
1509 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
1510 pCurScb
->SCB_HaStat
= 0x16; /* bad command */
1511 tul_append_done_scb(pCurHcb
, pCurScb
);
1517 /***************************************************************************/
1518 int tul_next_state(HCS
* pCurHcb
)
1522 next
= pCurHcb
->HCS_ActScb
->SCB_NxtStat
;
1526 next
= tul_state_1(pCurHcb
);
1529 next
= tul_state_2(pCurHcb
);
1532 next
= tul_state_3(pCurHcb
);
1535 next
= tul_state_4(pCurHcb
);
1538 next
= tul_state_5(pCurHcb
);
1541 next
= tul_state_6(pCurHcb
);
1544 next
= tul_state_7(pCurHcb
);
1547 return (tul_bus_device_reset(pCurHcb
));
1549 return (tul_bad_seq(pCurHcb
));
1557 /***************************************************************************/
1558 /* sTate after selection with attention & stop */
1559 int tul_state_1(HCS
* pCurHcb
)
1561 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1562 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
1567 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
1568 tul_append_busy_scb(pCurHcb
, pCurScb
);
1570 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurTcb
->TCS_SConfig0
);
1572 if (pCurHcb
->HCS_Phase
== MSG_OUT
) {
1574 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, (TSC_EN_BUS_IN
| TSC_HW_RESELECT
));
1576 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_Ident
);
1578 if (pCurScb
->SCB_TagMsg
) {
1579 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_TagMsg
);
1580 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_TagId
);
1582 if ((pCurTcb
->TCS_Flags
& (TCF_WDTR_DONE
| TCF_NO_WDTR
)) == 0) {
1584 pCurTcb
->TCS_Flags
|= TCF_WDTR_DONE
;
1586 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_EXTEND
);
1587 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 2); /* Extended msg length */
1588 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 3); /* Sync request */
1589 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 1); /* Start from 16 bits */
1590 } else if ((pCurTcb
->TCS_Flags
& (TCF_SYNC_DONE
| TCF_NO_SYNC_NEGO
)) == 0) {
1592 pCurTcb
->TCS_Flags
|= TCF_SYNC_DONE
;
1594 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_EXTEND
);
1595 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 3); /* extended msg length */
1596 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 1); /* sync request */
1597 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, tul_rate_tbl
[pCurTcb
->TCS_Flags
& TCF_SCSI_RATE
]);
1598 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MAX_OFFSET
); /* REQ/ACK offset */
1600 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1601 if (wait_tulip(pCurHcb
) == -1)
1604 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1605 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, (TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)));
1610 /***************************************************************************/
1611 /* state after selection with attention */
1612 /* state after selection with attention3 */
1613 int tul_state_2(HCS
* pCurHcb
)
1615 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1616 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
1621 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
1622 tul_append_busy_scb(pCurHcb
, pCurScb
);
1624 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurTcb
->TCS_SConfig0
);
1626 if (pCurHcb
->HCS_JSStatus1
& TSS_CMD_PH_CMP
) {
1629 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1630 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, (TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)));
1634 /***************************************************************************/
1635 /* state before CDB xfer is done */
1636 int tul_state_3(HCS
* pCurHcb
)
1638 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1639 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
1646 switch (pCurHcb
->HCS_Phase
) {
1647 case CMD_OUT
: /* Command out phase */
1648 for (i
= 0; i
< (int) pCurScb
->SCB_CDBLen
; i
++)
1649 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_CDB
[i
]);
1650 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1651 if (wait_tulip(pCurHcb
) == -1)
1653 if (pCurHcb
->HCS_Phase
== CMD_OUT
) {
1654 return (tul_bad_seq(pCurHcb
));
1658 case MSG_IN
: /* Message in phase */
1659 pCurScb
->SCB_NxtStat
= 3;
1660 if (tul_msgin(pCurHcb
) == -1)
1664 case STATUS_IN
: /* Status phase */
1665 if (tul_status_msg(pCurHcb
) == -1)
1669 case MSG_OUT
: /* Message out phase */
1670 if (pCurTcb
->TCS_Flags
& (TCF_SYNC_DONE
| TCF_NO_SYNC_NEGO
)) {
1672 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_NOP
); /* msg nop */
1673 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1674 if (wait_tulip(pCurHcb
) == -1)
1678 pCurTcb
->TCS_Flags
|= TCF_SYNC_DONE
;
1680 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_EXTEND
);
1681 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 3); /* ext. msg len */
1682 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 1); /* sync request */
1683 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, tul_rate_tbl
[pCurTcb
->TCS_Flags
& TCF_SCSI_RATE
]);
1684 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MAX_OFFSET
); /* REQ/ACK offset */
1685 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1686 if (wait_tulip(pCurHcb
) == -1)
1688 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1689 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7));
1695 return (tul_bad_seq(pCurHcb
));
1701 /***************************************************************************/
1702 int tul_state_4(HCS
* pCurHcb
)
1704 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1709 if ((pCurScb
->SCB_Flags
& SCF_DIR
) == SCF_NO_XF
) {
1710 return (6); /* Go to state 6 */
1713 if (pCurScb
->SCB_BufLen
== 0)
1714 return (6); /* Go to state 6 */
1716 switch (pCurHcb
->HCS_Phase
) {
1718 case STATUS_IN
: /* Status phase */
1719 if ((pCurScb
->SCB_Flags
& SCF_DIR
) != 0) { /* if direction bit set then report data underrun */
1720 pCurScb
->SCB_HaStat
= HOST_DO_DU
;
1722 if ((tul_status_msg(pCurHcb
)) == -1)
1726 case MSG_IN
: /* Message in phase */
1727 pCurScb
->SCB_NxtStat
= 0x4;
1728 if (tul_msgin(pCurHcb
) == -1)
1732 case MSG_OUT
: /* Message out phase */
1733 if (pCurHcb
->HCS_JSStatus0
& TSS_PAR_ERROR
) {
1734 pCurScb
->SCB_BufLen
= 0;
1735 pCurScb
->SCB_HaStat
= HOST_DO_DU
;
1736 if (tul_msgout_ide(pCurHcb
) == -1)
1738 return (6); /* Go to state 6 */
1740 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_NOP
); /* msg nop */
1741 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1742 if (wait_tulip(pCurHcb
) == -1)
1747 case DATA_IN
: /* Data in phase */
1748 return (tul_xfer_data_in(pCurHcb
));
1750 case DATA_OUT
: /* Data out phase */
1751 return (tul_xfer_data_out(pCurHcb
));
1754 return (tul_bad_seq(pCurHcb
));
1760 /***************************************************************************/
1761 /* state after dma xfer done or phase change before xfer done */
1762 int tul_state_5(HCS
* pCurHcb
)
1764 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1765 long cnt
, xcnt
; /* cannot use unsigned !! code: if (xcnt < 0) */
1770 /*------ get remaining count -------*/
1772 cnt
= TUL_RDLONG(pCurHcb
->HCS_Base
, TUL_SCnt0
) & 0x0FFFFFF;
1774 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_XCmd
) & 0x20) {
1775 /* ----------------------- DATA_IN ----------------------------- */
1776 /* check scsi parity error */
1777 if (pCurHcb
->HCS_JSStatus0
& TSS_PAR_ERROR
) {
1778 pCurScb
->SCB_HaStat
= HOST_DO_DU
;
1780 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_XStatus
) & XPEND
) { /* DMA xfer pending, Send STOP */
1781 /* tell Hardware scsi xfer has been terminated */
1782 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCtrl
, TUL_RD(pCurHcb
->HCS_Base
, TUL_XCtrl
) | 0x80);
1783 /* wait until DMA xfer not pending */
1784 while (TUL_RD(pCurHcb
->HCS_Base
, TUL_XStatus
) & XPEND
);
1787 /*-------- DATA OUT -----------*/
1788 if ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus1
) & TSS_XFER_CMP
) == 0) {
1789 if (pCurHcb
->HCS_ActTcs
->TCS_JS_Period
& TSC_WIDE_SCSI
)
1790 cnt
+= (TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifoCnt
) & 0x1F) << 1;
1792 cnt
+= (TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifoCnt
) & 0x1F);
1794 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_XStatus
) & XPEND
) { /* if DMA xfer is pending, abort DMA xfer */
1795 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_X_ABT
);
1796 /* wait Abort DMA xfer done */
1797 while ((TUL_RD(pCurHcb
->HCS_Base
, TUL_Int
) & XABT
) == 0);
1799 if ((cnt
== 1) && (pCurHcb
->HCS_Phase
== DATA_OUT
)) {
1800 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1801 if (wait_tulip(pCurHcb
) == -1) {
1806 if ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus1
) & TSS_XFER_CMP
) == 0)
1807 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1812 pCurScb
->SCB_BufLen
= 0;
1813 return (6); /* Go to state 6 */
1815 /* Update active data pointer */
1816 xcnt
= (long) pCurScb
->SCB_BufLen
- cnt
; /* xcnt== bytes already xferred */
1817 pCurScb
->SCB_BufLen
= (U32
) cnt
; /* cnt == bytes left to be xferred */
1818 if (pCurScb
->SCB_Flags
& SCF_SG
) {
1822 sgp
= &pCurScb
->SCB_SGList
[pCurScb
->SCB_SGIdx
];
1823 for (i
= pCurScb
->SCB_SGIdx
; i
< pCurScb
->SCB_SGMax
; sgp
++, i
++) {
1824 xcnt
-= (long) sgp
->SG_Len
;
1825 if (xcnt
< 0) { /* this sgp xfer half done */
1826 xcnt
+= (long) sgp
->SG_Len
; /* xcnt == bytes xferred in this sgp */
1827 sgp
->SG_Ptr
+= (U32
) xcnt
; /* new ptr to be xfer */
1828 sgp
->SG_Len
-= (U32
) xcnt
; /* new len to be xfer */
1829 pCurScb
->SCB_BufPtr
+= ((U32
) (i
- pCurScb
->SCB_SGIdx
) << 3);
1830 /* new SG table ptr */
1831 pCurScb
->SCB_SGLen
= (BYTE
) (pCurScb
->SCB_SGMax
- i
);
1832 /* new SG table len */
1833 pCurScb
->SCB_SGIdx
= (WORD
) i
;
1834 /* for next disc and come in this loop */
1835 return (4); /* Go to state 4 */
1837 /* else (xcnt >= 0 , i.e. this sgp already xferred */
1839 return (6); /* Go to state 6 */
1841 pCurScb
->SCB_BufPtr
+= (U32
) xcnt
;
1843 return (4); /* Go to state 4 */
1846 /***************************************************************************/
1847 /* state after Data phase */
1848 int tul_state_6(HCS
* pCurHcb
)
1850 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1856 switch (pCurHcb
->HCS_Phase
) {
1857 case STATUS_IN
: /* Status phase */
1858 if ((tul_status_msg(pCurHcb
)) == -1)
1862 case MSG_IN
: /* Message in phase */
1863 pCurScb
->SCB_NxtStat
= 6;
1864 if ((tul_msgin(pCurHcb
)) == -1)
1868 case MSG_OUT
: /* Message out phase */
1869 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_NOP
); /* msg nop */
1870 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1871 if (wait_tulip(pCurHcb
) == -1)
1875 case DATA_IN
: /* Data in phase */
1876 return (tul_xpad_in(pCurHcb
));
1878 case DATA_OUT
: /* Data out phase */
1879 return (tul_xpad_out(pCurHcb
));
1882 return (tul_bad_seq(pCurHcb
));
1887 /***************************************************************************/
1888 int tul_state_7(HCS
* pCurHcb
)
1895 /* flush SCSI FIFO */
1896 cnt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifoCnt
) & 0x1F;
1898 for (i
= 0; i
< cnt
; i
++)
1899 TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
1901 switch (pCurHcb
->HCS_Phase
) {
1902 case DATA_IN
: /* Data in phase */
1903 case DATA_OUT
: /* Data out phase */
1904 return (tul_bad_seq(pCurHcb
));
1906 return (6); /* Go to state 6 */
1910 /***************************************************************************/
1911 int tul_xfer_data_in(HCS
* pCurHcb
)
1913 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1915 if ((pCurScb
->SCB_Flags
& SCF_DIR
) == SCF_DOUT
) {
1916 return (6); /* wrong direction */
1918 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, pCurScb
->SCB_BufLen
);
1920 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_DMA_IN
); /* 7/25/95 */
1922 if (pCurScb
->SCB_Flags
& SCF_SG
) { /* S/G xfer */
1923 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XCntH
, ((ULONG
) pCurScb
->SCB_SGLen
) << 3);
1924 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XAddH
, pCurScb
->SCB_BufPtr
);
1925 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_SG_IN
);
1927 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XCntH
, pCurScb
->SCB_BufLen
);
1928 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XAddH
, pCurScb
->SCB_BufPtr
);
1929 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_X_IN
);
1931 pCurScb
->SCB_NxtStat
= 0x5;
1932 return (0); /* return to OS, wait xfer done , let jas_isr come in */
1936 /***************************************************************************/
1937 int tul_xfer_data_out(HCS
* pCurHcb
)
1939 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1941 if ((pCurScb
->SCB_Flags
& SCF_DIR
) == SCF_DIN
) {
1942 return (6); /* wrong direction */
1944 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, pCurScb
->SCB_BufLen
);
1945 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_DMA_OUT
);
1947 if (pCurScb
->SCB_Flags
& SCF_SG
) { /* S/G xfer */
1948 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XCntH
, ((ULONG
) pCurScb
->SCB_SGLen
) << 3);
1949 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XAddH
, pCurScb
->SCB_BufPtr
);
1950 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_SG_OUT
);
1952 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XCntH
, pCurScb
->SCB_BufLen
);
1953 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XAddH
, pCurScb
->SCB_BufPtr
);
1954 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_X_OUT
);
1957 pCurScb
->SCB_NxtStat
= 0x5;
1958 return (0); /* return to OS, wait xfer done , let jas_isr come in */
1962 /***************************************************************************/
1963 int tul_xpad_in(HCS
* pCurHcb
)
1965 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1966 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
1968 if ((pCurScb
->SCB_Flags
& SCF_DIR
) != SCF_NO_DCHK
) {
1969 pCurScb
->SCB_HaStat
= HOST_DO_DU
; /* over run */
1972 if (pCurTcb
->TCS_JS_Period
& TSC_WIDE_SCSI
)
1973 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 2);
1975 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
1977 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
1978 if ((wait_tulip(pCurHcb
)) == -1) {
1981 if (pCurHcb
->HCS_Phase
!= DATA_IN
) {
1982 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1985 TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
1989 int tul_xpad_out(HCS
* pCurHcb
)
1991 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1992 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
1994 if ((pCurScb
->SCB_Flags
& SCF_DIR
) != SCF_NO_DCHK
) {
1995 pCurScb
->SCB_HaStat
= HOST_DO_DU
; /* over run */
1998 if (pCurTcb
->TCS_JS_Period
& TSC_WIDE_SCSI
)
1999 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 2);
2001 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2003 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 0);
2004 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2005 if ((wait_tulip(pCurHcb
)) == -1) {
2008 if (pCurHcb
->HCS_Phase
!= DATA_OUT
) { /* Disable wide CPU to allow read 16 bits */
2009 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
);
2010 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2017 /***************************************************************************/
2018 int tul_status_msg(HCS
* pCurHcb
)
2019 { /* status & MSG_IN */
2020 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
2023 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_CMD_COMP
);
2024 if ((wait_tulip(pCurHcb
)) == -1) {
2028 pCurScb
->SCB_TaStat
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
2030 if (pCurHcb
->HCS_Phase
== MSG_OUT
) {
2031 if (pCurHcb
->HCS_JSStatus0
& TSS_PAR_ERROR
) {
2032 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_PARITY
);
2034 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_NOP
);
2036 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2037 return (wait_tulip(pCurHcb
));
2039 if (pCurHcb
->HCS_Phase
== MSG_IN
) {
2040 msg
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
2041 if (pCurHcb
->HCS_JSStatus0
& TSS_PAR_ERROR
) { /* Parity error */
2042 if ((tul_msgin_accept(pCurHcb
)) == -1)
2044 if (pCurHcb
->HCS_Phase
!= MSG_OUT
)
2045 return (tul_bad_seq(pCurHcb
));
2046 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_PARITY
);
2047 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2048 return (wait_tulip(pCurHcb
));
2050 if (msg
== 0) { /* Command complete */
2052 if ((pCurScb
->SCB_TaStat
& 0x18) == 0x10) { /* No link support */
2053 return (tul_bad_seq(pCurHcb
));
2055 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2056 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_MSG_ACCEPT
);
2057 return tul_wait_done_disc(pCurHcb
);
2060 if ((msg
== MSG_LINK_COMP
) || (msg
== MSG_LINK_FLAG
)) {
2061 if ((pCurScb
->SCB_TaStat
& 0x18) == 0x10)
2062 return (tul_msgin_accept(pCurHcb
));
2065 return (tul_bad_seq(pCurHcb
));
2069 /***************************************************************************/
2071 int int_tul_busfree(HCS
* pCurHcb
)
2073 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
2075 if (pCurScb
!= NULL
) {
2076 if (pCurScb
->SCB_Status
& SCB_SELECT
) { /* selection timeout */
2077 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
2078 pCurScb
->SCB_HaStat
= HOST_SEL_TOUT
;
2079 tul_append_done_scb(pCurHcb
, pCurScb
);
2080 } else { /* Unexpected bus free */
2081 tul_unlink_busy_scb(pCurHcb
, pCurScb
);
2082 pCurScb
->SCB_HaStat
= HOST_BUS_FREE
;
2083 tul_append_done_scb(pCurHcb
, pCurScb
);
2085 pCurHcb
->HCS_ActScb
= NULL
;
2086 pCurHcb
->HCS_ActTcs
= NULL
;
2088 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
); /* Flush SCSI FIFO */
2089 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, TSC_INITDEFAULT
);
2090 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
); /* Enable HW reselect */
2095 /***************************************************************************/
2096 /* scsi bus reset */
2097 static int int_tul_scsi_rst(HCS
* pCurHcb
)
2102 /* if DMA xfer is pending, abort DMA xfer */
2103 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_XStatus
) & 0x01) {
2104 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_X_ABT
| TAX_X_CLR_FIFO
);
2105 /* wait Abort DMA xfer done */
2106 while ((TUL_RD(pCurHcb
->HCS_Base
, TUL_Int
) & 0x04) == 0);
2107 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2109 /* Abort all active & disconnected scb */
2110 while ((pCurScb
= tul_pop_busy_scb(pCurHcb
)) != NULL
) {
2111 pCurScb
->SCB_HaStat
= HOST_BAD_PHAS
;
2112 tul_append_done_scb(pCurHcb
, pCurScb
);
2114 pCurHcb
->HCS_ActScb
= NULL
;
2115 pCurHcb
->HCS_ActTcs
= NULL
;
2117 /* clr sync nego. done flag */
2118 for (i
= 0; i
< pCurHcb
->HCS_MaxTar
; i
++) {
2119 pCurHcb
->HCS_Tcs
[i
].TCS_Flags
&= ~(TCF_SYNC_DONE
| TCF_WDTR_DONE
);
2125 /***************************************************************************/
2126 /* scsi reselection */
2127 int int_tul_resel(HCS
* pCurHcb
)
2134 if ((pCurScb
= pCurHcb
->HCS_ActScb
) != NULL
) {
2135 if (pCurScb
->SCB_Status
& SCB_SELECT
) { /* if waiting for selection complete */
2136 pCurScb
->SCB_Status
&= ~SCB_SELECT
;
2138 pCurHcb
->HCS_ActScb
= NULL
;
2140 /* --------- get target id---------------------- */
2141 tar
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SBusId
);
2142 /* ------ get LUN from Identify message----------- */
2143 lun
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SIdent
) & 0x0F;
2144 /* 07/22/98 from 0x1F -> 0x0F */
2145 pCurTcb
= &pCurHcb
->HCS_Tcs
[tar
];
2146 pCurHcb
->HCS_ActTcs
= pCurTcb
;
2147 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurTcb
->TCS_SConfig0
);
2148 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SPeriod
, pCurTcb
->TCS_JS_Period
);
2151 /* ------------- tag queueing ? ------------------- */
2152 if (pCurTcb
->TCS_DrvFlags
& TCF_DRV_EN_TAG
) {
2153 if ((tul_msgin_accept(pCurHcb
)) == -1)
2155 if (pCurHcb
->HCS_Phase
!= MSG_IN
)
2157 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2158 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2159 if ((wait_tulip(pCurHcb
)) == -1)
2161 msg
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
); /* Read Tag Message */
2163 if ((msg
< MSG_STAG
) || (msg
> MSG_OTAG
)) /* Is simple Tag */
2166 if ((tul_msgin_accept(pCurHcb
)) == -1)
2169 if (pCurHcb
->HCS_Phase
!= MSG_IN
)
2172 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2173 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2174 if ((wait_tulip(pCurHcb
)) == -1)
2176 tag
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
); /* Read Tag ID */
2177 pCurScb
= pCurHcb
->HCS_Scb
+ tag
;
2178 if ((pCurScb
->SCB_Target
!= tar
) || (pCurScb
->SCB_Lun
!= lun
)) {
2179 return tul_msgout_abort_tag(pCurHcb
);
2181 if (pCurScb
->SCB_Status
!= SCB_BUSY
) { /* 03/24/95 */
2182 return tul_msgout_abort_tag(pCurHcb
);
2184 pCurHcb
->HCS_ActScb
= pCurScb
;
2185 if ((tul_msgin_accept(pCurHcb
)) == -1)
2187 } else { /* No tag */
2189 if ((pCurScb
= tul_find_busy_scb(pCurHcb
, tar
| (lun
<< 8))) == NULL
) {
2190 return tul_msgout_abort_targ(pCurHcb
);
2192 pCurHcb
->HCS_ActScb
= pCurScb
;
2193 if (!(pCurTcb
->TCS_DrvFlags
& TCF_DRV_EN_TAG
)) {
2194 if ((tul_msgin_accept(pCurHcb
)) == -1)
2202 /***************************************************************************/
2203 static int int_tul_bad_seq(HCS
* pCurHcb
)
2204 { /* target wrong phase */
2208 tul_reset_scsi(pCurHcb
, 10);
2210 while ((pCurScb
= tul_pop_busy_scb(pCurHcb
)) != NULL
) {
2211 pCurScb
->SCB_HaStat
= HOST_BAD_PHAS
;
2212 tul_append_done_scb(pCurHcb
, pCurScb
);
2214 for (i
= 0; i
< pCurHcb
->HCS_MaxTar
; i
++) {
2215 pCurHcb
->HCS_Tcs
[i
].TCS_Flags
&= ~(TCF_SYNC_DONE
| TCF_WDTR_DONE
);
2221 /***************************************************************************/
2222 int tul_msgout_abort_targ(HCS
* pCurHcb
)
2225 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2226 if (tul_msgin_accept(pCurHcb
) == -1)
2228 if (pCurHcb
->HCS_Phase
!= MSG_OUT
)
2229 return (tul_bad_seq(pCurHcb
));
2231 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_ABORT
);
2232 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2234 return tul_wait_disc(pCurHcb
);
2237 /***************************************************************************/
2238 int tul_msgout_abort_tag(HCS
* pCurHcb
)
2241 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2242 if (tul_msgin_accept(pCurHcb
) == -1)
2244 if (pCurHcb
->HCS_Phase
!= MSG_OUT
)
2245 return (tul_bad_seq(pCurHcb
));
2247 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_ABORT_TAG
);
2248 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2250 return tul_wait_disc(pCurHcb
);
2254 /***************************************************************************/
2255 int tul_msgin(HCS
* pCurHcb
)
2261 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2263 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2264 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2265 if ((wait_tulip(pCurHcb
)) == -1)
2268 switch (TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
)) {
2269 case MSG_DISC
: /* Disconnect msg */
2270 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_MSG_ACCEPT
);
2272 return tul_wait_disc(pCurHcb
);
2277 tul_msgin_accept(pCurHcb
);
2280 case MSG_REJ
: /* Clear ATN first */
2281 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
,
2282 (TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)));
2283 pCurTcb
= pCurHcb
->HCS_ActTcs
;
2284 if ((pCurTcb
->TCS_Flags
& (TCF_SYNC_DONE
| TCF_NO_SYNC_NEGO
)) == 0) { /* do sync nego */
2285 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2287 tul_msgin_accept(pCurHcb
);
2290 case MSG_EXTEND
: /* extended msg */
2291 tul_msgin_extend(pCurHcb
);
2294 case MSG_IGNOREWIDE
:
2295 tul_msgin_accept(pCurHcb
);
2299 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2300 if (wait_tulip(pCurHcb
) == -1)
2303 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 0); /* put pad */
2304 TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
); /* get IGNORE field */
2305 TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
); /* get pad */
2307 tul_msgin_accept(pCurHcb
);
2312 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2313 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_MSG_ACCEPT
);
2314 return tul_wait_done_disc(pCurHcb
);
2317 tul_msgout_reject(pCurHcb
);
2320 if (pCurHcb
->HCS_Phase
!= MSG_IN
)
2321 return (pCurHcb
->HCS_Phase
);
2323 /* statement won't reach here */
2329 /***************************************************************************/
2330 int tul_msgout_reject(HCS
* pCurHcb
)
2333 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2335 if ((tul_msgin_accept(pCurHcb
)) == -1)
2338 if (pCurHcb
->HCS_Phase
== MSG_OUT
) {
2339 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_REJ
); /* Msg reject */
2340 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2341 return (wait_tulip(pCurHcb
));
2343 return (pCurHcb
->HCS_Phase
);
2348 /***************************************************************************/
2349 int tul_msgout_ide(HCS
* pCurHcb
)
2351 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_IDE
); /* Initiator Detected Error */
2352 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2353 return (wait_tulip(pCurHcb
));
2357 /***************************************************************************/
2358 int tul_msgin_extend(HCS
* pCurHcb
)
2362 if (tul_msgin_accept(pCurHcb
) != MSG_IN
)
2363 return (pCurHcb
->HCS_Phase
);
2365 /* Get extended msg length */
2366 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2367 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2368 if (wait_tulip(pCurHcb
) == -1)
2371 len
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
2372 pCurHcb
->HCS_Msg
[0] = len
;
2373 for (idx
= 1; len
!= 0; len
--) {
2375 if ((tul_msgin_accept(pCurHcb
)) != MSG_IN
)
2376 return (pCurHcb
->HCS_Phase
);
2377 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2378 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2379 if (wait_tulip(pCurHcb
) == -1)
2381 pCurHcb
->HCS_Msg
[idx
++] = TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
2383 if (pCurHcb
->HCS_Msg
[1] == 1) { /* if it's synchronous data transfer request */
2384 if (pCurHcb
->HCS_Msg
[0] != 3) /* if length is not right */
2385 return (tul_msgout_reject(pCurHcb
));
2386 if (pCurHcb
->HCS_ActTcs
->TCS_Flags
& TCF_NO_SYNC_NEGO
) { /* Set OFFSET=0 to do async, nego back */
2387 pCurHcb
->HCS_Msg
[3] = 0;
2389 if ((tul_msgin_sync(pCurHcb
) == 0) &&
2390 (pCurHcb
->HCS_ActTcs
->TCS_Flags
& TCF_SYNC_DONE
)) {
2391 tul_sync_done(pCurHcb
);
2392 return (tul_msgin_accept(pCurHcb
));
2396 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2397 if ((tul_msgin_accept(pCurHcb
)) != MSG_OUT
)
2398 return (pCurHcb
->HCS_Phase
);
2400 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2402 tul_sync_done(pCurHcb
);
2404 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_EXTEND
);
2405 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 3);
2406 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 1);
2407 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurHcb
->HCS_Msg
[2]);
2408 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurHcb
->HCS_Msg
[3]);
2410 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2411 return (wait_tulip(pCurHcb
));
2413 if ((pCurHcb
->HCS_Msg
[0] != 2) || (pCurHcb
->HCS_Msg
[1] != 3))
2414 return (tul_msgout_reject(pCurHcb
));
2415 /* if it's WIDE DATA XFER REQ */
2416 if (pCurHcb
->HCS_ActTcs
->TCS_Flags
& TCF_NO_WDTR
) {
2417 pCurHcb
->HCS_Msg
[2] = 0;
2419 if (pCurHcb
->HCS_Msg
[2] > 2) /* > 32 bits */
2420 return (tul_msgout_reject(pCurHcb
));
2421 if (pCurHcb
->HCS_Msg
[2] == 2) { /* == 32 */
2422 pCurHcb
->HCS_Msg
[2] = 1;
2424 if ((pCurHcb
->HCS_ActTcs
->TCS_Flags
& TCF_NO_WDTR
) == 0) {
2426 if ((pCurHcb
->HCS_ActTcs
->TCS_Flags
& (TCF_SYNC_DONE
| TCF_NO_SYNC_NEGO
)) == 0)
2427 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2428 return (tul_msgin_accept(pCurHcb
));
2432 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2434 if (tul_msgin_accept(pCurHcb
) != MSG_OUT
)
2435 return (pCurHcb
->HCS_Phase
);
2437 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_EXTEND
);
2438 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 2);
2439 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 3);
2440 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurHcb
->HCS_Msg
[2]);
2441 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2442 return (wait_tulip(pCurHcb
));
2445 /***************************************************************************/
2446 int tul_msgin_sync(HCS
* pCurHcb
)
2448 char default_period
;
2450 default_period
= tul_rate_tbl
[pCurHcb
->HCS_ActTcs
->TCS_Flags
& TCF_SCSI_RATE
];
2451 if (pCurHcb
->HCS_Msg
[3] > MAX_OFFSET
) {
2452 pCurHcb
->HCS_Msg
[3] = MAX_OFFSET
;
2453 if (pCurHcb
->HCS_Msg
[2] < default_period
) {
2454 pCurHcb
->HCS_Msg
[2] = default_period
;
2457 if (pCurHcb
->HCS_Msg
[2] >= 59) { /* Change to async */
2458 pCurHcb
->HCS_Msg
[3] = 0;
2462 /* offset requests asynchronous transfers ? */
2463 if (pCurHcb
->HCS_Msg
[3] == 0) {
2466 if (pCurHcb
->HCS_Msg
[2] < default_period
) {
2467 pCurHcb
->HCS_Msg
[2] = default_period
;
2470 if (pCurHcb
->HCS_Msg
[2] >= 59) {
2471 pCurHcb
->HCS_Msg
[3] = 0;
2478 /***************************************************************************/
2479 int wdtr_done(HCS
* pCurHcb
)
2481 pCurHcb
->HCS_ActTcs
->TCS_Flags
&= ~TCF_SYNC_DONE
;
2482 pCurHcb
->HCS_ActTcs
->TCS_Flags
|= TCF_WDTR_DONE
;
2484 pCurHcb
->HCS_ActTcs
->TCS_JS_Period
= 0;
2485 if (pCurHcb
->HCS_Msg
[2]) { /* if 16 bit */
2486 pCurHcb
->HCS_ActTcs
->TCS_JS_Period
|= TSC_WIDE_SCSI
;
2488 pCurHcb
->HCS_ActTcs
->TCS_SConfig0
&= ~TSC_ALT_PERIOD
;
2489 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurHcb
->HCS_ActTcs
->TCS_SConfig0
);
2490 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SPeriod
, pCurHcb
->HCS_ActTcs
->TCS_JS_Period
);
2495 /***************************************************************************/
2496 int tul_sync_done(HCS
* pCurHcb
)
2500 pCurHcb
->HCS_ActTcs
->TCS_Flags
|= TCF_SYNC_DONE
;
2502 if (pCurHcb
->HCS_Msg
[3]) {
2503 pCurHcb
->HCS_ActTcs
->TCS_JS_Period
|= pCurHcb
->HCS_Msg
[3];
2504 for (i
= 0; i
< 8; i
++) {
2505 if (tul_rate_tbl
[i
] >= pCurHcb
->HCS_Msg
[2]) /* pick the big one */
2508 pCurHcb
->HCS_ActTcs
->TCS_JS_Period
|= (i
<< 4);
2509 pCurHcb
->HCS_ActTcs
->TCS_SConfig0
|= TSC_ALT_PERIOD
;
2511 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurHcb
->HCS_ActTcs
->TCS_SConfig0
);
2512 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SPeriod
, pCurHcb
->HCS_ActTcs
->TCS_JS_Period
);
2518 int tul_post_scsi_rst(HCS
* pCurHcb
)
2524 pCurHcb
->HCS_ActScb
= NULL
;
2525 pCurHcb
->HCS_ActTcs
= NULL
;
2526 pCurHcb
->HCS_Flags
= 0;
2528 while ((pCurScb
= tul_pop_busy_scb(pCurHcb
)) != NULL
) {
2529 pCurScb
->SCB_HaStat
= HOST_BAD_PHAS
;
2530 tul_append_done_scb(pCurHcb
, pCurScb
);
2532 /* clear sync done flag */
2533 pCurTcb
= &pCurHcb
->HCS_Tcs
[0];
2534 for (i
= 0; i
< pCurHcb
->HCS_MaxTar
; pCurTcb
++, i
++) {
2535 pCurTcb
->TCS_Flags
&= ~(TCF_SYNC_DONE
| TCF_WDTR_DONE
);
2536 /* Initialize the sync. xfer register values to an asyn xfer */
2537 pCurTcb
->TCS_JS_Period
= 0;
2538 pCurTcb
->TCS_SConfig0
= pCurHcb
->HCS_SConf1
;
2539 pCurHcb
->HCS_ActTags
[0] = 0; /* 07/22/98 */
2540 pCurHcb
->HCS_Tcs
[i
].TCS_Flags
&= ~TCF_BUSY
; /* 07/22/98 */
2546 /***************************************************************************/
2547 void tul_select_atn_stop(HCS
* pCurHcb
, SCB
* pCurScb
)
2549 pCurScb
->SCB_Status
|= SCB_SELECT
;
2550 pCurScb
->SCB_NxtStat
= 0x1;
2551 pCurHcb
->HCS_ActScb
= pCurScb
;
2552 pCurHcb
->HCS_ActTcs
= &pCurHcb
->HCS_Tcs
[pCurScb
->SCB_Target
];
2553 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_SELATNSTOP
);
2558 /***************************************************************************/
2559 void tul_select_atn(HCS
* pCurHcb
, SCB
* pCurScb
)
2563 pCurScb
->SCB_Status
|= SCB_SELECT
;
2564 pCurScb
->SCB_NxtStat
= 0x2;
2566 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_Ident
);
2567 for (i
= 0; i
< (int) pCurScb
->SCB_CDBLen
; i
++)
2568 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_CDB
[i
]);
2569 pCurHcb
->HCS_ActTcs
= &pCurHcb
->HCS_Tcs
[pCurScb
->SCB_Target
];
2570 pCurHcb
->HCS_ActScb
= pCurScb
;
2571 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_SEL_ATN
);
2575 /***************************************************************************/
2576 void tul_select_atn3(HCS
* pCurHcb
, SCB
* pCurScb
)
2580 pCurScb
->SCB_Status
|= SCB_SELECT
;
2581 pCurScb
->SCB_NxtStat
= 0x2;
2583 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_Ident
);
2584 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_TagMsg
);
2585 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_TagId
);
2586 for (i
= 0; i
< (int) pCurScb
->SCB_CDBLen
; i
++)
2587 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_CDB
[i
]);
2588 pCurHcb
->HCS_ActTcs
= &pCurHcb
->HCS_Tcs
[pCurScb
->SCB_Target
];
2589 pCurHcb
->HCS_ActScb
= pCurScb
;
2590 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_SEL_ATN3
);
2594 /***************************************************************************/
2595 /* SCSI Bus Device Reset */
2596 int tul_bus_device_reset(HCS
* pCurHcb
)
2598 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
2599 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
2600 SCB
*pTmpScb
, *pPrevScb
;
2603 if (pCurHcb
->HCS_Phase
!= MSG_OUT
) {
2604 return (int_tul_bad_seq(pCurHcb
)); /* Unexpected phase */
2606 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
2607 tul_release_scb(pCurHcb
, pCurScb
);
2610 tar
= pCurScb
->SCB_Target
; /* target */
2611 pCurTcb
->TCS_Flags
&= ~(TCF_SYNC_DONE
| TCF_WDTR_DONE
| TCF_BUSY
);
2612 /* clr sync. nego & WDTR flags 07/22/98 */
2614 /* abort all SCB with same target */
2615 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstBusy
; /* Check Busy queue */
2616 while (pTmpScb
!= NULL
) {
2618 if (pTmpScb
->SCB_Target
== tar
) {
2620 if (pTmpScb
== pCurHcb
->HCS_FirstBusy
) {
2621 if ((pCurHcb
->HCS_FirstBusy
= pTmpScb
->SCB_NxtScb
) == NULL
)
2622 pCurHcb
->HCS_LastBusy
= NULL
;
2624 pPrevScb
->SCB_NxtScb
= pTmpScb
->SCB_NxtScb
;
2625 if (pTmpScb
== pCurHcb
->HCS_LastBusy
)
2626 pCurHcb
->HCS_LastBusy
= pPrevScb
;
2628 pTmpScb
->SCB_HaStat
= HOST_ABORTED
;
2629 tul_append_done_scb(pCurHcb
, pTmpScb
);
2631 /* Previous haven't change */
2635 pTmpScb
= pTmpScb
->SCB_NxtScb
;
2638 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_DEVRST
);
2639 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2641 return tul_wait_disc(pCurHcb
);
2645 /***************************************************************************/
2646 int tul_msgin_accept(HCS
* pCurHcb
)
2648 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_MSG_ACCEPT
);
2649 return (wait_tulip(pCurHcb
));
2652 /***************************************************************************/
2653 int wait_tulip(HCS
* pCurHcb
)
2656 while (!((pCurHcb
->HCS_JSStatus0
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus0
))
2657 & TSS_INT_PENDING
));
2659 pCurHcb
->HCS_JSInt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
);
2660 pCurHcb
->HCS_Phase
= pCurHcb
->HCS_JSStatus0
& TSS_PH_MASK
;
2661 pCurHcb
->HCS_JSStatus1
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus1
);
2663 if (pCurHcb
->HCS_JSInt
& TSS_RESEL_INT
) { /* if SCSI bus reset detected */
2664 return (int_tul_resel(pCurHcb
));
2666 if (pCurHcb
->HCS_JSInt
& TSS_SEL_TIMEOUT
) { /* if selected/reselected timeout interrupt */
2667 return (int_tul_busfree(pCurHcb
));
2669 if (pCurHcb
->HCS_JSInt
& TSS_SCSIRST_INT
) { /* if SCSI bus reset detected */
2670 return (int_tul_scsi_rst(pCurHcb
));
2672 if (pCurHcb
->HCS_JSInt
& TSS_DISC_INT
) { /* BUS disconnection */
2673 if (pCurHcb
->HCS_Flags
& HCF_EXPECT_DONE_DISC
) {
2674 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
); /* Flush SCSI FIFO */
2675 tul_unlink_busy_scb(pCurHcb
, pCurHcb
->HCS_ActScb
);
2676 pCurHcb
->HCS_ActScb
->SCB_HaStat
= 0;
2677 tul_append_done_scb(pCurHcb
, pCurHcb
->HCS_ActScb
);
2678 pCurHcb
->HCS_ActScb
= NULL
;
2679 pCurHcb
->HCS_ActTcs
= NULL
;
2680 pCurHcb
->HCS_Flags
&= ~HCF_EXPECT_DONE_DISC
;
2681 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, TSC_INITDEFAULT
);
2682 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
); /* Enable HW reselect */
2685 if (pCurHcb
->HCS_Flags
& HCF_EXPECT_DISC
) {
2686 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
); /* Flush SCSI FIFO */
2687 pCurHcb
->HCS_ActScb
= NULL
;
2688 pCurHcb
->HCS_ActTcs
= NULL
;
2689 pCurHcb
->HCS_Flags
&= ~HCF_EXPECT_DISC
;
2690 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, TSC_INITDEFAULT
);
2691 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
); /* Enable HW reselect */
2694 return (int_tul_busfree(pCurHcb
));
2696 if (pCurHcb
->HCS_JSInt
& (TSS_FUNC_COMP
| TSS_BUS_SERV
)) {
2697 return (pCurHcb
->HCS_Phase
);
2699 return (pCurHcb
->HCS_Phase
);
2701 /***************************************************************************/
2702 int tul_wait_disc(HCS
* pCurHcb
)
2705 while (!((pCurHcb
->HCS_JSStatus0
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus0
))
2706 & TSS_INT_PENDING
));
2709 pCurHcb
->HCS_JSInt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
);
2711 if (pCurHcb
->HCS_JSInt
& TSS_SCSIRST_INT
) { /* if SCSI bus reset detected */
2712 return (int_tul_scsi_rst(pCurHcb
));
2714 if (pCurHcb
->HCS_JSInt
& TSS_DISC_INT
) { /* BUS disconnection */
2715 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
); /* Flush SCSI FIFO */
2716 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, TSC_INITDEFAULT
);
2717 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
); /* Enable HW reselect */
2718 pCurHcb
->HCS_ActScb
= NULL
;
2721 return (tul_bad_seq(pCurHcb
));
2724 /***************************************************************************/
2725 int tul_wait_done_disc(HCS
* pCurHcb
)
2729 while (!((pCurHcb
->HCS_JSStatus0
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus0
))
2730 & TSS_INT_PENDING
));
2732 pCurHcb
->HCS_JSInt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
);
2735 if (pCurHcb
->HCS_JSInt
& TSS_SCSIRST_INT
) { /* if SCSI bus reset detected */
2736 return (int_tul_scsi_rst(pCurHcb
));
2738 if (pCurHcb
->HCS_JSInt
& TSS_DISC_INT
) { /* BUS disconnection */
2739 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
); /* Flush SCSI FIFO */
2740 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, TSC_INITDEFAULT
);
2741 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
); /* Enable HW reselect */
2742 tul_unlink_busy_scb(pCurHcb
, pCurHcb
->HCS_ActScb
);
2744 tul_append_done_scb(pCurHcb
, pCurHcb
->HCS_ActScb
);
2745 pCurHcb
->HCS_ActScb
= NULL
;
2748 return (tul_bad_seq(pCurHcb
));
2751 static irqreturn_t
i91u_intr(int irqno
, void *dev_id
)
2753 struct Scsi_Host
*dev
= dev_id
;
2754 unsigned long flags
;
2756 spin_lock_irqsave(dev
->host_lock
, flags
);
2757 tul_isr((HCS
*)dev
->base
);
2758 spin_unlock_irqrestore(dev
->host_lock
, flags
);
2762 static int tul_NewReturnNumberOfAdapters(void)
2764 struct pci_dev
*pDev
= NULL
; /* Start from none */
2770 init_i91uAdapter_table();
2772 for (i
= 0; i
< ARRAY_SIZE(i91u_pci_devices
); i
++)
2774 while ((pDev
= pci_find_device(i91u_pci_devices
[i
].vendor
, i91u_pci_devices
[i
].device
, pDev
)) != NULL
) {
2775 if (pci_enable_device(pDev
))
2777 pci_read_config_dword(pDev
, 0x44, (u32
*) & dRegValue
);
2778 wBIOS
= (UWORD
) (dRegValue
& 0xFF);
2779 if (((dRegValue
& 0xFF00) >> 8) == 0xFF)
2781 wBIOS
= (wBIOS
<< 8) + ((UWORD
) ((dRegValue
& 0xFF00) >> 8));
2782 if (pci_set_dma_mask(pDev
, DMA_32BIT_MASK
)) {
2784 "i91u: Could not set 32 bit DMA mask\n");
2788 if (Addi91u_into_Adapter_table(wBIOS
,
2789 (pDev
->resource
[0].start
),
2801 static int i91u_detect(struct scsi_host_template
* tpnt
)
2804 struct Scsi_Host
*hreg
;
2805 unsigned long i
; /* 01/14/98 */
2806 int ok
= 0, iAdapters
;
2810 /* Get total number of adapters in the motherboard */
2811 iAdapters
= tul_NewReturnNumberOfAdapters();
2812 if (iAdapters
== 0) /* If no tulip founded, return */
2815 tul_num_ch
= (iAdapters
> tul_num_ch
) ? tul_num_ch
: iAdapters
;
2816 /* Update actually channel number */
2817 if (tul_tag_enable
) { /* 1.01i */
2818 tul_num_scb
= MAX_TARGETS
* i91u_MAXQUEUE
;
2820 tul_num_scb
= MAX_TARGETS
+ 3; /* 1-tape, 1-CD_ROM, 1- extra */
2821 } /* Update actually SCBs per adapter */
2823 /* Get total memory needed for HCS */
2824 i
= tul_num_ch
* sizeof(HCS
);
2825 memset((unsigned char *) &tul_hcs
[0], 0, i
); /* Initialize tul_hcs 0 */
2826 /* Get total memory needed for SCB */
2828 for (; tul_num_scb
>= MAX_TARGETS
+ 3; tul_num_scb
--) {
2829 i
= tul_num_ch
* tul_num_scb
* sizeof(SCB
);
2830 if ((tul_scb
= kmalloc(i
, GFP_ATOMIC
| GFP_DMA
)) != NULL
)
2833 if (tul_scb
== NULL
) {
2834 printk("i91u: SCB memory allocation error\n");
2837 memset((unsigned char *) tul_scb
, 0, i
);
2839 for (i
= 0, pHCB
= &tul_hcs
[0]; /* Get pointer for control block */
2842 get_tulipPCIConfig(pHCB
, i
);
2844 dBiosAdr
= pHCB
->HCS_BIOS
;
2845 dBiosAdr
= (dBiosAdr
<< 4);
2847 pbBiosAdr
= phys_to_virt(dBiosAdr
);
2849 init_tulip(pHCB
, tul_scb
+ (i
* tul_num_scb
), tul_num_scb
, pbBiosAdr
, 10);
2850 request_region(pHCB
->HCS_Base
, 256, "i91u"); /* Register */
2852 pHCB
->HCS_Index
= i
; /* 7/29/98 */
2853 hreg
= scsi_register(tpnt
, sizeof(HCS
));
2855 release_region(pHCB
->HCS_Base
, 256);
2858 hreg
->io_port
= pHCB
->HCS_Base
;
2859 hreg
->n_io_port
= 0xff;
2860 hreg
->can_queue
= tul_num_scb
; /* 03/05/98 */
2861 hreg
->unique_id
= pHCB
->HCS_Base
;
2862 hreg
->max_id
= pHCB
->HCS_MaxTar
;
2863 hreg
->max_lun
= 32; /* 10/21/97 */
2864 hreg
->irq
= pHCB
->HCS_Intr
;
2865 hreg
->this_id
= pHCB
->HCS_SCSI_ID
; /* Assign HCS index */
2866 hreg
->base
= (unsigned long)pHCB
;
2867 hreg
->sg_tablesize
= TOTAL_SG_ENTRY
; /* Maximun support is 32 */
2869 /* Initial tulip chip */
2870 ok
= request_irq(pHCB
->HCS_Intr
, i91u_intr
, IRQF_DISABLED
| IRQF_SHARED
, "i91u", hreg
);
2872 printk(KERN_WARNING
"i91u: unable to request IRQ %d\n\n", pHCB
->HCS_Intr
);
2878 tpnt
->can_queue
= 1;
2883 static void i91uBuildSCB(HCS
* pHCB
, SCB
* pSCB
, struct scsi_cmnd
* SCpnt
)
2884 { /* Create corresponding SCB */
2885 struct scatterlist
*pSrbSG
;
2886 SG
*pSG
; /* Pointer to SG list */
2889 dma_addr_t dma_addr
;
2891 pSCB
->SCB_Post
= i91uSCBPost
; /* i91u's callback routine */
2892 pSCB
->SCB_Srb
= SCpnt
;
2893 pSCB
->SCB_Opcode
= ExecSCSI
;
2894 pSCB
->SCB_Flags
= SCF_POST
; /* After SCSI done, call post routine */
2895 pSCB
->SCB_Target
= SCpnt
->device
->id
;
2896 pSCB
->SCB_Lun
= SCpnt
->device
->lun
;
2897 pSCB
->SCB_Ident
= SCpnt
->device
->lun
| DISC_ALLOW
;
2899 pSCB
->SCB_Flags
|= SCF_SENSE
; /* Turn on auto request sense */
2900 dma_addr
= dma_map_single(&pHCB
->pci_dev
->dev
, SCpnt
->sense_buffer
,
2901 SENSE_SIZE
, DMA_FROM_DEVICE
);
2902 pSCB
->SCB_SensePtr
= cpu_to_le32((u32
)dma_addr
);
2903 pSCB
->SCB_SenseLen
= cpu_to_le32(SENSE_SIZE
);
2904 SCpnt
->SCp
.ptr
= (char *)(unsigned long)dma_addr
;
2906 pSCB
->SCB_CDBLen
= SCpnt
->cmd_len
;
2907 pSCB
->SCB_HaStat
= 0;
2908 pSCB
->SCB_TaStat
= 0;
2909 memcpy(&pSCB
->SCB_CDB
[0], &SCpnt
->cmnd
, SCpnt
->cmd_len
);
2911 if (SCpnt
->device
->tagged_supported
) { /* Tag Support */
2912 pSCB
->SCB_TagMsg
= SIMPLE_QUEUE_TAG
; /* Do simple tag only */
2914 pSCB
->SCB_TagMsg
= 0; /* No tag support */
2916 /* todo handle map_sg error */
2917 if (SCpnt
->use_sg
) {
2918 dma_addr
= dma_map_single(&pHCB
->pci_dev
->dev
, &pSCB
->SCB_SGList
[0],
2919 sizeof(struct SG_Struc
) * TOTAL_SG_ENTRY
,
2921 pSCB
->SCB_BufPtr
= cpu_to_le32((u32
)dma_addr
);
2922 SCpnt
->SCp
.dma_handle
= dma_addr
;
2924 pSrbSG
= (struct scatterlist
*) SCpnt
->request_buffer
;
2925 pSCB
->SCB_SGLen
= dma_map_sg(&pHCB
->pci_dev
->dev
, pSrbSG
,
2926 SCpnt
->use_sg
, SCpnt
->sc_data_direction
);
2928 pSCB
->SCB_Flags
|= SCF_SG
; /* Turn on SG list flag */
2929 for (i
= 0, TotalLen
= 0, pSG
= &pSCB
->SCB_SGList
[0]; /* 1.01g */
2930 i
< pSCB
->SCB_SGLen
; i
++, pSG
++, pSrbSG
++) {
2931 pSG
->SG_Ptr
= cpu_to_le32((u32
)sg_dma_address(pSrbSG
));
2932 TotalLen
+= pSG
->SG_Len
= cpu_to_le32((u32
)sg_dma_len(pSrbSG
));
2935 pSCB
->SCB_BufLen
= (SCpnt
->request_bufflen
> TotalLen
) ?
2936 TotalLen
: SCpnt
->request_bufflen
;
2937 } else if (SCpnt
->request_bufflen
) { /* Non SG */
2938 dma_addr
= dma_map_single(&pHCB
->pci_dev
->dev
, SCpnt
->request_buffer
,
2939 SCpnt
->request_bufflen
,
2940 SCpnt
->sc_data_direction
);
2941 SCpnt
->SCp
.dma_handle
= dma_addr
;
2942 pSCB
->SCB_BufPtr
= cpu_to_le32((u32
)dma_addr
);
2943 pSCB
->SCB_BufLen
= cpu_to_le32((u32
)SCpnt
->request_bufflen
);
2944 pSCB
->SCB_SGLen
= 0;
2946 pSCB
->SCB_BufLen
= 0;
2947 pSCB
->SCB_SGLen
= 0;
2951 static int i91u_queuecommand(struct scsi_cmnd
*cmd
,
2952 void (*done
)(struct scsi_cmnd
*))
2954 HCS
*pHCB
= (HCS
*) cmd
->device
->host
->base
;
2957 cmd
->scsi_done
= done
;
2959 pSCB
= tul_alloc_scb(pHCB
);
2961 return SCSI_MLQUEUE_HOST_BUSY
;
2963 i91uBuildSCB(pHCB
, pSCB
, cmd
);
2964 tul_exec_scb(pHCB
, pSCB
);
2968 #if 0 /* no new EH yet */
2970 * Abort a queued command
2971 * (commands that are on the bus can't be aborted easily)
2973 static int i91u_abort(struct scsi_cmnd
* SCpnt
)
2977 pHCB
= (HCS
*) SCpnt
->device
->host
->base
;
2978 return tul_abort_srb(pHCB
, SCpnt
);
2982 * Reset registers, reset a hanging bus and
2983 * kill active and disconnected commands for target w/o soft reset
2985 static int i91u_reset(struct scsi_cmnd
* SCpnt
, unsigned int reset_flags
)
2986 { /* I need Host Control Block Information */
2989 pHCB
= (HCS
*) SCpnt
->device
->host
->base
;
2991 if (reset_flags
& (SCSI_RESET_SUGGEST_BUS_RESET
| SCSI_RESET_SUGGEST_HOST_RESET
))
2992 return tul_reset_scsi_bus(pHCB
);
2994 return tul_device_reset(pHCB
, SCpnt
, SCpnt
->device
->id
, reset_flags
);
2998 static int i91u_bus_reset(struct scsi_cmnd
* SCpnt
)
3002 pHCB
= (HCS
*) SCpnt
->device
->host
->base
;
3004 spin_lock_irq(SCpnt
->device
->host
->host_lock
);
3005 tul_reset_scsi(pHCB
, 0);
3006 spin_unlock_irq(SCpnt
->device
->host
->host_lock
);
3012 * Return the "logical geometry"
3014 static int i91u_biosparam(struct scsi_device
*sdev
, struct block_device
*dev
,
3015 sector_t capacity
, int *info_array
)
3017 HCS
*pHcb
; /* Point to Host adapter control block */
3020 pHcb
= (HCS
*) sdev
->host
->base
;
3021 pTcb
= &pHcb
->HCS_Tcs
[sdev
->id
];
3023 if (pTcb
->TCS_DrvHead
) {
3024 info_array
[0] = pTcb
->TCS_DrvHead
;
3025 info_array
[1] = pTcb
->TCS_DrvSector
;
3026 info_array
[2] = (unsigned long)capacity
/ pTcb
->TCS_DrvHead
/ pTcb
->TCS_DrvSector
;
3028 if (pTcb
->TCS_DrvFlags
& TCF_DRV_255_63
) {
3029 info_array
[0] = 255;
3031 info_array
[2] = (unsigned long)capacity
/ 255 / 63;
3035 info_array
[2] = (unsigned long)capacity
>> 11;
3039 #if defined(DEBUG_BIOSPARAM)
3040 if (i91u_debug
& debug_biosparam
) {
3041 printk("bios geometry: head=%d, sec=%d, cyl=%d\n",
3042 info_array
[0], info_array
[1], info_array
[2]);
3043 printk("WARNING: check, if the bios geometry is correct.\n");
3050 static void i91u_unmap_cmnd(struct pci_dev
*pci_dev
, struct scsi_cmnd
*cmnd
)
3052 /* auto sense buffer */
3053 if (cmnd
->SCp
.ptr
) {
3054 dma_unmap_single(&pci_dev
->dev
,
3055 (dma_addr_t
)((unsigned long)cmnd
->SCp
.ptr
),
3056 SENSE_SIZE
, DMA_FROM_DEVICE
);
3057 cmnd
->SCp
.ptr
= NULL
;
3060 /* request buffer */
3062 dma_unmap_single(&pci_dev
->dev
, cmnd
->SCp
.dma_handle
,
3063 sizeof(struct SG_Struc
) * TOTAL_SG_ENTRY
,
3066 dma_unmap_sg(&pci_dev
->dev
, cmnd
->request_buffer
,
3068 cmnd
->sc_data_direction
);
3069 } else if (cmnd
->request_bufflen
) {
3070 dma_unmap_single(&pci_dev
->dev
, cmnd
->SCp
.dma_handle
,
3071 cmnd
->request_bufflen
,
3072 cmnd
->sc_data_direction
);
3076 /*****************************************************************************
3077 Function name : i91uSCBPost
3078 Description : This is callback routine be called when tulip finish one
3080 Input : pHCB - Pointer to host adapter control block.
3081 pSCB - Pointer to SCSI control block.
3084 *****************************************************************************/
3085 static void i91uSCBPost(BYTE
* pHcb
, BYTE
* pScb
)
3087 struct scsi_cmnd
*pSRB
; /* Pointer to SCSI request block */
3091 pHCB
= (HCS
*) pHcb
;
3092 pSCB
= (SCB
*) pScb
;
3093 if ((pSRB
= pSCB
->SCB_Srb
) == 0) {
3094 printk("i91uSCBPost: SRB pointer is empty\n");
3096 tul_release_scb(pHCB
, pSCB
); /* Release SCB for current channel */
3099 switch (pSCB
->SCB_HaStat
) {
3101 case 0xa: /* Linked command complete without error and linked normally */
3102 case 0xb: /* Linked command complete without error interrupt generated */
3103 pSCB
->SCB_HaStat
= 0;
3106 case 0x11: /* Selection time out-The initiator selection or target
3107 reselection was not complete within the SCSI Time out period */
3108 pSCB
->SCB_HaStat
= DID_TIME_OUT
;
3111 case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus
3112 phase sequence was requested by the target. The host adapter
3113 will generate a SCSI Reset Condition, notifying the host with
3115 pSCB
->SCB_HaStat
= DID_RESET
;
3118 case 0x1a: /* SCB Aborted. 07/21/98 */
3119 pSCB
->SCB_HaStat
= DID_ABORT
;
3122 case 0x12: /* Data overrun/underrun-The target attempted to transfer more data
3123 than was allocated by the Data Length field or the sum of the
3124 Scatter / Gather Data Length fields. */
3125 case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */
3126 case 0x16: /* Invalid SCB Operation Code. */
3129 printk("ini9100u: %x %x\n", pSCB
->SCB_HaStat
, pSCB
->SCB_TaStat
);
3130 pSCB
->SCB_HaStat
= DID_ERROR
; /* Couldn't find any better */
3134 pSRB
->result
= pSCB
->SCB_TaStat
| (pSCB
->SCB_HaStat
<< 16);
3137 printk("pSRB is NULL\n");
3140 i91u_unmap_cmnd(pHCB
->pci_dev
, pSRB
);
3141 pSRB
->scsi_done(pSRB
); /* Notify system DONE */
3143 tul_release_scb(pHCB
, pSCB
); /* Release SCB for current channel */
3147 * Release ressources
3149 static int i91u_release(struct Scsi_Host
*hreg
)
3151 free_irq(hreg
->irq
, hreg
);
3152 release_region(hreg
->io_port
, 256);
3155 MODULE_LICENSE("Dual BSD/GPL");
3157 static struct scsi_host_template driver_template
= {
3158 .proc_name
= "INI9100U",
3160 .detect
= i91u_detect
,
3161 .release
= i91u_release
,
3162 .queuecommand
= i91u_queuecommand
,
3163 // .abort = i91u_abort,
3164 // .reset = i91u_reset,
3165 .eh_bus_reset_handler
= i91u_bus_reset
,
3166 .bios_param
= i91u_biosparam
,
3169 .sg_tablesize
= SG_ALL
,
3171 .use_clustering
= ENABLE_CLUSTERING
,
3173 #include "scsi_module.c"