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 TUL_RDWORD(x,y) (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
159 typedef struct PCI_ID_Struc
{
160 unsigned short vendor_id
;
161 unsigned short device_id
;
164 static int tul_num_ch
= 4; /* Maximum 4 adapters */
165 static int tul_num_scb
;
166 static int tul_tag_enable
= 1;
170 static int setup_debug
= 0;
173 static void i91uSCBPost(BYTE
* pHcb
, BYTE
* pScb
);
175 static const PCI_ID i91u_pci_devices
[] = {
176 { INI_VENDOR_ID
, I950_DEVICE_ID
},
177 { INI_VENDOR_ID
, I940_DEVICE_ID
},
178 { INI_VENDOR_ID
, I935_DEVICE_ID
},
179 { INI_VENDOR_ID
, I920_DEVICE_ID
},
180 { DMX_VENDOR_ID
, I920_DEVICE_ID
},
183 #define DEBUG_INTERRUPT 0
184 #define DEBUG_QUEUE 0
185 #define DEBUG_STATE 0
188 /*--- external functions --*/
189 static void tul_se2_wait(void);
191 /*--- forward refrence ---*/
192 static SCB
*tul_find_busy_scb(HCS
* pCurHcb
, WORD tarlun
);
193 static SCB
*tul_find_done_scb(HCS
* pCurHcb
);
195 static int tulip_main(HCS
* pCurHcb
);
197 static int tul_next_state(HCS
* pCurHcb
);
198 static int tul_state_1(HCS
* pCurHcb
);
199 static int tul_state_2(HCS
* pCurHcb
);
200 static int tul_state_3(HCS
* pCurHcb
);
201 static int tul_state_4(HCS
* pCurHcb
);
202 static int tul_state_5(HCS
* pCurHcb
);
203 static int tul_state_6(HCS
* pCurHcb
);
204 static int tul_state_7(HCS
* pCurHcb
);
205 static int tul_xfer_data_in(HCS
* pCurHcb
);
206 static int tul_xfer_data_out(HCS
* pCurHcb
);
207 static int tul_xpad_in(HCS
* pCurHcb
);
208 static int tul_xpad_out(HCS
* pCurHcb
);
209 static int tul_status_msg(HCS
* pCurHcb
);
211 static int tul_msgin(HCS
* pCurHcb
);
212 static int tul_msgin_sync(HCS
* pCurHcb
);
213 static int tul_msgin_accept(HCS
* pCurHcb
);
214 static int tul_msgout_reject(HCS
* pCurHcb
);
215 static int tul_msgin_extend(HCS
* pCurHcb
);
217 static int tul_msgout_ide(HCS
* pCurHcb
);
218 static int tul_msgout_abort_targ(HCS
* pCurHcb
);
219 static int tul_msgout_abort_tag(HCS
* pCurHcb
);
221 static int tul_bus_device_reset(HCS
* pCurHcb
);
222 static void tul_select_atn(HCS
* pCurHcb
, SCB
* pCurScb
);
223 static void tul_select_atn3(HCS
* pCurHcb
, SCB
* pCurScb
);
224 static void tul_select_atn_stop(HCS
* pCurHcb
, SCB
* pCurScb
);
225 static int int_tul_busfree(HCS
* pCurHcb
);
226 static int int_tul_scsi_rst(HCS
* pCurHcb
);
227 static int int_tul_bad_seq(HCS
* pCurHcb
);
228 static int int_tul_resel(HCS
* pCurHcb
);
229 static int tul_sync_done(HCS
* pCurHcb
);
230 static int wdtr_done(HCS
* pCurHcb
);
231 static int wait_tulip(HCS
* pCurHcb
);
232 static int tul_wait_done_disc(HCS
* pCurHcb
);
233 static int tul_wait_disc(HCS
* pCurHcb
);
234 static void tulip_scsi(HCS
* pCurHcb
);
235 static int tul_post_scsi_rst(HCS
* pCurHcb
);
237 static void tul_se2_ew_en(WORD CurBase
);
238 static void tul_se2_ew_ds(WORD CurBase
);
239 static int tul_se2_rd_all(WORD CurBase
);
240 static void tul_se2_update_all(WORD CurBase
); /* setup default pattern */
241 static void tul_read_eeprom(WORD CurBase
);
243 /* ---- INTERNAL VARIABLES ---- */
244 static HCS tul_hcs
[MAX_SUPPORTED_ADAPTERS
];
245 static INI_ADPT_STRUCT i91u_adpt
[MAX_SUPPORTED_ADAPTERS
];
247 /*NVRAM nvram, *nvramp = &nvram; */
248 static NVRAM i91unvram
;
249 static NVRAM
*i91unvramp
;
253 static UCHAR i91udftNvRam
[64] =
255 /*----------- header -----------*/
256 0x25, 0xc9, /* Signature */
259 /* -- Host Adapter Structure -- */
260 0x95, /* ModelByte0 */
261 0x00, /* ModelByte1 */
262 0x00, /* ModelInfo */
264 NBC1_DEFAULT
, /* BIOSConfig1 */
268 /* SCSI channel 0 and target Structure */
270 NCC1_DEFAULT
, /* SCSIconfig1 */
272 0x10, /* NumSCSItarget */
274 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
275 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
276 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
277 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
279 /* SCSI channel 1 and target Structure */
281 NCC1_DEFAULT
, /* SCSIconfig1 */
283 0x10, /* NumSCSItarget */
285 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
286 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
287 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
288 NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
, NTC_DEFAULT
,
289 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
290 0, 0}; /* - CheckSum - */
293 static UCHAR tul_rate_tbl
[8] = /* fast 20 */
295 /* nanosecond devide by 4 */
297 18, /* 75ns, 13.3M */
300 37, /* 150ns, 6.6M */
301 43, /* 175ns, 5.7M */
306 static void tul_do_pause(unsigned amount
)
307 { /* Pause for amount jiffies */
308 unsigned long the_time
= jiffies
+ amount
;
310 while (time_before_eq(jiffies
, the_time
));
313 /*-- forward reference --*/
315 /*******************************************************************
316 Use memeory refresh time ~ 15us * 2
317 ********************************************************************/
318 void tul_se2_wait(void)
325 readByte
= TUL_RD(0, 0x61);
326 if ((readByte
& 0x10) == 0x10) {
328 readByte
= TUL_RD(0, 0x61);
329 if ((readByte
& 0x10) == 0x10)
333 readByte
= TUL_RD(0, 0x61);
334 if ((readByte
& 0x10) != 0x10)
339 readByte
= TUL_RD(0, 0x61);
340 if ((readByte
& 0x10) == 0x10)
344 readByte
= TUL_RD(0, 0x61);
345 if ((readByte
& 0x10) != 0x10)
353 /******************************************************************
354 Input: instruction for Serial E2PROM
356 EX: se2_rd(0 call se2_instr() to send address and read command
358 StartBit OP_Code Address Data
359 --------- -------- ------------------ -------
360 1 1 , 0 A5,A4,A3,A2,A1,A0 D15-D0
362 +-----------------------------------------------------
365 +--+ +--+ +--+ +--+ +--+
368 CLK -------+ +--+ +--+ +--+ +--+ +--
369 (leading edge trigger)
373 DI ----+ +--0------------------
374 (address and cmd sent to nvram)
376 -------------------------------------------+
379 (data sent from nvram)
382 ******************************************************************/
383 static void tul_se2_instr(WORD CurBase
, UCHAR instr
)
388 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2DO
); /* cs+start bit */
390 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2CLK
| SE2DO
); /* +CLK */
393 for (i
= 0; i
< 8; i
++) {
395 b
= SE2CS
| SE2DO
; /* -CLK+dataBit */
397 b
= SE2CS
; /* -CLK */
398 TUL_WR(CurBase
+ TUL_NVRAM
, b
);
400 TUL_WR(CurBase
+ TUL_NVRAM
, b
| SE2CLK
); /* +CLK */
404 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* -CLK */
410 /******************************************************************
411 Function name : tul_se2_ew_en
412 Description : Enable erase/write state of serial EEPROM
413 ******************************************************************/
414 void tul_se2_ew_en(WORD CurBase
)
416 tul_se2_instr(CurBase
, 0x30); /* EWEN */
417 TUL_WR(CurBase
+ TUL_NVRAM
, 0); /* -CS */
423 /************************************************************************
424 Disable erase/write state of serial EEPROM
425 *************************************************************************/
426 void tul_se2_ew_ds(WORD CurBase
)
428 tul_se2_instr(CurBase
, 0); /* EWDS */
429 TUL_WR(CurBase
+ TUL_NVRAM
, 0); /* -CS */
435 /******************************************************************
436 Input :address of Serial E2PROM
437 Output :value stored in Serial E2PROM
438 *******************************************************************/
439 static USHORT
tul_se2_rd(WORD CurBase
, ULONG adr
)
441 UCHAR instr
, readByte
;
445 instr
= (UCHAR
) (adr
| 0x80);
446 tul_se2_instr(CurBase
, instr
); /* READ INSTR */
449 for (i
= 15; i
>= 0; i
--) {
450 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2CLK
); /* +CLK */
452 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* -CLK */
454 /* sample data after the following edge of clock */
455 readByte
= TUL_RD(CurBase
, TUL_NVRAM
);
457 readWord
+= (readByte
<< i
);
458 tul_se2_wait(); /* 6/20/95 */
461 TUL_WR(CurBase
+ TUL_NVRAM
, 0); /* no chip select */
467 /******************************************************************
468 Input: new value in Serial E2PROM, address of Serial E2PROM
469 *******************************************************************/
470 static void tul_se2_wr(WORD CurBase
, UCHAR adr
, USHORT writeWord
)
476 instr
= (UCHAR
) (adr
| 0x40);
477 tul_se2_instr(CurBase
, instr
); /* WRITE INSTR */
478 for (i
= 15; i
>= 0; i
--) {
479 if (writeWord
& 0x8000)
480 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2DO
); /* -CLK+dataBit 1 */
482 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* -CLK+dataBit 0 */
484 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2CLK
); /* +CLK */
488 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* -CLK */
490 TUL_WR(CurBase
+ TUL_NVRAM
, 0); /* -CS */
493 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* +CS */
497 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
| SE2CLK
); /* +CLK */
499 TUL_WR(CurBase
+ TUL_NVRAM
, SE2CS
); /* -CLK */
501 if ((readByte
= TUL_RD(CurBase
, TUL_NVRAM
)) & SE2DI
)
502 break; /* write complete */
504 TUL_WR(CurBase
+ TUL_NVRAM
, 0); /* -CS */
509 /***********************************************************************
510 Read SCSI H/A configuration parameters from serial EEPROM
511 ************************************************************************/
512 int tul_se2_rd_all(WORD CurBase
)
518 i91unvramp
= &i91unvram
;
519 np
= (USHORT
*) i91unvramp
;
520 for (i
= 0; i
< 32; i
++) {
521 *np
++ = tul_se2_rd(CurBase
, i
);
524 /*--------------------Is signature "ini" ok ? ----------------*/
525 if (i91unvramp
->NVM_Signature
!= INI_SIGNATURE
)
527 /*---------------------- Is ckecksum ok ? ----------------------*/
528 np
= (USHORT
*) i91unvramp
;
529 for (i
= 0; i
< 31; i
++)
531 if (i91unvramp
->NVM_CheckSum
!= (USHORT
) chksum
)
537 /***********************************************************************
538 Update SCSI H/A configuration parameters from serial EEPROM
539 ************************************************************************/
540 void tul_se2_update_all(WORD CurBase
)
541 { /* setup default pattern */
546 i91unvramp
= &i91unvram
;
547 /* Calculate checksum first */
548 np
= (USHORT
*) i91udftNvRam
;
549 for (i
= 0; i
< 31; i
++)
551 *np
= (USHORT
) chksum
;
552 tul_se2_ew_en(CurBase
); /* Enable write */
554 np
= (USHORT
*) i91udftNvRam
;
555 np1
= (USHORT
*) i91unvramp
;
556 for (i
= 0; i
< 32; i
++, np
++, np1
++) {
558 tul_se2_wr(CurBase
, i
, *np
);
562 tul_se2_ew_ds(CurBase
); /* Disable write */
566 /*************************************************************************
567 Function name : read_eeprom
568 **************************************************************************/
569 void tul_read_eeprom(WORD CurBase
)
573 i91unvramp
= &i91unvram
;
574 /*------Enable EEProm programming ---*/
575 gctrl
= TUL_RD(CurBase
, TUL_GCTRL
);
576 TUL_WR(CurBase
+ TUL_GCTRL
, gctrl
| TUL_GCTRL_EEPROM_BIT
);
577 if (tul_se2_rd_all(CurBase
) != 1) {
578 tul_se2_update_all(CurBase
); /* setup default pattern */
579 tul_se2_rd_all(CurBase
); /* load again */
581 /*------ Disable EEProm programming ---*/
582 gctrl
= TUL_RD(CurBase
, TUL_GCTRL
);
583 TUL_WR(CurBase
+ TUL_GCTRL
, gctrl
& ~TUL_GCTRL_EEPROM_BIT
);
586 static int Addi91u_into_Adapter_table(WORD wBIOS
, WORD wBASE
, BYTE bInterrupt
,
587 BYTE bBus
, BYTE bDevice
)
591 for (i
= 0; i
< MAX_SUPPORTED_ADAPTERS
; i
++) {
592 if (i91u_adpt
[i
].ADPT_BIOS
< wBIOS
)
594 if (i91u_adpt
[i
].ADPT_BIOS
== wBIOS
) {
595 if (i91u_adpt
[i
].ADPT_BASE
== wBASE
) {
596 if (i91u_adpt
[i
].ADPT_Bus
!= 0xFF)
598 } else if (i91u_adpt
[i
].ADPT_BASE
< wBASE
)
601 for (j
= MAX_SUPPORTED_ADAPTERS
- 1; j
> i
; j
--) {
602 i91u_adpt
[j
].ADPT_BASE
= i91u_adpt
[j
- 1].ADPT_BASE
;
603 i91u_adpt
[j
].ADPT_INTR
= i91u_adpt
[j
- 1].ADPT_INTR
;
604 i91u_adpt
[j
].ADPT_BIOS
= i91u_adpt
[j
- 1].ADPT_BIOS
;
605 i91u_adpt
[j
].ADPT_Bus
= i91u_adpt
[j
- 1].ADPT_Bus
;
606 i91u_adpt
[j
].ADPT_Device
= i91u_adpt
[j
- 1].ADPT_Device
;
608 i91u_adpt
[i
].ADPT_BASE
= wBASE
;
609 i91u_adpt
[i
].ADPT_INTR
= bInterrupt
;
610 i91u_adpt
[i
].ADPT_BIOS
= wBIOS
;
611 i91u_adpt
[i
].ADPT_Bus
= bBus
;
612 i91u_adpt
[i
].ADPT_Device
= bDevice
;
618 static void init_i91uAdapter_table(void)
622 for (i
= 0; i
< MAX_SUPPORTED_ADAPTERS
; i
++) { /* Initialize adapter structure */
623 i91u_adpt
[i
].ADPT_BIOS
= 0xffff;
624 i91u_adpt
[i
].ADPT_BASE
= 0xffff;
625 i91u_adpt
[i
].ADPT_INTR
= 0xff;
626 i91u_adpt
[i
].ADPT_Bus
= 0xff;
627 i91u_adpt
[i
].ADPT_Device
= 0xff;
632 static void tul_stop_bm(HCS
* pCurHcb
)
635 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_XStatus
) & XPEND
) { /* if DMA xfer is pending, abort DMA xfer */
636 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_X_ABT
| TAX_X_CLR_FIFO
);
637 /* wait Abort DMA xfer done */
638 while ((TUL_RD(pCurHcb
->HCS_Base
, TUL_Int
) & XABT
) == 0);
640 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
643 /***************************************************************************/
644 static void get_tulipPCIConfig(HCS
* pCurHcb
, int ch_idx
)
646 pCurHcb
->HCS_Base
= i91u_adpt
[ch_idx
].ADPT_BASE
; /* Supply base address */
647 pCurHcb
->HCS_BIOS
= i91u_adpt
[ch_idx
].ADPT_BIOS
; /* Supply BIOS address */
648 pCurHcb
->HCS_Intr
= i91u_adpt
[ch_idx
].ADPT_INTR
; /* Supply interrupt line */
652 /***************************************************************************/
653 static int tul_reset_scsi(HCS
* pCurHcb
, int seconds
)
655 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_RST_BUS
);
657 while (!((pCurHcb
->HCS_JSInt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
)) & TSS_SCSIRST_INT
));
658 /* reset tulip chip */
660 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, 0);
662 /* Stall for a while, wait for target's firmware ready,make it 2 sec ! */
663 /* SONY 5200 tape drive won't work if only stall for 1 sec */
664 tul_do_pause(seconds
* HZ
);
666 TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
);
668 return (SCSI_RESET_SUCCESS
);
671 /***************************************************************************/
672 static int init_tulip(HCS
* pCurHcb
, SCB
* scbp
, int tul_num_scb
,
673 BYTE
* pbBiosAdr
, int seconds
)
678 SCB
*pTmpScb
, *pPrevScb
= NULL
;
680 pCurHcb
->HCS_NumScbs
= tul_num_scb
;
681 pCurHcb
->HCS_Semaph
= 1;
682 spin_lock_init(&pCurHcb
->HCS_SemaphLock
);
683 pCurHcb
->HCS_JSStatus0
= 0;
684 pCurHcb
->HCS_Scb
= scbp
;
685 pCurHcb
->HCS_NxtPend
= scbp
;
686 pCurHcb
->HCS_NxtAvail
= scbp
;
687 for (i
= 0, pTmpScb
= scbp
; i
< tul_num_scb
; i
++, pTmpScb
++) {
688 pTmpScb
->SCB_TagId
= i
;
690 pPrevScb
->SCB_NxtScb
= pTmpScb
;
693 pPrevScb
->SCB_NxtScb
= NULL
;
694 pCurHcb
->HCS_ScbEnd
= pTmpScb
;
695 pCurHcb
->HCS_FirstAvail
= scbp
;
696 pCurHcb
->HCS_LastAvail
= pPrevScb
;
697 spin_lock_init(&pCurHcb
->HCS_AvailLock
);
698 pCurHcb
->HCS_FirstPend
= NULL
;
699 pCurHcb
->HCS_LastPend
= NULL
;
700 pCurHcb
->HCS_FirstBusy
= NULL
;
701 pCurHcb
->HCS_LastBusy
= NULL
;
702 pCurHcb
->HCS_FirstDone
= NULL
;
703 pCurHcb
->HCS_LastDone
= NULL
;
704 pCurHcb
->HCS_ActScb
= NULL
;
705 pCurHcb
->HCS_ActTcs
= NULL
;
707 tul_read_eeprom(pCurHcb
->HCS_Base
);
708 /*---------- get H/A configuration -------------*/
709 if (i91unvramp
->NVM_SCSIInfo
[0].NVM_NumOfTarg
== 8)
710 pCurHcb
->HCS_MaxTar
= 8;
712 pCurHcb
->HCS_MaxTar
= 16;
714 pCurHcb
->HCS_Config
= i91unvramp
->NVM_SCSIInfo
[0].NVM_ChConfig1
;
716 pCurHcb
->HCS_SCSI_ID
= i91unvramp
->NVM_SCSIInfo
[0].NVM_ChSCSIID
;
717 pCurHcb
->HCS_IdMask
= ~(1 << pCurHcb
->HCS_SCSI_ID
);
720 /* Enable parity error response */
721 TUL_WR(pCurHcb
->HCS_Base
+ TUL_PCMD
, TUL_RD(pCurHcb
->HCS_Base
, TUL_PCMD
) | 0x40);
724 /* Mask all the interrupt */
725 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
727 tul_stop_bm(pCurHcb
);
728 /* --- Initialize the tulip --- */
729 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_RST_CHIP
);
731 /* program HBA's SCSI ID */
732 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SScsiId
, pCurHcb
->HCS_SCSI_ID
<< 4);
734 /* Enable Initiator Mode ,phase latch,alternate sync period mode,
735 disable SCSI reset */
736 if (pCurHcb
->HCS_Config
& HCC_EN_PAR
)
737 pCurHcb
->HCS_SConf1
= (TSC_INITDEFAULT
| TSC_EN_SCSI_PAR
);
739 pCurHcb
->HCS_SConf1
= (TSC_INITDEFAULT
);
740 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurHcb
->HCS_SConf1
);
742 /* Enable HW reselect */
743 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
);
745 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SPeriod
, 0);
747 /* selection time out = 250 ms */
748 TUL_WR(pCurHcb
->HCS_Base
+ TUL_STimeOut
, 153);
750 /*--------- Enable SCSI terminator -----*/
751 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCtrl
, (pCurHcb
->HCS_Config
& (HCC_ACT_TERM1
| HCC_ACT_TERM2
)));
752 TUL_WR(pCurHcb
->HCS_Base
+ TUL_GCTRL1
,
753 ((pCurHcb
->HCS_Config
& HCC_AUTO_TERM
) >> 4) | (TUL_RD(pCurHcb
->HCS_Base
, TUL_GCTRL1
) & 0xFE));
756 pwFlags
= & (i91unvramp
->NVM_SCSIInfo
[0].NVM_Targ0Config
),
757 pbHeads
= pbBiosAdr
+ 0x180;
758 i
< pCurHcb
->HCS_MaxTar
;
760 pCurHcb
->HCS_Tcs
[i
].TCS_Flags
= *pwFlags
& ~(TCF_SYNC_DONE
| TCF_WDTR_DONE
);
761 if (pCurHcb
->HCS_Tcs
[i
].TCS_Flags
& TCF_EN_255
)
762 pCurHcb
->HCS_Tcs
[i
].TCS_DrvFlags
= TCF_DRV_255_63
;
764 pCurHcb
->HCS_Tcs
[i
].TCS_DrvFlags
= 0;
765 pCurHcb
->HCS_Tcs
[i
].TCS_JS_Period
= 0;
766 pCurHcb
->HCS_Tcs
[i
].TCS_SConfig0
= pCurHcb
->HCS_SConf1
;
767 pCurHcb
->HCS_Tcs
[i
].TCS_DrvHead
= *pbHeads
++;
768 if (pCurHcb
->HCS_Tcs
[i
].TCS_DrvHead
== 255)
769 pCurHcb
->HCS_Tcs
[i
].TCS_DrvFlags
= TCF_DRV_255_63
;
771 pCurHcb
->HCS_Tcs
[i
].TCS_DrvFlags
= 0;
772 pCurHcb
->HCS_Tcs
[i
].TCS_DrvSector
= *pbHeads
++;
773 pCurHcb
->HCS_Tcs
[i
].TCS_Flags
&= ~TCF_BUSY
;
774 pCurHcb
->HCS_ActTags
[i
] = 0;
775 pCurHcb
->HCS_MaxTags
[i
] = 0xFF;
777 printk("i91u: PCI Base=0x%04X, IRQ=%d, BIOS=0x%04X0, SCSI ID=%d\n",
778 pCurHcb
->HCS_Base
, pCurHcb
->HCS_Intr
,
779 pCurHcb
->HCS_BIOS
, pCurHcb
->HCS_SCSI_ID
);
780 /*------------------- reset SCSI Bus ---------------------------*/
781 if (pCurHcb
->HCS_Config
& HCC_SCSI_RESET
) {
782 printk("i91u: Reset SCSI Bus ... \n");
783 tul_reset_scsi(pCurHcb
, seconds
);
785 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCFG1
, 0x17);
786 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SIntEnable
, 0xE9);
790 /***************************************************************************/
791 static SCB
*tul_alloc_scb(HCS
* hcsp
)
795 spin_lock_irqsave(&(hcsp
->HCS_AvailLock
), flags
);
796 if ((pTmpScb
= hcsp
->HCS_FirstAvail
) != NULL
) {
798 printk("find scb at %08lx\n", (ULONG
) pTmpScb
);
800 if ((hcsp
->HCS_FirstAvail
= pTmpScb
->SCB_NxtScb
) == NULL
)
801 hcsp
->HCS_LastAvail
= NULL
;
802 pTmpScb
->SCB_NxtScb
= NULL
;
803 pTmpScb
->SCB_Status
= SCB_RENT
;
805 spin_unlock_irqrestore(&(hcsp
->HCS_AvailLock
), flags
);
809 /***************************************************************************/
810 static void tul_release_scb(HCS
* hcsp
, SCB
* scbp
)
815 printk("Release SCB %lx; ", (ULONG
) scbp
);
817 spin_lock_irqsave(&(hcsp
->HCS_AvailLock
), flags
);
818 scbp
->SCB_Srb
= NULL
;
819 scbp
->SCB_Status
= 0;
820 scbp
->SCB_NxtScb
= NULL
;
821 if (hcsp
->HCS_LastAvail
!= NULL
) {
822 hcsp
->HCS_LastAvail
->SCB_NxtScb
= scbp
;
823 hcsp
->HCS_LastAvail
= scbp
;
825 hcsp
->HCS_FirstAvail
= scbp
;
826 hcsp
->HCS_LastAvail
= scbp
;
828 spin_unlock_irqrestore(&(hcsp
->HCS_AvailLock
), flags
);
831 /***************************************************************************/
832 static void tul_append_pend_scb(HCS
* pCurHcb
, SCB
* scbp
)
836 printk("Append pend SCB %lx; ", (ULONG
) scbp
);
838 scbp
->SCB_Status
= SCB_PEND
;
839 scbp
->SCB_NxtScb
= NULL
;
840 if (pCurHcb
->HCS_LastPend
!= NULL
) {
841 pCurHcb
->HCS_LastPend
->SCB_NxtScb
= scbp
;
842 pCurHcb
->HCS_LastPend
= scbp
;
844 pCurHcb
->HCS_FirstPend
= scbp
;
845 pCurHcb
->HCS_LastPend
= scbp
;
849 /***************************************************************************/
850 static void tul_push_pend_scb(HCS
* pCurHcb
, SCB
* scbp
)
854 printk("Push pend SCB %lx; ", (ULONG
) scbp
);
856 scbp
->SCB_Status
= SCB_PEND
;
857 if ((scbp
->SCB_NxtScb
= pCurHcb
->HCS_FirstPend
) != NULL
) {
858 pCurHcb
->HCS_FirstPend
= scbp
;
860 pCurHcb
->HCS_FirstPend
= scbp
;
861 pCurHcb
->HCS_LastPend
= scbp
;
865 /***************************************************************************/
866 static SCB
*tul_find_first_pend_scb(HCS
* pCurHcb
)
871 pFirstPend
= pCurHcb
->HCS_FirstPend
;
872 while (pFirstPend
!= NULL
) {
873 if (pFirstPend
->SCB_Opcode
!= ExecSCSI
) {
876 if (pFirstPend
->SCB_TagMsg
== 0) {
877 if ((pCurHcb
->HCS_ActTags
[pFirstPend
->SCB_Target
] == 0) &&
878 !(pCurHcb
->HCS_Tcs
[pFirstPend
->SCB_Target
].TCS_Flags
& TCF_BUSY
)) {
882 if ((pCurHcb
->HCS_ActTags
[pFirstPend
->SCB_Target
] >=
883 pCurHcb
->HCS_MaxTags
[pFirstPend
->SCB_Target
]) |
884 (pCurHcb
->HCS_Tcs
[pFirstPend
->SCB_Target
].TCS_Flags
& TCF_BUSY
)) {
885 pFirstPend
= pFirstPend
->SCB_NxtScb
;
890 pFirstPend
= pFirstPend
->SCB_NxtScb
;
896 /***************************************************************************/
897 static void tul_unlink_pend_scb(HCS
* pCurHcb
, SCB
* pCurScb
)
899 SCB
*pTmpScb
, *pPrevScb
;
902 printk("unlink pend SCB %lx; ", (ULONG
) pCurScb
);
905 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstPend
;
906 while (pTmpScb
!= NULL
) {
907 if (pCurScb
== pTmpScb
) { /* Unlink this SCB */
908 if (pTmpScb
== pCurHcb
->HCS_FirstPend
) {
909 if ((pCurHcb
->HCS_FirstPend
= pTmpScb
->SCB_NxtScb
) == NULL
)
910 pCurHcb
->HCS_LastPend
= NULL
;
912 pPrevScb
->SCB_NxtScb
= pTmpScb
->SCB_NxtScb
;
913 if (pTmpScb
== pCurHcb
->HCS_LastPend
)
914 pCurHcb
->HCS_LastPend
= pPrevScb
;
916 pTmpScb
->SCB_NxtScb
= NULL
;
920 pTmpScb
= pTmpScb
->SCB_NxtScb
;
924 /***************************************************************************/
925 static void tul_append_busy_scb(HCS
* pCurHcb
, SCB
* scbp
)
929 printk("append busy SCB %lx; ", (ULONG
) scbp
);
931 if (scbp
->SCB_TagMsg
)
932 pCurHcb
->HCS_ActTags
[scbp
->SCB_Target
]++;
934 pCurHcb
->HCS_Tcs
[scbp
->SCB_Target
].TCS_Flags
|= TCF_BUSY
;
935 scbp
->SCB_Status
= SCB_BUSY
;
936 scbp
->SCB_NxtScb
= NULL
;
937 if (pCurHcb
->HCS_LastBusy
!= NULL
) {
938 pCurHcb
->HCS_LastBusy
->SCB_NxtScb
= scbp
;
939 pCurHcb
->HCS_LastBusy
= scbp
;
941 pCurHcb
->HCS_FirstBusy
= scbp
;
942 pCurHcb
->HCS_LastBusy
= scbp
;
946 /***************************************************************************/
947 static SCB
*tul_pop_busy_scb(HCS
* pCurHcb
)
952 if ((pTmpScb
= pCurHcb
->HCS_FirstBusy
) != NULL
) {
953 if ((pCurHcb
->HCS_FirstBusy
= pTmpScb
->SCB_NxtScb
) == NULL
)
954 pCurHcb
->HCS_LastBusy
= NULL
;
955 pTmpScb
->SCB_NxtScb
= NULL
;
956 if (pTmpScb
->SCB_TagMsg
)
957 pCurHcb
->HCS_ActTags
[pTmpScb
->SCB_Target
]--;
959 pCurHcb
->HCS_Tcs
[pTmpScb
->SCB_Target
].TCS_Flags
&= ~TCF_BUSY
;
962 printk("Pop busy SCB %lx; ", (ULONG
) pTmpScb
);
967 /***************************************************************************/
968 static void tul_unlink_busy_scb(HCS
* pCurHcb
, SCB
* pCurScb
)
970 SCB
*pTmpScb
, *pPrevScb
;
973 printk("unlink busy SCB %lx; ", (ULONG
) pCurScb
);
976 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstBusy
;
977 while (pTmpScb
!= NULL
) {
978 if (pCurScb
== pTmpScb
) { /* Unlink this SCB */
979 if (pTmpScb
== pCurHcb
->HCS_FirstBusy
) {
980 if ((pCurHcb
->HCS_FirstBusy
= pTmpScb
->SCB_NxtScb
) == NULL
)
981 pCurHcb
->HCS_LastBusy
= NULL
;
983 pPrevScb
->SCB_NxtScb
= pTmpScb
->SCB_NxtScb
;
984 if (pTmpScb
== pCurHcb
->HCS_LastBusy
)
985 pCurHcb
->HCS_LastBusy
= pPrevScb
;
987 pTmpScb
->SCB_NxtScb
= NULL
;
988 if (pTmpScb
->SCB_TagMsg
)
989 pCurHcb
->HCS_ActTags
[pTmpScb
->SCB_Target
]--;
991 pCurHcb
->HCS_Tcs
[pTmpScb
->SCB_Target
].TCS_Flags
&= ~TCF_BUSY
;
995 pTmpScb
= pTmpScb
->SCB_NxtScb
;
1000 /***************************************************************************/
1001 SCB
*tul_find_busy_scb(HCS
* pCurHcb
, WORD tarlun
)
1003 SCB
*pTmpScb
, *pPrevScb
;
1007 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstBusy
;
1008 while (pTmpScb
!= NULL
) {
1009 scbp_tarlun
= (pTmpScb
->SCB_Lun
<< 8) | (pTmpScb
->SCB_Target
);
1010 if (scbp_tarlun
== tarlun
) { /* Unlink this SCB */
1014 pTmpScb
= pTmpScb
->SCB_NxtScb
;
1017 printk("find busy SCB %lx; ", (ULONG
) pTmpScb
);
1022 /***************************************************************************/
1023 static void tul_append_done_scb(HCS
* pCurHcb
, SCB
* scbp
)
1027 printk("append done SCB %lx; ", (ULONG
) scbp
);
1030 scbp
->SCB_Status
= SCB_DONE
;
1031 scbp
->SCB_NxtScb
= NULL
;
1032 if (pCurHcb
->HCS_LastDone
!= NULL
) {
1033 pCurHcb
->HCS_LastDone
->SCB_NxtScb
= scbp
;
1034 pCurHcb
->HCS_LastDone
= scbp
;
1036 pCurHcb
->HCS_FirstDone
= scbp
;
1037 pCurHcb
->HCS_LastDone
= scbp
;
1041 /***************************************************************************/
1042 SCB
*tul_find_done_scb(HCS
* pCurHcb
)
1047 if ((pTmpScb
= pCurHcb
->HCS_FirstDone
) != NULL
) {
1048 if ((pCurHcb
->HCS_FirstDone
= pTmpScb
->SCB_NxtScb
) == NULL
)
1049 pCurHcb
->HCS_LastDone
= NULL
;
1050 pTmpScb
->SCB_NxtScb
= NULL
;
1053 printk("find done SCB %lx; ", (ULONG
) pTmpScb
);
1058 /***************************************************************************/
1059 static int tul_abort_srb(HCS
* pCurHcb
, struct scsi_cmnd
*srbp
)
1062 SCB
*pTmpScb
, *pPrevScb
;
1064 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1066 if ((pCurHcb
->HCS_Semaph
== 0) && (pCurHcb
->HCS_ActScb
== NULL
)) {
1067 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1068 /* disable Jasmin SCSI Int */
1070 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1072 tulip_main(pCurHcb
);
1074 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1076 pCurHcb
->HCS_Semaph
= 1;
1077 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1079 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1081 return SCSI_ABORT_SNOOZE
;
1083 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstPend
; /* Check Pend queue */
1084 while (pTmpScb
!= NULL
) {
1086 if (pTmpScb
->SCB_Srb
== srbp
) {
1087 if (pTmpScb
== pCurHcb
->HCS_ActScb
) {
1088 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1089 return SCSI_ABORT_BUSY
;
1090 } else if (pTmpScb
== pCurHcb
->HCS_FirstPend
) {
1091 if ((pCurHcb
->HCS_FirstPend
= pTmpScb
->SCB_NxtScb
) == NULL
)
1092 pCurHcb
->HCS_LastPend
= NULL
;
1094 pPrevScb
->SCB_NxtScb
= pTmpScb
->SCB_NxtScb
;
1095 if (pTmpScb
== pCurHcb
->HCS_LastPend
)
1096 pCurHcb
->HCS_LastPend
= pPrevScb
;
1098 pTmpScb
->SCB_HaStat
= HOST_ABORTED
;
1099 pTmpScb
->SCB_Flags
|= SCF_DONE
;
1100 if (pTmpScb
->SCB_Flags
& SCF_POST
)
1101 (*pTmpScb
->SCB_Post
) ((BYTE
*) pCurHcb
, (BYTE
*) pTmpScb
);
1102 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1103 return SCSI_ABORT_SUCCESS
;
1106 pTmpScb
= pTmpScb
->SCB_NxtScb
;
1109 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstBusy
; /* Check Busy queue */
1110 while (pTmpScb
!= NULL
) {
1112 if (pTmpScb
->SCB_Srb
== srbp
) {
1114 if (pTmpScb
== pCurHcb
->HCS_ActScb
) {
1115 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1116 return SCSI_ABORT_BUSY
;
1117 } else if (pTmpScb
->SCB_TagMsg
== 0) {
1118 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1119 return SCSI_ABORT_BUSY
;
1121 pCurHcb
->HCS_ActTags
[pTmpScb
->SCB_Target
]--;
1122 if (pTmpScb
== pCurHcb
->HCS_FirstBusy
) {
1123 if ((pCurHcb
->HCS_FirstBusy
= pTmpScb
->SCB_NxtScb
) == NULL
)
1124 pCurHcb
->HCS_LastBusy
= NULL
;
1126 pPrevScb
->SCB_NxtScb
= pTmpScb
->SCB_NxtScb
;
1127 if (pTmpScb
== pCurHcb
->HCS_LastBusy
)
1128 pCurHcb
->HCS_LastBusy
= pPrevScb
;
1130 pTmpScb
->SCB_NxtScb
= NULL
;
1133 pTmpScb
->SCB_HaStat
= HOST_ABORTED
;
1134 pTmpScb
->SCB_Flags
|= SCF_DONE
;
1135 if (pTmpScb
->SCB_Flags
& SCF_POST
)
1136 (*pTmpScb
->SCB_Post
) ((BYTE
*) pCurHcb
, (BYTE
*) pTmpScb
);
1137 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1138 return SCSI_ABORT_SUCCESS
;
1142 pTmpScb
= pTmpScb
->SCB_NxtScb
;
1144 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1145 return (SCSI_ABORT_NOT_RUNNING
);
1148 /***************************************************************************/
1149 static int tul_bad_seq(HCS
* pCurHcb
)
1153 printk("tul_bad_seg c=%d\n", pCurHcb
->HCS_Index
);
1155 if ((pCurScb
= pCurHcb
->HCS_ActScb
) != NULL
) {
1156 tul_unlink_busy_scb(pCurHcb
, pCurScb
);
1157 pCurScb
->SCB_HaStat
= HOST_BAD_PHAS
;
1158 pCurScb
->SCB_TaStat
= 0;
1159 tul_append_done_scb(pCurHcb
, pCurScb
);
1161 tul_stop_bm(pCurHcb
);
1163 tul_reset_scsi(pCurHcb
, 8); /* 7/29/98 */
1165 return (tul_post_scsi_rst(pCurHcb
));
1170 /************************************************************************/
1171 static int tul_device_reset(HCS
* pCurHcb
, struct scsi_cmnd
*pSrb
,
1172 unsigned int target
, unsigned int ResetFlags
)
1176 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1178 if (ResetFlags
& SCSI_RESET_ASYNCHRONOUS
) {
1180 if ((pCurHcb
->HCS_Semaph
== 0) && (pCurHcb
->HCS_ActScb
== NULL
)) {
1181 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1182 /* disable Jasmin SCSI Int */
1184 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1186 tulip_main(pCurHcb
);
1188 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1190 pCurHcb
->HCS_Semaph
= 1;
1191 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1193 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1195 return SCSI_RESET_SNOOZE
;
1197 pScb
= pCurHcb
->HCS_FirstBusy
; /* Check Busy queue */
1198 while (pScb
!= NULL
) {
1199 if (pScb
->SCB_Srb
== pSrb
)
1201 pScb
= pScb
->SCB_NxtScb
;
1204 printk("Unable to Reset - No SCB Found\n");
1206 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1207 return SCSI_RESET_NOT_RUNNING
;
1210 if ((pScb
= tul_alloc_scb(pCurHcb
)) == NULL
) {
1211 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1212 return SCSI_RESET_NOT_RUNNING
;
1214 pScb
->SCB_Opcode
= BusDevRst
;
1215 pScb
->SCB_Flags
= SCF_POST
;
1216 pScb
->SCB_Target
= target
;
1219 pScb
->SCB_Srb
= NULL
;
1220 if (ResetFlags
& SCSI_RESET_SYNCHRONOUS
) {
1221 pScb
->SCB_Srb
= pSrb
;
1223 tul_push_pend_scb(pCurHcb
, pScb
); /* push this SCB to Pending queue */
1225 if (pCurHcb
->HCS_Semaph
== 1) {
1226 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1227 /* disable Jasmin SCSI Int */
1228 pCurHcb
->HCS_Semaph
= 0;
1230 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1232 tulip_main(pCurHcb
);
1234 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1236 pCurHcb
->HCS_Semaph
= 1;
1237 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1239 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1240 return SCSI_RESET_PENDING
;
1243 static int tul_reset_scsi_bus(HCS
* pCurHcb
)
1247 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1248 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1249 pCurHcb
->HCS_Semaph
= 0;
1251 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1253 tul_stop_bm(pCurHcb
);
1255 tul_reset_scsi(pCurHcb
, 2); /* 7/29/98 */
1257 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1258 tul_post_scsi_rst(pCurHcb
);
1260 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1262 tulip_main(pCurHcb
);
1264 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1266 pCurHcb
->HCS_Semaph
= 1;
1267 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1268 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1269 return (SCSI_RESET_SUCCESS
| SCSI_RESET_HOST_RESET
);
1274 /************************************************************************/
1275 static void tul_exec_scb(HCS
* pCurHcb
, SCB
* pCurScb
)
1279 pCurScb
->SCB_Mode
= 0;
1281 pCurScb
->SCB_SGIdx
= 0;
1282 pCurScb
->SCB_SGMax
= pCurScb
->SCB_SGLen
;
1284 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1286 tul_append_pend_scb(pCurHcb
, pCurScb
); /* Append this SCB to Pending queue */
1288 /* VVVVV 07/21/98 */
1289 if (pCurHcb
->HCS_Semaph
== 1) {
1290 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1291 /* disable Jasmin SCSI Int */
1292 pCurHcb
->HCS_Semaph
= 0;
1294 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1296 tulip_main(pCurHcb
);
1298 spin_lock_irqsave(&(pCurHcb
->HCS_SemaphLock
), flags
);
1300 pCurHcb
->HCS_Semaph
= 1;
1301 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1303 spin_unlock_irqrestore(&(pCurHcb
->HCS_SemaphLock
), flags
);
1307 /***************************************************************************/
1308 static int tul_isr(HCS
* pCurHcb
)
1310 /* Enter critical section */
1312 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_Int
) & TSS_INT_PENDING
) {
1313 if (pCurHcb
->HCS_Semaph
== 1) {
1314 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x1F);
1315 /* Disable Tulip SCSI Int */
1316 pCurHcb
->HCS_Semaph
= 0;
1318 tulip_main(pCurHcb
);
1320 pCurHcb
->HCS_Semaph
= 1;
1321 TUL_WR(pCurHcb
->HCS_Base
+ TUL_Mask
, 0x0F);
1328 /***************************************************************************/
1329 int tulip_main(HCS
* pCurHcb
)
1335 tulip_scsi(pCurHcb
); /* Call tulip_scsi */
1337 while ((pCurScb
= tul_find_done_scb(pCurHcb
)) != NULL
) { /* find done entry */
1338 if (pCurScb
->SCB_TaStat
== INI_QUEUE_FULL
) {
1339 pCurHcb
->HCS_MaxTags
[pCurScb
->SCB_Target
] =
1340 pCurHcb
->HCS_ActTags
[pCurScb
->SCB_Target
] - 1;
1341 pCurScb
->SCB_TaStat
= 0;
1342 tul_append_pend_scb(pCurHcb
, pCurScb
);
1345 if (!(pCurScb
->SCB_Mode
& SCM_RSENS
)) { /* not in auto req. sense mode */
1346 if (pCurScb
->SCB_TaStat
== 2) {
1348 /* clr sync. nego flag */
1350 if (pCurScb
->SCB_Flags
& SCF_SENSE
) {
1352 len
= pCurScb
->SCB_SenseLen
;
1355 pCurScb
->SCB_BufLen
= pCurScb
->SCB_SenseLen
;
1356 pCurScb
->SCB_BufPtr
= pCurScb
->SCB_SensePtr
;
1357 pCurScb
->SCB_Flags
&= ~(SCF_SG
| SCF_DIR
); /* for xfer_data_in */
1358 /* pCurScb->SCB_Flags |= SCF_NO_DCHK; */
1359 /* so, we won't report worng direction in xfer_data_in,
1360 and won't report HOST_DO_DU in state_6 */
1361 pCurScb
->SCB_Mode
= SCM_RSENS
;
1362 pCurScb
->SCB_Ident
&= 0xBF; /* Disable Disconnect */
1363 pCurScb
->SCB_TagMsg
= 0;
1364 pCurScb
->SCB_TaStat
= 0;
1365 pCurScb
->SCB_CDBLen
= 6;
1366 pCurScb
->SCB_CDB
[0] = SCSICMD_RequestSense
;
1367 pCurScb
->SCB_CDB
[1] = 0;
1368 pCurScb
->SCB_CDB
[2] = 0;
1369 pCurScb
->SCB_CDB
[3] = 0;
1370 pCurScb
->SCB_CDB
[4] = len
;
1371 pCurScb
->SCB_CDB
[5] = 0;
1372 tul_push_pend_scb(pCurHcb
, pCurScb
);
1376 } else { /* in request sense mode */
1378 if (pCurScb
->SCB_TaStat
== 2) { /* check contition status again after sending
1379 requset sense cmd 0x3 */
1380 pCurScb
->SCB_HaStat
= HOST_BAD_PHAS
;
1382 pCurScb
->SCB_TaStat
= 2;
1384 pCurScb
->SCB_Flags
|= SCF_DONE
;
1385 if (pCurScb
->SCB_Flags
& SCF_POST
) {
1386 (*pCurScb
->SCB_Post
) ((BYTE
*) pCurHcb
, (BYTE
*) pCurScb
);
1391 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus0
) & TSS_INT_PENDING
)
1394 if (pCurHcb
->HCS_ActScb
) { /* return to OS and wait for xfer_done_ISR/Selected_ISR */
1395 return 1; /* return to OS, enable interrupt */
1397 /* Check pending SCB */
1398 if (tul_find_first_pend_scb(pCurHcb
) == NULL
) {
1399 return 1; /* return to OS, enable interrupt */
1401 } /* End of for loop */
1402 /* statement won't reach here */
1408 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
1409 /***************************************************************************/
1410 /***************************************************************************/
1411 /***************************************************************************/
1412 /***************************************************************************/
1414 /***************************************************************************/
1415 void tulip_scsi(HCS
* pCurHcb
)
1420 /* make sure to service interrupt asap */
1422 if ((pCurHcb
->HCS_JSStatus0
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus0
)) & TSS_INT_PENDING
) {
1424 pCurHcb
->HCS_Phase
= pCurHcb
->HCS_JSStatus0
& TSS_PH_MASK
;
1425 pCurHcb
->HCS_JSStatus1
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus1
);
1426 pCurHcb
->HCS_JSInt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
);
1427 if (pCurHcb
->HCS_JSInt
& TSS_SCSIRST_INT
) { /* SCSI bus reset detected */
1428 int_tul_scsi_rst(pCurHcb
);
1431 if (pCurHcb
->HCS_JSInt
& TSS_RESEL_INT
) { /* if selected/reselected interrupt */
1432 if (int_tul_resel(pCurHcb
) == 0)
1433 tul_next_state(pCurHcb
);
1436 if (pCurHcb
->HCS_JSInt
& TSS_SEL_TIMEOUT
) {
1437 int_tul_busfree(pCurHcb
);
1440 if (pCurHcb
->HCS_JSInt
& TSS_DISC_INT
) { /* BUS disconnection */
1441 int_tul_busfree(pCurHcb
); /* unexpected bus free or sel timeout */
1444 if (pCurHcb
->HCS_JSInt
& (TSS_FUNC_COMP
| TSS_BUS_SERV
)) { /* func complete or Bus service */
1445 if ((pCurScb
= pCurHcb
->HCS_ActScb
) != NULL
)
1446 tul_next_state(pCurHcb
);
1450 if (pCurHcb
->HCS_ActScb
!= NULL
)
1453 if ((pCurScb
= tul_find_first_pend_scb(pCurHcb
)) == NULL
)
1456 /* program HBA's SCSI ID & target SCSI ID */
1457 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SScsiId
,
1458 (pCurHcb
->HCS_SCSI_ID
<< 4) | (pCurScb
->SCB_Target
& 0x0F));
1459 if (pCurScb
->SCB_Opcode
== ExecSCSI
) {
1460 pCurTcb
= &pCurHcb
->HCS_Tcs
[pCurScb
->SCB_Target
];
1462 if (pCurScb
->SCB_TagMsg
)
1463 pCurTcb
->TCS_DrvFlags
|= TCF_DRV_EN_TAG
;
1465 pCurTcb
->TCS_DrvFlags
&= ~TCF_DRV_EN_TAG
;
1467 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SPeriod
, pCurTcb
->TCS_JS_Period
);
1468 if ((pCurTcb
->TCS_Flags
& (TCF_WDTR_DONE
| TCF_NO_WDTR
)) == 0) { /* do wdtr negotiation */
1469 tul_select_atn_stop(pCurHcb
, pCurScb
);
1471 if ((pCurTcb
->TCS_Flags
& (TCF_SYNC_DONE
| TCF_NO_SYNC_NEGO
)) == 0) { /* do sync negotiation */
1472 tul_select_atn_stop(pCurHcb
, pCurScb
);
1474 if (pCurScb
->SCB_TagMsg
)
1475 tul_select_atn3(pCurHcb
, pCurScb
);
1477 tul_select_atn(pCurHcb
, pCurScb
);
1480 if (pCurScb
->SCB_Flags
& SCF_POLL
) {
1481 while (wait_tulip(pCurHcb
) != -1) {
1482 if (tul_next_state(pCurHcb
) == -1)
1486 } else if (pCurScb
->SCB_Opcode
== BusDevRst
) {
1487 tul_select_atn_stop(pCurHcb
, pCurScb
);
1488 pCurScb
->SCB_NxtStat
= 8;
1489 if (pCurScb
->SCB_Flags
& SCF_POLL
) {
1490 while (wait_tulip(pCurHcb
) != -1) {
1491 if (tul_next_state(pCurHcb
) == -1)
1495 } else if (pCurScb
->SCB_Opcode
== AbortCmd
) {
1496 if (tul_abort_srb(pCurHcb
, pCurScb
->SCB_Srb
) != 0) {
1499 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
1501 tul_release_scb(pCurHcb
, pCurScb
);
1503 pCurScb
->SCB_Opcode
= BusDevRst
;
1504 tul_select_atn_stop(pCurHcb
, pCurScb
);
1505 pCurScb
->SCB_NxtStat
= 8;
1510 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
1511 pCurScb
->SCB_HaStat
= 0x16; /* bad command */
1512 tul_append_done_scb(pCurHcb
, pCurScb
);
1518 /***************************************************************************/
1519 int tul_next_state(HCS
* pCurHcb
)
1523 next
= pCurHcb
->HCS_ActScb
->SCB_NxtStat
;
1527 next
= tul_state_1(pCurHcb
);
1530 next
= tul_state_2(pCurHcb
);
1533 next
= tul_state_3(pCurHcb
);
1536 next
= tul_state_4(pCurHcb
);
1539 next
= tul_state_5(pCurHcb
);
1542 next
= tul_state_6(pCurHcb
);
1545 next
= tul_state_7(pCurHcb
);
1548 return (tul_bus_device_reset(pCurHcb
));
1550 return (tul_bad_seq(pCurHcb
));
1558 /***************************************************************************/
1559 /* sTate after selection with attention & stop */
1560 int tul_state_1(HCS
* pCurHcb
)
1562 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1563 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
1568 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
1569 tul_append_busy_scb(pCurHcb
, pCurScb
);
1571 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurTcb
->TCS_SConfig0
);
1573 if (pCurHcb
->HCS_Phase
== MSG_OUT
) {
1575 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, (TSC_EN_BUS_IN
| TSC_HW_RESELECT
));
1577 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_Ident
);
1579 if (pCurScb
->SCB_TagMsg
) {
1580 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_TagMsg
);
1581 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_TagId
);
1583 if ((pCurTcb
->TCS_Flags
& (TCF_WDTR_DONE
| TCF_NO_WDTR
)) == 0) {
1585 pCurTcb
->TCS_Flags
|= TCF_WDTR_DONE
;
1587 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_EXTEND
);
1588 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 2); /* Extended msg length */
1589 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 3); /* Sync request */
1590 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 1); /* Start from 16 bits */
1591 } else if ((pCurTcb
->TCS_Flags
& (TCF_SYNC_DONE
| TCF_NO_SYNC_NEGO
)) == 0) {
1593 pCurTcb
->TCS_Flags
|= TCF_SYNC_DONE
;
1595 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_EXTEND
);
1596 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 3); /* extended msg length */
1597 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 1); /* sync request */
1598 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, tul_rate_tbl
[pCurTcb
->TCS_Flags
& TCF_SCSI_RATE
]);
1599 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MAX_OFFSET
); /* REQ/ACK offset */
1601 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1602 if (wait_tulip(pCurHcb
) == -1)
1605 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1606 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, (TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)));
1611 /***************************************************************************/
1612 /* state after selection with attention */
1613 /* state after selection with attention3 */
1614 int tul_state_2(HCS
* pCurHcb
)
1616 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1617 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
1622 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
1623 tul_append_busy_scb(pCurHcb
, pCurScb
);
1625 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurTcb
->TCS_SConfig0
);
1627 if (pCurHcb
->HCS_JSStatus1
& TSS_CMD_PH_CMP
) {
1630 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1631 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, (TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)));
1635 /***************************************************************************/
1636 /* state before CDB xfer is done */
1637 int tul_state_3(HCS
* pCurHcb
)
1639 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1640 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
1647 switch (pCurHcb
->HCS_Phase
) {
1648 case CMD_OUT
: /* Command out phase */
1649 for (i
= 0; i
< (int) pCurScb
->SCB_CDBLen
; i
++)
1650 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_CDB
[i
]);
1651 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1652 if (wait_tulip(pCurHcb
) == -1)
1654 if (pCurHcb
->HCS_Phase
== CMD_OUT
) {
1655 return (tul_bad_seq(pCurHcb
));
1659 case MSG_IN
: /* Message in phase */
1660 pCurScb
->SCB_NxtStat
= 3;
1661 if (tul_msgin(pCurHcb
) == -1)
1665 case STATUS_IN
: /* Status phase */
1666 if (tul_status_msg(pCurHcb
) == -1)
1670 case MSG_OUT
: /* Message out phase */
1671 if (pCurTcb
->TCS_Flags
& (TCF_SYNC_DONE
| TCF_NO_SYNC_NEGO
)) {
1673 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_NOP
); /* msg nop */
1674 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1675 if (wait_tulip(pCurHcb
) == -1)
1679 pCurTcb
->TCS_Flags
|= TCF_SYNC_DONE
;
1681 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_EXTEND
);
1682 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 3); /* ext. msg len */
1683 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 1); /* sync request */
1684 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, tul_rate_tbl
[pCurTcb
->TCS_Flags
& TCF_SCSI_RATE
]);
1685 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MAX_OFFSET
); /* REQ/ACK offset */
1686 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1687 if (wait_tulip(pCurHcb
) == -1)
1689 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1690 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7));
1696 return (tul_bad_seq(pCurHcb
));
1702 /***************************************************************************/
1703 int tul_state_4(HCS
* pCurHcb
)
1705 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1710 if ((pCurScb
->SCB_Flags
& SCF_DIR
) == SCF_NO_XF
) {
1711 return (6); /* Go to state 6 */
1714 if (pCurScb
->SCB_BufLen
== 0)
1715 return (6); /* Go to state 6 */
1717 switch (pCurHcb
->HCS_Phase
) {
1719 case STATUS_IN
: /* Status phase */
1720 if ((pCurScb
->SCB_Flags
& SCF_DIR
) != 0) { /* if direction bit set then report data underrun */
1721 pCurScb
->SCB_HaStat
= HOST_DO_DU
;
1723 if ((tul_status_msg(pCurHcb
)) == -1)
1727 case MSG_IN
: /* Message in phase */
1728 pCurScb
->SCB_NxtStat
= 0x4;
1729 if (tul_msgin(pCurHcb
) == -1)
1733 case MSG_OUT
: /* Message out phase */
1734 if (pCurHcb
->HCS_JSStatus0
& TSS_PAR_ERROR
) {
1735 pCurScb
->SCB_BufLen
= 0;
1736 pCurScb
->SCB_HaStat
= HOST_DO_DU
;
1737 if (tul_msgout_ide(pCurHcb
) == -1)
1739 return (6); /* Go to state 6 */
1741 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_NOP
); /* msg nop */
1742 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1743 if (wait_tulip(pCurHcb
) == -1)
1748 case DATA_IN
: /* Data in phase */
1749 return (tul_xfer_data_in(pCurHcb
));
1751 case DATA_OUT
: /* Data out phase */
1752 return (tul_xfer_data_out(pCurHcb
));
1755 return (tul_bad_seq(pCurHcb
));
1761 /***************************************************************************/
1762 /* state after dma xfer done or phase change before xfer done */
1763 int tul_state_5(HCS
* pCurHcb
)
1765 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1766 long cnt
, xcnt
; /* cannot use unsigned !! code: if (xcnt < 0) */
1771 /*------ get remaining count -------*/
1773 cnt
= TUL_RDLONG(pCurHcb
->HCS_Base
, TUL_SCnt0
) & 0x0FFFFFF;
1775 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_XCmd
) & 0x20) {
1776 /* ----------------------- DATA_IN ----------------------------- */
1777 /* check scsi parity error */
1778 if (pCurHcb
->HCS_JSStatus0
& TSS_PAR_ERROR
) {
1779 pCurScb
->SCB_HaStat
= HOST_DO_DU
;
1781 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_XStatus
) & XPEND
) { /* DMA xfer pending, Send STOP */
1782 /* tell Hardware scsi xfer has been terminated */
1783 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCtrl
, TUL_RD(pCurHcb
->HCS_Base
, TUL_XCtrl
) | 0x80);
1784 /* wait until DMA xfer not pending */
1785 while (TUL_RD(pCurHcb
->HCS_Base
, TUL_XStatus
) & XPEND
);
1788 /*-------- DATA OUT -----------*/
1789 if ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus1
) & TSS_XFER_CMP
) == 0) {
1790 if (pCurHcb
->HCS_ActTcs
->TCS_JS_Period
& TSC_WIDE_SCSI
)
1791 cnt
+= (TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifoCnt
) & 0x1F) << 1;
1793 cnt
+= (TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifoCnt
) & 0x1F);
1795 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_XStatus
) & XPEND
) { /* if DMA xfer is pending, abort DMA xfer */
1796 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_X_ABT
);
1797 /* wait Abort DMA xfer done */
1798 while ((TUL_RD(pCurHcb
->HCS_Base
, TUL_Int
) & XABT
) == 0);
1800 if ((cnt
== 1) && (pCurHcb
->HCS_Phase
== DATA_OUT
)) {
1801 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1802 if (wait_tulip(pCurHcb
) == -1) {
1807 if ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus1
) & TSS_XFER_CMP
) == 0)
1808 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1813 pCurScb
->SCB_BufLen
= 0;
1814 return (6); /* Go to state 6 */
1816 /* Update active data pointer */
1817 xcnt
= (long) pCurScb
->SCB_BufLen
- cnt
; /* xcnt== bytes already xferred */
1818 pCurScb
->SCB_BufLen
= (U32
) cnt
; /* cnt == bytes left to be xferred */
1819 if (pCurScb
->SCB_Flags
& SCF_SG
) {
1823 sgp
= &pCurScb
->SCB_SGList
[pCurScb
->SCB_SGIdx
];
1824 for (i
= pCurScb
->SCB_SGIdx
; i
< pCurScb
->SCB_SGMax
; sgp
++, i
++) {
1825 xcnt
-= (long) sgp
->SG_Len
;
1826 if (xcnt
< 0) { /* this sgp xfer half done */
1827 xcnt
+= (long) sgp
->SG_Len
; /* xcnt == bytes xferred in this sgp */
1828 sgp
->SG_Ptr
+= (U32
) xcnt
; /* new ptr to be xfer */
1829 sgp
->SG_Len
-= (U32
) xcnt
; /* new len to be xfer */
1830 pCurScb
->SCB_BufPtr
+= ((U32
) (i
- pCurScb
->SCB_SGIdx
) << 3);
1831 /* new SG table ptr */
1832 pCurScb
->SCB_SGLen
= (BYTE
) (pCurScb
->SCB_SGMax
- i
);
1833 /* new SG table len */
1834 pCurScb
->SCB_SGIdx
= (WORD
) i
;
1835 /* for next disc and come in this loop */
1836 return (4); /* Go to state 4 */
1838 /* else (xcnt >= 0 , i.e. this sgp already xferred */
1840 return (6); /* Go to state 6 */
1842 pCurScb
->SCB_BufPtr
+= (U32
) xcnt
;
1844 return (4); /* Go to state 4 */
1847 /***************************************************************************/
1848 /* state after Data phase */
1849 int tul_state_6(HCS
* pCurHcb
)
1851 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1857 switch (pCurHcb
->HCS_Phase
) {
1858 case STATUS_IN
: /* Status phase */
1859 if ((tul_status_msg(pCurHcb
)) == -1)
1863 case MSG_IN
: /* Message in phase */
1864 pCurScb
->SCB_NxtStat
= 6;
1865 if ((tul_msgin(pCurHcb
)) == -1)
1869 case MSG_OUT
: /* Message out phase */
1870 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_NOP
); /* msg nop */
1871 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
1872 if (wait_tulip(pCurHcb
) == -1)
1876 case DATA_IN
: /* Data in phase */
1877 return (tul_xpad_in(pCurHcb
));
1879 case DATA_OUT
: /* Data out phase */
1880 return (tul_xpad_out(pCurHcb
));
1883 return (tul_bad_seq(pCurHcb
));
1888 /***************************************************************************/
1889 int tul_state_7(HCS
* pCurHcb
)
1896 /* flush SCSI FIFO */
1897 cnt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifoCnt
) & 0x1F;
1899 for (i
= 0; i
< cnt
; i
++)
1900 TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
1902 switch (pCurHcb
->HCS_Phase
) {
1903 case DATA_IN
: /* Data in phase */
1904 case DATA_OUT
: /* Data out phase */
1905 return (tul_bad_seq(pCurHcb
));
1907 return (6); /* Go to state 6 */
1911 /***************************************************************************/
1912 int tul_xfer_data_in(HCS
* pCurHcb
)
1914 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1916 if ((pCurScb
->SCB_Flags
& SCF_DIR
) == SCF_DOUT
) {
1917 return (6); /* wrong direction */
1919 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, pCurScb
->SCB_BufLen
);
1921 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_DMA_IN
); /* 7/25/95 */
1923 if (pCurScb
->SCB_Flags
& SCF_SG
) { /* S/G xfer */
1924 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XCntH
, ((ULONG
) pCurScb
->SCB_SGLen
) << 3);
1925 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XAddH
, pCurScb
->SCB_BufPtr
);
1926 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_SG_IN
);
1928 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XCntH
, pCurScb
->SCB_BufLen
);
1929 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XAddH
, pCurScb
->SCB_BufPtr
);
1930 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_X_IN
);
1932 pCurScb
->SCB_NxtStat
= 0x5;
1933 return (0); /* return to OS, wait xfer done , let jas_isr come in */
1937 /***************************************************************************/
1938 int tul_xfer_data_out(HCS
* pCurHcb
)
1940 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1942 if ((pCurScb
->SCB_Flags
& SCF_DIR
) == SCF_DIN
) {
1943 return (6); /* wrong direction */
1945 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, pCurScb
->SCB_BufLen
);
1946 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_DMA_OUT
);
1948 if (pCurScb
->SCB_Flags
& SCF_SG
) { /* S/G xfer */
1949 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XCntH
, ((ULONG
) pCurScb
->SCB_SGLen
) << 3);
1950 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XAddH
, pCurScb
->SCB_BufPtr
);
1951 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_SG_OUT
);
1953 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XCntH
, pCurScb
->SCB_BufLen
);
1954 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_XAddH
, pCurScb
->SCB_BufPtr
);
1955 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_X_OUT
);
1958 pCurScb
->SCB_NxtStat
= 0x5;
1959 return (0); /* return to OS, wait xfer done , let jas_isr come in */
1963 /***************************************************************************/
1964 int tul_xpad_in(HCS
* pCurHcb
)
1966 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1967 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
1969 if ((pCurScb
->SCB_Flags
& SCF_DIR
) != SCF_NO_DCHK
) {
1970 pCurScb
->SCB_HaStat
= HOST_DO_DU
; /* over run */
1973 if (pCurTcb
->TCS_JS_Period
& TSC_WIDE_SCSI
)
1974 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 2);
1976 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
1978 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
1979 if ((wait_tulip(pCurHcb
)) == -1) {
1982 if (pCurHcb
->HCS_Phase
!= DATA_IN
) {
1983 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
1986 TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
1990 int tul_xpad_out(HCS
* pCurHcb
)
1992 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
1993 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
1995 if ((pCurScb
->SCB_Flags
& SCF_DIR
) != SCF_NO_DCHK
) {
1996 pCurScb
->SCB_HaStat
= HOST_DO_DU
; /* over run */
1999 if (pCurTcb
->TCS_JS_Period
& TSC_WIDE_SCSI
)
2000 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 2);
2002 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2004 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 0);
2005 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2006 if ((wait_tulip(pCurHcb
)) == -1) {
2009 if (pCurHcb
->HCS_Phase
!= DATA_OUT
) { /* Disable wide CPU to allow read 16 bits */
2010 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
);
2011 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2018 /***************************************************************************/
2019 int tul_status_msg(HCS
* pCurHcb
)
2020 { /* status & MSG_IN */
2021 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
2024 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_CMD_COMP
);
2025 if ((wait_tulip(pCurHcb
)) == -1) {
2029 pCurScb
->SCB_TaStat
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
2031 if (pCurHcb
->HCS_Phase
== MSG_OUT
) {
2032 if (pCurHcb
->HCS_JSStatus0
& TSS_PAR_ERROR
) {
2033 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_PARITY
);
2035 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_NOP
);
2037 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2038 return (wait_tulip(pCurHcb
));
2040 if (pCurHcb
->HCS_Phase
== MSG_IN
) {
2041 msg
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
2042 if (pCurHcb
->HCS_JSStatus0
& TSS_PAR_ERROR
) { /* Parity error */
2043 if ((tul_msgin_accept(pCurHcb
)) == -1)
2045 if (pCurHcb
->HCS_Phase
!= MSG_OUT
)
2046 return (tul_bad_seq(pCurHcb
));
2047 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_PARITY
);
2048 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2049 return (wait_tulip(pCurHcb
));
2051 if (msg
== 0) { /* Command complete */
2053 if ((pCurScb
->SCB_TaStat
& 0x18) == 0x10) { /* No link support */
2054 return (tul_bad_seq(pCurHcb
));
2056 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2057 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_MSG_ACCEPT
);
2058 return tul_wait_done_disc(pCurHcb
);
2061 if ((msg
== MSG_LINK_COMP
) || (msg
== MSG_LINK_FLAG
)) {
2062 if ((pCurScb
->SCB_TaStat
& 0x18) == 0x10)
2063 return (tul_msgin_accept(pCurHcb
));
2066 return (tul_bad_seq(pCurHcb
));
2070 /***************************************************************************/
2072 int int_tul_busfree(HCS
* pCurHcb
)
2074 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
2076 if (pCurScb
!= NULL
) {
2077 if (pCurScb
->SCB_Status
& SCB_SELECT
) { /* selection timeout */
2078 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
2079 pCurScb
->SCB_HaStat
= HOST_SEL_TOUT
;
2080 tul_append_done_scb(pCurHcb
, pCurScb
);
2081 } else { /* Unexpected bus free */
2082 tul_unlink_busy_scb(pCurHcb
, pCurScb
);
2083 pCurScb
->SCB_HaStat
= HOST_BUS_FREE
;
2084 tul_append_done_scb(pCurHcb
, pCurScb
);
2086 pCurHcb
->HCS_ActScb
= NULL
;
2087 pCurHcb
->HCS_ActTcs
= NULL
;
2089 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
); /* Flush SCSI FIFO */
2090 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, TSC_INITDEFAULT
);
2091 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
); /* Enable HW reselect */
2096 /***************************************************************************/
2097 /* scsi bus reset */
2098 static int int_tul_scsi_rst(HCS
* pCurHcb
)
2103 /* if DMA xfer is pending, abort DMA xfer */
2104 if (TUL_RD(pCurHcb
->HCS_Base
, TUL_XStatus
) & 0x01) {
2105 TUL_WR(pCurHcb
->HCS_Base
+ TUL_XCmd
, TAX_X_ABT
| TAX_X_CLR_FIFO
);
2106 /* wait Abort DMA xfer done */
2107 while ((TUL_RD(pCurHcb
->HCS_Base
, TUL_Int
) & 0x04) == 0);
2108 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2110 /* Abort all active & disconnected scb */
2111 while ((pCurScb
= tul_pop_busy_scb(pCurHcb
)) != NULL
) {
2112 pCurScb
->SCB_HaStat
= HOST_BAD_PHAS
;
2113 tul_append_done_scb(pCurHcb
, pCurScb
);
2115 pCurHcb
->HCS_ActScb
= NULL
;
2116 pCurHcb
->HCS_ActTcs
= NULL
;
2118 /* clr sync nego. done flag */
2119 for (i
= 0; i
< pCurHcb
->HCS_MaxTar
; i
++) {
2120 pCurHcb
->HCS_Tcs
[i
].TCS_Flags
&= ~(TCF_SYNC_DONE
| TCF_WDTR_DONE
);
2126 /***************************************************************************/
2127 /* scsi reselection */
2128 int int_tul_resel(HCS
* pCurHcb
)
2135 if ((pCurScb
= pCurHcb
->HCS_ActScb
) != NULL
) {
2136 if (pCurScb
->SCB_Status
& SCB_SELECT
) { /* if waiting for selection complete */
2137 pCurScb
->SCB_Status
&= ~SCB_SELECT
;
2139 pCurHcb
->HCS_ActScb
= NULL
;
2141 /* --------- get target id---------------------- */
2142 tar
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SBusId
);
2143 /* ------ get LUN from Identify message----------- */
2144 lun
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SIdent
) & 0x0F;
2145 /* 07/22/98 from 0x1F -> 0x0F */
2146 pCurTcb
= &pCurHcb
->HCS_Tcs
[tar
];
2147 pCurHcb
->HCS_ActTcs
= pCurTcb
;
2148 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurTcb
->TCS_SConfig0
);
2149 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SPeriod
, pCurTcb
->TCS_JS_Period
);
2152 /* ------------- tag queueing ? ------------------- */
2153 if (pCurTcb
->TCS_DrvFlags
& TCF_DRV_EN_TAG
) {
2154 if ((tul_msgin_accept(pCurHcb
)) == -1)
2156 if (pCurHcb
->HCS_Phase
!= MSG_IN
)
2158 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2159 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2160 if ((wait_tulip(pCurHcb
)) == -1)
2162 msg
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
); /* Read Tag Message */
2164 if ((msg
< MSG_STAG
) || (msg
> MSG_OTAG
)) /* Is simple Tag */
2167 if ((tul_msgin_accept(pCurHcb
)) == -1)
2170 if (pCurHcb
->HCS_Phase
!= MSG_IN
)
2173 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2174 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2175 if ((wait_tulip(pCurHcb
)) == -1)
2177 tag
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
); /* Read Tag ID */
2178 pCurScb
= pCurHcb
->HCS_Scb
+ tag
;
2179 if ((pCurScb
->SCB_Target
!= tar
) || (pCurScb
->SCB_Lun
!= lun
)) {
2180 return tul_msgout_abort_tag(pCurHcb
);
2182 if (pCurScb
->SCB_Status
!= SCB_BUSY
) { /* 03/24/95 */
2183 return tul_msgout_abort_tag(pCurHcb
);
2185 pCurHcb
->HCS_ActScb
= pCurScb
;
2186 if ((tul_msgin_accept(pCurHcb
)) == -1)
2188 } else { /* No tag */
2190 if ((pCurScb
= tul_find_busy_scb(pCurHcb
, tar
| (lun
<< 8))) == NULL
) {
2191 return tul_msgout_abort_targ(pCurHcb
);
2193 pCurHcb
->HCS_ActScb
= pCurScb
;
2194 if (!(pCurTcb
->TCS_DrvFlags
& TCF_DRV_EN_TAG
)) {
2195 if ((tul_msgin_accept(pCurHcb
)) == -1)
2203 /***************************************************************************/
2204 static int int_tul_bad_seq(HCS
* pCurHcb
)
2205 { /* target wrong phase */
2209 tul_reset_scsi(pCurHcb
, 10);
2211 while ((pCurScb
= tul_pop_busy_scb(pCurHcb
)) != NULL
) {
2212 pCurScb
->SCB_HaStat
= HOST_BAD_PHAS
;
2213 tul_append_done_scb(pCurHcb
, pCurScb
);
2215 for (i
= 0; i
< pCurHcb
->HCS_MaxTar
; i
++) {
2216 pCurHcb
->HCS_Tcs
[i
].TCS_Flags
&= ~(TCF_SYNC_DONE
| TCF_WDTR_DONE
);
2222 /***************************************************************************/
2223 int tul_msgout_abort_targ(HCS
* pCurHcb
)
2226 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2227 if (tul_msgin_accept(pCurHcb
) == -1)
2229 if (pCurHcb
->HCS_Phase
!= MSG_OUT
)
2230 return (tul_bad_seq(pCurHcb
));
2232 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_ABORT
);
2233 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2235 return tul_wait_disc(pCurHcb
);
2238 /***************************************************************************/
2239 int tul_msgout_abort_tag(HCS
* pCurHcb
)
2242 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2243 if (tul_msgin_accept(pCurHcb
) == -1)
2245 if (pCurHcb
->HCS_Phase
!= MSG_OUT
)
2246 return (tul_bad_seq(pCurHcb
));
2248 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_ABORT_TAG
);
2249 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2251 return tul_wait_disc(pCurHcb
);
2255 /***************************************************************************/
2256 int tul_msgin(HCS
* pCurHcb
)
2262 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2264 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2265 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2266 if ((wait_tulip(pCurHcb
)) == -1)
2269 switch (TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
)) {
2270 case MSG_DISC
: /* Disconnect msg */
2271 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_MSG_ACCEPT
);
2273 return tul_wait_disc(pCurHcb
);
2278 tul_msgin_accept(pCurHcb
);
2281 case MSG_REJ
: /* Clear ATN first */
2282 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
,
2283 (TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)));
2284 pCurTcb
= pCurHcb
->HCS_ActTcs
;
2285 if ((pCurTcb
->TCS_Flags
& (TCF_SYNC_DONE
| TCF_NO_SYNC_NEGO
)) == 0) { /* do sync nego */
2286 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2288 tul_msgin_accept(pCurHcb
);
2291 case MSG_EXTEND
: /* extended msg */
2292 tul_msgin_extend(pCurHcb
);
2295 case MSG_IGNOREWIDE
:
2296 tul_msgin_accept(pCurHcb
);
2300 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2301 if (wait_tulip(pCurHcb
) == -1)
2304 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 0); /* put pad */
2305 TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
); /* get IGNORE field */
2306 TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
); /* get pad */
2308 tul_msgin_accept(pCurHcb
);
2313 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2314 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_MSG_ACCEPT
);
2315 return tul_wait_done_disc(pCurHcb
);
2318 tul_msgout_reject(pCurHcb
);
2321 if (pCurHcb
->HCS_Phase
!= MSG_IN
)
2322 return (pCurHcb
->HCS_Phase
);
2324 /* statement won't reach here */
2330 /***************************************************************************/
2331 int tul_msgout_reject(HCS
* pCurHcb
)
2334 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2336 if ((tul_msgin_accept(pCurHcb
)) == -1)
2339 if (pCurHcb
->HCS_Phase
== MSG_OUT
) {
2340 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_REJ
); /* Msg reject */
2341 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2342 return (wait_tulip(pCurHcb
));
2344 return (pCurHcb
->HCS_Phase
);
2349 /***************************************************************************/
2350 int tul_msgout_ide(HCS
* pCurHcb
)
2352 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_IDE
); /* Initiator Detected Error */
2353 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2354 return (wait_tulip(pCurHcb
));
2358 /***************************************************************************/
2359 int tul_msgin_extend(HCS
* pCurHcb
)
2363 if (tul_msgin_accept(pCurHcb
) != MSG_IN
)
2364 return (pCurHcb
->HCS_Phase
);
2366 /* Get extended msg length */
2367 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2368 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2369 if (wait_tulip(pCurHcb
) == -1)
2372 len
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
2373 pCurHcb
->HCS_Msg
[0] = len
;
2374 for (idx
= 1; len
!= 0; len
--) {
2376 if ((tul_msgin_accept(pCurHcb
)) != MSG_IN
)
2377 return (pCurHcb
->HCS_Phase
);
2378 TUL_WRLONG(pCurHcb
->HCS_Base
+ TUL_SCnt0
, 1);
2379 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_IN
);
2380 if (wait_tulip(pCurHcb
) == -1)
2382 pCurHcb
->HCS_Msg
[idx
++] = TUL_RD(pCurHcb
->HCS_Base
, TUL_SFifo
);
2384 if (pCurHcb
->HCS_Msg
[1] == 1) { /* if it's synchronous data transfer request */
2385 if (pCurHcb
->HCS_Msg
[0] != 3) /* if length is not right */
2386 return (tul_msgout_reject(pCurHcb
));
2387 if (pCurHcb
->HCS_ActTcs
->TCS_Flags
& TCF_NO_SYNC_NEGO
) { /* Set OFFSET=0 to do async, nego back */
2388 pCurHcb
->HCS_Msg
[3] = 0;
2390 if ((tul_msgin_sync(pCurHcb
) == 0) &&
2391 (pCurHcb
->HCS_ActTcs
->TCS_Flags
& TCF_SYNC_DONE
)) {
2392 tul_sync_done(pCurHcb
);
2393 return (tul_msgin_accept(pCurHcb
));
2397 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2398 if ((tul_msgin_accept(pCurHcb
)) != MSG_OUT
)
2399 return (pCurHcb
->HCS_Phase
);
2401 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
);
2403 tul_sync_done(pCurHcb
);
2405 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_EXTEND
);
2406 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 3);
2407 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 1);
2408 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurHcb
->HCS_Msg
[2]);
2409 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurHcb
->HCS_Msg
[3]);
2411 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2412 return (wait_tulip(pCurHcb
));
2414 if ((pCurHcb
->HCS_Msg
[0] != 2) || (pCurHcb
->HCS_Msg
[1] != 3))
2415 return (tul_msgout_reject(pCurHcb
));
2416 /* if it's WIDE DATA XFER REQ */
2417 if (pCurHcb
->HCS_ActTcs
->TCS_Flags
& TCF_NO_WDTR
) {
2418 pCurHcb
->HCS_Msg
[2] = 0;
2420 if (pCurHcb
->HCS_Msg
[2] > 2) /* > 32 bits */
2421 return (tul_msgout_reject(pCurHcb
));
2422 if (pCurHcb
->HCS_Msg
[2] == 2) { /* == 32 */
2423 pCurHcb
->HCS_Msg
[2] = 1;
2425 if ((pCurHcb
->HCS_ActTcs
->TCS_Flags
& TCF_NO_WDTR
) == 0) {
2427 if ((pCurHcb
->HCS_ActTcs
->TCS_Flags
& (TCF_SYNC_DONE
| TCF_NO_SYNC_NEGO
)) == 0)
2428 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2429 return (tul_msgin_accept(pCurHcb
));
2433 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SSignal
, ((TUL_RD(pCurHcb
->HCS_Base
, TUL_SSignal
) & (TSC_SET_ACK
| 7)) | TSC_SET_ATN
));
2435 if (tul_msgin_accept(pCurHcb
) != MSG_OUT
)
2436 return (pCurHcb
->HCS_Phase
);
2438 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_EXTEND
);
2439 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 2);
2440 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, 3);
2441 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurHcb
->HCS_Msg
[2]);
2442 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2443 return (wait_tulip(pCurHcb
));
2446 /***************************************************************************/
2447 int tul_msgin_sync(HCS
* pCurHcb
)
2449 char default_period
;
2451 default_period
= tul_rate_tbl
[pCurHcb
->HCS_ActTcs
->TCS_Flags
& TCF_SCSI_RATE
];
2452 if (pCurHcb
->HCS_Msg
[3] > MAX_OFFSET
) {
2453 pCurHcb
->HCS_Msg
[3] = MAX_OFFSET
;
2454 if (pCurHcb
->HCS_Msg
[2] < default_period
) {
2455 pCurHcb
->HCS_Msg
[2] = default_period
;
2458 if (pCurHcb
->HCS_Msg
[2] >= 59) { /* Change to async */
2459 pCurHcb
->HCS_Msg
[3] = 0;
2463 /* offset requests asynchronous transfers ? */
2464 if (pCurHcb
->HCS_Msg
[3] == 0) {
2467 if (pCurHcb
->HCS_Msg
[2] < default_period
) {
2468 pCurHcb
->HCS_Msg
[2] = default_period
;
2471 if (pCurHcb
->HCS_Msg
[2] >= 59) {
2472 pCurHcb
->HCS_Msg
[3] = 0;
2479 /***************************************************************************/
2480 int wdtr_done(HCS
* pCurHcb
)
2482 pCurHcb
->HCS_ActTcs
->TCS_Flags
&= ~TCF_SYNC_DONE
;
2483 pCurHcb
->HCS_ActTcs
->TCS_Flags
|= TCF_WDTR_DONE
;
2485 pCurHcb
->HCS_ActTcs
->TCS_JS_Period
= 0;
2486 if (pCurHcb
->HCS_Msg
[2]) { /* if 16 bit */
2487 pCurHcb
->HCS_ActTcs
->TCS_JS_Period
|= TSC_WIDE_SCSI
;
2489 pCurHcb
->HCS_ActTcs
->TCS_SConfig0
&= ~TSC_ALT_PERIOD
;
2490 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurHcb
->HCS_ActTcs
->TCS_SConfig0
);
2491 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SPeriod
, pCurHcb
->HCS_ActTcs
->TCS_JS_Period
);
2496 /***************************************************************************/
2497 int tul_sync_done(HCS
* pCurHcb
)
2501 pCurHcb
->HCS_ActTcs
->TCS_Flags
|= TCF_SYNC_DONE
;
2503 if (pCurHcb
->HCS_Msg
[3]) {
2504 pCurHcb
->HCS_ActTcs
->TCS_JS_Period
|= pCurHcb
->HCS_Msg
[3];
2505 for (i
= 0; i
< 8; i
++) {
2506 if (tul_rate_tbl
[i
] >= pCurHcb
->HCS_Msg
[2]) /* pick the big one */
2509 pCurHcb
->HCS_ActTcs
->TCS_JS_Period
|= (i
<< 4);
2510 pCurHcb
->HCS_ActTcs
->TCS_SConfig0
|= TSC_ALT_PERIOD
;
2512 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, pCurHcb
->HCS_ActTcs
->TCS_SConfig0
);
2513 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SPeriod
, pCurHcb
->HCS_ActTcs
->TCS_JS_Period
);
2519 int tul_post_scsi_rst(HCS
* pCurHcb
)
2525 pCurHcb
->HCS_ActScb
= NULL
;
2526 pCurHcb
->HCS_ActTcs
= NULL
;
2527 pCurHcb
->HCS_Flags
= 0;
2529 while ((pCurScb
= tul_pop_busy_scb(pCurHcb
)) != NULL
) {
2530 pCurScb
->SCB_HaStat
= HOST_BAD_PHAS
;
2531 tul_append_done_scb(pCurHcb
, pCurScb
);
2533 /* clear sync done flag */
2534 pCurTcb
= &pCurHcb
->HCS_Tcs
[0];
2535 for (i
= 0; i
< pCurHcb
->HCS_MaxTar
; pCurTcb
++, i
++) {
2536 pCurTcb
->TCS_Flags
&= ~(TCF_SYNC_DONE
| TCF_WDTR_DONE
);
2537 /* Initialize the sync. xfer register values to an asyn xfer */
2538 pCurTcb
->TCS_JS_Period
= 0;
2539 pCurTcb
->TCS_SConfig0
= pCurHcb
->HCS_SConf1
;
2540 pCurHcb
->HCS_ActTags
[0] = 0; /* 07/22/98 */
2541 pCurHcb
->HCS_Tcs
[i
].TCS_Flags
&= ~TCF_BUSY
; /* 07/22/98 */
2547 /***************************************************************************/
2548 void tul_select_atn_stop(HCS
* pCurHcb
, SCB
* pCurScb
)
2550 pCurScb
->SCB_Status
|= SCB_SELECT
;
2551 pCurScb
->SCB_NxtStat
= 0x1;
2552 pCurHcb
->HCS_ActScb
= pCurScb
;
2553 pCurHcb
->HCS_ActTcs
= &pCurHcb
->HCS_Tcs
[pCurScb
->SCB_Target
];
2554 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_SELATNSTOP
);
2559 /***************************************************************************/
2560 void tul_select_atn(HCS
* pCurHcb
, SCB
* pCurScb
)
2564 pCurScb
->SCB_Status
|= SCB_SELECT
;
2565 pCurScb
->SCB_NxtStat
= 0x2;
2567 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_Ident
);
2568 for (i
= 0; i
< (int) pCurScb
->SCB_CDBLen
; i
++)
2569 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_CDB
[i
]);
2570 pCurHcb
->HCS_ActTcs
= &pCurHcb
->HCS_Tcs
[pCurScb
->SCB_Target
];
2571 pCurHcb
->HCS_ActScb
= pCurScb
;
2572 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_SEL_ATN
);
2576 /***************************************************************************/
2577 void tul_select_atn3(HCS
* pCurHcb
, SCB
* pCurScb
)
2581 pCurScb
->SCB_Status
|= SCB_SELECT
;
2582 pCurScb
->SCB_NxtStat
= 0x2;
2584 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_Ident
);
2585 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_TagMsg
);
2586 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_TagId
);
2587 for (i
= 0; i
< (int) pCurScb
->SCB_CDBLen
; i
++)
2588 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, pCurScb
->SCB_CDB
[i
]);
2589 pCurHcb
->HCS_ActTcs
= &pCurHcb
->HCS_Tcs
[pCurScb
->SCB_Target
];
2590 pCurHcb
->HCS_ActScb
= pCurScb
;
2591 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_SEL_ATN3
);
2595 /***************************************************************************/
2596 /* SCSI Bus Device Reset */
2597 int tul_bus_device_reset(HCS
* pCurHcb
)
2599 SCB
*pCurScb
= pCurHcb
->HCS_ActScb
;
2600 TCS
*pCurTcb
= pCurHcb
->HCS_ActTcs
;
2601 SCB
*pTmpScb
, *pPrevScb
;
2604 if (pCurHcb
->HCS_Phase
!= MSG_OUT
) {
2605 return (int_tul_bad_seq(pCurHcb
)); /* Unexpected phase */
2607 tul_unlink_pend_scb(pCurHcb
, pCurScb
);
2608 tul_release_scb(pCurHcb
, pCurScb
);
2611 tar
= pCurScb
->SCB_Target
; /* target */
2612 pCurTcb
->TCS_Flags
&= ~(TCF_SYNC_DONE
| TCF_WDTR_DONE
| TCF_BUSY
);
2613 /* clr sync. nego & WDTR flags 07/22/98 */
2615 /* abort all SCB with same target */
2616 pPrevScb
= pTmpScb
= pCurHcb
->HCS_FirstBusy
; /* Check Busy queue */
2617 while (pTmpScb
!= NULL
) {
2619 if (pTmpScb
->SCB_Target
== tar
) {
2621 if (pTmpScb
== pCurHcb
->HCS_FirstBusy
) {
2622 if ((pCurHcb
->HCS_FirstBusy
= pTmpScb
->SCB_NxtScb
) == NULL
)
2623 pCurHcb
->HCS_LastBusy
= NULL
;
2625 pPrevScb
->SCB_NxtScb
= pTmpScb
->SCB_NxtScb
;
2626 if (pTmpScb
== pCurHcb
->HCS_LastBusy
)
2627 pCurHcb
->HCS_LastBusy
= pPrevScb
;
2629 pTmpScb
->SCB_HaStat
= HOST_ABORTED
;
2630 tul_append_done_scb(pCurHcb
, pTmpScb
);
2632 /* Previous haven't change */
2636 pTmpScb
= pTmpScb
->SCB_NxtScb
;
2639 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SFifo
, MSG_DEVRST
);
2640 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_XF_FIFO_OUT
);
2642 return tul_wait_disc(pCurHcb
);
2646 /***************************************************************************/
2647 int tul_msgin_accept(HCS
* pCurHcb
)
2649 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCmd
, TSC_MSG_ACCEPT
);
2650 return (wait_tulip(pCurHcb
));
2653 /***************************************************************************/
2654 int wait_tulip(HCS
* pCurHcb
)
2657 while (!((pCurHcb
->HCS_JSStatus0
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus0
))
2658 & TSS_INT_PENDING
));
2660 pCurHcb
->HCS_JSInt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
);
2661 pCurHcb
->HCS_Phase
= pCurHcb
->HCS_JSStatus0
& TSS_PH_MASK
;
2662 pCurHcb
->HCS_JSStatus1
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus1
);
2664 if (pCurHcb
->HCS_JSInt
& TSS_RESEL_INT
) { /* if SCSI bus reset detected */
2665 return (int_tul_resel(pCurHcb
));
2667 if (pCurHcb
->HCS_JSInt
& TSS_SEL_TIMEOUT
) { /* if selected/reselected timeout interrupt */
2668 return (int_tul_busfree(pCurHcb
));
2670 if (pCurHcb
->HCS_JSInt
& TSS_SCSIRST_INT
) { /* if SCSI bus reset detected */
2671 return (int_tul_scsi_rst(pCurHcb
));
2673 if (pCurHcb
->HCS_JSInt
& TSS_DISC_INT
) { /* BUS disconnection */
2674 if (pCurHcb
->HCS_Flags
& HCF_EXPECT_DONE_DISC
) {
2675 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
); /* Flush SCSI FIFO */
2676 tul_unlink_busy_scb(pCurHcb
, pCurHcb
->HCS_ActScb
);
2677 pCurHcb
->HCS_ActScb
->SCB_HaStat
= 0;
2678 tul_append_done_scb(pCurHcb
, pCurHcb
->HCS_ActScb
);
2679 pCurHcb
->HCS_ActScb
= NULL
;
2680 pCurHcb
->HCS_ActTcs
= NULL
;
2681 pCurHcb
->HCS_Flags
&= ~HCF_EXPECT_DONE_DISC
;
2682 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, TSC_INITDEFAULT
);
2683 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
); /* Enable HW reselect */
2686 if (pCurHcb
->HCS_Flags
& HCF_EXPECT_DISC
) {
2687 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
); /* Flush SCSI FIFO */
2688 pCurHcb
->HCS_ActScb
= NULL
;
2689 pCurHcb
->HCS_ActTcs
= NULL
;
2690 pCurHcb
->HCS_Flags
&= ~HCF_EXPECT_DISC
;
2691 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, TSC_INITDEFAULT
);
2692 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
); /* Enable HW reselect */
2695 return (int_tul_busfree(pCurHcb
));
2697 if (pCurHcb
->HCS_JSInt
& (TSS_FUNC_COMP
| TSS_BUS_SERV
)) {
2698 return (pCurHcb
->HCS_Phase
);
2700 return (pCurHcb
->HCS_Phase
);
2702 /***************************************************************************/
2703 int tul_wait_disc(HCS
* pCurHcb
)
2706 while (!((pCurHcb
->HCS_JSStatus0
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus0
))
2707 & TSS_INT_PENDING
));
2710 pCurHcb
->HCS_JSInt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
);
2712 if (pCurHcb
->HCS_JSInt
& TSS_SCSIRST_INT
) { /* if SCSI bus reset detected */
2713 return (int_tul_scsi_rst(pCurHcb
));
2715 if (pCurHcb
->HCS_JSInt
& TSS_DISC_INT
) { /* BUS disconnection */
2716 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
); /* Flush SCSI FIFO */
2717 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, TSC_INITDEFAULT
);
2718 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
); /* Enable HW reselect */
2719 pCurHcb
->HCS_ActScb
= NULL
;
2722 return (tul_bad_seq(pCurHcb
));
2725 /***************************************************************************/
2726 int tul_wait_done_disc(HCS
* pCurHcb
)
2730 while (!((pCurHcb
->HCS_JSStatus0
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SStatus0
))
2731 & TSS_INT_PENDING
));
2733 pCurHcb
->HCS_JSInt
= TUL_RD(pCurHcb
->HCS_Base
, TUL_SInt
);
2736 if (pCurHcb
->HCS_JSInt
& TSS_SCSIRST_INT
) { /* if SCSI bus reset detected */
2737 return (int_tul_scsi_rst(pCurHcb
));
2739 if (pCurHcb
->HCS_JSInt
& TSS_DISC_INT
) { /* BUS disconnection */
2740 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl0
, TSC_FLUSH_FIFO
); /* Flush SCSI FIFO */
2741 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SConfig
, TSC_INITDEFAULT
);
2742 TUL_WR(pCurHcb
->HCS_Base
+ TUL_SCtrl1
, TSC_HW_RESELECT
); /* Enable HW reselect */
2743 tul_unlink_busy_scb(pCurHcb
, pCurHcb
->HCS_ActScb
);
2745 tul_append_done_scb(pCurHcb
, pCurHcb
->HCS_ActScb
);
2746 pCurHcb
->HCS_ActScb
= NULL
;
2749 return (tul_bad_seq(pCurHcb
));
2752 static irqreturn_t
i91u_intr(int irqno
, void *dev_id
, struct pt_regs
*regs
)
2754 struct Scsi_Host
*dev
= dev_id
;
2755 unsigned long flags
;
2757 spin_lock_irqsave(dev
->host_lock
, flags
);
2758 tul_isr((HCS
*)dev
->base
);
2759 spin_unlock_irqrestore(dev
->host_lock
, flags
);
2763 static int tul_NewReturnNumberOfAdapters(void)
2765 struct pci_dev
*pDev
= NULL
; /* Start from none */
2771 init_i91uAdapter_table();
2773 for (i
= 0; i
< ARRAY_SIZE(i91u_pci_devices
); i
++)
2775 while ((pDev
= pci_find_device(i91u_pci_devices
[i
].vendor_id
, i91u_pci_devices
[i
].device_id
, pDev
)) != NULL
) {
2776 if (pci_enable_device(pDev
))
2778 pci_read_config_dword(pDev
, 0x44, (u32
*) & dRegValue
);
2779 wBIOS
= (UWORD
) (dRegValue
& 0xFF);
2780 if (((dRegValue
& 0xFF00) >> 8) == 0xFF)
2782 wBIOS
= (wBIOS
<< 8) + ((UWORD
) ((dRegValue
& 0xFF00) >> 8));
2783 if (pci_set_dma_mask(pDev
, DMA_32BIT_MASK
)) {
2785 "i91u: Could not set 32 bit DMA mask\n");
2789 if (Addi91u_into_Adapter_table(wBIOS
,
2790 (pDev
->resource
[0].start
),
2802 static int i91u_detect(struct scsi_host_template
* tpnt
)
2805 struct Scsi_Host
*hreg
;
2806 unsigned long i
; /* 01/14/98 */
2807 int ok
= 0, iAdapters
;
2811 /* Get total number of adapters in the motherboard */
2812 iAdapters
= tul_NewReturnNumberOfAdapters();
2813 if (iAdapters
== 0) /* If no tulip founded, return */
2816 tul_num_ch
= (iAdapters
> tul_num_ch
) ? tul_num_ch
: iAdapters
;
2817 /* Update actually channel number */
2818 if (tul_tag_enable
) { /* 1.01i */
2819 tul_num_scb
= MAX_TARGETS
* i91u_MAXQUEUE
;
2821 tul_num_scb
= MAX_TARGETS
+ 3; /* 1-tape, 1-CD_ROM, 1- extra */
2822 } /* Update actually SCBs per adapter */
2824 /* Get total memory needed for HCS */
2825 i
= tul_num_ch
* sizeof(HCS
);
2826 memset((unsigned char *) &tul_hcs
[0], 0, i
); /* Initialize tul_hcs 0 */
2827 /* Get total memory needed for SCB */
2829 for (; tul_num_scb
>= MAX_TARGETS
+ 3; tul_num_scb
--) {
2830 i
= tul_num_ch
* tul_num_scb
* sizeof(SCB
);
2831 if ((tul_scb
= (SCB
*) kmalloc(i
, GFP_ATOMIC
| GFP_DMA
)) != NULL
)
2834 if (tul_scb
== NULL
) {
2835 printk("i91u: SCB memory allocation error\n");
2838 memset((unsigned char *) tul_scb
, 0, i
);
2840 for (i
= 0, pHCB
= &tul_hcs
[0]; /* Get pointer for control block */
2843 get_tulipPCIConfig(pHCB
, i
);
2845 dBiosAdr
= pHCB
->HCS_BIOS
;
2846 dBiosAdr
= (dBiosAdr
<< 4);
2848 pbBiosAdr
= phys_to_virt(dBiosAdr
);
2850 init_tulip(pHCB
, tul_scb
+ (i
* tul_num_scb
), tul_num_scb
, pbBiosAdr
, 10);
2851 request_region(pHCB
->HCS_Base
, 256, "i91u"); /* Register */
2853 pHCB
->HCS_Index
= i
; /* 7/29/98 */
2854 hreg
= scsi_register(tpnt
, sizeof(HCS
));
2856 release_region(pHCB
->HCS_Base
, 256);
2859 hreg
->io_port
= pHCB
->HCS_Base
;
2860 hreg
->n_io_port
= 0xff;
2861 hreg
->can_queue
= tul_num_scb
; /* 03/05/98 */
2862 hreg
->unique_id
= pHCB
->HCS_Base
;
2863 hreg
->max_id
= pHCB
->HCS_MaxTar
;
2864 hreg
->max_lun
= 32; /* 10/21/97 */
2865 hreg
->irq
= pHCB
->HCS_Intr
;
2866 hreg
->this_id
= pHCB
->HCS_SCSI_ID
; /* Assign HCS index */
2867 hreg
->base
= (unsigned long)pHCB
;
2868 hreg
->sg_tablesize
= TOTAL_SG_ENTRY
; /* Maximun support is 32 */
2870 /* Initial tulip chip */
2871 ok
= request_irq(pHCB
->HCS_Intr
, i91u_intr
, SA_INTERRUPT
| SA_SHIRQ
, "i91u", hreg
);
2873 printk(KERN_WARNING
"i91u: unable to request IRQ %d\n\n", pHCB
->HCS_Intr
);
2879 tpnt
->can_queue
= 1;
2884 static void i91uBuildSCB(HCS
* pHCB
, SCB
* pSCB
, struct scsi_cmnd
* SCpnt
)
2885 { /* Create corresponding SCB */
2886 struct scatterlist
*pSrbSG
;
2887 SG
*pSG
; /* Pointer to SG list */
2890 dma_addr_t dma_addr
;
2892 pSCB
->SCB_Post
= i91uSCBPost
; /* i91u's callback routine */
2893 pSCB
->SCB_Srb
= SCpnt
;
2894 pSCB
->SCB_Opcode
= ExecSCSI
;
2895 pSCB
->SCB_Flags
= SCF_POST
; /* After SCSI done, call post routine */
2896 pSCB
->SCB_Target
= SCpnt
->device
->id
;
2897 pSCB
->SCB_Lun
= SCpnt
->device
->lun
;
2898 pSCB
->SCB_Ident
= SCpnt
->device
->lun
| DISC_ALLOW
;
2900 pSCB
->SCB_Flags
|= SCF_SENSE
; /* Turn on auto request sense */
2901 dma_addr
= dma_map_single(&pHCB
->pci_dev
->dev
, SCpnt
->sense_buffer
,
2902 SENSE_SIZE
, DMA_FROM_DEVICE
);
2903 pSCB
->SCB_SensePtr
= cpu_to_le32((u32
)dma_addr
);
2904 pSCB
->SCB_SenseLen
= cpu_to_le32(SENSE_SIZE
);
2905 SCpnt
->SCp
.ptr
= (char *)(unsigned long)dma_addr
;
2907 pSCB
->SCB_CDBLen
= SCpnt
->cmd_len
;
2908 pSCB
->SCB_HaStat
= 0;
2909 pSCB
->SCB_TaStat
= 0;
2910 memcpy(&pSCB
->SCB_CDB
[0], &SCpnt
->cmnd
, SCpnt
->cmd_len
);
2912 if (SCpnt
->device
->tagged_supported
) { /* Tag Support */
2913 pSCB
->SCB_TagMsg
= SIMPLE_QUEUE_TAG
; /* Do simple tag only */
2915 pSCB
->SCB_TagMsg
= 0; /* No tag support */
2917 /* todo handle map_sg error */
2918 if (SCpnt
->use_sg
) {
2919 dma_addr
= dma_map_single(&pHCB
->pci_dev
->dev
, &pSCB
->SCB_SGList
[0],
2920 sizeof(struct SG_Struc
) * TOTAL_SG_ENTRY
,
2922 pSCB
->SCB_BufPtr
= cpu_to_le32((u32
)dma_addr
);
2923 SCpnt
->SCp
.dma_handle
= dma_addr
;
2925 pSrbSG
= (struct scatterlist
*) SCpnt
->request_buffer
;
2926 pSCB
->SCB_SGLen
= dma_map_sg(&pHCB
->pci_dev
->dev
, pSrbSG
,
2927 SCpnt
->use_sg
, SCpnt
->sc_data_direction
);
2929 pSCB
->SCB_Flags
|= SCF_SG
; /* Turn on SG list flag */
2930 for (i
= 0, TotalLen
= 0, pSG
= &pSCB
->SCB_SGList
[0]; /* 1.01g */
2931 i
< pSCB
->SCB_SGLen
; i
++, pSG
++, pSrbSG
++) {
2932 pSG
->SG_Ptr
= cpu_to_le32((u32
)sg_dma_address(pSrbSG
));
2933 TotalLen
+= pSG
->SG_Len
= cpu_to_le32((u32
)sg_dma_len(pSrbSG
));
2936 pSCB
->SCB_BufLen
= (SCpnt
->request_bufflen
> TotalLen
) ?
2937 TotalLen
: SCpnt
->request_bufflen
;
2938 } else if (SCpnt
->request_bufflen
) { /* Non SG */
2939 dma_addr
= dma_map_single(&pHCB
->pci_dev
->dev
, SCpnt
->request_buffer
,
2940 SCpnt
->request_bufflen
,
2941 SCpnt
->sc_data_direction
);
2942 SCpnt
->SCp
.dma_handle
= dma_addr
;
2943 pSCB
->SCB_BufPtr
= cpu_to_le32((u32
)dma_addr
);
2944 pSCB
->SCB_BufLen
= cpu_to_le32((u32
)SCpnt
->request_bufflen
);
2945 pSCB
->SCB_SGLen
= 0;
2947 pSCB
->SCB_BufLen
= 0;
2948 pSCB
->SCB_SGLen
= 0;
2952 static int i91u_queuecommand(struct scsi_cmnd
*cmd
,
2953 void (*done
)(struct scsi_cmnd
*))
2955 HCS
*pHCB
= (HCS
*) cmd
->device
->host
->base
;
2958 cmd
->scsi_done
= done
;
2960 pSCB
= tul_alloc_scb(pHCB
);
2962 return SCSI_MLQUEUE_HOST_BUSY
;
2964 i91uBuildSCB(pHCB
, pSCB
, cmd
);
2965 tul_exec_scb(pHCB
, pSCB
);
2969 #if 0 /* no new EH yet */
2971 * Abort a queued command
2972 * (commands that are on the bus can't be aborted easily)
2974 static int i91u_abort(struct scsi_cmnd
* SCpnt
)
2978 pHCB
= (HCS
*) SCpnt
->device
->host
->base
;
2979 return tul_abort_srb(pHCB
, SCpnt
);
2983 * Reset registers, reset a hanging bus and
2984 * kill active and disconnected commands for target w/o soft reset
2986 static int i91u_reset(struct scsi_cmnd
* SCpnt
, unsigned int reset_flags
)
2987 { /* I need Host Control Block Information */
2990 pHCB
= (HCS
*) SCpnt
->device
->host
->base
;
2992 if (reset_flags
& (SCSI_RESET_SUGGEST_BUS_RESET
| SCSI_RESET_SUGGEST_HOST_RESET
))
2993 return tul_reset_scsi_bus(pHCB
);
2995 return tul_device_reset(pHCB
, SCpnt
, SCpnt
->device
->id
, reset_flags
);
2999 static int i91u_bus_reset(struct scsi_cmnd
* SCpnt
)
3003 pHCB
= (HCS
*) SCpnt
->device
->host
->base
;
3005 spin_lock_irq(SCpnt
->device
->host
->host_lock
);
3006 tul_reset_scsi(pHCB
, 0);
3007 spin_unlock_irq(SCpnt
->device
->host
->host_lock
);
3013 * Return the "logical geometry"
3015 static int i91u_biosparam(struct scsi_device
*sdev
, struct block_device
*dev
,
3016 sector_t capacity
, int *info_array
)
3018 HCS
*pHcb
; /* Point to Host adapter control block */
3021 pHcb
= (HCS
*) sdev
->host
->base
;
3022 pTcb
= &pHcb
->HCS_Tcs
[sdev
->id
];
3024 if (pTcb
->TCS_DrvHead
) {
3025 info_array
[0] = pTcb
->TCS_DrvHead
;
3026 info_array
[1] = pTcb
->TCS_DrvSector
;
3027 info_array
[2] = (unsigned long)capacity
/ pTcb
->TCS_DrvHead
/ pTcb
->TCS_DrvSector
;
3029 if (pTcb
->TCS_DrvFlags
& TCF_DRV_255_63
) {
3030 info_array
[0] = 255;
3032 info_array
[2] = (unsigned long)capacity
/ 255 / 63;
3036 info_array
[2] = (unsigned long)capacity
>> 11;
3040 #if defined(DEBUG_BIOSPARAM)
3041 if (i91u_debug
& debug_biosparam
) {
3042 printk("bios geometry: head=%d, sec=%d, cyl=%d\n",
3043 info_array
[0], info_array
[1], info_array
[2]);
3044 printk("WARNING: check, if the bios geometry is correct.\n");
3051 static void i91u_unmap_cmnd(struct pci_dev
*pci_dev
, struct scsi_cmnd
*cmnd
)
3053 /* auto sense buffer */
3054 if (cmnd
->SCp
.ptr
) {
3055 dma_unmap_single(&pci_dev
->dev
,
3056 (dma_addr_t
)((unsigned long)cmnd
->SCp
.ptr
),
3057 SENSE_SIZE
, DMA_FROM_DEVICE
);
3058 cmnd
->SCp
.ptr
= NULL
;
3061 /* request buffer */
3063 dma_unmap_single(&pci_dev
->dev
, cmnd
->SCp
.dma_handle
,
3064 sizeof(struct SG_Struc
) * TOTAL_SG_ENTRY
,
3067 dma_unmap_sg(&pci_dev
->dev
, cmnd
->request_buffer
,
3069 cmnd
->sc_data_direction
);
3070 } else if (cmnd
->request_bufflen
) {
3071 dma_unmap_single(&pci_dev
->dev
, cmnd
->SCp
.dma_handle
,
3072 cmnd
->request_bufflen
,
3073 cmnd
->sc_data_direction
);
3077 /*****************************************************************************
3078 Function name : i91uSCBPost
3079 Description : This is callback routine be called when tulip finish one
3081 Input : pHCB - Pointer to host adapter control block.
3082 pSCB - Pointer to SCSI control block.
3085 *****************************************************************************/
3086 static void i91uSCBPost(BYTE
* pHcb
, BYTE
* pScb
)
3088 struct scsi_cmnd
*pSRB
; /* Pointer to SCSI request block */
3092 pHCB
= (HCS
*) pHcb
;
3093 pSCB
= (SCB
*) pScb
;
3094 if ((pSRB
= pSCB
->SCB_Srb
) == 0) {
3095 printk("i91uSCBPost: SRB pointer is empty\n");
3097 tul_release_scb(pHCB
, pSCB
); /* Release SCB for current channel */
3100 switch (pSCB
->SCB_HaStat
) {
3102 case 0xa: /* Linked command complete without error and linked normally */
3103 case 0xb: /* Linked command complete without error interrupt generated */
3104 pSCB
->SCB_HaStat
= 0;
3107 case 0x11: /* Selection time out-The initiator selection or target
3108 reselection was not complete within the SCSI Time out period */
3109 pSCB
->SCB_HaStat
= DID_TIME_OUT
;
3112 case 0x14: /* Target bus phase sequence failure-An invalid bus phase or bus
3113 phase sequence was requested by the target. The host adapter
3114 will generate a SCSI Reset Condition, notifying the host with
3116 pSCB
->SCB_HaStat
= DID_RESET
;
3119 case 0x1a: /* SCB Aborted. 07/21/98 */
3120 pSCB
->SCB_HaStat
= DID_ABORT
;
3123 case 0x12: /* Data overrun/underrun-The target attempted to transfer more data
3124 than was allocated by the Data Length field or the sum of the
3125 Scatter / Gather Data Length fields. */
3126 case 0x13: /* Unexpected bus free-The target dropped the SCSI BSY at an unexpected time. */
3127 case 0x16: /* Invalid SCB Operation Code. */
3130 printk("ini9100u: %x %x\n", pSCB
->SCB_HaStat
, pSCB
->SCB_TaStat
);
3131 pSCB
->SCB_HaStat
= DID_ERROR
; /* Couldn't find any better */
3135 pSRB
->result
= pSCB
->SCB_TaStat
| (pSCB
->SCB_HaStat
<< 16);
3138 printk("pSRB is NULL\n");
3141 i91u_unmap_cmnd(pHCB
->pci_dev
, pSRB
);
3142 pSRB
->scsi_done(pSRB
); /* Notify system DONE */
3144 tul_release_scb(pHCB
, pSCB
); /* Release SCB for current channel */
3148 * Release ressources
3150 static int i91u_release(struct Scsi_Host
*hreg
)
3152 free_irq(hreg
->irq
, hreg
);
3153 release_region(hreg
->io_port
, 256);
3156 MODULE_LICENSE("Dual BSD/GPL");
3158 static struct scsi_host_template driver_template
= {
3159 .proc_name
= "INI9100U",
3161 .detect
= i91u_detect
,
3162 .release
= i91u_release
,
3163 .queuecommand
= i91u_queuecommand
,
3164 // .abort = i91u_abort,
3165 // .reset = i91u_reset,
3166 .eh_bus_reset_handler
= i91u_bus_reset
,
3167 .bios_param
= i91u_biosparam
,
3170 .sg_tablesize
= SG_ALL
,
3172 .use_clustering
= ENABLE_CLUSTERING
,
3174 #include "scsi_module.c"