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/config.h>
122 #include <linux/kernel.h>
123 #include <linux/proc_fs.h>
124 #include <linux/string.h>
125 #include <linux/interrupt.h>
126 #include <linux/ioport.h>
127 #include <linux/sched.h>
128 #include <linux/slab.h>
129 #include <linux/jiffies.h>
130 #include <linux/dma-mapping.h>
133 #include <scsi/scsi.h>
134 #include <scsi/scsi_cmnd.h>
135 #include <scsi/scsi_device.h>
136 #include <scsi/scsi_host.h>
137 #include <scsi/scsi_tcq.h>
141 #define SENSE_SIZE 14
143 #define i91u_MAXQUEUE 2
144 #define i91u_REVID "Initio INI-9X00U/UW SCSI device driver; Revision: 1.04a"
146 #define INI_VENDOR_ID 0x1101 /* Initio's PCI vendor ID */
147 #define DMX_VENDOR_ID 0x134a /* Domex's PCI vendor ID */
148 #define I950_DEVICE_ID 0x9500 /* Initio's inic-950 product ID */
149 #define I940_DEVICE_ID 0x9400 /* Initio's inic-940 product ID */
150 #define I935_DEVICE_ID 0x9401 /* Initio's inic-935 product ID */
151 #define I920_DEVICE_ID 0x0002 /* Initio's other product ID */
154 static unsigned int i91u_debug
= DEBUG_DEFAULT
;
157 #define TULSZ(sz) (sizeof(sz) / sizeof(sz[0]))
158 #define TUL_RDWORD(x,y) (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
160 typedef struct PCI_ID_Struc
{
161 unsigned short vendor_id
;
162 unsigned short device_id
;
165 static int tul_num_ch
= 4; /* Maximum 4 adapters */
166 static int tul_num_scb
;
167 static int tul_tag_enable
= 1;
171 static int setup_debug
= 0;
174 static void i91uSCBPost(BYTE
* pHcb
, BYTE
* pScb
);
176 static const PCI_ID i91u_pci_devices
[] = {
177 { INI_VENDOR_ID
, I950_DEVICE_ID
},
178 { INI_VENDOR_ID
, I940_DEVICE_ID
},
179 { INI_VENDOR_ID
, I935_DEVICE_ID
},
180 { INI_VENDOR_ID
, I920_DEVICE_ID
},
181 { DMX_VENDOR_ID
, I920_DEVICE_ID
},
184 #define DEBUG_INTERRUPT 0
185 #define DEBUG_QUEUE 0
186 #define DEBUG_STATE 0
189 /*--- external functions --*/
190 static void tul_se2_wait(void);
192 /*--- forward refrence ---*/
193 static SCB
*tul_find_busy_scb(HCS
* pCurHcb
, WORD tarlun
);
194 static SCB
*tul_find_done_scb(HCS
* pCurHcb
);
196 static int tulip_main(HCS
* pCurHcb
);
198 static int tul_next_state(HCS
* pCurHcb
);
199 static int tul_state_1(HCS
* pCurHcb
);
200 static int tul_state_2(HCS
* pCurHcb
);
201 static int tul_state_3(HCS
* pCurHcb
);
202 static int tul_state_4(HCS
* pCurHcb
);
203 static int tul_state_5(HCS
* pCurHcb
);
204 static int tul_state_6(HCS
* pCurHcb
);
205 static int tul_state_7(HCS
* pCurHcb
);
206 static int tul_xfer_data_in(HCS
* pCurHcb
);
207 static int tul_xfer_data_out(HCS
* pCurHcb
);
208 static int tul_xpad_in(HCS
* pCurHcb
);
209 static int tul_xpad_out(HCS
* pCurHcb
);
210 static int tul_status_msg(HCS
* pCurHcb
);
212 static int tul_msgin(HCS
* pCurHcb
);
213 static int tul_msgin_sync(HCS
* pCurHcb
);
214 static int tul_msgin_accept(HCS
* pCurHcb
);
215 static int tul_msgout_reject(HCS
* pCurHcb
);
216 static int tul_msgin_extend(HCS
* pCurHcb
);
218 static int tul_msgout_ide(HCS
* pCurHcb
);
219 static int tul_msgout_abort_targ(HCS
* pCurHcb
);
220 static int tul_msgout_abort_tag(HCS
* pCurHcb
);
222 static int tul_bus_device_reset(HCS
* pCurHcb
);
223 static void tul_select_atn(HCS
* pCurHcb
, SCB
* pCurScb
);
224 static void tul_select_atn3(HCS
* pCurHcb
, SCB
* pCurScb
);
225 static void tul_select_atn_stop(HCS
* pCurHcb
, SCB
* pCurScb
);
226 static int int_tul_busfree(HCS
* pCurHcb
);
227 static int int_tul_scsi_rst(HCS
* pCurHcb
);
228 static int int_tul_bad_seq(HCS
* pCurHcb
);
229 static int int_tul_resel(HCS
* pCurHcb
);
230 static int tul_sync_done(HCS
* pCurHcb
);
231 static int wdtr_done(HCS
* pCurHcb
);
232 static int wait_tulip(HCS
* pCurHcb
);
233 static int tul_wait_done_disc(HCS
* pCurHcb
);
234 static int tul_wait_disc(HCS
* pCurHcb
);
235 static void tulip_scsi(HCS
* pCurHcb
);
236 static int tul_post_scsi_rst(HCS
* pCurHcb
);
238 static void tul_se2_ew_en(WORD CurBase
);
239 static void tul_se2_ew_ds(WORD CurBase
);
240 static int tul_se2_rd_all(WORD CurBase
);
241 static void tul_se2_update_all(WORD CurBase
); /* setup default pattern */
242 static void tul_read_eeprom(WORD CurBase
);
244 /* ---- INTERNAL VARIABLES ---- */
245 static HCS tul_hcs
[MAX_SUPPORTED_ADAPTERS
];
246 static INI_ADPT_STRUCT i91u_adpt
[MAX_SUPPORTED_ADAPTERS
];
248 /*NVRAM nvram, *nvramp = &nvram; */
249 static NVRAM i91unvram
;
250 static NVRAM
*i91unvramp
;
254 static UCHAR i91udftNvRam
[64] =
256 /*----------- header -----------*/
257 0x25, 0xc9, /* Signature */
260 /* -- Host Adapter Structure -- */
261 0x95, /* ModelByte0 */
262 0x00, /* ModelByte1 */
263 0x00, /* ModelInfo */
265 NBC1_DEFAULT
, /* BIOSConfig1 */
269 /* SCSI channel 0 and target Structure */
271 NCC1_DEFAULT
, /* SCSIconfig1 */
273 0x10, /* NumSCSItarget */
275 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
276 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
277 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
278 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
280 /* SCSI channel 1 and target Structure */
282 NCC1_DEFAULT
, /* SCSIconfig1 */
284 0x10, /* NumSCSItarget */
286 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
287 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
288 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
289 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
290 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
291 0, 0}; /* - CheckSum - */
294 static UCHAR tul_rate_tbl
[8] = /* fast 20 */
296 /* nanosecond devide by 4 */
298 18, /* 75ns, 13.3M */
301 37, /* 150ns, 6.6M */
302 43, /* 175ns, 5.7M */
307 static void tul_do_pause(unsigned amount
)
308 { /* Pause for amount jiffies */
309 unsigned long the_time
= jiffies
+ amount
;
311 while (time_before_eq(jiffies
, the_time
));
314 /*-- forward reference --*/
316 /*******************************************************************
317 Use memeory refresh time ~ 15us * 2
318 ********************************************************************/
319 void tul_se2_wait(void)
326 readByte
= TUL_RD(0, 0x61);
327 if ((readByte
& 0x10) == 0x10) {
329 readByte
= TUL_RD(0, 0x61);
330 if ((readByte
& 0x10) == 0x10)
334 readByte
= TUL_RD(0, 0x61);
335 if ((readByte
& 0x10) != 0x10)
340 readByte
= TUL_RD(0, 0x61);
341 if ((readByte
& 0x10) == 0x10)
345 readByte
= TUL_RD(0, 0x61);
346 if ((readByte
& 0x10) != 0x10)
354 /******************************************************************
355 Input: instruction for Serial E2PROM
357 EX: se2_rd(0 call se2_instr() to send address and read command
359 StartBit OP_Code Address Data
360 --------- -------- ------------------ -------
361 1 1 , 0 A5,A4,A3,A2,A1,A0 D15-D0
363 +-----------------------------------------------------
366 +--+ +--+ +--+ +--+ +--+
369 CLK -------+ +--+ +--+ +--+ +--+ +--
370 (leading edge trigger)
374 DI ----+ +--0------------------
375 (address and cmd sent to nvram)
377 -------------------------------------------+
380 (data sent from nvram)
383 ******************************************************************/
384 static void tul_se2_instr(WORD CurBase
, UCHAR instr
)
389 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2DO
); /* cs+start bit */
391 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2CLK
| SE2DO
); /* +CLK */
394 for (i
= 0; i
< 8; i
++) {
396 b
= SE2CS
| SE2DO
; /* -CLK+dataBit */
398 b
= SE2CS
; /* -CLK */
399 TUL_WR(CurBase
+ TUL_NVRAM
, b
);
401 TUL_WR(CurBase
+ TUL_NVRAM
, b
| SE2CLK
); /* +CLK */
405 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* -CLK */
411 /******************************************************************
412 Function name : tul_se2_ew_en
413 Description : Enable erase/write state of serial EEPROM
414 ******************************************************************/
415 void tul_se2_ew_en(WORD CurBase
)
417 tul_se2_instr(CurBase
, 0x30); /* EWEN */
418 TUL_WR(CurBase
+ TUL_NVRAM
, 0); /* -CS */
424 /************************************************************************
425 Disable erase/write state of serial EEPROM
426 *************************************************************************/
427 void tul_se2_ew_ds(WORD CurBase
)
429 tul_se2_instr(CurBase
, 0); /* EWDS */
430 TUL_WR(CurBase
+ TUL_NVRAM
, 0); /* -CS */
436 /******************************************************************
437 Input :address of Serial E2PROM
438 Output :value stored in Serial E2PROM
439 *******************************************************************/
440 static USHORT
tul_se2_rd(WORD CurBase
, ULONG adr
)
442 UCHAR instr
, readByte
;
446 instr
= (UCHAR
) (adr
| 0x80);
447 tul_se2_instr(CurBase
, instr
); /* READ INSTR */
450 for (i
= 15; i
>= 0; i
--) {
451 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2CLK
); /* +CLK */
453 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* -CLK */
455 /* sample data after the following edge of clock */
456 readByte
= TUL_RD(CurBase
, TUL_NVRAM
);
458 readWord
+= (readByte
<< i
);
459 tul_se2_wait(); /* 6/20/95 */
462 TUL_WR(CurBase
+ TUL_NVRAM
, 0); /* no chip select */
468 /******************************************************************
469 Input: new value in Serial E2PROM, address of Serial E2PROM
470 *******************************************************************/
471 static void tul_se2_wr(WORD CurBase
, UCHAR adr
, USHORT writeWord
)
477 instr
= (UCHAR
) (adr
| 0x40);
478 tul_se2_instr(CurBase
, instr
); /* WRITE INSTR */
479 for (i
= 15; i
>= 0; i
--) {
480 if (writeWord
& 0x8000)
481 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2DO
); /* -CLK+dataBit 1 */
483 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* -CLK+dataBit 0 */
485 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2CLK
); /* +CLK */
489 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* -CLK */
491 TUL_WR(CurBase
+ TUL_NVRAM
, 0); /* -CS */
494 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* +CS */
498 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2CLK
); /* +CLK */
500 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* -CLK */
502 if ((readByte
= TUL_RD(CurBase
, TUL_NVRAM
)) & SE2DI
)
503 break; /* write complete */
505 TUL_WR(CurBase
+ TUL_NVRAM
, 0); /* -CS */
510 /***********************************************************************
511 Read SCSI H/A configuration parameters from serial EEPROM
512 ************************************************************************/
513 int tul_se2_rd_all(WORD CurBase
)
519 i91unvramp
= &i91unvram
;
520 np
= (USHORT
*) i91unvramp
;
521 for (i
= 0; i
< 32; i
++) {
522 *np
++ = tul_se2_rd(CurBase
, i
);
525 /*--------------------Is signature "ini" ok ? ----------------*/
526 if (i91unvramp
->NVM_Signature
!= INI_SIGNATURE
)
528 /*---------------------- Is ckecksum ok ? ----------------------*/
529 np
= (USHORT
*) i91unvramp
;
530 for (i
= 0; i
< 31; i
++)
532 if (i91unvramp
->NVM_CheckSum
!= (USHORT
) chksum
)
538 /***********************************************************************
539 Update SCSI H/A configuration parameters from serial EEPROM
540 ************************************************************************/
541 void tul_se2_update_all(WORD CurBase
)
542 { /* setup default pattern */
547 i91unvramp
= &i91unvram
;
548 /* Calculate checksum first */
549 np
= (USHORT
*) i91udftNvRam
;
550 for (i
= 0; i
< 31; i
++)
552 *np
= (USHORT
) chksum
;
553 tul_se2_ew_en(CurBase
); /* Enable write */
555 np
= (USHORT
*) i91udftNvRam
;
556 np1
= (USHORT
*) i91unvramp
;
557 for (i
= 0; i
< 32; i
++, np
++, np1
++) {
559 tul_se2_wr(CurBase
, i
, *np
);
563 tul_se2_ew_ds(CurBase
); /* Disable write */
567 /*************************************************************************
568 Function name : read_eeprom
569 **************************************************************************/
570 void tul_read_eeprom(WORD CurBase
)
574 i91unvramp
= &i91unvram
;
575 /*------Enable EEProm programming ---*/
576 gctrl
= TUL_RD(CurBase
, TUL_GCTRL
);
577 TUL_WR(CurBase
+ TUL_GCTRL
, gctrl
| TUL_GCTRL_EEPROM_BIT
);
578 if (tul_se2_rd_all(CurBase
) != 1) {
579 tul_se2_update_all(CurBase
); /* setup default pattern */
580 tul_se2_rd_all(CurBase
); /* load again */
582 /*------ Disable EEProm programming ---*/
583 gctrl
= TUL_RD(CurBase
, TUL_GCTRL
);
584 TUL_WR(CurBase
+ TUL_GCTRL
, gctrl
& ~TUL_GCTRL_EEPROM_BIT
);
587 static int Addi91u_into_Adapter_table(WORD wBIOS
, WORD wBASE
, BYTE bInterrupt
,
588 BYTE bBus
, BYTE bDevice
)
592 for (i
= 0; i
< MAX_SUPPORTED_ADAPTERS
; i
++) {
593 if (i91u_adpt
[i
].ADPT_BIOS
< wBIOS
)
595 if (i91u_adpt
[i
].ADPT_BIOS
== wBIOS
) {
596 if (i91u_adpt
[i
].ADPT_BASE
== wBASE
) {
597 if (i91u_adpt
[i
].ADPT_Bus
!= 0xFF)
599 } else if (i91u_adpt
[i
].ADPT_BASE
< wBASE
)
602 for (j
= MAX_SUPPORTED_ADAPTERS
- 1; j
> i
; j
--) {
603 i91u_adpt
[j
].ADPT_BASE
= i91u_adpt
[j
- 1].ADPT_BASE
;
604 i91u_adpt
[j
].ADPT_INTR
= i91u_adpt
[j
- 1].ADPT_INTR
;
605 i91u_adpt
[j
].ADPT_BIOS
= i91u_adpt
[j
- 1].ADPT_BIOS
;
606 i91u_adpt
[j
].ADPT_Bus
= i91u_adpt
[j
- 1].ADPT_Bus
;
607 i91u_adpt
[j
].ADPT_Device
= i91u_adpt
[j
- 1].ADPT_Device
;
609 i91u_adpt
[i
].ADPT_BASE
= wBASE
;
610 i91u_adpt
[i
].ADPT_INTR
= bInterrupt
;
611 i91u_adpt
[i
].ADPT_BIOS
= wBIOS
;
612 i91u_adpt
[i
].ADPT_Bus
= bBus
;
613 i91u_adpt
[i
].ADPT_Device
= bDevice
;
619 static void init_i91uAdapter_table(void)
623 for (i
= 0; i
< MAX_SUPPORTED_ADAPTERS
; i
++) { /* Initialize adapter structure */
624 i91u_adpt
[i
].ADPT_BIOS
= 0xffff;
625 i91u_adpt
[i
].ADPT_BASE
= 0xffff;
626 i91u_adpt
[i
].ADPT_INTR
= 0xff;
627 i91u_adpt
[i
].ADPT_Bus
= 0xff;
628 i91u_adpt
[i
].ADPT_Device
= 0xff;
633 static void tul_stop_bm(HCS
* pCurHcb
)
636 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_XStatus
) & XPEND
) { /* if DMA xfer is pending, abort DMA xfer */
637 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_X_ABT
| TAX_X_CLR_FIFO
);
638 /* wait Abort DMA xfer done */
639 while ((TUL_RD(pCurHcb
->HCS_Base
, TUL_Int
) & XABT
) == 0);
641 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
644 /***************************************************************************/
645 static void get_tulipPCIConfig(HCS
* pCurHcb
, int ch_idx
)
647 pCurHcb
->HCS_Base
= i91u_adpt
[ch_idx
].ADPT_BASE
; /* Supply base address */
648 pCurHcb
->HCS_BIOS
= i91u_adpt
[ch_idx
].ADPT_BIOS
; /* Supply BIOS address */
649 pCurHcb
->HCS_Intr
= i91u_adpt
[ch_idx
].ADPT_INTR
; /* Supply interrupt line */
653 /***************************************************************************/
654 static int tul_reset_scsi(HCS
* pCurHcb
, int seconds
)
656 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_RST_BUS
);
658 while (!((pCurHcb
->HCS_JSInt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
)) & TSS_SCSIRST_INT
));
659 /* reset tulip chip */
661 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, 0);
663 /* Stall for a while, wait for target's firmware ready,make it 2 sec ! */
664 /* SONY 5200 tape drive won't work if only stall for 1 sec */
665 tul_do_pause(seconds
* HZ
);
667 TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
);
669 return (SCSI_RESET_SUCCESS
);
672 /***************************************************************************/
673 static int init_tulip(HCS
* pCurHcb
, SCB
* scbp
, int tul_num_scb
,
674 BYTE
* pbBiosAdr
, int seconds
)
679 SCB
*pTmpScb
, *pPrevScb
= NULL
;
681 pCurHcb
->HCS_NumScbs
= tul_num_scb
;
682 pCurHcb
->HCS_Semaph
= 1;
683 spin_lock_init(&pCurHcb
->HCS_SemaphLock
);
684 pCurHcb
->HCS_JSStatus0
= 0;
685 pCurHcb
->HCS_Scb
= scbp
;
686 pCurHcb
->HCS_NxtPend
= scbp
;
687 pCurHcb
->HCS_NxtAvail
= scbp
;
688 for (i
= 0, pTmpScb
= scbp
; i
< tul_num_scb
; i
++, pTmpScb
++) {
689 pTmpScb
->SCB_TagId
= i
;
691 pPrevScb
->SCB_NxtScb
= pTmpScb
;
694 pPrevScb
->SCB_NxtScb
= NULL
;
695 pCurHcb
->HCS_ScbEnd
= pTmpScb
;
696 pCurHcb
->HCS_FirstAvail
= scbp
;
697 pCurHcb
->HCS_LastAvail
= pPrevScb
;
698 spin_lock_init(&pCurHcb
->HCS_AvailLock
);
699 pCurHcb
->HCS_FirstPend
= NULL
;
700 pCurHcb
->HCS_LastPend
= NULL
;
701 pCurHcb
->HCS_FirstBusy
= NULL
;
702 pCurHcb
->HCS_LastBusy
= NULL
;
703 pCurHcb
->HCS_FirstDone
= NULL
;
704 pCurHcb
->HCS_LastDone
= NULL
;
705 pCurHcb
->HCS_ActScb
= NULL
;
706 pCurHcb
->HCS_ActTcs
= NULL
;
708 tul_read_eeprom(pCurHcb
->HCS_Base
);
709 /*---------- get H/A configuration -------------*/
710 if (i91unvramp
->NVM_SCSIInfo
[0].NVM_NumOfTarg
== 8)
711 pCurHcb
->HCS_MaxTar
= 8;
713 pCurHcb
->HCS_MaxTar
= 16;
715 pCurHcb
->HCS_Config
= i91unvramp
->NVM_SCSIInfo
[0].NVM_ChConfig1
;
717 pCurHcb
->HCS_SCSI_ID
= i91unvramp
->NVM_SCSIInfo
[0].NVM_ChSCSIID
;
718 pCurHcb
->HCS_IdMask
= ~(1 << pCurHcb
->HCS_SCSI_ID
);
721 /* Enable parity error response */
722 TUL_WR(pCurHcb
->HCS_Base
+ TUL_PCMD
, TUL_RD(pCurHcb
->HCS_Base
, TUL_PCMD
) | 0x40);
725 /* Mask all the interrupt */
726 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
728 tul_stop_bm(pCurHcb
);
729 /* --- Initialize the tulip --- */
730 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_RST_CHIP
);
732 /* program HBA's SCSI ID */
733 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SScsiId
, pCurHcb
->HCS_SCSI_ID
<< 4);
735 /* Enable Initiator Mode ,phase latch,alternate sync period mode,
736 disable SCSI reset */
737 if (pCurHcb
->HCS_Config
& HCC_EN_PAR
)
738 pCurHcb
->HCS_SConf1
= (TSC_INITDEFAULT
| TSC_EN_SCSI_PAR
);
740 pCurHcb
->HCS_SConf1
= (TSC_INITDEFAULT
);
741 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurHcb
->HCS_SConf1
);
743 /* Enable HW reselect */
744 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
);
746 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SPeriod
, 0);
748 /* selection time out = 250 ms */
749 TUL_WR(pCurHcb
->HCS_Base
+ TUL_STimeOut
, 153);
751 /*--------- Enable SCSI terminator -----*/
752 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCtrl
, (pCurHcb
->HCS_Config
& (HCC_ACT_TERM1
| HCC_ACT_TERM2
)));
753 TUL_WR(pCurHcb
->HCS_Base
+ TUL_GCTRL1
,
754 ((pCurHcb
->HCS_Config
& HCC_AUTO_TERM
) >> 4) | (TUL_RD(pCurHcb
->HCS_Base
, TUL_GCTRL1
) & 0xFE));
757 pwFlags
= & (i91unvramp
->NVM_SCSIInfo
[0].NVM_Targ0Config
),
758 pbHeads
= pbBiosAdr
+ 0x180;
759 i
< pCurHcb
->HCS_MaxTar
;
761 pCurHcb
->HCS_Tcs
[i
].TCS_Flags
= *pwFlags
& ~(TCF_SYNC_DONE
| TCF_WDTR_DONE
);
762 if (pCurHcb
->HCS_Tcs
[i
].TCS_Flags
& TCF_EN_255
)
763 pCurHcb
->HCS_Tcs
[i
].TCS_DrvFlags
= TCF_DRV_255_63
;
765 pCurHcb
->HCS_Tcs
[i
].TCS_DrvFlags
= 0;
766 pCurHcb
->HCS_Tcs
[i
].TCS_JS_Period
= 0;
767 pCurHcb
->HCS_Tcs
[i
].TCS_SConfig0
= pCurHcb
->HCS_SConf1
;
768 pCurHcb
->HCS_Tcs
[i
].TCS_DrvHead
= *pbHeads
++;
769 if (pCurHcb
->HCS_Tcs
[i
].TCS_DrvHead
== 255)
770 pCurHcb
->HCS_Tcs
[i
].TCS_DrvFlags
= TCF_DRV_255_63
;
772 pCurHcb
->HCS_Tcs
[i
].TCS_DrvFlags
= 0;
773 pCurHcb
->HCS_Tcs
[i
].TCS_DrvSector
= *pbHeads
++;
774 pCurHcb
->HCS_Tcs
[i
].TCS_Flags
&= ~TCF_BUSY
;
775 pCurHcb
->HCS_ActTags
[i
] = 0;
776 pCurHcb
->HCS_MaxTags
[i
] = 0xFF;
778 printk("i91u: PCI Base=0x%04X, IRQ=%d, BIOS=0x%04X0, SCSI ID=%d\n",
779 pCurHcb
->HCS_Base
, pCurHcb
->HCS_Intr
,
780 pCurHcb
->HCS_BIOS
, pCurHcb
->HCS_SCSI_ID
);
781 /*------------------- reset SCSI Bus ---------------------------*/
782 if (pCurHcb
->HCS_Config
& HCC_SCSI_RESET
) {
783 printk("i91u: Reset SCSI Bus ... \n");
784 tul_reset_scsi(pCurHcb
, seconds
);
786 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCFG1
, 0x17);
787 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SIntEnable
, 0xE9);
791 /***************************************************************************/
792 static SCB
*tul_alloc_scb(HCS
* hcsp
)
796 spin_lock_irqsave(&(hcsp
->HCS_AvailLock
), flags
);
797 if ((pTmpScb
= hcsp
->HCS_FirstAvail
) != NULL
) {
799 printk("find scb at %08lx\n", (ULONG
) pTmpScb
);
801 if ((hcsp
->HCS_FirstAvail
= pTmpScb
->SCB_NxtScb
) == NULL
)
802 hcsp
->HCS_LastAvail
= NULL
;
803 pTmpScb
->SCB_NxtScb
= NULL
;
804 pTmpScb
->SCB_Status
= SCB_RENT
;
806 spin_unlock_irqrestore(&(hcsp
->HCS_AvailLock
), flags
);
810 /***************************************************************************/
811 static void tul_release_scb(HCS
* hcsp
, SCB
* scbp
)
816 printk("Release SCB %lx; ", (ULONG
) scbp
);
818 spin_lock_irqsave(&(hcsp
->HCS_AvailLock
), flags
);
819 scbp
->SCB_Srb
= NULL
;
820 scbp
->SCB_Status
= 0;
821 scbp
->SCB_NxtScb
= NULL
;
822 if (hcsp
->HCS_LastAvail
!= NULL
) {
823 hcsp
->HCS_LastAvail
->SCB_NxtScb
= scbp
;
824 hcsp
->HCS_LastAvail
= scbp
;
826 hcsp
->HCS_FirstAvail
= scbp
;
827 hcsp
->HCS_LastAvail
= scbp
;
829 spin_unlock_irqrestore(&(hcsp
->HCS_AvailLock
), flags
);
832 /***************************************************************************/
833 static void tul_append_pend_scb(HCS
* pCurHcb
, SCB
* scbp
)
837 printk("Append pend SCB %lx; ", (ULONG
) scbp
);
839 scbp
->SCB_Status
= SCB_PEND
;
840 scbp
->SCB_NxtScb
= NULL
;
841 if (pCurHcb
->HCS_LastPend
!= NULL
) {
842 pCurHcb
->HCS_LastPend
->SCB_NxtScb
= scbp
;
843 pCurHcb
->HCS_LastPend
= scbp
;
845 pCurHcb
->HCS_FirstPend
= scbp
;
846 pCurHcb
->HCS_LastPend
= scbp
;
850 /***************************************************************************/
851 static void tul_push_pend_scb(HCS
* pCurHcb
, SCB
* scbp
)
855 printk("Push pend SCB %lx; ", (ULONG
) scbp
);
857 scbp
->SCB_Status
= SCB_PEND
;
858 if ((scbp
->SCB_NxtScb
= pCurHcb
->HCS_FirstPend
) != NULL
) {
859 pCurHcb
->HCS_FirstPend
= scbp
;
861 pCurHcb
->HCS_FirstPend
= scbp
;
862 pCurHcb
->HCS_LastPend
= scbp
;
866 /***************************************************************************/
867 static SCB
*tul_find_first_pend_scb(HCS
* pCurHcb
)
872 pFirstPend
= pCurHcb
->HCS_FirstPend
;
873 while (pFirstPend
!= NULL
) {
874 if (pFirstPend
->SCB_Opcode
!= ExecSCSI
) {
877 if (pFirstPend
->SCB_TagMsg
== 0) {
878 if ((pCurHcb
->HCS_ActTags
[pFirstPend
->SCB_Target
] == 0) &&
879 !(pCurHcb
->HCS_Tcs
[pFirstPend
->SCB_Target
].TCS_Flags
& TCF_BUSY
)) {
883 if ((pCurHcb
->HCS_ActTags
[pFirstPend
->SCB_Target
] >=
884 pCurHcb
->HCS_MaxTags
[pFirstPend
->SCB_Target
]) |
885 (pCurHcb
->HCS_Tcs
[pFirstPend
->SCB_Target
].TCS_Flags
& TCF_BUSY
)) {
886 pFirstPend
= pFirstPend
->SCB_NxtScb
;
891 pFirstPend
= pFirstPend
->SCB_NxtScb
;
897 /***************************************************************************/
898 static void tul_unlink_pend_scb(HCS
* pCurHcb
, SCB
* pCurScb
)
900 SCB
*pTmpScb
, *pPrevScb
;
903 printk("unlink pend SCB %lx; ", (ULONG
) pCurScb
);
906 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstPend
;
907 while (pTmpScb
!= NULL
) {
908 if (pCurScb
== pTmpScb
) { /* Unlink this SCB */
909 if (pTmpScb
== pCurHcb
->HCS_FirstPend
) {
910 if ((pCurHcb
->HCS_FirstPend
= pTmpScb
->SCB_NxtScb
) == NULL
)
911 pCurHcb
->HCS_LastPend
= NULL
;
913 pPrevScb
->SCB_NxtScb
= pTmpScb
->SCB_NxtScb
;
914 if (pTmpScb
== pCurHcb
->HCS_LastPend
)
915 pCurHcb
->HCS_LastPend
= pPrevScb
;
917 pTmpScb
->SCB_NxtScb
= NULL
;
921 pTmpScb
= pTmpScb
->SCB_NxtScb
;
925 /***************************************************************************/
926 static void tul_append_busy_scb(HCS
* pCurHcb
, SCB
* scbp
)
930 printk("append busy SCB %lx; ", (ULONG
) scbp
);
932 if (scbp
->SCB_TagMsg
)
933 pCurHcb
->HCS_ActTags
[scbp
->SCB_Target
]++;
935 pCurHcb
->HCS_Tcs
[scbp
->SCB_Target
].TCS_Flags
|= TCF_BUSY
;
936 scbp
->SCB_Status
= SCB_BUSY
;
937 scbp
->SCB_NxtScb
= NULL
;
938 if (pCurHcb
->HCS_LastBusy
!= NULL
) {
939 pCurHcb
->HCS_LastBusy
->SCB_NxtScb
= scbp
;
940 pCurHcb
->HCS_LastBusy
= scbp
;
942 pCurHcb
->HCS_FirstBusy
= scbp
;
943 pCurHcb
->HCS_LastBusy
= scbp
;
947 /***************************************************************************/
948 static SCB
*tul_pop_busy_scb(HCS
* pCurHcb
)
953 if ((pTmpScb
= pCurHcb
->HCS_FirstBusy
) != NULL
) {
954 if ((pCurHcb
->HCS_FirstBusy
= pTmpScb
->SCB_NxtScb
) == NULL
)
955 pCurHcb
->HCS_LastBusy
= NULL
;
956 pTmpScb
->SCB_NxtScb
= NULL
;
957 if (pTmpScb
->SCB_TagMsg
)
958 pCurHcb
->HCS_ActTags
[pTmpScb
->SCB_Target
]--;
960 pCurHcb
->HCS_Tcs
[pTmpScb
->SCB_Target
].TCS_Flags
&= ~TCF_BUSY
;
963 printk("Pop busy SCB %lx; ", (ULONG
) pTmpScb
);
968 /***************************************************************************/
969 static void tul_unlink_busy_scb(HCS
* pCurHcb
, SCB
* pCurScb
)
971 SCB
*pTmpScb
, *pPrevScb
;
974 printk("unlink busy SCB %lx; ", (ULONG
) pCurScb
);
977 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstBusy
;
978 while (pTmpScb
!= NULL
) {
979 if (pCurScb
== pTmpScb
) { /* Unlink this SCB */
980 if (pTmpScb
== pCurHcb
->HCS_FirstBusy
) {
981 if ((pCurHcb
->HCS_FirstBusy
= pTmpScb
->SCB_NxtScb
) == NULL
)
982 pCurHcb
->HCS_LastBusy
= NULL
;
984 pPrevScb
->SCB_NxtScb
= pTmpScb
->SCB_NxtScb
;
985 if (pTmpScb
== pCurHcb
->HCS_LastBusy
)
986 pCurHcb
->HCS_LastBusy
= pPrevScb
;
988 pTmpScb
->SCB_NxtScb
= NULL
;
989 if (pTmpScb
->SCB_TagMsg
)
990 pCurHcb
->HCS_ActTags
[pTmpScb
->SCB_Target
]--;
992 pCurHcb
->HCS_Tcs
[pTmpScb
->SCB_Target
].TCS_Flags
&= ~TCF_BUSY
;
996 pTmpScb
= pTmpScb
->SCB_NxtScb
;
1001 /***************************************************************************/
1002 SCB
*tul_find_busy_scb(HCS
* pCurHcb
, WORD tarlun
)
1004 SCB
*pTmpScb
, *pPrevScb
;
1008 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstBusy
;
1009 while (pTmpScb
!= NULL
) {
1010 scbp_tarlun
= (pTmpScb
->SCB_Lun
<< 8) | (pTmpScb
->SCB_Target
);
1011 if (scbp_tarlun
== tarlun
) { /* Unlink this SCB */
1015 pTmpScb
= pTmpScb
->SCB_NxtScb
;
1018 printk("find busy SCB %lx; ", (ULONG
) pTmpScb
);
1023 /***************************************************************************/
1024 static void tul_append_done_scb(HCS
* pCurHcb
, SCB
* scbp
)
1028 printk("append done SCB %lx; ", (ULONG
) scbp
);
1031 scbp
->SCB_Status
= SCB_DONE
;
1032 scbp
->SCB_NxtScb
= NULL
;
1033 if (pCurHcb
->HCS_LastDone
!= NULL
) {
1034 pCurHcb
->HCS_LastDone
->SCB_NxtScb
= scbp
;
1035 pCurHcb
->HCS_LastDone
= scbp
;
1037 pCurHcb
->HCS_FirstDone
= scbp
;
1038 pCurHcb
->HCS_LastDone
= scbp
;
1042 /***************************************************************************/
1043 SCB
*tul_find_done_scb(HCS
* pCurHcb
)
1048 if ((pTmpScb
= pCurHcb
->HCS_FirstDone
) != NULL
) {
1049 if ((pCurHcb
->HCS_FirstDone
= pTmpScb
->SCB_NxtScb
) == NULL
)
1050 pCurHcb
->HCS_LastDone
= NULL
;
1051 pTmpScb
->SCB_NxtScb
= NULL
;
1054 printk("find done SCB %lx; ", (ULONG
) pTmpScb
);
1059 /***************************************************************************/
1060 static int tul_abort_srb(HCS
* pCurHcb
, struct scsi_cmnd
*srbp
)
1063 SCB
*pTmpScb
, *pPrevScb
;
1065 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1067 if ((pCurHcb
->HCS_Semaph
== 0) && (pCurHcb
->HCS_ActScb
== NULL
)) {
1068 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1069 /* disable Jasmin SCSI Int */
1071 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1073 tulip_main(pCurHcb
);
1075 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1077 pCurHcb
->HCS_Semaph
= 1;
1078 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1080 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1082 return SCSI_ABORT_SNOOZE
;
1084 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstPend
; /* Check Pend queue */
1085 while (pTmpScb
!= NULL
) {
1087 if (pTmpScb
->SCB_Srb
== srbp
) {
1088 if (pTmpScb
== pCurHcb
->HCS_ActScb
) {
1089 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1090 return SCSI_ABORT_BUSY
;
1091 } else if (pTmpScb
== pCurHcb
->HCS_FirstPend
) {
1092 if ((pCurHcb
->HCS_FirstPend
= pTmpScb
->SCB_NxtScb
) == NULL
)
1093 pCurHcb
->HCS_LastPend
= NULL
;
1095 pPrevScb
->SCB_NxtScb
= pTmpScb
->SCB_NxtScb
;
1096 if (pTmpScb
== pCurHcb
->HCS_LastPend
)
1097 pCurHcb
->HCS_LastPend
= pPrevScb
;
1099 pTmpScb
->SCB_HaStat
= HOST_ABORTED
;
1100 pTmpScb
->SCB_Flags
|= SCF_DONE
;
1101 if (pTmpScb
->SCB_Flags
& SCF_POST
)
1102 (*pTmpScb
->SCB_Post
) ((BYTE
*) pCurHcb
, (BYTE
*) pTmpScb
);
1103 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1104 return SCSI_ABORT_SUCCESS
;
1107 pTmpScb
= pTmpScb
->SCB_NxtScb
;
1110 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstBusy
; /* Check Busy queue */
1111 while (pTmpScb
!= NULL
) {
1113 if (pTmpScb
->SCB_Srb
== srbp
) {
1115 if (pTmpScb
== pCurHcb
->HCS_ActScb
) {
1116 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1117 return SCSI_ABORT_BUSY
;
1118 } else if (pTmpScb
->SCB_TagMsg
== 0) {
1119 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1120 return SCSI_ABORT_BUSY
;
1122 pCurHcb
->HCS_ActTags
[pTmpScb
->SCB_Target
]--;
1123 if (pTmpScb
== pCurHcb
->HCS_FirstBusy
) {
1124 if ((pCurHcb
->HCS_FirstBusy
= pTmpScb
->SCB_NxtScb
) == NULL
)
1125 pCurHcb
->HCS_LastBusy
= NULL
;
1127 pPrevScb
->SCB_NxtScb
= pTmpScb
->SCB_NxtScb
;
1128 if (pTmpScb
== pCurHcb
->HCS_LastBusy
)
1129 pCurHcb
->HCS_LastBusy
= pPrevScb
;
1131 pTmpScb
->SCB_NxtScb
= NULL
;
1134 pTmpScb
->SCB_HaStat
= HOST_ABORTED
;
1135 pTmpScb
->SCB_Flags
|= SCF_DONE
;
1136 if (pTmpScb
->SCB_Flags
& SCF_POST
)
1137 (*pTmpScb
->SCB_Post
) ((BYTE
*) pCurHcb
, (BYTE
*) pTmpScb
);
1138 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1139 return SCSI_ABORT_SUCCESS
;
1143 pTmpScb
= pTmpScb
->SCB_NxtScb
;
1145 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1146 return (SCSI_ABORT_NOT_RUNNING
);
1149 /***************************************************************************/
1150 static int tul_bad_seq(HCS
* pCurHcb
)
1154 printk("tul_bad_seg c=%d\n", pCurHcb
->HCS_Index
);
1156 if ((pCurScb
= pCurHcb
->HCS_ActScb
) != NULL
) {
1157 tul_unlink_busy_scb(pCurHcb
, pCurScb
);
1158 pCurScb
->SCB_HaStat
= HOST_BAD_PHAS
;
1159 pCurScb
->SCB_TaStat
= 0;
1160 tul_append_done_scb(pCurHcb
, pCurScb
);
1162 tul_stop_bm(pCurHcb
);
1164 tul_reset_scsi(pCurHcb
, 8); /* 7/29/98 */
1166 return (tul_post_scsi_rst(pCurHcb
));
1171 /************************************************************************/
1172 static int tul_device_reset(HCS
* pCurHcb
, struct scsi_cmnd
*pSrb
,
1173 unsigned int target
, unsigned int ResetFlags
)
1177 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1179 if (ResetFlags
& SCSI_RESET_ASYNCHRONOUS
) {
1181 if ((pCurHcb
->HCS_Semaph
== 0) && (pCurHcb
->HCS_ActScb
== NULL
)) {
1182 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1183 /* disable Jasmin SCSI Int */
1185 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1187 tulip_main(pCurHcb
);
1189 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1191 pCurHcb
->HCS_Semaph
= 1;
1192 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1194 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1196 return SCSI_RESET_SNOOZE
;
1198 pScb
= pCurHcb
->HCS_FirstBusy
; /* Check Busy queue */
1199 while (pScb
!= NULL
) {
1200 if (pScb
->SCB_Srb
== pSrb
)
1202 pScb
= pScb
->SCB_NxtScb
;
1205 printk("Unable to Reset - No SCB Found\n");
1207 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1208 return SCSI_RESET_NOT_RUNNING
;
1211 if ((pScb
= tul_alloc_scb(pCurHcb
)) == NULL
) {
1212 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1213 return SCSI_RESET_NOT_RUNNING
;
1215 pScb
->SCB_Opcode
= BusDevRst
;
1216 pScb
->SCB_Flags
= SCF_POST
;
1217 pScb
->SCB_Target
= target
;
1220 pScb
->SCB_Srb
= NULL
;
1221 if (ResetFlags
& SCSI_RESET_SYNCHRONOUS
) {
1222 pScb
->SCB_Srb
= pSrb
;
1224 tul_push_pend_scb(pCurHcb
, pScb
); /* push this SCB to Pending queue */
1226 if (pCurHcb
->HCS_Semaph
== 1) {
1227 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1228 /* disable Jasmin SCSI Int */
1229 pCurHcb
->HCS_Semaph
= 0;
1231 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1233 tulip_main(pCurHcb
);
1235 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1237 pCurHcb
->HCS_Semaph
= 1;
1238 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1240 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1241 return SCSI_RESET_PENDING
;
1244 static int tul_reset_scsi_bus(HCS
* pCurHcb
)
1248 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1249 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1250 pCurHcb
->HCS_Semaph
= 0;
1252 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1254 tul_stop_bm(pCurHcb
);
1256 tul_reset_scsi(pCurHcb
, 2); /* 7/29/98 */
1258 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1259 tul_post_scsi_rst(pCurHcb
);
1261 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1263 tulip_main(pCurHcb
);
1265 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1267 pCurHcb
->HCS_Semaph
= 1;
1268 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1269 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1270 return (SCSI_RESET_SUCCESS
| SCSI_RESET_HOST_RESET
);
1275 /************************************************************************/
1276 static void tul_exec_scb(HCS
* pCurHcb
, SCB
* pCurScb
)
1280 pCurScb
->SCB_Mode
= 0;
1282 pCurScb
->SCB_SGIdx
= 0;
1283 pCurScb
->SCB_SGMax
= pCurScb
->SCB_SGLen
;
1285 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1287 tul_append_pend_scb(pCurHcb
, pCurScb
); /* Append this SCB to Pending queue */
1289 /* VVVVV 07/21/98 */
1290 if (pCurHcb
->HCS_Semaph
== 1) {
1291 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1292 /* disable Jasmin SCSI Int */
1293 pCurHcb
->HCS_Semaph
= 0;
1295 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1297 tulip_main(pCurHcb
);
1299 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1301 pCurHcb
->HCS_Semaph
= 1;
1302 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1304 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1308 /***************************************************************************/
1309 static int tul_isr(HCS
* pCurHcb
)
1311 /* Enter critical section */
1313 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_Int
) & TSS_INT_PENDING
) {
1314 if (pCurHcb
->HCS_Semaph
== 1) {
1315 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1316 /* Disable Tulip SCSI Int */
1317 pCurHcb
->HCS_Semaph
= 0;
1319 tulip_main(pCurHcb
);
1321 pCurHcb
->HCS_Semaph
= 1;
1322 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1329 /***************************************************************************/
1330 int tulip_main(HCS
* pCurHcb
)
1336 tulip_scsi(pCurHcb
); /* Call tulip_scsi */
1338 while ((pCurScb
= tul_find_done_scb(pCurHcb
)) != NULL
) { /* find done entry */
1339 if (pCurScb
->SCB_TaStat
== INI_QUEUE_FULL
) {
1340 pCurHcb
->HCS_MaxTags
[pCurScb
->SCB_Target
] =
1341 pCurHcb
->HCS_ActTags
[pCurScb
->SCB_Target
] - 1;
1342 pCurScb
->SCB_TaStat
= 0;
1343 tul_append_pend_scb(pCurHcb
, pCurScb
);
1346 if (!(pCurScb
->SCB_Mode
& SCM_RSENS
)) { /* not in auto req. sense mode */
1347 if (pCurScb
->SCB_TaStat
== 2) {
1349 /* clr sync. nego flag */
1351 if (pCurScb
->SCB_Flags
& SCF_SENSE
) {
1353 len
= pCurScb
->SCB_SenseLen
;
1356 pCurScb
->SCB_BufLen
= pCurScb
->SCB_SenseLen
;
1357 pCurScb
->SCB_BufPtr
= pCurScb
->SCB_SensePtr
;
1358 pCurScb
->SCB_Flags
&= ~(SCF_SG
| SCF_DIR
); /* for xfer_data_in */
1359 /* pCurScb->SCB_Flags |= SCF_NO_DCHK; */
1360 /* so, we won't report worng direction in xfer_data_in,
1361 and won't report HOST_DO_DU in state_6 */
1362 pCurScb
->SCB_Mode
= SCM_RSENS
;
1363 pCurScb
->SCB_Ident
&= 0xBF; /* Disable Disconnect */
1364 pCurScb
->SCB_TagMsg
= 0;
1365 pCurScb
->SCB_TaStat
= 0;
1366 pCurScb
->SCB_CDBLen
= 6;
1367 pCurScb
->SCB_CDB
[0] = SCSICMD_RequestSense
;
1368 pCurScb
->SCB_CDB
[1] = 0;
1369 pCurScb
->SCB_CDB
[2] = 0;
1370 pCurScb
->SCB_CDB
[3] = 0;
1371 pCurScb
->SCB_CDB
[4] = len
;
1372 pCurScb
->SCB_CDB
[5] = 0;
1373 tul_push_pend_scb(pCurHcb
, pCurScb
);
1377 } else { /* in request sense mode */
1379 if (pCurScb
->SCB_TaStat
== 2) { /* check contition status again after sending
1380 requset sense cmd 0x3 */
1381 pCurScb
->SCB_HaStat
= HOST_BAD_PHAS
;
1383 pCurScb
->SCB_TaStat
= 2;
1385 pCurScb
->SCB_Flags
|= SCF_DONE
;
1386 if (pCurScb
->SCB_Flags
& SCF_POST
) {
1387 (*pCurScb
->SCB_Post
) ((BYTE
*) pCurHcb
, (BYTE
*) pCurScb
);
1392 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus0
) & TSS_INT_PENDING
)
1395 if (pCurHcb
->HCS_ActScb
) { /* return to OS and wait for xfer_done_ISR/Selected_ISR */
1396 return 1; /* return to OS, enable interrupt */
1398 /* Check pending SCB */
1399 if (tul_find_first_pend_scb(pCurHcb
) == NULL
) {
1400 return 1; /* return to OS, enable interrupt */
1402 } /* End of for loop */
1403 /* statement won't reach here */
1409 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
1410 /***************************************************************************/
1411 /***************************************************************************/
1412 /***************************************************************************/
1413 /***************************************************************************/
1415 /***************************************************************************/
1416 void tulip_scsi(HCS
* pCurHcb
)
1421 /* make sure to service interrupt asap */
1423 if ((pCurHcb
->HCS_JSStatus0
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus0
)) & TSS_INT_PENDING
) {
1425 pCurHcb
->HCS_Phase
= pCurHcb
->HCS_JSStatus0
& TSS_PH_MASK
;
1426 pCurHcb
->HCS_JSStatus1
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus1
);
1427 pCurHcb
->HCS_JSInt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
);
1428 if (pCurHcb
->HCS_JSInt
& TSS_SCSIRST_INT
) { /* SCSI bus reset detected */
1429 int_tul_scsi_rst(pCurHcb
);
1432 if (pCurHcb
->HCS_JSInt
& TSS_RESEL_INT
) { /* if selected/reselected interrupt */
1433 if (int_tul_resel(pCurHcb
) == 0)
1434 tul_next_state(pCurHcb
);
1437 if (pCurHcb
->HCS_JSInt
& TSS_SEL_TIMEOUT
) {
1438 int_tul_busfree(pCurHcb
);
1441 if (pCurHcb
->HCS_JSInt
& TSS_DISC_INT
) { /* BUS disconnection */
1442 int_tul_busfree(pCurHcb
); /* unexpected bus free or sel timeout */
1445 if (pCurHcb
->HCS_JSInt
& (TSS_FUNC_COMP
| TSS_BUS_SERV
)) { /* func complete or Bus service */
1446 if ((pCurScb
= pCurHcb
->HCS_ActScb
) != NULL
)
1447 tul_next_state(pCurHcb
);
1451 if (pCurHcb
->HCS_ActScb
!= NULL
)
1454 if ((pCurScb
= tul_find_first_pend_scb(pCurHcb
)) == NULL
)
1457 /* program HBA's SCSI ID & target SCSI ID */
1458 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SScsiId
,
1459 (pCurHcb
->HCS_SCSI_ID
<< 4) | (pCurScb
->SCB_Target
& 0x0F));
1460 if (pCurScb
->SCB_Opcode
== ExecSCSI
) {
1461 pCurTcb
= &pCurHcb
->HCS_Tcs
[pCurScb
->SCB_Target
];
1463 if (pCurScb
->SCB_TagMsg
)
1464 pCurTcb
->TCS_DrvFlags
|= TCF_DRV_EN_TAG
;
1466 pCurTcb
->TCS_DrvFlags
&= ~TCF_DRV_EN_TAG
;
1468 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SPeriod
, pCurTcb
->TCS_JS_Period
);
1469 if ((pCurTcb
->TCS_Flags
& (TCF_WDTR_DONE
| TCF_NO_WDTR
)) == 0) { /* do wdtr negotiation */
1470 tul_select_atn_stop(pCurHcb
, pCurScb
);
1472 if ((pCurTcb
->TCS_Flags
& (TCF_SYNC_DONE
| TCF_NO_SYNC_NEGO
)) == 0) { /* do sync negotiation */
1473 tul_select_atn_stop(pCurHcb
, pCurScb
);
1475 if (pCurScb
->SCB_TagMsg
)
1476 tul_select_atn3(pCurHcb
, pCurScb
);
1478 tul_select_atn(pCurHcb
, pCurScb
);
1481 if (pCurScb
->SCB_Flags
& SCF_POLL
) {
1482 while (wait_tulip(pCurHcb
) != -1) {
1483 if (tul_next_state(pCurHcb
) == -1)
1487 } else if (pCurScb
->SCB_Opcode
== BusDevRst
) {
1488 tul_select_atn_stop(pCurHcb
, pCurScb
);
1489 pCurScb
->SCB_NxtStat
= 8;
1490 if (pCurScb
->SCB_Flags
& SCF_POLL
) {
1491 while (wait_tulip(pCurHcb
) != -1) {
1492 if (tul_next_state(pCurHcb
) == -1)
1496 } else if (pCurScb
->SCB_Opcode
== AbortCmd
) {
1497 if (tul_abort_srb(pCurHcb
, pCurScb
->SCB_Srb
) != 0) {
1500 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
1502 tul_release_scb(pCurHcb
, pCurScb
);
1504 pCurScb
->SCB_Opcode
= BusDevRst
;
1505 tul_select_atn_stop(pCurHcb
, pCurScb
);
1506 pCurScb
->SCB_NxtStat
= 8;
1511 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
1512 pCurScb
->SCB_HaStat
= 0x16; /* bad command */
1513 tul_append_done_scb(pCurHcb
, pCurScb
);
1519 /***************************************************************************/
1520 int tul_next_state(HCS
* pCurHcb
)
1524 next
= pCurHcb
->HCS_ActScb
->SCB_NxtStat
;
1528 next
= tul_state_1(pCurHcb
);
1531 next
= tul_state_2(pCurHcb
);
1534 next
= tul_state_3(pCurHcb
);
1537 next
= tul_state_4(pCurHcb
);
1540 next
= tul_state_5(pCurHcb
);
1543 next
= tul_state_6(pCurHcb
);
1546 next
= tul_state_7(pCurHcb
);
1549 return (tul_bus_device_reset(pCurHcb
));
1551 return (tul_bad_seq(pCurHcb
));
1559 /***************************************************************************/
1560 /* sTate after selection with attention & stop */
1561 int tul_state_1(HCS
* pCurHcb
)
1563 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1564 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
1569 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
1570 tul_append_busy_scb(pCurHcb
, pCurScb
);
1572 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurTcb
->TCS_SConfig0
);
1574 if (pCurHcb
->HCS_Phase
== MSG_OUT
) {
1576 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, (TSC_EN_BUS_IN
| TSC_HW_RESELECT
));
1578 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_Ident
);
1580 if (pCurScb
->SCB_TagMsg
) {
1581 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_TagMsg
);
1582 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_TagId
);
1584 if ((pCurTcb
->TCS_Flags
& (TCF_WDTR_DONE
| TCF_NO_WDTR
)) == 0) {
1586 pCurTcb
->TCS_Flags
|= TCF_WDTR_DONE
;
1588 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_EXTEND
);
1589 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 2); /* Extended msg length */
1590 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 3); /* Sync request */
1591 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 1); /* Start from 16 bits */
1592 } else if ((pCurTcb
->TCS_Flags
& (TCF_SYNC_DONE
| TCF_NO_SYNC_NEGO
)) == 0) {
1594 pCurTcb
->TCS_Flags
|= TCF_SYNC_DONE
;
1596 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_EXTEND
);
1597 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 3); /* extended msg length */
1598 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 1); /* sync request */
1599 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, tul_rate_tbl
[pCurTcb
->TCS_Flags
& TCF_SCSI_RATE
]);
1600 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MAX_OFFSET
); /* REQ/ACK offset */
1602 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1603 if (wait_tulip(pCurHcb
) == -1)
1606 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1607 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, (TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)));
1612 /***************************************************************************/
1613 /* state after selection with attention */
1614 /* state after selection with attention3 */
1615 int tul_state_2(HCS
* pCurHcb
)
1617 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1618 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
1623 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
1624 tul_append_busy_scb(pCurHcb
, pCurScb
);
1626 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurTcb
->TCS_SConfig0
);
1628 if (pCurHcb
->HCS_JSStatus1
& TSS_CMD_PH_CMP
) {
1631 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1632 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, (TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)));
1636 /***************************************************************************/
1637 /* state before CDB xfer is done */
1638 int tul_state_3(HCS
* pCurHcb
)
1640 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1641 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
1648 switch (pCurHcb
->HCS_Phase
) {
1649 case CMD_OUT
: /* Command out phase */
1650 for (i
= 0; i
< (int) pCurScb
->SCB_CDBLen
; i
++)
1651 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_CDB
[i
]);
1652 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1653 if (wait_tulip(pCurHcb
) == -1)
1655 if (pCurHcb
->HCS_Phase
== CMD_OUT
) {
1656 return (tul_bad_seq(pCurHcb
));
1660 case MSG_IN
: /* Message in phase */
1661 pCurScb
->SCB_NxtStat
= 3;
1662 if (tul_msgin(pCurHcb
) == -1)
1666 case STATUS_IN
: /* Status phase */
1667 if (tul_status_msg(pCurHcb
) == -1)
1671 case MSG_OUT
: /* Message out phase */
1672 if (pCurTcb
->TCS_Flags
& (TCF_SYNC_DONE
| TCF_NO_SYNC_NEGO
)) {
1674 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_NOP
); /* msg nop */
1675 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1676 if (wait_tulip(pCurHcb
) == -1)
1680 pCurTcb
->TCS_Flags
|= TCF_SYNC_DONE
;
1682 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_EXTEND
);
1683 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 3); /* ext. msg len */
1684 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 1); /* sync request */
1685 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, tul_rate_tbl
[pCurTcb
->TCS_Flags
& TCF_SCSI_RATE
]);
1686 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MAX_OFFSET
); /* REQ/ACK offset */
1687 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1688 if (wait_tulip(pCurHcb
) == -1)
1690 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1691 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7));
1697 return (tul_bad_seq(pCurHcb
));
1703 /***************************************************************************/
1704 int tul_state_4(HCS
* pCurHcb
)
1706 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1711 if ((pCurScb
->SCB_Flags
& SCF_DIR
) == SCF_NO_XF
) {
1712 return (6); /* Go to state 6 */
1715 if (pCurScb
->SCB_BufLen
== 0)
1716 return (6); /* Go to state 6 */
1718 switch (pCurHcb
->HCS_Phase
) {
1720 case STATUS_IN
: /* Status phase */
1721 if ((pCurScb
->SCB_Flags
& SCF_DIR
) != 0) { /* if direction bit set then report data underrun */
1722 pCurScb
->SCB_HaStat
= HOST_DO_DU
;
1724 if ((tul_status_msg(pCurHcb
)) == -1)
1728 case MSG_IN
: /* Message in phase */
1729 pCurScb
->SCB_NxtStat
= 0x4;
1730 if (tul_msgin(pCurHcb
) == -1)
1734 case MSG_OUT
: /* Message out phase */
1735 if (pCurHcb
->HCS_JSStatus0
& TSS_PAR_ERROR
) {
1736 pCurScb
->SCB_BufLen
= 0;
1737 pCurScb
->SCB_HaStat
= HOST_DO_DU
;
1738 if (tul_msgout_ide(pCurHcb
) == -1)
1740 return (6); /* Go to state 6 */
1742 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_NOP
); /* msg nop */
1743 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1744 if (wait_tulip(pCurHcb
) == -1)
1749 case DATA_IN
: /* Data in phase */
1750 return (tul_xfer_data_in(pCurHcb
));
1752 case DATA_OUT
: /* Data out phase */
1753 return (tul_xfer_data_out(pCurHcb
));
1756 return (tul_bad_seq(pCurHcb
));
1762 /***************************************************************************/
1763 /* state after dma xfer done or phase change before xfer done */
1764 int tul_state_5(HCS
* pCurHcb
)
1766 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1767 long cnt
, xcnt
; /* cannot use unsigned !! code: if (xcnt < 0) */
1772 /*------ get remaining count -------*/
1774 cnt
= TUL_RDLONG(pCurHcb
->HCS_Base
, TUL_SCnt0
) & 0x0FFFFFF;
1776 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_XCmd
) & 0x20) {
1777 /* ----------------------- DATA_IN ----------------------------- */
1778 /* check scsi parity error */
1779 if (pCurHcb
->HCS_JSStatus0
& TSS_PAR_ERROR
) {
1780 pCurScb
->SCB_HaStat
= HOST_DO_DU
;
1782 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_XStatus
) & XPEND
) { /* DMA xfer pending, Send STOP */
1783 /* tell Hardware scsi xfer has been terminated */
1784 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCtrl
, TUL_RD(pCurHcb
->HCS_Base
, TUL_XCtrl
) | 0x80);
1785 /* wait until DMA xfer not pending */
1786 while (TUL_RD(pCurHcb
->HCS_Base
, TUL_XStatus
) & XPEND
);
1789 /*-------- DATA OUT -----------*/
1790 if ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus1
) & TSS_XFER_CMP
) == 0) {
1791 if (pCurHcb
->HCS_ActTcs
->TCS_JS_Period
& TSC_WIDE_SCSI
)
1792 cnt
+= (TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifoCnt
) & 0x1F) << 1;
1794 cnt
+= (TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifoCnt
) & 0x1F);
1796 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_XStatus
) & XPEND
) { /* if DMA xfer is pending, abort DMA xfer */
1797 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_X_ABT
);
1798 /* wait Abort DMA xfer done */
1799 while ((TUL_RD(pCurHcb
->HCS_Base
, TUL_Int
) & XABT
) == 0);
1801 if ((cnt
== 1) && (pCurHcb
->HCS_Phase
== DATA_OUT
)) {
1802 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1803 if (wait_tulip(pCurHcb
) == -1) {
1808 if ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus1
) & TSS_XFER_CMP
) == 0)
1809 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1814 pCurScb
->SCB_BufLen
= 0;
1815 return (6); /* Go to state 6 */
1817 /* Update active data pointer */
1818 xcnt
= (long) pCurScb
->SCB_BufLen
- cnt
; /* xcnt== bytes already xferred */
1819 pCurScb
->SCB_BufLen
= (U32
) cnt
; /* cnt == bytes left to be xferred */
1820 if (pCurScb
->SCB_Flags
& SCF_SG
) {
1824 sgp
= &pCurScb
->SCB_SGList
[pCurScb
->SCB_SGIdx
];
1825 for (i
= pCurScb
->SCB_SGIdx
; i
< pCurScb
->SCB_SGMax
; sgp
++, i
++) {
1826 xcnt
-= (long) sgp
->SG_Len
;
1827 if (xcnt
< 0) { /* this sgp xfer half done */
1828 xcnt
+= (long) sgp
->SG_Len
; /* xcnt == bytes xferred in this sgp */
1829 sgp
->SG_Ptr
+= (U32
) xcnt
; /* new ptr to be xfer */
1830 sgp
->SG_Len
-= (U32
) xcnt
; /* new len to be xfer */
1831 pCurScb
->SCB_BufPtr
+= ((U32
) (i
- pCurScb
->SCB_SGIdx
) << 3);
1832 /* new SG table ptr */
1833 pCurScb
->SCB_SGLen
= (BYTE
) (pCurScb
->SCB_SGMax
- i
);
1834 /* new SG table len */
1835 pCurScb
->SCB_SGIdx
= (WORD
) i
;
1836 /* for next disc and come in this loop */
1837 return (4); /* Go to state 4 */
1839 /* else (xcnt >= 0 , i.e. this sgp already xferred */
1841 return (6); /* Go to state 6 */
1843 pCurScb
->SCB_BufPtr
+= (U32
) xcnt
;
1845 return (4); /* Go to state 4 */
1848 /***************************************************************************/
1849 /* state after Data phase */
1850 int tul_state_6(HCS
* pCurHcb
)
1852 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1858 switch (pCurHcb
->HCS_Phase
) {
1859 case STATUS_IN
: /* Status phase */
1860 if ((tul_status_msg(pCurHcb
)) == -1)
1864 case MSG_IN
: /* Message in phase */
1865 pCurScb
->SCB_NxtStat
= 6;
1866 if ((tul_msgin(pCurHcb
)) == -1)
1870 case MSG_OUT
: /* Message out phase */
1871 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_NOP
); /* msg nop */
1872 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1873 if (wait_tulip(pCurHcb
) == -1)
1877 case DATA_IN
: /* Data in phase */
1878 return (tul_xpad_in(pCurHcb
));
1880 case DATA_OUT
: /* Data out phase */
1881 return (tul_xpad_out(pCurHcb
));
1884 return (tul_bad_seq(pCurHcb
));
1889 /***************************************************************************/
1890 int tul_state_7(HCS
* pCurHcb
)
1897 /* flush SCSI FIFO */
1898 cnt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifoCnt
) & 0x1F;
1900 for (i
= 0; i
< cnt
; i
++)
1901 TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
1903 switch (pCurHcb
->HCS_Phase
) {
1904 case DATA_IN
: /* Data in phase */
1905 case DATA_OUT
: /* Data out phase */
1906 return (tul_bad_seq(pCurHcb
));
1908 return (6); /* Go to state 6 */
1912 /***************************************************************************/
1913 int tul_xfer_data_in(HCS
* pCurHcb
)
1915 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1917 if ((pCurScb
->SCB_Flags
& SCF_DIR
) == SCF_DOUT
) {
1918 return (6); /* wrong direction */
1920 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, pCurScb
->SCB_BufLen
);
1922 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_DMA_IN
); /* 7/25/95 */
1924 if (pCurScb
->SCB_Flags
& SCF_SG
) { /* S/G xfer */
1925 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XCntH
, ((ULONG
) pCurScb
->SCB_SGLen
) << 3);
1926 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XAddH
, pCurScb
->SCB_BufPtr
);
1927 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_SG_IN
);
1929 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XCntH
, pCurScb
->SCB_BufLen
);
1930 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XAddH
, pCurScb
->SCB_BufPtr
);
1931 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_X_IN
);
1933 pCurScb
->SCB_NxtStat
= 0x5;
1934 return (0); /* return to OS, wait xfer done , let jas_isr come in */
1938 /***************************************************************************/
1939 int tul_xfer_data_out(HCS
* pCurHcb
)
1941 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1943 if ((pCurScb
->SCB_Flags
& SCF_DIR
) == SCF_DIN
) {
1944 return (6); /* wrong direction */
1946 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, pCurScb
->SCB_BufLen
);
1947 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_DMA_OUT
);
1949 if (pCurScb
->SCB_Flags
& SCF_SG
) { /* S/G xfer */
1950 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XCntH
, ((ULONG
) pCurScb
->SCB_SGLen
) << 3);
1951 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XAddH
, pCurScb
->SCB_BufPtr
);
1952 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_SG_OUT
);
1954 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XCntH
, pCurScb
->SCB_BufLen
);
1955 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XAddH
, pCurScb
->SCB_BufPtr
);
1956 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_X_OUT
);
1959 pCurScb
->SCB_NxtStat
= 0x5;
1960 return (0); /* return to OS, wait xfer done , let jas_isr come in */
1964 /***************************************************************************/
1965 int tul_xpad_in(HCS
* pCurHcb
)
1967 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1968 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
1970 if ((pCurScb
->SCB_Flags
& SCF_DIR
) != SCF_NO_DCHK
) {
1971 pCurScb
->SCB_HaStat
= HOST_DO_DU
; /* over run */
1974 if (pCurTcb
->TCS_JS_Period
& TSC_WIDE_SCSI
)
1975 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 2);
1977 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
1979 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
1980 if ((wait_tulip(pCurHcb
)) == -1) {
1983 if (pCurHcb
->HCS_Phase
!= DATA_IN
) {
1984 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1987 TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
1991 int tul_xpad_out(HCS
* pCurHcb
)
1993 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1994 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
1996 if ((pCurScb
->SCB_Flags
& SCF_DIR
) != SCF_NO_DCHK
) {
1997 pCurScb
->SCB_HaStat
= HOST_DO_DU
; /* over run */
2000 if (pCurTcb
->TCS_JS_Period
& TSC_WIDE_SCSI
)
2001 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 2);
2003 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2005 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 0);
2006 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2007 if ((wait_tulip(pCurHcb
)) == -1) {
2010 if (pCurHcb
->HCS_Phase
!= DATA_OUT
) { /* Disable wide CPU to allow read 16 bits */
2011 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
);
2012 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2019 /***************************************************************************/
2020 int tul_status_msg(HCS
* pCurHcb
)
2021 { /* status & MSG_IN */
2022 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
2025 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_CMD_COMP
);
2026 if ((wait_tulip(pCurHcb
)) == -1) {
2030 pCurScb
->SCB_TaStat
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
2032 if (pCurHcb
->HCS_Phase
== MSG_OUT
) {
2033 if (pCurHcb
->HCS_JSStatus0
& TSS_PAR_ERROR
) {
2034 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_PARITY
);
2036 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_NOP
);
2038 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2039 return (wait_tulip(pCurHcb
));
2041 if (pCurHcb
->HCS_Phase
== MSG_IN
) {
2042 msg
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
2043 if (pCurHcb
->HCS_JSStatus0
& TSS_PAR_ERROR
) { /* Parity error */
2044 if ((tul_msgin_accept(pCurHcb
)) == -1)
2046 if (pCurHcb
->HCS_Phase
!= MSG_OUT
)
2047 return (tul_bad_seq(pCurHcb
));
2048 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_PARITY
);
2049 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2050 return (wait_tulip(pCurHcb
));
2052 if (msg
== 0) { /* Command complete */
2054 if ((pCurScb
->SCB_TaStat
& 0x18) == 0x10) { /* No link support */
2055 return (tul_bad_seq(pCurHcb
));
2057 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2058 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_MSG_ACCEPT
);
2059 return tul_wait_done_disc(pCurHcb
);
2062 if ((msg
== MSG_LINK_COMP
) || (msg
== MSG_LINK_FLAG
)) {
2063 if ((pCurScb
->SCB_TaStat
& 0x18) == 0x10)
2064 return (tul_msgin_accept(pCurHcb
));
2067 return (tul_bad_seq(pCurHcb
));
2071 /***************************************************************************/
2073 int int_tul_busfree(HCS
* pCurHcb
)
2075 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
2077 if (pCurScb
!= NULL
) {
2078 if (pCurScb
->SCB_Status
& SCB_SELECT
) { /* selection timeout */
2079 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
2080 pCurScb
->SCB_HaStat
= HOST_SEL_TOUT
;
2081 tul_append_done_scb(pCurHcb
, pCurScb
);
2082 } else { /* Unexpected bus free */
2083 tul_unlink_busy_scb(pCurHcb
, pCurScb
);
2084 pCurScb
->SCB_HaStat
= HOST_BUS_FREE
;
2085 tul_append_done_scb(pCurHcb
, pCurScb
);
2087 pCurHcb
->HCS_ActScb
= NULL
;
2088 pCurHcb
->HCS_ActTcs
= NULL
;
2090 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
); /* Flush SCSI FIFO */
2091 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, TSC_INITDEFAULT
);
2092 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
); /* Enable HW reselect */
2097 /***************************************************************************/
2098 /* scsi bus reset */
2099 static int int_tul_scsi_rst(HCS
* pCurHcb
)
2104 /* if DMA xfer is pending, abort DMA xfer */
2105 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_XStatus
) & 0x01) {
2106 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_X_ABT
| TAX_X_CLR_FIFO
);
2107 /* wait Abort DMA xfer done */
2108 while ((TUL_RD(pCurHcb
->HCS_Base
, TUL_Int
) & 0x04) == 0);
2109 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2111 /* Abort all active & disconnected scb */
2112 while ((pCurScb
= tul_pop_busy_scb(pCurHcb
)) != NULL
) {
2113 pCurScb
->SCB_HaStat
= HOST_BAD_PHAS
;
2114 tul_append_done_scb(pCurHcb
, pCurScb
);
2116 pCurHcb
->HCS_ActScb
= NULL
;
2117 pCurHcb
->HCS_ActTcs
= NULL
;
2119 /* clr sync nego. done flag */
2120 for (i
= 0; i
< pCurHcb
->HCS_MaxTar
; i
++) {
2121 pCurHcb
->HCS_Tcs
[i
].TCS_Flags
&= ~(TCF_SYNC_DONE
| TCF_WDTR_DONE
);
2127 /***************************************************************************/
2128 /* scsi reselection */
2129 int int_tul_resel(HCS
* pCurHcb
)
2136 if ((pCurScb
= pCurHcb
->HCS_ActScb
) != NULL
) {
2137 if (pCurScb
->SCB_Status
& SCB_SELECT
) { /* if waiting for selection complete */
2138 pCurScb
->SCB_Status
&= ~SCB_SELECT
;
2140 pCurHcb
->HCS_ActScb
= NULL
;
2142 /* --------- get target id---------------------- */
2143 tar
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SBusId
);
2144 /* ------ get LUN from Identify message----------- */
2145 lun
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SIdent
) & 0x0F;
2146 /* 07/22/98 from 0x1F -> 0x0F */
2147 pCurTcb
= &pCurHcb
->HCS_Tcs
[tar
];
2148 pCurHcb
->HCS_ActTcs
= pCurTcb
;
2149 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurTcb
->TCS_SConfig0
);
2150 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SPeriod
, pCurTcb
->TCS_JS_Period
);
2153 /* ------------- tag queueing ? ------------------- */
2154 if (pCurTcb
->TCS_DrvFlags
& TCF_DRV_EN_TAG
) {
2155 if ((tul_msgin_accept(pCurHcb
)) == -1)
2157 if (pCurHcb
->HCS_Phase
!= MSG_IN
)
2159 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2160 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2161 if ((wait_tulip(pCurHcb
)) == -1)
2163 msg
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
); /* Read Tag Message */
2165 if ((msg
< MSG_STAG
) || (msg
> MSG_OTAG
)) /* Is simple Tag */
2168 if ((tul_msgin_accept(pCurHcb
)) == -1)
2171 if (pCurHcb
->HCS_Phase
!= MSG_IN
)
2174 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2175 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2176 if ((wait_tulip(pCurHcb
)) == -1)
2178 tag
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
); /* Read Tag ID */
2179 pCurScb
= pCurHcb
->HCS_Scb
+ tag
;
2180 if ((pCurScb
->SCB_Target
!= tar
) || (pCurScb
->SCB_Lun
!= lun
)) {
2181 return tul_msgout_abort_tag(pCurHcb
);
2183 if (pCurScb
->SCB_Status
!= SCB_BUSY
) { /* 03/24/95 */
2184 return tul_msgout_abort_tag(pCurHcb
);
2186 pCurHcb
->HCS_ActScb
= pCurScb
;
2187 if ((tul_msgin_accept(pCurHcb
)) == -1)
2189 } else { /* No tag */
2191 if ((pCurScb
= tul_find_busy_scb(pCurHcb
, tar
| (lun
<< 8))) == NULL
) {
2192 return tul_msgout_abort_targ(pCurHcb
);
2194 pCurHcb
->HCS_ActScb
= pCurScb
;
2195 if (!(pCurTcb
->TCS_DrvFlags
& TCF_DRV_EN_TAG
)) {
2196 if ((tul_msgin_accept(pCurHcb
)) == -1)
2204 /***************************************************************************/
2205 static int int_tul_bad_seq(HCS
* pCurHcb
)
2206 { /* target wrong phase */
2210 tul_reset_scsi(pCurHcb
, 10);
2212 while ((pCurScb
= tul_pop_busy_scb(pCurHcb
)) != NULL
) {
2213 pCurScb
->SCB_HaStat
= HOST_BAD_PHAS
;
2214 tul_append_done_scb(pCurHcb
, pCurScb
);
2216 for (i
= 0; i
< pCurHcb
->HCS_MaxTar
; i
++) {
2217 pCurHcb
->HCS_Tcs
[i
].TCS_Flags
&= ~(TCF_SYNC_DONE
| TCF_WDTR_DONE
);
2223 /***************************************************************************/
2224 int tul_msgout_abort_targ(HCS
* pCurHcb
)
2227 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2228 if (tul_msgin_accept(pCurHcb
) == -1)
2230 if (pCurHcb
->HCS_Phase
!= MSG_OUT
)
2231 return (tul_bad_seq(pCurHcb
));
2233 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_ABORT
);
2234 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2236 return tul_wait_disc(pCurHcb
);
2239 /***************************************************************************/
2240 int tul_msgout_abort_tag(HCS
* pCurHcb
)
2243 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2244 if (tul_msgin_accept(pCurHcb
) == -1)
2246 if (pCurHcb
->HCS_Phase
!= MSG_OUT
)
2247 return (tul_bad_seq(pCurHcb
));
2249 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_ABORT_TAG
);
2250 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2252 return tul_wait_disc(pCurHcb
);
2256 /***************************************************************************/
2257 int tul_msgin(HCS
* pCurHcb
)
2263 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2265 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2266 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2267 if ((wait_tulip(pCurHcb
)) == -1)
2270 switch (TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
)) {
2271 case MSG_DISC
: /* Disconnect msg */
2272 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_MSG_ACCEPT
);
2274 return tul_wait_disc(pCurHcb
);
2279 tul_msgin_accept(pCurHcb
);
2282 case MSG_REJ
: /* Clear ATN first */
2283 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
,
2284 (TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)));
2285 pCurTcb
= pCurHcb
->HCS_ActTcs
;
2286 if ((pCurTcb
->TCS_Flags
& (TCF_SYNC_DONE
| TCF_NO_SYNC_NEGO
)) == 0) { /* do sync nego */
2287 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2289 tul_msgin_accept(pCurHcb
);
2292 case MSG_EXTEND
: /* extended msg */
2293 tul_msgin_extend(pCurHcb
);
2296 case MSG_IGNOREWIDE
:
2297 tul_msgin_accept(pCurHcb
);
2301 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2302 if (wait_tulip(pCurHcb
) == -1)
2305 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 0); /* put pad */
2306 TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
); /* get IGNORE field */
2307 TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
); /* get pad */
2309 tul_msgin_accept(pCurHcb
);
2314 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2315 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_MSG_ACCEPT
);
2316 return tul_wait_done_disc(pCurHcb
);
2319 tul_msgout_reject(pCurHcb
);
2322 if (pCurHcb
->HCS_Phase
!= MSG_IN
)
2323 return (pCurHcb
->HCS_Phase
);
2325 /* statement won't reach here */
2331 /***************************************************************************/
2332 int tul_msgout_reject(HCS
* pCurHcb
)
2335 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2337 if ((tul_msgin_accept(pCurHcb
)) == -1)
2340 if (pCurHcb
->HCS_Phase
== MSG_OUT
) {
2341 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_REJ
); /* Msg reject */
2342 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2343 return (wait_tulip(pCurHcb
));
2345 return (pCurHcb
->HCS_Phase
);
2350 /***************************************************************************/
2351 int tul_msgout_ide(HCS
* pCurHcb
)
2353 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_IDE
); /* Initiator Detected Error */
2354 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2355 return (wait_tulip(pCurHcb
));
2359 /***************************************************************************/
2360 int tul_msgin_extend(HCS
* pCurHcb
)
2364 if (tul_msgin_accept(pCurHcb
) != MSG_IN
)
2365 return (pCurHcb
->HCS_Phase
);
2367 /* Get extended msg length */
2368 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2369 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2370 if (wait_tulip(pCurHcb
) == -1)
2373 len
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
2374 pCurHcb
->HCS_Msg
[0] = len
;
2375 for (idx
= 1; len
!= 0; len
--) {
2377 if ((tul_msgin_accept(pCurHcb
)) != MSG_IN
)
2378 return (pCurHcb
->HCS_Phase
);
2379 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2380 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2381 if (wait_tulip(pCurHcb
) == -1)
2383 pCurHcb
->HCS_Msg
[idx
++] = TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
2385 if (pCurHcb
->HCS_Msg
[1] == 1) { /* if it's synchronous data transfer request */
2386 if (pCurHcb
->HCS_Msg
[0] != 3) /* if length is not right */
2387 return (tul_msgout_reject(pCurHcb
));
2388 if (pCurHcb
->HCS_ActTcs
->TCS_Flags
& TCF_NO_SYNC_NEGO
) { /* Set OFFSET=0 to do async, nego back */
2389 pCurHcb
->HCS_Msg
[3] = 0;
2391 if ((tul_msgin_sync(pCurHcb
) == 0) &&
2392 (pCurHcb
->HCS_ActTcs
->TCS_Flags
& TCF_SYNC_DONE
)) {
2393 tul_sync_done(pCurHcb
);
2394 return (tul_msgin_accept(pCurHcb
));
2398 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2399 if ((tul_msgin_accept(pCurHcb
)) != MSG_OUT
)
2400 return (pCurHcb
->HCS_Phase
);
2402 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2404 tul_sync_done(pCurHcb
);
2406 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_EXTEND
);
2407 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 3);
2408 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 1);
2409 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurHcb
->HCS_Msg
[2]);
2410 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurHcb
->HCS_Msg
[3]);
2412 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2413 return (wait_tulip(pCurHcb
));
2415 if ((pCurHcb
->HCS_Msg
[0] != 2) || (pCurHcb
->HCS_Msg
[1] != 3))
2416 return (tul_msgout_reject(pCurHcb
));
2417 /* if it's WIDE DATA XFER REQ */
2418 if (pCurHcb
->HCS_ActTcs
->TCS_Flags
& TCF_NO_WDTR
) {
2419 pCurHcb
->HCS_Msg
[2] = 0;
2421 if (pCurHcb
->HCS_Msg
[2] > 2) /* > 32 bits */
2422 return (tul_msgout_reject(pCurHcb
));
2423 if (pCurHcb
->HCS_Msg
[2] == 2) { /* == 32 */
2424 pCurHcb
->HCS_Msg
[2] = 1;
2426 if ((pCurHcb
->HCS_ActTcs
->TCS_Flags
& TCF_NO_WDTR
) == 0) {
2428 if ((pCurHcb
->HCS_ActTcs
->TCS_Flags
& (TCF_SYNC_DONE
| TCF_NO_SYNC_NEGO
)) == 0)
2429 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2430 return (tul_msgin_accept(pCurHcb
));
2434 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2436 if (tul_msgin_accept(pCurHcb
) != MSG_OUT
)
2437 return (pCurHcb
->HCS_Phase
);
2439 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_EXTEND
);
2440 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 2);
2441 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 3);
2442 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurHcb
->HCS_Msg
[2]);
2443 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2444 return (wait_tulip(pCurHcb
));
2447 /***************************************************************************/
2448 int tul_msgin_sync(HCS
* pCurHcb
)
2450 char default_period
;
2452 default_period
= tul_rate_tbl
[pCurHcb
->HCS_ActTcs
->TCS_Flags
& TCF_SCSI_RATE
];
2453 if (pCurHcb
->HCS_Msg
[3] > MAX_OFFSET
) {
2454 pCurHcb
->HCS_Msg
[3] = MAX_OFFSET
;
2455 if (pCurHcb
->HCS_Msg
[2] < default_period
) {
2456 pCurHcb
->HCS_Msg
[2] = default_period
;
2459 if (pCurHcb
->HCS_Msg
[2] >= 59) { /* Change to async */
2460 pCurHcb
->HCS_Msg
[3] = 0;
2464 /* offset requests asynchronous transfers ? */
2465 if (pCurHcb
->HCS_Msg
[3] == 0) {
2468 if (pCurHcb
->HCS_Msg
[2] < default_period
) {
2469 pCurHcb
->HCS_Msg
[2] = default_period
;
2472 if (pCurHcb
->HCS_Msg
[2] >= 59) {
2473 pCurHcb
->HCS_Msg
[3] = 0;
2480 /***************************************************************************/
2481 int wdtr_done(HCS
* pCurHcb
)
2483 pCurHcb
->HCS_ActTcs
->TCS_Flags
&= ~TCF_SYNC_DONE
;
2484 pCurHcb
->HCS_ActTcs
->TCS_Flags
|= TCF_WDTR_DONE
;
2486 pCurHcb
->HCS_ActTcs
->TCS_JS_Period
= 0;
2487 if (pCurHcb
->HCS_Msg
[2]) { /* if 16 bit */
2488 pCurHcb
->HCS_ActTcs
->TCS_JS_Period
|= TSC_WIDE_SCSI
;
2490 pCurHcb
->HCS_ActTcs
->TCS_SConfig0
&= ~TSC_ALT_PERIOD
;
2491 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurHcb
->HCS_ActTcs
->TCS_SConfig0
);
2492 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SPeriod
, pCurHcb
->HCS_ActTcs
->TCS_JS_Period
);
2497 /***************************************************************************/
2498 int tul_sync_done(HCS
* pCurHcb
)
2502 pCurHcb
->HCS_ActTcs
->TCS_Flags
|= TCF_SYNC_DONE
;
2504 if (pCurHcb
->HCS_Msg
[3]) {
2505 pCurHcb
->HCS_ActTcs
->TCS_JS_Period
|= pCurHcb
->HCS_Msg
[3];
2506 for (i
= 0; i
< 8; i
++) {
2507 if (tul_rate_tbl
[i
] >= pCurHcb
->HCS_Msg
[2]) /* pick the big one */
2510 pCurHcb
->HCS_ActTcs
->TCS_JS_Period
|= (i
<< 4);
2511 pCurHcb
->HCS_ActTcs
->TCS_SConfig0
|= TSC_ALT_PERIOD
;
2513 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurHcb
->HCS_ActTcs
->TCS_SConfig0
);
2514 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SPeriod
, pCurHcb
->HCS_ActTcs
->TCS_JS_Period
);
2520 int tul_post_scsi_rst(HCS
* pCurHcb
)
2526 pCurHcb
->HCS_ActScb
= NULL
;
2527 pCurHcb
->HCS_ActTcs
= NULL
;
2528 pCurHcb
->HCS_Flags
= 0;
2530 while ((pCurScb
= tul_pop_busy_scb(pCurHcb
)) != NULL
) {
2531 pCurScb
->SCB_HaStat
= HOST_BAD_PHAS
;
2532 tul_append_done_scb(pCurHcb
, pCurScb
);
2534 /* clear sync done flag */
2535 pCurTcb
= &pCurHcb
->HCS_Tcs
[0];
2536 for (i
= 0; i
< pCurHcb
->HCS_MaxTar
; pCurTcb
++, i
++) {
2537 pCurTcb
->TCS_Flags
&= ~(TCF_SYNC_DONE
| TCF_WDTR_DONE
);
2538 /* Initialize the sync. xfer register values to an asyn xfer */
2539 pCurTcb
->TCS_JS_Period
= 0;
2540 pCurTcb
->TCS_SConfig0
= pCurHcb
->HCS_SConf1
;
2541 pCurHcb
->HCS_ActTags
[0] = 0; /* 07/22/98 */
2542 pCurHcb
->HCS_Tcs
[i
].TCS_Flags
&= ~TCF_BUSY
; /* 07/22/98 */
2548 /***************************************************************************/
2549 void tul_select_atn_stop(HCS
* pCurHcb
, SCB
* pCurScb
)
2551 pCurScb
->SCB_Status
|= SCB_SELECT
;
2552 pCurScb
->SCB_NxtStat
= 0x1;
2553 pCurHcb
->HCS_ActScb
= pCurScb
;
2554 pCurHcb
->HCS_ActTcs
= &pCurHcb
->HCS_Tcs
[pCurScb
->SCB_Target
];
2555 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_SELATNSTOP
);
2560 /***************************************************************************/
2561 void tul_select_atn(HCS
* pCurHcb
, SCB
* pCurScb
)
2565 pCurScb
->SCB_Status
|= SCB_SELECT
;
2566 pCurScb
->SCB_NxtStat
= 0x2;
2568 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_Ident
);
2569 for (i
= 0; i
< (int) pCurScb
->SCB_CDBLen
; i
++)
2570 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_CDB
[i
]);
2571 pCurHcb
->HCS_ActTcs
= &pCurHcb
->HCS_Tcs
[pCurScb
->SCB_Target
];
2572 pCurHcb
->HCS_ActScb
= pCurScb
;
2573 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_SEL_ATN
);
2577 /***************************************************************************/
2578 void tul_select_atn3(HCS
* pCurHcb
, SCB
* pCurScb
)
2582 pCurScb
->SCB_Status
|= SCB_SELECT
;
2583 pCurScb
->SCB_NxtStat
= 0x2;
2585 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_Ident
);
2586 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_TagMsg
);
2587 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_TagId
);
2588 for (i
= 0; i
< (int) pCurScb
->SCB_CDBLen
; i
++)
2589 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_CDB
[i
]);
2590 pCurHcb
->HCS_ActTcs
= &pCurHcb
->HCS_Tcs
[pCurScb
->SCB_Target
];
2591 pCurHcb
->HCS_ActScb
= pCurScb
;
2592 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_SEL_ATN3
);
2596 /***************************************************************************/
2597 /* SCSI Bus Device Reset */
2598 int tul_bus_device_reset(HCS
* pCurHcb
)
2600 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
2601 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
2602 SCB
*pTmpScb
, *pPrevScb
;
2605 if (pCurHcb
->HCS_Phase
!= MSG_OUT
) {
2606 return (int_tul_bad_seq(pCurHcb
)); /* Unexpected phase */
2608 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
2609 tul_release_scb(pCurHcb
, pCurScb
);
2612 tar
= pCurScb
->SCB_Target
; /* target */
2613 pCurTcb
->TCS_Flags
&= ~(TCF_SYNC_DONE
| TCF_WDTR_DONE
| TCF_BUSY
);
2614 /* clr sync. nego & WDTR flags 07/22/98 */
2616 /* abort all SCB with same target */
2617 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstBusy
; /* Check Busy queue */
2618 while (pTmpScb
!= NULL
) {
2620 if (pTmpScb
->SCB_Target
== tar
) {
2622 if (pTmpScb
== pCurHcb
->HCS_FirstBusy
) {
2623 if ((pCurHcb
->HCS_FirstBusy
= pTmpScb
->SCB_NxtScb
) == NULL
)
2624 pCurHcb
->HCS_LastBusy
= NULL
;
2626 pPrevScb
->SCB_NxtScb
= pTmpScb
->SCB_NxtScb
;
2627 if (pTmpScb
== pCurHcb
->HCS_LastBusy
)
2628 pCurHcb
->HCS_LastBusy
= pPrevScb
;
2630 pTmpScb
->SCB_HaStat
= HOST_ABORTED
;
2631 tul_append_done_scb(pCurHcb
, pTmpScb
);
2633 /* Previous haven't change */
2637 pTmpScb
= pTmpScb
->SCB_NxtScb
;
2640 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_DEVRST
);
2641 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2643 return tul_wait_disc(pCurHcb
);
2647 /***************************************************************************/
2648 int tul_msgin_accept(HCS
* pCurHcb
)
2650 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_MSG_ACCEPT
);
2651 return (wait_tulip(pCurHcb
));
2654 /***************************************************************************/
2655 int wait_tulip(HCS
* pCurHcb
)
2658 while (!((pCurHcb
->HCS_JSStatus0
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus0
))
2659 & TSS_INT_PENDING
));
2661 pCurHcb
->HCS_JSInt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
);
2662 pCurHcb
->HCS_Phase
= pCurHcb
->HCS_JSStatus0
& TSS_PH_MASK
;
2663 pCurHcb
->HCS_JSStatus1
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus1
);
2665 if (pCurHcb
->HCS_JSInt
& TSS_RESEL_INT
) { /* if SCSI bus reset detected */
2666 return (int_tul_resel(pCurHcb
));
2668 if (pCurHcb
->HCS_JSInt
& TSS_SEL_TIMEOUT
) { /* if selected/reselected timeout interrupt */
2669 return (int_tul_busfree(pCurHcb
));
2671 if (pCurHcb
->HCS_JSInt
& TSS_SCSIRST_INT
) { /* if SCSI bus reset detected */
2672 return (int_tul_scsi_rst(pCurHcb
));
2674 if (pCurHcb
->HCS_JSInt
& TSS_DISC_INT
) { /* BUS disconnection */
2675 if (pCurHcb
->HCS_Flags
& HCF_EXPECT_DONE_DISC
) {
2676 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
); /* Flush SCSI FIFO */
2677 tul_unlink_busy_scb(pCurHcb
, pCurHcb
->HCS_ActScb
);
2678 pCurHcb
->HCS_ActScb
->SCB_HaStat
= 0;
2679 tul_append_done_scb(pCurHcb
, pCurHcb
->HCS_ActScb
);
2680 pCurHcb
->HCS_ActScb
= NULL
;
2681 pCurHcb
->HCS_ActTcs
= NULL
;
2682 pCurHcb
->HCS_Flags
&= ~HCF_EXPECT_DONE_DISC
;
2683 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, TSC_INITDEFAULT
);
2684 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
); /* Enable HW reselect */
2687 if (pCurHcb
->HCS_Flags
& HCF_EXPECT_DISC
) {
2688 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
); /* Flush SCSI FIFO */
2689 pCurHcb
->HCS_ActScb
= NULL
;
2690 pCurHcb
->HCS_ActTcs
= NULL
;
2691 pCurHcb
->HCS_Flags
&= ~HCF_EXPECT_DISC
;
2692 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, TSC_INITDEFAULT
);
2693 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
); /* Enable HW reselect */
2696 return (int_tul_busfree(pCurHcb
));
2698 if (pCurHcb
->HCS_JSInt
& (TSS_FUNC_COMP
| TSS_BUS_SERV
)) {
2699 return (pCurHcb
->HCS_Phase
);
2701 return (pCurHcb
->HCS_Phase
);
2703 /***************************************************************************/
2704 int tul_wait_disc(HCS
* pCurHcb
)
2707 while (!((pCurHcb
->HCS_JSStatus0
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus0
))
2708 & TSS_INT_PENDING
));
2711 pCurHcb
->HCS_JSInt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
);
2713 if (pCurHcb
->HCS_JSInt
& TSS_SCSIRST_INT
) { /* if SCSI bus reset detected */
2714 return (int_tul_scsi_rst(pCurHcb
));
2716 if (pCurHcb
->HCS_JSInt
& TSS_DISC_INT
) { /* BUS disconnection */
2717 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
); /* Flush SCSI FIFO */
2718 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, TSC_INITDEFAULT
);
2719 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
); /* Enable HW reselect */
2720 pCurHcb
->HCS_ActScb
= NULL
;
2723 return (tul_bad_seq(pCurHcb
));
2726 /***************************************************************************/
2727 int tul_wait_done_disc(HCS
* pCurHcb
)
2731 while (!((pCurHcb
->HCS_JSStatus0
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus0
))
2732 & TSS_INT_PENDING
));
2734 pCurHcb
->HCS_JSInt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
);
2737 if (pCurHcb
->HCS_JSInt
& TSS_SCSIRST_INT
) { /* if SCSI bus reset detected */
2738 return (int_tul_scsi_rst(pCurHcb
));
2740 if (pCurHcb
->HCS_JSInt
& TSS_DISC_INT
) { /* BUS disconnection */
2741 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
); /* Flush SCSI FIFO */
2742 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, TSC_INITDEFAULT
);
2743 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
); /* Enable HW reselect */
2744 tul_unlink_busy_scb(pCurHcb
, pCurHcb
->HCS_ActScb
);
2746 tul_append_done_scb(pCurHcb
, pCurHcb
->HCS_ActScb
);
2747 pCurHcb
->HCS_ActScb
= NULL
;
2750 return (tul_bad_seq(pCurHcb
));
2753 static irqreturn_t
i91u_intr(int irqno
, void *dev_id
, struct pt_regs
*regs
)
2755 struct Scsi_Host
*dev
= dev_id
;
2756 unsigned long flags
;
2758 spin_lock_irqsave(dev
->host_lock
, flags
);
2759 tul_isr((HCS
*)dev
->base
);
2760 spin_unlock_irqrestore(dev
->host_lock
, flags
);
2764 static int tul_NewReturnNumberOfAdapters(void)
2766 struct pci_dev
*pDev
= NULL
; /* Start from none */
2772 init_i91uAdapter_table();
2774 for (i
= 0; i
< TULSZ(i91u_pci_devices
); i
++)
2776 while ((pDev
= pci_find_device(i91u_pci_devices
[i
].vendor_id
, i91u_pci_devices
[i
].device_id
, pDev
)) != NULL
) {
2777 if (pci_enable_device(pDev
))
2779 pci_read_config_dword(pDev
, 0x44, (u32
*) & dRegValue
);
2780 wBIOS
= (UWORD
) (dRegValue
& 0xFF);
2781 if (((dRegValue
& 0xFF00) >> 8) == 0xFF)
2783 wBIOS
= (wBIOS
<< 8) + ((UWORD
) ((dRegValue
& 0xFF00) >> 8));
2784 if (pci_set_dma_mask(pDev
, DMA_32BIT_MASK
)) {
2786 "i91u: Could not set 32 bit DMA mask\n");
2790 if (Addi91u_into_Adapter_table(wBIOS
,
2791 (pDev
->resource
[0].start
),
2803 static int i91u_detect(struct scsi_host_template
* tpnt
)
2806 struct Scsi_Host
*hreg
;
2807 unsigned long i
; /* 01/14/98 */
2808 int ok
= 0, iAdapters
;
2812 /* Get total number of adapters in the motherboard */
2813 iAdapters
= tul_NewReturnNumberOfAdapters();
2814 if (iAdapters
== 0) /* If no tulip founded, return */
2817 tul_num_ch
= (iAdapters
> tul_num_ch
) ? tul_num_ch
: iAdapters
;
2818 /* Update actually channel number */
2819 if (tul_tag_enable
) { /* 1.01i */
2820 tul_num_scb
= MAX_TARGETS
* i91u_MAXQUEUE
;
2822 tul_num_scb
= MAX_TARGETS
+ 3; /* 1-tape, 1-CD_ROM, 1- extra */
2823 } /* Update actually SCBs per adapter */
2825 /* Get total memory needed for HCS */
2826 i
= tul_num_ch
* sizeof(HCS
);
2827 memset((unsigned char *) &tul_hcs
[0], 0, i
); /* Initialize tul_hcs 0 */
2828 /* Get total memory needed for SCB */
2830 for (; tul_num_scb
>= MAX_TARGETS
+ 3; tul_num_scb
--) {
2831 i
= tul_num_ch
* tul_num_scb
* sizeof(SCB
);
2832 if ((tul_scb
= (SCB
*) kmalloc(i
, GFP_ATOMIC
| GFP_DMA
)) != NULL
)
2835 if (tul_scb
== NULL
) {
2836 printk("i91u: SCB memory allocation error\n");
2839 memset((unsigned char *) tul_scb
, 0, i
);
2841 for (i
= 0, pHCB
= &tul_hcs
[0]; /* Get pointer for control block */
2844 get_tulipPCIConfig(pHCB
, i
);
2846 dBiosAdr
= pHCB
->HCS_BIOS
;
2847 dBiosAdr
= (dBiosAdr
<< 4);
2849 pbBiosAdr
= phys_to_virt(dBiosAdr
);
2851 init_tulip(pHCB
, tul_scb
+ (i
* tul_num_scb
), tul_num_scb
, pbBiosAdr
, 10);
2852 request_region(pHCB
->HCS_Base
, 256, "i91u"); /* Register */
2854 pHCB
->HCS_Index
= i
; /* 7/29/98 */
2855 hreg
= scsi_register(tpnt
, sizeof(HCS
));
2857 release_region(pHCB
->HCS_Base
, 256);
2860 hreg
->io_port
= pHCB
->HCS_Base
;
2861 hreg
->n_io_port
= 0xff;
2862 hreg
->can_queue
= tul_num_scb
; /* 03/05/98 */
2863 hreg
->unique_id
= pHCB
->HCS_Base
;
2864 hreg
->max_id
= pHCB
->HCS_MaxTar
;
2865 hreg
->max_lun
= 32; /* 10/21/97 */
2866 hreg
->irq
= pHCB
->HCS_Intr
;
2867 hreg
->this_id
= pHCB
->HCS_SCSI_ID
; /* Assign HCS index */
2868 hreg
->base
= (unsigned long)pHCB
;
2869 hreg
->sg_tablesize
= TOTAL_SG_ENTRY
; /* Maximun support is 32 */
2871 /* Initial tulip chip */
2872 ok
= request_irq(pHCB
->HCS_Intr
, i91u_intr
, SA_INTERRUPT
| SA_SHIRQ
, "i91u", hreg
);
2874 printk(KERN_WARNING
"i91u: unable to request IRQ %d\n\n", pHCB
->HCS_Intr
);
2880 tpnt
->can_queue
= 1;
2885 static void i91uBuildSCB(HCS
* pHCB
, SCB
* pSCB
, struct scsi_cmnd
* SCpnt
)
2886 { /* Create corresponding SCB */
2887 struct scatterlist
*pSrbSG
;
2888 SG
*pSG
; /* Pointer to SG list */
2891 dma_addr_t dma_addr
;
2893 pSCB
->SCB_Post
= i91uSCBPost
; /* i91u's callback routine */
2894 pSCB
->SCB_Srb
= SCpnt
;
2895 pSCB
->SCB_Opcode
= ExecSCSI
;
2896 pSCB
->SCB_Flags
= SCF_POST
; /* After SCSI done, call post routine */
2897 pSCB
->SCB_Target
= SCpnt
->device
->id
;
2898 pSCB
->SCB_Lun
= SCpnt
->device
->lun
;
2899 pSCB
->SCB_Ident
= SCpnt
->device
->lun
| DISC_ALLOW
;
2901 pSCB
->SCB_Flags
|= SCF_SENSE
; /* Turn on auto request sense */
2902 dma_addr
= dma_map_single(&pHCB
->pci_dev
->dev
, SCpnt
->sense_buffer
,
2903 SENSE_SIZE
, DMA_FROM_DEVICE
);
2904 pSCB
->SCB_SensePtr
= cpu_to_le32((u32
)dma_addr
);
2905 pSCB
->SCB_SenseLen
= cpu_to_le32(SENSE_SIZE
);
2906 SCpnt
->SCp
.ptr
= (char *)(unsigned long)dma_addr
;
2908 pSCB
->SCB_CDBLen
= SCpnt
->cmd_len
;
2909 pSCB
->SCB_HaStat
= 0;
2910 pSCB
->SCB_TaStat
= 0;
2911 memcpy(&pSCB
->SCB_CDB
[0], &SCpnt
->cmnd
, SCpnt
->cmd_len
);
2913 if (SCpnt
->device
->tagged_supported
) { /* Tag Support */
2914 pSCB
->SCB_TagMsg
= SIMPLE_QUEUE_TAG
; /* Do simple tag only */
2916 pSCB
->SCB_TagMsg
= 0; /* No tag support */
2918 /* todo handle map_sg error */
2919 if (SCpnt
->use_sg
) {
2920 dma_addr
= dma_map_single(&pHCB
->pci_dev
->dev
, &pSCB
->SCB_SGList
[0],
2921 sizeof(struct SG_Struc
) * TOTAL_SG_ENTRY
,
2923 pSCB
->SCB_BufPtr
= cpu_to_le32((u32
)dma_addr
);
2924 SCpnt
->SCp
.dma_handle
= dma_addr
;
2926 pSrbSG
= (struct scatterlist
*) SCpnt
->request_buffer
;
2927 pSCB
->SCB_SGLen
= dma_map_sg(&pHCB
->pci_dev
->dev
, pSrbSG
,
2928 SCpnt
->use_sg
, SCpnt
->sc_data_direction
);
2930 pSCB
->SCB_Flags
|= SCF_SG
; /* Turn on SG list flag */
2931 for (i
= 0, TotalLen
= 0, pSG
= &pSCB
->SCB_SGList
[0]; /* 1.01g */
2932 i
< pSCB
->SCB_SGLen
; i
++, pSG
++, pSrbSG
++) {
2933 pSG
->SG_Ptr
= cpu_to_le32((u32
)sg_dma_address(pSrbSG
));
2934 TotalLen
+= pSG
->SG_Len
= cpu_to_le32((u32
)sg_dma_len(pSrbSG
));
2937 pSCB
->SCB_BufLen
= (SCpnt
->request_bufflen
> TotalLen
) ?
2938 TotalLen
: SCpnt
->request_bufflen
;
2939 } else if (SCpnt
->request_bufflen
) { /* Non SG */
2940 dma_addr
= dma_map_single(&pHCB
->pci_dev
->dev
, SCpnt
->request_buffer
,
2941 SCpnt
->request_bufflen
,
2942 SCpnt
->sc_data_direction
);
2943 SCpnt
->SCp
.dma_handle
= dma_addr
;
2944 pSCB
->SCB_BufPtr
= cpu_to_le32((u32
)dma_addr
);
2945 pSCB
->SCB_BufLen
= cpu_to_le32((u32
)SCpnt
->request_bufflen
);
2946 pSCB
->SCB_SGLen
= 0;
2948 pSCB
->SCB_BufLen
= 0;
2949 pSCB
->SCB_SGLen
= 0;
2953 static int i91u_queuecommand(struct scsi_cmnd
*cmd
,
2954 void (*done
)(struct scsi_cmnd
*))
2956 HCS
*pHCB
= (HCS
*) cmd
->device
->host
->base
;
2959 cmd
->scsi_done
= done
;
2961 pSCB
= tul_alloc_scb(pHCB
);
2963 return SCSI_MLQUEUE_HOST_BUSY
;
2965 i91uBuildSCB(pHCB
, pSCB
, cmd
);
2966 tul_exec_scb(pHCB
, pSCB
);
2970 #if 0 /* no new EH yet */
2972 * Abort a queued command
2973 * (commands that are on the bus can't be aborted easily)
2975 static int i91u_abort(struct scsi_cmnd
* SCpnt
)
2979 pHCB
= (HCS
*) SCpnt
->device
->host
->base
;
2980 return tul_abort_srb(pHCB
, SCpnt
);
2984 * Reset registers, reset a hanging bus and
2985 * kill active and disconnected commands for target w/o soft reset
2987 static int i91u_reset(struct scsi_cmnd
* SCpnt
, unsigned int reset_flags
)
2988 { /* I need Host Control Block Information */
2991 pHCB
= (HCS
*) SCpnt
->device
->host
->base
;
2993 if (reset_flags
& (SCSI_RESET_SUGGEST_BUS_RESET
| SCSI_RESET_SUGGEST_HOST_RESET
))
2994 return tul_reset_scsi_bus(pHCB
);
2996 return tul_device_reset(pHCB
, SCpnt
, SCpnt
->device
->id
, reset_flags
);
3000 static int i91u_bus_reset(struct scsi_cmnd
* SCpnt
)
3004 pHCB
= (HCS
*) SCpnt
->device
->host
->base
;
3006 spin_lock_irq(SCpnt
->device
->host
->host_lock
);
3007 tul_reset_scsi(pHCB
, 0);
3008 spin_unlock_irq(SCpnt
->device
->host
->host_lock
);
3014 * Return the "logical geometry"
3016 static int i91u_biosparam(struct scsi_device
*sdev
, struct block_device
*dev
,
3017 sector_t capacity
, int *info_array
)
3019 HCS
*pHcb
; /* Point to Host adapter control block */
3022 pHcb
= (HCS
*) sdev
->host
->base
;
3023 pTcb
= &pHcb
->HCS_Tcs
[sdev
->id
];
3025 if (pTcb
->TCS_DrvHead
) {
3026 info_array
[0] = pTcb
->TCS_DrvHead
;
3027 info_array
[1] = pTcb
->TCS_DrvSector
;
3028 info_array
[2] = (unsigned long)capacity
/ pTcb
->TCS_DrvHead
/ pTcb
->TCS_DrvSector
;
3030 if (pTcb
->TCS_DrvFlags
& TCF_DRV_255_63
) {
3031 info_array
[0] = 255;
3033 info_array
[2] = (unsigned long)capacity
/ 255 / 63;
3037 info_array
[2] = (unsigned long)capacity
>> 11;
3041 #if defined(DEBUG_BIOSPARAM)
3042 if (i91u_debug
& debug_biosparam
) {
3043 printk("bios geometry: head=%d, sec=%d, cyl=%d\n",
3044 info_array
[0], info_array
[1], info_array
[2]);
3045 printk("WARNING: check, if the bios geometry is correct.\n");
3052 static void i91u_unmap_cmnd(struct pci_dev
*pci_dev
, struct scsi_cmnd
*cmnd
)
3054 /* auto sense buffer */
3055 if (cmnd
->SCp
.ptr
) {
3056 dma_unmap_single(&pci_dev
->dev
,
3057 (dma_addr_t
)((unsigned long)cmnd
->SCp
.ptr
),
3058 SENSE_SIZE
, DMA_FROM_DEVICE
);
3059 cmnd
->SCp
.ptr
= NULL
;
3062 /* request buffer */
3064 dma_unmap_single(&pci_dev
->dev
, cmnd
->SCp
.dma_handle
,
3065 sizeof(struct SG_Struc
) * TOTAL_SG_ENTRY
,
3068 dma_unmap_sg(&pci_dev
->dev
, cmnd
->request_buffer
,
3070 cmnd
->sc_data_direction
);
3071 } else if (cmnd
->request_bufflen
) {
3072 dma_unmap_single(&pci_dev
->dev
, cmnd
->SCp
.dma_handle
,
3073 cmnd
->request_bufflen
,
3074 cmnd
->sc_data_direction
);
3078 /*****************************************************************************
3079 Function name : i91uSCBPost
3080 Description : This is callback routine be called when tulip finish one
3082 Input : pHCB - Pointer to host adapter control block.
3083 pSCB - Pointer to SCSI control block.
3086 *****************************************************************************/
3087 static void i91uSCBPost(BYTE
* pHcb
, BYTE
* pScb
)
3089 struct scsi_cmnd
*pSRB
; /* Pointer to SCSI request block */
3093 pHCB
= (HCS
*) pHcb
;
3094 pSCB
= (SCB
*) pScb
;
3095 if ((pSRB
= pSCB
->SCB_Srb
) == 0) {
3096 printk("i91uSCBPost: SRB pointer is empty\n");
3098 tul_release_scb(pHCB
, pSCB
); /* Release SCB for current channel */
3101 switch (pSCB
->SCB_HaStat
) {
3103 case 0xa: /* Linked command complete without error and linked normally */
3104 case 0xb: /* Linked command complete without error interrupt generated */
3105 pSCB
->SCB_HaStat
= 0;
3108 case 0x11: /* Selection time out-The initiator selection or target
3109 reselection was not complete within the SCSI Time out period */
3110 pSCB
->SCB_HaStat
= DID_TIME_OUT
;
3113 case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus
3114 phase sequence was requested by the target. The host adapter
3115 will generate a SCSI Reset Condition, notifying the host with
3117 pSCB
->SCB_HaStat
= DID_RESET
;
3120 case 0x1a: /* SCB Aborted. 07/21/98 */
3121 pSCB
->SCB_HaStat
= DID_ABORT
;
3124 case 0x12: /* Data overrun/underrun-The target attempted to transfer more data
3125 than was allocated by the Data Length field or the sum of the
3126 Scatter / Gather Data Length fields. */
3127 case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */
3128 case 0x16: /* Invalid SCB Operation Code. */
3131 printk("ini9100u: %x %x\n", pSCB
->SCB_HaStat
, pSCB
->SCB_TaStat
);
3132 pSCB
->SCB_HaStat
= DID_ERROR
; /* Couldn't find any better */
3136 pSRB
->result
= pSCB
->SCB_TaStat
| (pSCB
->SCB_HaStat
<< 16);
3139 printk("pSRB is NULL\n");
3142 i91u_unmap_cmnd(pHCB
->pci_dev
, pSRB
);
3143 pSRB
->scsi_done(pSRB
); /* Notify system DONE */
3145 tul_release_scb(pHCB
, pSCB
); /* Release SCB for current channel */
3149 * Release ressources
3151 static int i91u_release(struct Scsi_Host
*hreg
)
3153 free_irq(hreg
->irq
, hreg
);
3154 release_region(hreg
->io_port
, 256);
3157 MODULE_LICENSE("Dual BSD/GPL");
3159 static struct scsi_host_template driver_template
= {
3160 .proc_name
= "INI9100U",
3162 .detect
= i91u_detect
,
3163 .release
= i91u_release
,
3164 .queuecommand
= i91u_queuecommand
,
3165 // .abort = i91u_abort,
3166 // .reset = i91u_reset,
3167 .eh_bus_reset_handler
= i91u_bus_reset
,
3168 .bios_param
= i91u_biosparam
,
3171 .sg_tablesize
= SG_ALL
,
3173 .use_clustering
= ENABLE_CLUSTERING
,
3175 #include "scsi_module.c"