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