1/**************************************************************************
2 * Initio 9100 device driver for Linux.
3 *
4 * Copyright (c) 1994-1998 Initio Corporation
5 * Copyright (c) 1998 Bas Vermeulen <bvermeul@blackstar.xs4all.nl>
6 * All rights reserved.
7 *
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.
12 *
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.
17 *
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.
21 *
22 * --------------------------------------------------------------------------
23 *
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.
35 *
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.
42 *
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.
54 *
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**********************************************************************/
76
77#define DEBUG_INTERRUPT 0
78#define DEBUG_QUEUE     0
79#define DEBUG_STATE     0
80#define INT_DISC	0
81
82
83#ifndef CVT_LINUX_VERSION
84#define	CVT_LINUX_VERSION(V,P,S)	(V * 65536 + P * 256 + S)
85#endif
86
87#ifndef LINUX_VERSION_CODE
88#include <linux/version.h>
89#endif
90
91#include <linux/sched.h>
92#include <linux/delay.h>
93#include <linux/blk.h>
94#include <asm/io.h>
95
96#include "i91uscsi.h"
97
98/*--- external functions --*/
99static void tul_se2_wait(void);
100
101/*--- forward refrence ---*/
102static SCB *tul_find_busy_scb(HCS * pCurHcb, WORD tarlun);
103static SCB *tul_find_done_scb(HCS * pCurHcb);
104
105static int tulip_main(HCS * pCurHcb);
106
107static int tul_next_state(HCS * pCurHcb);
108static int tul_state_1(HCS * pCurHcb);
109static int tul_state_2(HCS * pCurHcb);
110static int tul_state_3(HCS * pCurHcb);
111static int tul_state_4(HCS * pCurHcb);
112static int tul_state_5(HCS * pCurHcb);
113static int tul_state_6(HCS * pCurHcb);
114static int tul_state_7(HCS * pCurHcb);
115static int tul_xfer_data_in(HCS * pCurHcb);
116static int tul_xfer_data_out(HCS * pCurHcb);
117static int tul_xpad_in(HCS * pCurHcb);
118static int tul_xpad_out(HCS * pCurHcb);
119static int tul_status_msg(HCS * pCurHcb);
120
121static int tul_msgin(HCS * pCurHcb);
122static int tul_msgin_sync(HCS * pCurHcb);
123static int tul_msgin_accept(HCS * pCurHcb);
124static int tul_msgout_reject(HCS * pCurHcb);
125static int tul_msgin_extend(HCS * pCurHcb);
126
127static int tul_msgout_ide(HCS * pCurHcb);
128static int tul_msgout_abort_targ(HCS * pCurHcb);
129static int tul_msgout_abort_tag(HCS * pCurHcb);
130
131static int tul_bus_device_reset(HCS * pCurHcb);
132static void tul_select_atn(HCS * pCurHcb, SCB * pCurScb);
133static void tul_select_atn3(HCS * pCurHcb, SCB * pCurScb);
134static void tul_select_atn_stop(HCS * pCurHcb, SCB * pCurScb);
135static int int_tul_busfree(HCS * pCurHcb);
136int int_tul_scsi_rst(HCS * pCurHcb);
137static int int_tul_bad_seq(HCS * pCurHcb);
138static int int_tul_resel(HCS * pCurHcb);
139static int tul_sync_done(HCS * pCurHcb);
140static int wdtr_done(HCS * pCurHcb);
141static int wait_tulip(HCS * pCurHcb);
142static int tul_wait_done_disc(HCS * pCurHcb);
143static int tul_wait_disc(HCS * pCurHcb);
144static void tulip_scsi(HCS * pCurHcb);
145static int tul_post_scsi_rst(HCS * pCurHcb);
146
147static void tul_se2_ew_en(WORD CurBase);
148static void tul_se2_ew_ds(WORD CurBase);
149static int tul_se2_rd_all(WORD CurBase);
150static void tul_se2_update_all(WORD CurBase);	/* setup default pattern */
151static void tul_read_eeprom(WORD CurBase);
152
153				/* ---- EXTERNAL VARIABLES ---- */
154HCS tul_hcs[MAX_SUPPORTED_ADAPTERS];
155				/* ---- INTERNAL VARIABLES ---- */
156static INI_ADPT_STRUCT i91u_adpt[MAX_SUPPORTED_ADAPTERS];
157
158/*NVRAM nvram, *nvramp = &nvram; */
159static NVRAM i91unvram;
160static NVRAM *i91unvramp;
161
162
163
164static UCHAR i91udftNvRam[64] =
165{
166/*----------- header -----------*/
167	0x25, 0xc9,		/* Signature    */
168	0x40,			/* Size         */
169	0x01,			/* Revision     */
170	/* -- Host Adapter Structure -- */
171	0x95,			/* ModelByte0   */
172	0x00,			/* ModelByte1   */
173	0x00,			/* ModelInfo    */
174	0x01,			/* NumOfCh      */
175	NBC1_DEFAULT,		/* BIOSConfig1  */
176	0,			/* BIOSConfig2  */
177	0,			/* HAConfig1    */
178	0,			/* HAConfig2    */
179	/* SCSI channel 0 and target Structure  */
180	7,			/* SCSIid       */
181	NCC1_DEFAULT,		/* SCSIconfig1  */
182	0,			/* SCSIconfig2  */
183	0x10,			/* NumSCSItarget */
184
185	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
186	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
187	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
188	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
189
190	/* SCSI channel 1 and target Structure  */
191	7,			/* SCSIid       */
192	NCC1_DEFAULT,		/* SCSIconfig1  */
193	0,			/* SCSIconfig2  */
194	0x10,			/* NumSCSItarget */
195
196	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
197	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
198	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
199	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
200	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
201	0, 0};			/*      - CheckSum -            */
202
203
204static UCHAR tul_rate_tbl[8] =	/* fast 20      */
205{
206				/* nanosecond devide by 4 */
207	12,			/* 50ns,  20M   */
208	18,			/* 75ns,  13.3M */
209	25,			/* 100ns, 10M   */
210	31,			/* 125ns, 8M    */
211	37,			/* 150ns, 6.6M  */
212	43,			/* 175ns, 5.7M  */
213	50,			/* 200ns, 5M    */
214	62			/* 250ns, 4M    */
215};
216
217extern int tul_num_ch;
218
219
220static void tul_do_pause(unsigned amount)
221{				/* Pause for amount jiffies */
222	unsigned long the_time = jiffies + amount;
223
224#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
225	while (time_before_eq(jiffies, the_time));
226#else
227	while (jiffies < the_time);
228#endif
229}
230
231/*-- forward reference --*/
232
233/*******************************************************************
234	Use memeory refresh time        ~ 15us * 2
235********************************************************************/
236void tul_se2_wait()
237{
238	udelay(30);
239}
240
241
242/******************************************************************
243 Input: instruction for  Serial E2PROM
244
245 EX: se2_rd(0 call se2_instr() to send address and read command
246
247	 StartBit  OP_Code   Address                Data
248	 --------- --------  ------------------     -------
249	 1         1 , 0     A5,A4,A3,A2,A1,A0      D15-D0
250
251		 +-----------------------------------------------------
252		 |
253 CS -----+
254			+--+  +--+  +--+  +--+  +--+
255			^  |  ^  |  ^  |  ^  |  ^  |
256			|  |  |  |  |  |  |  |  |  |
257 CLK -------+  +--+  +--+  +--+  +--+  +--
258 (leading edge trigger)
259
260		 +--1-----1--+
261		 | SB    OP  |  OP    A5    A4
262 DI  ----+           +--0------------------
263 (address and cmd sent to nvram)
264
265	 -------------------------------------------+
266												|
267 DO                                             +---
268 (data sent from nvram)
269
270
271******************************************************************/
272void tul_se2_instr(WORD CurBase, UCHAR instr)
273{
274	int i;
275	UCHAR b;
276
277	TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2DO);	/* cs+start bit */
278	tul_se2_wait();
279	TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK | SE2DO);	/* +CLK */
280	tul_se2_wait();
281
282	for (i = 0; i < 8; i++) {
283		if (instr & 0x80)
284			b = SE2CS | SE2DO;	/* -CLK+dataBit */
285		else
286			b = SE2CS;	/* -CLK */
287		TUL_WR(CurBase + TUL_NVRAM, b);
288		tul_se2_wait();
289		TUL_WR(CurBase + TUL_NVRAM, b | SE2CLK);	/* +CLK */
290		tul_se2_wait();
291		instr <<= 1;
292	}
293	TUL_WR(CurBase + TUL_NVRAM, SE2CS);	/* -CLK */
294	tul_se2_wait();
295	return;
296}
297
298
299/******************************************************************
300 Function name  : tul_se2_ew_en
301 Description    : Enable erase/write state of serial EEPROM
302******************************************************************/
303void tul_se2_ew_en(WORD CurBase)
304{
305	tul_se2_instr(CurBase, 0x30);	/* EWEN */
306	TUL_WR(CurBase + TUL_NVRAM, 0);		/* -CS  */
307	tul_se2_wait();
308	return;
309}
310
311
312/************************************************************************
313 Disable erase/write state of serial EEPROM
314*************************************************************************/
315void tul_se2_ew_ds(WORD CurBase)
316{
317	tul_se2_instr(CurBase, 0);	/* EWDS */
318	TUL_WR(CurBase + TUL_NVRAM, 0);		/* -CS  */
319	tul_se2_wait();
320	return;
321}
322
323
324/******************************************************************
325	Input  :address of Serial E2PROM
326	Output :value stored in  Serial E2PROM
327*******************************************************************/
328USHORT tul_se2_rd(WORD CurBase, ULONG adr)
329{
330	UCHAR instr, readByte;
331	USHORT readWord;
332	int i;
333
334	instr = (UCHAR) (adr | 0x80);
335	tul_se2_instr(CurBase, instr);	/* READ INSTR */
336	readWord = 0;
337
338	for (i = 15; i >= 0; i--) {
339		TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK);	/* +CLK */
340		tul_se2_wait();
341		TUL_WR(CurBase + TUL_NVRAM, SE2CS);	/* -CLK */
342
343		/* sample data after the following edge of clock  */
344		readByte = TUL_RD(CurBase, TUL_NVRAM);
345		readByte &= SE2DI;
346		readWord += (readByte << i);
347		tul_se2_wait();	/* 6/20/95 */
348	}
349
350	TUL_WR(CurBase + TUL_NVRAM, 0);		/* no chip select */
351	tul_se2_wait();
352	return readWord;
353}
354
355
356/******************************************************************
357 Input: new value in  Serial E2PROM, address of Serial E2PROM
358*******************************************************************/
359void tul_se2_wr(WORD CurBase, UCHAR adr, USHORT writeWord)
360{
361	UCHAR readByte;
362	UCHAR instr;
363	int i;
364
365	instr = (UCHAR) (adr | 0x40);
366	tul_se2_instr(CurBase, instr);	/* WRITE INSTR */
367	for (i = 15; i >= 0; i--) {
368		if (writeWord & 0x8000)
369			TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2DO);	/* -CLK+dataBit 1 */
370		else
371			TUL_WR(CurBase + TUL_NVRAM, SE2CS);	/* -CLK+dataBit 0 */
372		tul_se2_wait();
373		TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK);	/* +CLK */
374		tul_se2_wait();
375		writeWord <<= 1;
376	}
377	TUL_WR(CurBase + TUL_NVRAM, SE2CS);	/* -CLK */
378	tul_se2_wait();
379	TUL_WR(CurBase + TUL_NVRAM, 0);		/* -CS  */
380	tul_se2_wait();
381
382	TUL_WR(CurBase + TUL_NVRAM, SE2CS);	/* +CS  */
383	tul_se2_wait();
384
385	for (;;) {
386		TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK);	/* +CLK */
387		tul_se2_wait();
388		TUL_WR(CurBase + TUL_NVRAM, SE2CS);	/* -CLK */
389		tul_se2_wait();
390		if ((readByte = TUL_RD(CurBase, TUL_NVRAM)) & SE2DI)
391			break;	/* write complete */
392	}
393	TUL_WR(CurBase + TUL_NVRAM, 0);		/* -CS */
394	return;
395}
396
397
398/***********************************************************************
399 Read SCSI H/A configuration parameters from serial EEPROM
400************************************************************************/
401int tul_se2_rd_all(WORD CurBase)
402{
403	int i;
404	ULONG chksum = 0;
405	USHORT *np;
406
407	i91unvramp = &i91unvram;
408	np = (USHORT *) i91unvramp;
409	for (i = 0; i < 32; i++) {
410		*np++ = tul_se2_rd(CurBase, i);
411	}
412
413/*--------------------Is signature "ini" ok ? ----------------*/
414	if (i91unvramp->NVM_Signature != INI_SIGNATURE)
415		return -1;
416/*---------------------- Is ckecksum ok ? ----------------------*/
417	np = (USHORT *) i91unvramp;
418	for (i = 0; i < 31; i++)
419		chksum += *np++;
420	if (i91unvramp->NVM_CheckSum != (USHORT) chksum)
421		return -1;
422	return 1;
423}
424
425
426/***********************************************************************
427 Update SCSI H/A configuration parameters from serial EEPROM
428************************************************************************/
429void tul_se2_update_all(WORD CurBase)
430{				/* setup default pattern */
431	int i;
432	ULONG chksum = 0;
433	USHORT *np, *np1;
434
435	i91unvramp = &i91unvram;
436	/* Calculate checksum first */
437	np = (USHORT *) i91udftNvRam;
438	for (i = 0; i < 31; i++)
439		chksum += *np++;
440	*np = (USHORT) chksum;
441	tul_se2_ew_en(CurBase);	/* Enable write  */
442
443	np = (USHORT *) i91udftNvRam;
444	np1 = (USHORT *) i91unvramp;
445	for (i = 0; i < 32; i++, np++, np1++) {
446		if (*np != *np1) {
447			tul_se2_wr(CurBase, i, *np);
448		}
449	}
450
451	tul_se2_ew_ds(CurBase);	/* Disable write   */
452	return;
453}
454
455/*************************************************************************
456 Function name  : read_eeprom
457**************************************************************************/
458void tul_read_eeprom(WORD CurBase)
459{
460	UCHAR gctrl;
461
462	i91unvramp = &i91unvram;
463/*------Enable EEProm programming ---*/
464	gctrl = TUL_RD(CurBase, TUL_GCTRL);
465	TUL_WR(CurBase + TUL_GCTRL, gctrl | TUL_GCTRL_EEPROM_BIT);
466	if (tul_se2_rd_all(CurBase) != 1) {
467		tul_se2_update_all(CurBase);	/* setup default pattern */
468		tul_se2_rd_all(CurBase);	/* load again  */
469	}
470/*------ Disable EEProm programming ---*/
471	gctrl = TUL_RD(CurBase, TUL_GCTRL);
472	TUL_WR(CurBase + TUL_GCTRL, gctrl & ~TUL_GCTRL_EEPROM_BIT);
473}				/* read_eeprom */
474
475int Addi91u_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt,
476			       BYTE bBus, BYTE bDevice)
477{
478	int i, j;
479
480	for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) {
481		if (i91u_adpt[i].ADPT_BIOS < wBIOS)
482			continue;
483		if (i91u_adpt[i].ADPT_BIOS == wBIOS) {
484			if (i91u_adpt[i].ADPT_BASE == wBASE) {
485				if (i91u_adpt[i].ADPT_Bus != 0xFF)
486					return (FAILURE);
487			} else if (i91u_adpt[i].ADPT_BASE < wBASE)
488					continue;
489		}
490		for (j = MAX_SUPPORTED_ADAPTERS - 1; j > i; j--) {
491			i91u_adpt[j].ADPT_BASE = i91u_adpt[j - 1].ADPT_BASE;
492			i91u_adpt[j].ADPT_INTR = i91u_adpt[j - 1].ADPT_INTR;
493			i91u_adpt[j].ADPT_BIOS = i91u_adpt[j - 1].ADPT_BIOS;
494			i91u_adpt[j].ADPT_Bus = i91u_adpt[j - 1].ADPT_Bus;
495			i91u_adpt[j].ADPT_Device = i91u_adpt[j - 1].ADPT_Device;
496		}
497		i91u_adpt[i].ADPT_BASE = wBASE;
498		i91u_adpt[i].ADPT_INTR = bInterrupt;
499		i91u_adpt[i].ADPT_BIOS = wBIOS;
500		i91u_adpt[i].ADPT_Bus = bBus;
501		i91u_adpt[i].ADPT_Device = bDevice;
502		return (SUCCESSFUL);
503	}
504	return (FAILURE);
505}
506
507void init_i91uAdapter_table(void)
508{
509	int i;
510
511	for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) {	/* Initialize adapter structure */
512		i91u_adpt[i].ADPT_BIOS = 0xffff;
513		i91u_adpt[i].ADPT_BASE = 0xffff;
514		i91u_adpt[i].ADPT_INTR = 0xff;
515		i91u_adpt[i].ADPT_Bus = 0xff;
516		i91u_adpt[i].ADPT_Device = 0xff;
517	}
518	return;
519}
520
521void tul_stop_bm(HCS * pCurHcb)
522{
523
524	if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) {	/* if DMA xfer is pending, abort DMA xfer */
525		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO);
526		/* wait Abort DMA xfer done */
527		while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & XABT) == 0);
528	}
529	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
530}
531
532/***************************************************************************/
533void get_tulipPCIConfig(HCS * pCurHcb, int ch_idx)
534{
535	pCurHcb->HCS_Base = i91u_adpt[ch_idx].ADPT_BASE;	/* Supply base address  */
536	pCurHcb->HCS_BIOS = i91u_adpt[ch_idx].ADPT_BIOS;	/* Supply BIOS address  */
537	pCurHcb->HCS_Intr = i91u_adpt[ch_idx].ADPT_INTR;	/* Supply interrupt line */
538	return;
539}
540
541/***************************************************************************/
542int tul_reset_scsi(HCS * pCurHcb, int seconds)
543{
544	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_BUS);
545
546	while (!((pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt)) & TSS_SCSIRST_INT));
547	/* reset tulip chip */
548
549	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, 0);
550
551	/* Stall for a while, wait for target's firmware ready,make it 2 sec ! */
552	/* SONY 5200 tape drive won't work if only stall for 1 sec */
553	tul_do_pause(seconds * HZ);
554
555	TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
556
557	return (SCSI_RESET_SUCCESS);
558}
559
560/***************************************************************************/
561int init_tulip(HCS * pCurHcb, SCB * scbp, int tul_num_scb, BYTE * pbBiosAdr, int seconds)
562{
563	int i;
564	BYTE *pwFlags;
565	BYTE *pbHeads;
566	SCB *pTmpScb, *pPrevScb = NULL;
567
568	pCurHcb->HCS_NumScbs = tul_num_scb;
569	pCurHcb->HCS_Semaph = 1;
570#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
571	pCurHcb->HCS_SemaphLock = SPIN_LOCK_UNLOCKED;
572#endif
573	pCurHcb->HCS_JSStatus0 = 0;
574	pCurHcb->HCS_Scb = scbp;
575	pCurHcb->HCS_NxtPend = scbp;
576	pCurHcb->HCS_NxtAvail = scbp;
577	for (i = 0, pTmpScb = scbp; i < tul_num_scb; i++, pTmpScb++) {
578		pTmpScb->SCB_TagId = i;
579		if (i != 0)
580			pPrevScb->SCB_NxtScb = pTmpScb;
581		pPrevScb = pTmpScb;
582	}
583	pPrevScb->SCB_NxtScb = NULL;
584	pCurHcb->HCS_ScbEnd = pTmpScb;
585	pCurHcb->HCS_FirstAvail = scbp;
586	pCurHcb->HCS_LastAvail = pPrevScb;
587#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
588	pCurHcb->HCS_AvailLock = SPIN_LOCK_UNLOCKED;
589#endif
590	pCurHcb->HCS_FirstPend = NULL;
591	pCurHcb->HCS_LastPend = NULL;
592	pCurHcb->HCS_FirstBusy = NULL;
593	pCurHcb->HCS_LastBusy = NULL;
594	pCurHcb->HCS_FirstDone = NULL;
595	pCurHcb->HCS_LastDone = NULL;
596	pCurHcb->HCS_ActScb = NULL;
597	pCurHcb->HCS_ActTcs = NULL;
598
599	tul_read_eeprom(pCurHcb->HCS_Base);
600/*---------- get H/A configuration -------------*/
601	if (i91unvramp->NVM_SCSIInfo[0].NVM_NumOfTarg == 8)
602		pCurHcb->HCS_MaxTar = 8;
603	else
604		pCurHcb->HCS_MaxTar = 16;
605
606	pCurHcb->HCS_Config = i91unvramp->NVM_SCSIInfo[0].NVM_ChConfig1;
607
608	pCurHcb->HCS_SCSI_ID = i91unvramp->NVM_SCSIInfo[0].NVM_ChSCSIID;
609	pCurHcb->HCS_IdMask = ~(1 << pCurHcb->HCS_SCSI_ID);
610
611#if CHK_PARITY
612	/* Enable parity error response */
613	TUL_WR(pCurHcb->HCS_Base + TUL_PCMD, TUL_RD(pCurHcb->HCS_Base, TUL_PCMD) | 0x40);
614#endif
615
616	/* Mask all the interrupt       */
617	TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
618
619	tul_stop_bm(pCurHcb);
620	/* --- Initialize the tulip --- */
621	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_CHIP);
622
623	/* program HBA's SCSI ID        */
624	TUL_WR(pCurHcb->HCS_Base + TUL_SScsiId, pCurHcb->HCS_SCSI_ID << 4);
625
626	/* Enable Initiator Mode ,phase latch,alternate sync period mode,
627	   disable SCSI reset */
628	if (pCurHcb->HCS_Config & HCC_EN_PAR)
629		pCurHcb->HCS_SConf1 = (TSC_INITDEFAULT | TSC_EN_SCSI_PAR);
630	else
631		pCurHcb->HCS_SConf1 = (TSC_INITDEFAULT);
632	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_SConf1);
633
634	/* Enable HW reselect           */
635	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);
636
637	TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, 0);
638
639	/* selection time out = 250 ms */
640	TUL_WR(pCurHcb->HCS_Base + TUL_STimeOut, 153);
641
642/*--------- Enable SCSI terminator -----*/
643	TUL_WR(pCurHcb->HCS_Base + TUL_XCtrl, (pCurHcb->HCS_Config & (HCC_ACT_TERM1 | HCC_ACT_TERM2)));
644	TUL_WR(pCurHcb->HCS_Base + TUL_GCTRL1,
645	       ((pCurHcb->HCS_Config & HCC_AUTO_TERM) >> 4) | (TUL_RD(pCurHcb->HCS_Base, TUL_GCTRL1) & 0xFE));
646
647	for (i = 0,
648	     pwFlags = & (i91unvramp->NVM_SCSIInfo[0].NVM_Targ0Config),
649	     pbHeads = pbBiosAdr + 0x180;
650	     i < pCurHcb->HCS_MaxTar;
651	     i++, pwFlags++) {
652		pCurHcb->HCS_Tcs[i].TCS_Flags = *pwFlags & ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
653		if (pCurHcb->HCS_Tcs[i].TCS_Flags & TCF_EN_255)
654			pCurHcb->HCS_Tcs[i].TCS_DrvFlags = TCF_DRV_255_63;
655		else
656			pCurHcb->HCS_Tcs[i].TCS_DrvFlags = 0;
657		pCurHcb->HCS_Tcs[i].TCS_JS_Period = 0;
658		pCurHcb->HCS_Tcs[i].TCS_SConfig0 = pCurHcb->HCS_SConf1;
659		pCurHcb->HCS_Tcs[i].TCS_DrvHead = *pbHeads++;
660		if (pCurHcb->HCS_Tcs[i].TCS_DrvHead == 255)
661			pCurHcb->HCS_Tcs[i].TCS_DrvFlags = TCF_DRV_255_63;
662		else
663			pCurHcb->HCS_Tcs[i].TCS_DrvFlags = 0;
664		pCurHcb->HCS_Tcs[i].TCS_DrvSector = *pbHeads++;
665		pCurHcb->HCS_Tcs[i].TCS_Flags &= ~TCF_BUSY;
666		pCurHcb->HCS_ActTags[i] = 0;
667		pCurHcb->HCS_MaxTags[i] = 0xFF;
668	}			/* for                          */
669	printk("i91u: PCI Base=0x%04X, IRQ=%d, BIOS=0x%04X0, SCSI ID=%d\n",
670	       pCurHcb->HCS_Base, pCurHcb->HCS_Intr,
671	       pCurHcb->HCS_BIOS, pCurHcb->HCS_SCSI_ID);
672/*------------------- reset SCSI Bus ---------------------------*/
673	if (pCurHcb->HCS_Config & HCC_SCSI_RESET) {
674		printk("i91u: Reset SCSI Bus ... \n");
675		tul_reset_scsi(pCurHcb, seconds);
676	}
677	TUL_WR(pCurHcb->HCS_Base + TUL_SCFG1, 0x17);
678	TUL_WR(pCurHcb->HCS_Base + TUL_SIntEnable, 0xE9);
679	return (0);
680}
681
682/***************************************************************************/
683SCB *tul_alloc_scb(HCS * hcsp)
684{
685	SCB *pTmpScb;
686	ULONG flags;
687#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
688	spin_lock_irqsave(&(hcsp->HCS_AvailLock), flags);
689#else
690	save_flags(flags);
691	cli();
692#endif
693	if ((pTmpScb = hcsp->HCS_FirstAvail) != NULL) {
694#if DEBUG_QUEUE
695		printk("find scb at %08lx\n", (ULONG) pTmpScb);
696#endif
697		if ((hcsp->HCS_FirstAvail = pTmpScb->SCB_NxtScb) == NULL)
698			hcsp->HCS_LastAvail = NULL;
699		pTmpScb->SCB_NxtScb = NULL;
700		pTmpScb->SCB_Status = SCB_RENT;
701	}
702#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
703	spin_unlock_irqrestore(&(hcsp->HCS_AvailLock), flags);
704#else
705	restore_flags(flags);
706#endif
707	return (pTmpScb);
708}
709
710/***************************************************************************/
711void tul_release_scb(HCS * hcsp, SCB * scbp)
712{
713	ULONG flags;
714
715#if DEBUG_QUEUE
716	printk("Release SCB %lx; ", (ULONG) scbp);
717#endif
718#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
719	spin_lock_irqsave(&(hcsp->HCS_AvailLock), flags);
720#else
721	save_flags(flags);
722	cli();
723#endif
724	scbp->SCB_Srb = 0;
725	scbp->SCB_Status = 0;
726	scbp->SCB_NxtScb = NULL;
727	if (hcsp->HCS_LastAvail != NULL) {
728		hcsp->HCS_LastAvail->SCB_NxtScb = scbp;
729		hcsp->HCS_LastAvail = scbp;
730	} else {
731		hcsp->HCS_FirstAvail = scbp;
732		hcsp->HCS_LastAvail = scbp;
733	}
734#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
735	spin_unlock_irqrestore(&(hcsp->HCS_AvailLock), flags);
736#else
737	restore_flags(flags);
738#endif
739}
740
741/***************************************************************************/
742void tul_append_pend_scb(HCS * pCurHcb, SCB * scbp)
743{
744
745#if DEBUG_QUEUE
746	printk("Append pend SCB %lx; ", (ULONG) scbp);
747#endif
748	scbp->SCB_Status = SCB_PEND;
749	scbp->SCB_NxtScb = NULL;
750	if (pCurHcb->HCS_LastPend != NULL) {
751		pCurHcb->HCS_LastPend->SCB_NxtScb = scbp;
752		pCurHcb->HCS_LastPend = scbp;
753	} else {
754		pCurHcb->HCS_FirstPend = scbp;
755		pCurHcb->HCS_LastPend = scbp;
756	}
757}
758
759/***************************************************************************/
760void tul_push_pend_scb(HCS * pCurHcb, SCB * scbp)
761{
762
763#if DEBUG_QUEUE
764	printk("Push pend SCB %lx; ", (ULONG) scbp);
765#endif
766	scbp->SCB_Status = SCB_PEND;
767	if ((scbp->SCB_NxtScb = pCurHcb->HCS_FirstPend) != NULL) {
768		pCurHcb->HCS_FirstPend = scbp;
769	} else {
770		pCurHcb->HCS_FirstPend = scbp;
771		pCurHcb->HCS_LastPend = scbp;
772	}
773}
774
775/***************************************************************************/
776SCB *tul_find_first_pend_scb(HCS * pCurHcb)
777{
778	SCB *pFirstPend;
779
780
781	pFirstPend = pCurHcb->HCS_FirstPend;
782	while (pFirstPend != NULL) {
783		if (pFirstPend->SCB_Opcode != ExecSCSI) {
784			return (pFirstPend);
785		}
786		if (pFirstPend->SCB_TagMsg == 0) {
787			if ((pCurHcb->HCS_ActTags[pFirstPend->SCB_Target] == 0) &&
788			    !(pCurHcb->HCS_Tcs[pFirstPend->SCB_Target].TCS_Flags & TCF_BUSY)) {
789				return (pFirstPend);
790			}
791		} else {
792			if ((pCurHcb->HCS_ActTags[pFirstPend->SCB_Target] >=
793			  pCurHcb->HCS_MaxTags[pFirstPend->SCB_Target]) |
794			    (pCurHcb->HCS_Tcs[pFirstPend->SCB_Target].TCS_Flags & TCF_BUSY)) {
795				pFirstPend = pFirstPend->SCB_NxtScb;
796				continue;
797			}
798			return (pFirstPend);
799		}
800		pFirstPend = pFirstPend->SCB_NxtScb;
801	}
802
803
804	return (pFirstPend);
805}
806/***************************************************************************/
807SCB *tul_pop_pend_scb(HCS * pCurHcb)
808{
809	SCB *pTmpScb;
810
811	if ((pTmpScb = pCurHcb->HCS_FirstPend) != NULL) {
812		if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL)
813			pCurHcb->HCS_LastPend = NULL;
814		pTmpScb->SCB_NxtScb = NULL;
815	}
816#if DEBUG_QUEUE
817	printk("Pop pend SCB %lx; ", (ULONG) pTmpScb);
818#endif
819	return (pTmpScb);
820}
821
822
823/***************************************************************************/
824void tul_unlink_pend_scb(HCS * pCurHcb, SCB * pCurScb)
825{
826	SCB *pTmpScb, *pPrevScb;
827
828#if DEBUG_QUEUE
829	printk("unlink pend SCB %lx; ", (ULONG) pCurScb);
830#endif
831
832	pPrevScb = pTmpScb = pCurHcb->HCS_FirstPend;
833	while (pTmpScb != NULL) {
834		if (pCurScb == pTmpScb) {	/* Unlink this SCB              */
835			if (pTmpScb == pCurHcb->HCS_FirstPend) {
836				if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL)
837					pCurHcb->HCS_LastPend = NULL;
838			} else {
839				pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
840				if (pTmpScb == pCurHcb->HCS_LastPend)
841					pCurHcb->HCS_LastPend = pPrevScb;
842			}
843			pTmpScb->SCB_NxtScb = NULL;
844			break;
845		}
846		pPrevScb = pTmpScb;
847		pTmpScb = pTmpScb->SCB_NxtScb;
848	}
849	return;
850}
851/***************************************************************************/
852void tul_append_busy_scb(HCS * pCurHcb, SCB * scbp)
853{
854
855#if DEBUG_QUEUE
856	printk("append busy SCB %lx; ", (ULONG) scbp);
857#endif
858	if (scbp->SCB_TagMsg)
859		pCurHcb->HCS_ActTags[scbp->SCB_Target]++;
860	else
861		pCurHcb->HCS_Tcs[scbp->SCB_Target].TCS_Flags |= TCF_BUSY;
862	scbp->SCB_Status = SCB_BUSY;
863	scbp->SCB_NxtScb = NULL;
864	if (pCurHcb->HCS_LastBusy != NULL) {
865		pCurHcb->HCS_LastBusy->SCB_NxtScb = scbp;
866		pCurHcb->HCS_LastBusy = scbp;
867	} else {
868		pCurHcb->HCS_FirstBusy = scbp;
869		pCurHcb->HCS_LastBusy = scbp;
870	}
871}
872
873/***************************************************************************/
874SCB *tul_pop_busy_scb(HCS * pCurHcb)
875{
876	SCB *pTmpScb;
877
878
879	if ((pTmpScb = pCurHcb->HCS_FirstBusy) != NULL) {
880		if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
881			pCurHcb->HCS_LastBusy = NULL;
882		pTmpScb->SCB_NxtScb = NULL;
883		if (pTmpScb->SCB_TagMsg)
884			pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;
885		else
886			pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY;
887	}
888#if DEBUG_QUEUE
889	printk("Pop busy SCB %lx; ", (ULONG) pTmpScb);
890#endif
891	return (pTmpScb);
892}
893
894/***************************************************************************/
895void tul_unlink_busy_scb(HCS * pCurHcb, SCB * pCurScb)
896{
897	SCB *pTmpScb, *pPrevScb;
898
899#if DEBUG_QUEUE
900	printk("unlink busy SCB %lx; ", (ULONG) pCurScb);
901#endif
902
903	pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;
904	while (pTmpScb != NULL) {
905		if (pCurScb == pTmpScb) {	/* Unlink this SCB              */
906			if (pTmpScb == pCurHcb->HCS_FirstBusy) {
907				if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
908					pCurHcb->HCS_LastBusy = NULL;
909			} else {
910				pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
911				if (pTmpScb == pCurHcb->HCS_LastBusy)
912					pCurHcb->HCS_LastBusy = pPrevScb;
913			}
914			pTmpScb->SCB_NxtScb = NULL;
915			if (pTmpScb->SCB_TagMsg)
916				pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;
917			else
918				pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY;
919			break;
920		}
921		pPrevScb = pTmpScb;
922		pTmpScb = pTmpScb->SCB_NxtScb;
923	}
924	return;
925}
926
927/***************************************************************************/
928SCB *tul_find_busy_scb(HCS * pCurHcb, WORD tarlun)
929{
930	SCB *pTmpScb, *pPrevScb;
931	WORD scbp_tarlun;
932
933
934	pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;
935	while (pTmpScb != NULL) {
936		scbp_tarlun = (pTmpScb->SCB_Lun << 8) | (pTmpScb->SCB_Target);
937		if (scbp_tarlun == tarlun) {	/* Unlink this SCB              */
938			break;
939		}
940		pPrevScb = pTmpScb;
941		pTmpScb = pTmpScb->SCB_NxtScb;
942	}
943#if DEBUG_QUEUE
944	printk("find busy SCB %lx; ", (ULONG) pTmpScb);
945#endif
946	return (pTmpScb);
947}
948
949/***************************************************************************/
950void tul_append_done_scb(HCS * pCurHcb, SCB * scbp)
951{
952
953#if DEBUG_QUEUE
954	printk("append done SCB %lx; ", (ULONG) scbp);
955#endif
956
957	scbp->SCB_Status = SCB_DONE;
958	scbp->SCB_NxtScb = NULL;
959	if (pCurHcb->HCS_LastDone != NULL) {
960		pCurHcb->HCS_LastDone->SCB_NxtScb = scbp;
961		pCurHcb->HCS_LastDone = scbp;
962	} else {
963		pCurHcb->HCS_FirstDone = scbp;
964		pCurHcb->HCS_LastDone = scbp;
965	}
966}
967
968/***************************************************************************/
969SCB *tul_find_done_scb(HCS * pCurHcb)
970{
971	SCB *pTmpScb;
972
973
974	if ((pTmpScb = pCurHcb->HCS_FirstDone) != NULL) {
975		if ((pCurHcb->HCS_FirstDone = pTmpScb->SCB_NxtScb) == NULL)
976			pCurHcb->HCS_LastDone = NULL;
977		pTmpScb->SCB_NxtScb = NULL;
978	}
979#if DEBUG_QUEUE
980	printk("find done SCB %lx; ", (ULONG) pTmpScb);
981#endif
982	return (pTmpScb);
983}
984
985/***************************************************************************/
986int tul_abort_srb(HCS * pCurHcb, ULONG srbp)
987{
988	ULONG flags;
989	SCB *pTmpScb, *pPrevScb;
990
991#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
992	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
993#else
994	save_flags(flags);
995	cli();
996#endif
997
998	if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) {
999		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
1000		/* disable Jasmin SCSI Int        */
1001
1002#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1003                spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1004#endif
1005
1006		tulip_main(pCurHcb);
1007
1008#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1009        	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
1010#endif
1011
1012		pCurHcb->HCS_Semaph = 1;
1013		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
1014
1015#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1016		spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1017#else
1018		restore_flags(flags);
1019#endif
1020
1021		return SCSI_ABORT_SNOOZE;
1022	}
1023	pPrevScb = pTmpScb = pCurHcb->HCS_FirstPend;	/* Check Pend queue */
1024	while (pTmpScb != NULL) {
1025		/* 07/27/98 */
1026		if (pTmpScb->SCB_Srb == (unsigned char *) srbp) {
1027			if (pTmpScb == pCurHcb->HCS_ActScb) {
1028#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1029				spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1030#else
1031				restore_flags(flags);
1032#endif
1033				return SCSI_ABORT_BUSY;
1034			} else if (pTmpScb == pCurHcb->HCS_FirstPend) {
1035				if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL)
1036					pCurHcb->HCS_LastPend = NULL;
1037			} else {
1038				pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
1039				if (pTmpScb == pCurHcb->HCS_LastPend)
1040					pCurHcb->HCS_LastPend = pPrevScb;
1041			}
1042			pTmpScb->SCB_HaStat = HOST_ABORTED;
1043			pTmpScb->SCB_Flags |= SCF_DONE;
1044			if (pTmpScb->SCB_Flags & SCF_POST)
1045				(*pTmpScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pTmpScb);
1046#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1047			spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1048#else
1049			restore_flags(flags);
1050#endif
1051			return SCSI_ABORT_SUCCESS;
1052		}
1053		pPrevScb = pTmpScb;
1054		pTmpScb = pTmpScb->SCB_NxtScb;
1055	}
1056
1057	pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;	/* Check Busy queue */
1058	while (pTmpScb != NULL) {
1059
1060		if (pTmpScb->SCB_Srb == (unsigned char *) srbp) {
1061
1062			if (pTmpScb == pCurHcb->HCS_ActScb) {
1063#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1064				spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1065#else
1066				restore_flags(flags);
1067#endif
1068				return SCSI_ABORT_BUSY;
1069			} else if (pTmpScb->SCB_TagMsg == 0) {
1070#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1071				spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1072#else
1073				restore_flags(flags);
1074#endif
1075				return SCSI_ABORT_BUSY;
1076			} else {
1077				pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;
1078				if (pTmpScb == pCurHcb->HCS_FirstBusy) {
1079					if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
1080						pCurHcb->HCS_LastBusy = NULL;
1081				} else {
1082					pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
1083					if (pTmpScb == pCurHcb->HCS_LastBusy)
1084						pCurHcb->HCS_LastBusy = pPrevScb;
1085				}
1086				pTmpScb->SCB_NxtScb = NULL;
1087
1088
1089				pTmpScb->SCB_HaStat = HOST_ABORTED;
1090				pTmpScb->SCB_Flags |= SCF_DONE;
1091				if (pTmpScb->SCB_Flags & SCF_POST)
1092					(*pTmpScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pTmpScb);
1093#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1094				spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1095#else
1096				restore_flags(flags);
1097#endif
1098				return SCSI_ABORT_SUCCESS;
1099			}
1100		}
1101		pPrevScb = pTmpScb;
1102		pTmpScb = pTmpScb->SCB_NxtScb;
1103	}
1104#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1105	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1106#else
1107	restore_flags(flags);
1108#endif
1109	return (SCSI_ABORT_NOT_RUNNING);
1110}
1111
1112/***************************************************************************/
1113int tul_bad_seq(HCS * pCurHcb)
1114{
1115	SCB *pCurScb;
1116
1117	printk("tul_bad_seg c=%d\n", pCurHcb->HCS_Index);
1118
1119	if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) {
1120		tul_unlink_busy_scb(pCurHcb, pCurScb);
1121		pCurScb->SCB_HaStat = HOST_BAD_PHAS;
1122		pCurScb->SCB_TaStat = 0;
1123		tul_append_done_scb(pCurHcb, pCurScb);
1124	}
1125	tul_stop_bm(pCurHcb);
1126
1127	tul_reset_scsi(pCurHcb, 8);	/* 7/29/98 */
1128
1129	return (tul_post_scsi_rst(pCurHcb));
1130}
1131
1132/************************************************************************/
1133int tul_device_reset(HCS * pCurHcb, ULONG pSrb, unsigned int target, unsigned int ResetFlags)
1134{
1135	ULONG flags;
1136	SCB *pScb;
1137#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1138	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
1139#else
1140	save_flags(flags);
1141	cli();
1142#endif
1143
1144	if (ResetFlags & SCSI_RESET_ASYNCHRONOUS) {
1145
1146		if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) {
1147			TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
1148			/* disable Jasmin SCSI Int        */
1149
1150#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1151        		spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1152#endif
1153
1154			tulip_main(pCurHcb);
1155
1156#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1157        		spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
1158#endif
1159
1160			pCurHcb->HCS_Semaph = 1;
1161			TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
1162
1163#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1164			spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1165#else
1166			restore_flags(flags);
1167#endif
1168
1169			return SCSI_RESET_SNOOZE;
1170		}
1171		pScb = pCurHcb->HCS_FirstBusy;	/* Check Busy queue */
1172		while (pScb != NULL) {
1173			if (pScb->SCB_Srb == (unsigned char *) pSrb)
1174				break;
1175			pScb = pScb->SCB_NxtScb;
1176		}
1177		if (pScb == NULL) {
1178			printk("Unable to Reset - No SCB Found\n");
1179
1180#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1181			spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1182#else
1183			restore_flags(flags);
1184#endif
1185			return SCSI_RESET_NOT_RUNNING;
1186		}
1187	}
1188	if ((pScb = tul_alloc_scb(pCurHcb)) == NULL) {
1189#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1190		spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1191#else
1192		restore_flags(flags);
1193#endif
1194		return SCSI_RESET_NOT_RUNNING;
1195	}
1196	pScb->SCB_Opcode = BusDevRst;
1197	pScb->SCB_Flags = SCF_POST;
1198	pScb->SCB_Target = target;
1199	pScb->SCB_Mode = 0;
1200
1201	pScb->SCB_Srb = 0;
1202	if (ResetFlags & SCSI_RESET_SYNCHRONOUS) {
1203		pScb->SCB_Srb = (unsigned char *) pSrb;
1204	}
1205	tul_push_pend_scb(pCurHcb, pScb);	/* push this SCB to Pending queue */
1206
1207	if (pCurHcb->HCS_Semaph == 1) {
1208		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
1209		/* disable Jasmin SCSI Int        */
1210		pCurHcb->HCS_Semaph = 0;
1211
1212#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1213        	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1214#endif
1215
1216		tulip_main(pCurHcb);
1217
1218#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1219                spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
1220#endif
1221
1222		pCurHcb->HCS_Semaph = 1;
1223		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
1224	}
1225#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1226	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1227#else
1228	restore_flags(flags);
1229#endif
1230	return SCSI_RESET_PENDING;
1231}
1232
1233int tul_reset_scsi_bus(HCS * pCurHcb)
1234{
1235	ULONG flags;
1236
1237#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1238	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
1239#else
1240	save_flags(flags);
1241	cli();
1242#endif
1243	TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
1244	pCurHcb->HCS_Semaph = 0;
1245
1246#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1247	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1248#else
1249	restore_flags(flags);
1250#endif
1251
1252	tul_stop_bm(pCurHcb);
1253
1254	tul_reset_scsi(pCurHcb, 2);	/* 7/29/98 */
1255
1256#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1257	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
1258#else
1259	save_flags(flags);
1260	cli();
1261#endif
1262	tul_post_scsi_rst(pCurHcb);
1263
1264#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1265        spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1266#endif
1267
1268	tulip_main(pCurHcb);
1269
1270#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1271        spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
1272#endif
1273
1274	pCurHcb->HCS_Semaph = 1;
1275	TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
1276#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1277	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1278#else
1279	restore_flags(flags);
1280#endif
1281	return (SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET);
1282}
1283
1284/************************************************************************/
1285void tul_exec_scb(HCS * pCurHcb, SCB * pCurScb)
1286{
1287	ULONG flags;
1288
1289	pCurScb->SCB_Mode = 0;
1290
1291	pCurScb->SCB_SGIdx = 0;
1292	pCurScb->SCB_SGMax = pCurScb->SCB_SGLen;
1293
1294#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1295	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
1296#else
1297	save_flags(flags);
1298	cli();
1299#endif
1300
1301	tul_append_pend_scb(pCurHcb, pCurScb);	/* Append this SCB to Pending queue */
1302
1303/* VVVVV 07/21/98 */
1304	if (pCurHcb->HCS_Semaph == 1) {
1305		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
1306		/* disable Jasmin SCSI Int        */
1307		pCurHcb->HCS_Semaph = 0;
1308
1309#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1310        	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1311#endif
1312
1313		tulip_main(pCurHcb);
1314
1315#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1316        	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
1317#endif
1318
1319		pCurHcb->HCS_Semaph = 1;
1320		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
1321	}
1322#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
1323	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
1324#else
1325	restore_flags(flags);
1326#endif
1327	return;
1328}
1329
1330/***************************************************************************/
1331int tul_isr(HCS * pCurHcb)
1332{
1333	/* Enter critical section       */
1334
1335	if (TUL_RD(pCurHcb->HCS_Base, TUL_Int) & TSS_INT_PENDING) {
1336		if (pCurHcb->HCS_Semaph == 1) {
1337			TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
1338			/* Disable Tulip SCSI Int */
1339			pCurHcb->HCS_Semaph = 0;
1340
1341			tulip_main(pCurHcb);
1342
1343			pCurHcb->HCS_Semaph = 1;
1344			TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
1345			return (1);
1346		}
1347	}
1348	return (0);
1349}
1350
1351/***************************************************************************/
1352int tulip_main(HCS * pCurHcb)
1353{
1354	SCB *pCurScb;
1355
1356	for (;;) {
1357
1358		tulip_scsi(pCurHcb);	/* Call tulip_scsi              */
1359
1360		while ((pCurScb = tul_find_done_scb(pCurHcb)) != NULL) {	/* find done entry */
1361			if (pCurScb->SCB_TaStat == QUEUE_FULL) {
1362				pCurHcb->HCS_MaxTags[pCurScb->SCB_Target] =
1363				    pCurHcb->HCS_ActTags[pCurScb->SCB_Target] - 1;
1364				pCurScb->SCB_TaStat = 0;
1365				tul_append_pend_scb(pCurHcb, pCurScb);
1366				continue;
1367			}
1368			if (!(pCurScb->SCB_Mode & SCM_RSENS)) {		/* not in auto req. sense mode */
1369				if (pCurScb->SCB_TaStat == 2) {
1370
1371					/* clr sync. nego flag */
1372
1373					if (pCurScb->SCB_Flags & SCF_SENSE) {
1374						BYTE len;
1375						len = pCurScb->SCB_SenseLen;
1376						if (len == 0)
1377							len = 1;
1378						pCurScb->SCB_BufLen = pCurScb->SCB_SenseLen;
1379						pCurScb->SCB_BufPtr = pCurScb->SCB_SensePtr;
1380						pCurScb->SCB_Flags &= ~(SCF_SG | SCF_DIR);	/* for xfer_data_in */
1381/*                      pCurScb->SCB_Flags |= SCF_NO_DCHK;      */
1382						/* so, we won't report worng direction in xfer_data_in,
1383						   and won't report HOST_DO_DU in state_6 */
1384						pCurScb->SCB_Mode = SCM_RSENS;
1385						pCurScb->SCB_Ident &= 0xBF;	/* Disable Disconnect */
1386						pCurScb->SCB_TagMsg = 0;
1387						pCurScb->SCB_TaStat = 0;
1388						pCurScb->SCB_CDBLen = 6;
1389						pCurScb->SCB_CDB[0] = SCSICMD_RequestSense;
1390						pCurScb->SCB_CDB[1] = 0;
1391						pCurScb->SCB_CDB[2] = 0;
1392						pCurScb->SCB_CDB[3] = 0;
1393						pCurScb->SCB_CDB[4] = len;
1394						pCurScb->SCB_CDB[5] = 0;
1395						tul_push_pend_scb(pCurHcb, pCurScb);
1396						break;
1397					}
1398				}
1399			} else {	/* in request sense mode */
1400
1401				if (pCurScb->SCB_TaStat == 2) {		/* check contition status again after sending
1402									   requset sense cmd 0x3 */
1403					pCurScb->SCB_HaStat = HOST_BAD_PHAS;
1404				}
1405				pCurScb->SCB_TaStat = 2;
1406			}
1407			pCurScb->SCB_Flags |= SCF_DONE;
1408			if (pCurScb->SCB_Flags & SCF_POST) {
1409				(*pCurScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pCurScb);
1410			}
1411		}		/* while */
1412
1413		/* find_active: */
1414		if (TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0) & TSS_INT_PENDING)
1415			continue;
1416
1417		if (pCurHcb->HCS_ActScb) {	/* return to OS and wait for xfer_done_ISR/Selected_ISR */
1418			return 1;	/* return to OS, enable interrupt */
1419		}
1420		/* Check pending SCB            */
1421		if (tul_find_first_pend_scb(pCurHcb) == NULL) {
1422			return 1;	/* return to OS, enable interrupt */
1423		}
1424	}			/* End of for loop */
1425	/* statement won't reach here */
1426}
1427
1428
1429
1430
1431/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
1432/***************************************************************************/
1433/***************************************************************************/
1434/***************************************************************************/
1435/***************************************************************************/
1436
1437/***************************************************************************/
1438void tulip_scsi(HCS * pCurHcb)
1439{
1440	SCB *pCurScb;
1441	TCS *pCurTcb;
1442
1443	/* make sure to service interrupt asap */
1444
1445	if ((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0)) & TSS_INT_PENDING) {
1446
1447		pCurHcb->HCS_Phase = pCurHcb->HCS_JSStatus0 & TSS_PH_MASK;
1448		pCurHcb->HCS_JSStatus1 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1);
1449		pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
1450		if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {	/* SCSI bus reset detected      */
1451			int_tul_scsi_rst(pCurHcb);
1452			return;
1453		}
1454		if (pCurHcb->HCS_JSInt & TSS_RESEL_INT) {	/* if selected/reselected interrupt */
1455			if (int_tul_resel(pCurHcb) == 0)
1456				tul_next_state(pCurHcb);
1457			return;
1458		}
1459		if (pCurHcb->HCS_JSInt & TSS_SEL_TIMEOUT) {
1460			int_tul_busfree(pCurHcb);
1461			return;
1462		}
1463		if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {	/* BUS disconnection            */
1464			int_tul_busfree(pCurHcb);	/* unexpected bus free or sel timeout */
1465			return;
1466		}
1467		if (pCurHcb->HCS_JSInt & (TSS_FUNC_COMP | TSS_BUS_SERV)) {	/* func complete or Bus service */
1468			if ((pCurScb = pCurHcb->HCS_ActScb) != NULL)
1469				tul_next_state(pCurHcb);
1470			return;
1471		}
1472	}
1473	if (pCurHcb->HCS_ActScb != NULL)
1474		return;
1475
1476	if ((pCurScb = tul_find_first_pend_scb(pCurHcb)) == NULL)
1477		return;
1478
1479	/* program HBA's SCSI ID & target SCSI ID */
1480	TUL_WR(pCurHcb->HCS_Base + TUL_SScsiId,
1481	     (pCurHcb->HCS_SCSI_ID << 4) | (pCurScb->SCB_Target & 0x0F));
1482	if (pCurScb->SCB_Opcode == ExecSCSI) {
1483		pCurTcb = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
1484
1485		if (pCurScb->SCB_TagMsg)
1486			pCurTcb->TCS_DrvFlags |= TCF_DRV_EN_TAG;
1487		else
1488			pCurTcb->TCS_DrvFlags &= ~TCF_DRV_EN_TAG;
1489
1490		TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurTcb->TCS_JS_Period);
1491		if ((pCurTcb->TCS_Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {	/* do wdtr negotiation          */
1492			tul_select_atn_stop(pCurHcb, pCurScb);
1493		} else {
1494			if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {	/* do sync negotiation          */
1495				tul_select_atn_stop(pCurHcb, pCurScb);
1496			} else {
1497				if (pCurScb->SCB_TagMsg)
1498					tul_select_atn3(pCurHcb, pCurScb);
1499				else
1500					tul_select_atn(pCurHcb, pCurScb);
1501			}
1502		}
1503		if (pCurScb->SCB_Flags & SCF_POLL) {
1504			while (wait_tulip(pCurHcb) != -1) {
1505				if (tul_next_state(pCurHcb) == -1)
1506					break;
1507			}
1508		}
1509	} else if (pCurScb->SCB_Opcode == BusDevRst) {
1510		tul_select_atn_stop(pCurHcb, pCurScb);
1511		pCurScb->SCB_NxtStat = 8;
1512		if (pCurScb->SCB_Flags & SCF_POLL) {
1513			while (wait_tulip(pCurHcb) != -1) {
1514				if (tul_next_state(pCurHcb) == -1)
1515					break;
1516			}
1517		}
1518	} else if (pCurScb->SCB_Opcode == AbortCmd) {
1519		ULONG srbp;
1520
1521		srbp = (ULONG) pCurScb->SCB_Srb;
1522/* 08/03/98 */
1523		if (tul_abort_srb(pCurHcb, srbp) != 0) {
1524
1525
1526			tul_unlink_pend_scb(pCurHcb, pCurScb);
1527
1528			tul_release_scb(pCurHcb, pCurScb);
1529		} else {
1530			pCurScb->SCB_Opcode = BusDevRst;
1531			tul_select_atn_stop(pCurHcb, pCurScb);
1532			pCurScb->SCB_NxtStat = 8;
1533		}
1534
1535/* 08/03/98 */
1536	} else {
1537		tul_unlink_pend_scb(pCurHcb, pCurScb);
1538		pCurScb->SCB_HaStat = 0x16;	/* bad command */
1539		tul_append_done_scb(pCurHcb, pCurScb);
1540	}
1541	return;
1542}
1543
1544
1545/***************************************************************************/
1546int tul_next_state(HCS * pCurHcb)
1547{
1548	int next;
1549
1550	next = pCurHcb->HCS_ActScb->SCB_NxtStat;
1551	for (;;) {
1552		switch (next) {
1553		case 1:
1554			next = tul_state_1(pCurHcb);
1555			break;
1556		case 2:
1557			next = tul_state_2(pCurHcb);
1558			break;
1559		case 3:
1560			next = tul_state_3(pCurHcb);
1561			break;
1562		case 4:
1563			next = tul_state_4(pCurHcb);
1564			break;
1565		case 5:
1566			next = tul_state_5(pCurHcb);
1567			break;
1568		case 6:
1569			next = tul_state_6(pCurHcb);
1570			break;
1571		case 7:
1572			next = tul_state_7(pCurHcb);
1573			break;
1574		case 8:
1575			return (tul_bus_device_reset(pCurHcb));
1576		default:
1577			return (tul_bad_seq(pCurHcb));
1578		}
1579		if (next <= 0)
1580			return next;
1581	}
1582}
1583
1584
1585/***************************************************************************/
1586/* sTate after selection with attention & stop */
1587int tul_state_1(HCS * pCurHcb)
1588{
1589	SCB *pCurScb = pCurHcb->HCS_ActScb;
1590	TCS *pCurTcb = pCurHcb->HCS_ActTcs;
1591#if DEBUG_STATE
1592	printk("-s1-");
1593#endif
1594
1595	tul_unlink_pend_scb(pCurHcb, pCurScb);
1596	tul_append_busy_scb(pCurHcb, pCurScb);
1597
1598	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0);
1599	/* ATN on */
1600	if (pCurHcb->HCS_Phase == MSG_OUT) {
1601
1602		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, (TSC_EN_BUS_IN | TSC_HW_RESELECT));
1603
1604		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident);
1605
1606		if (pCurScb->SCB_TagMsg) {
1607			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagMsg);
1608			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagId);
1609		}
1610		if ((pCurTcb->TCS_Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {
1611
1612			pCurTcb->TCS_Flags |= TCF_WDTR_DONE;
1613
1614			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
1615			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 2);	/* Extended msg length */
1616			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);	/* Sync request */
1617			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);	/* Start from 16 bits */
1618		} else if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {
1619
1620			pCurTcb->TCS_Flags |= TCF_SYNC_DONE;
1621
1622			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
1623			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);	/* extended msg length */
1624			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);	/* sync request */
1625			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, tul_rate_tbl[pCurTcb->TCS_Flags & TCF_SCSI_RATE]);
1626			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MAX_OFFSET);	/* REQ/ACK offset */
1627		}
1628		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
1629		if (wait_tulip(pCurHcb) == -1)
1630			return (-1);
1631	}
1632	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
1633	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)));
1634	return (3);
1635}
1636
1637
1638/***************************************************************************/
1639/* state after selection with attention */
1640/* state after selection with attention3 */
1641int tul_state_2(HCS * pCurHcb)
1642{
1643	SCB *pCurScb = pCurHcb->HCS_ActScb;
1644	TCS *pCurTcb = pCurHcb->HCS_ActTcs;
1645#if DEBUG_STATE
1646	printk("-s2-");
1647#endif
1648
1649	tul_unlink_pend_scb(pCurHcb, pCurScb);
1650	tul_append_busy_scb(pCurHcb, pCurScb);
1651
1652	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0);
1653
1654	if (pCurHcb->HCS_JSStatus1 & TSS_CMD_PH_CMP) {
1655		return (4);
1656	}
1657	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
1658	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)));
1659	return (3);
1660}
1661
1662/***************************************************************************/
1663/* state before CDB xfer is done */
1664int tul_state_3(HCS * pCurHcb)
1665{
1666	SCB *pCurScb = pCurHcb->HCS_ActScb;
1667	TCS *pCurTcb = pCurHcb->HCS_ActTcs;
1668	int i;
1669
1670#if DEBUG_STATE
1671	printk("-s3-");
1672#endif
1673	for (;;) {
1674		switch (pCurHcb->HCS_Phase) {
1675		case CMD_OUT:	/* Command out phase            */
1676			for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++)
1677				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]);
1678			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
1679			if (wait_tulip(pCurHcb) == -1)
1680				return (-1);
1681			if (pCurHcb->HCS_Phase == CMD_OUT) {
1682				return (tul_bad_seq(pCurHcb));
1683			}
1684			return (4);
1685
1686		case MSG_IN:	/* Message in phase             */
1687			pCurScb->SCB_NxtStat = 3;
1688			if (tul_msgin(pCurHcb) == -1)
1689				return (-1);
1690			break;
1691
1692		case STATUS_IN:	/* Status phase                 */
1693			if (tul_status_msg(pCurHcb) == -1)
1694				return (-1);
1695			break;
1696
1697		case MSG_OUT:	/* Message out phase            */
1698			if (pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) {
1699
1700				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);		/* msg nop */
1701				TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
1702				if (wait_tulip(pCurHcb) == -1)
1703					return (-1);
1704
1705			} else {
1706				pCurTcb->TCS_Flags |= TCF_SYNC_DONE;
1707
1708				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
1709				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);	/* ext. msg len */
1710				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);	/* sync request */
1711				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, tul_rate_tbl[pCurTcb->TCS_Flags & TCF_SCSI_RATE]);
1712				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MAX_OFFSET);	/* REQ/ACK offset */
1713				TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
1714				if (wait_tulip(pCurHcb) == -1)
1715					return (-1);
1716				TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
1717				TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7));
1718
1719			}
1720			break;
1721
1722		default:
1723			return (tul_bad_seq(pCurHcb));
1724		}
1725	}
1726}
1727
1728
1729/***************************************************************************/
1730int tul_state_4(HCS * pCurHcb)
1731{
1732	SCB *pCurScb = pCurHcb->HCS_ActScb;
1733
1734#if DEBUG_STATE
1735	printk("-s4-");
1736#endif
1737	if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_NO_XF) {
1738		return (6);	/* Go to state 6                */
1739	}
1740	for (;;) {
1741		if (pCurScb->SCB_BufLen == 0)
1742			return (6);	/* Go to state 6                */
1743
1744		switch (pCurHcb->HCS_Phase) {
1745
1746		case STATUS_IN:	/* Status phase                 */
1747			if ((pCurScb->SCB_Flags & SCF_DIR) != 0) {	/* if direction bit set then report data underrun */
1748				pCurScb->SCB_HaStat = HOST_DO_DU;
1749			}
1750			if ((tul_status_msg(pCurHcb)) == -1)
1751				return (-1);
1752			break;
1753
1754		case MSG_IN:	/* Message in phase             */
1755			pCurScb->SCB_NxtStat = 0x4;
1756			if (tul_msgin(pCurHcb) == -1)
1757				return (-1);
1758			break;
1759
1760		case MSG_OUT:	/* Message out phase            */
1761			if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {
1762				pCurScb->SCB_BufLen = 0;
1763				pCurScb->SCB_HaStat = HOST_DO_DU;
1764				if (tul_msgout_ide(pCurHcb) == -1)
1765					return (-1);
1766				return (6);	/* Go to state 6                */
1767			} else {
1768				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);		/* msg nop */
1769				TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
1770				if (wait_tulip(pCurHcb) == -1)
1771					return (-1);
1772			}
1773			break;
1774
1775		case DATA_IN:	/* Data in phase                */
1776			return (tul_xfer_data_in(pCurHcb));
1777
1778		case DATA_OUT:	/* Data out phase               */
1779			return (tul_xfer_data_out(pCurHcb));
1780
1781		default:
1782			return (tul_bad_seq(pCurHcb));
1783		}
1784	}
1785}
1786
1787
1788/***************************************************************************/
1789/* state after dma xfer done or phase change before xfer done */
1790int tul_state_5(HCS * pCurHcb)
1791{
1792	SCB *pCurScb = pCurHcb->HCS_ActScb;
1793	long cnt, xcnt;		/* cannot use unsigned !! code: if (xcnt < 0) */
1794
1795#if DEBUG_STATE
1796	printk("-s5-");
1797#endif
1798/*------ get remaining count -------*/
1799
1800	cnt = TUL_RDLONG(pCurHcb->HCS_Base, TUL_SCnt0) & 0x0FFFFFF;
1801
1802	if (TUL_RD(pCurHcb->HCS_Base, TUL_XCmd) & 0x20) {
1803		/* ----------------------- DATA_IN ----------------------------- */
1804		/* check scsi parity error */
1805		if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {
1806			pCurScb->SCB_HaStat = HOST_DO_DU;
1807		}
1808		if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) {	/* DMA xfer pending, Send STOP  */
1809			/* tell Hardware  scsi xfer has been terminated */
1810			TUL_WR(pCurHcb->HCS_Base + TUL_XCtrl, TUL_RD(pCurHcb->HCS_Base, TUL_XCtrl) | 0x80);
1811			/* wait until DMA xfer not pending */
1812			while (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND);
1813		}
1814	} else {
1815/*-------- DATA OUT -----------*/
1816		if ((TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1) & TSS_XFER_CMP) == 0) {
1817			if (pCurHcb->HCS_ActTcs->TCS_JS_Period & TSC_WIDE_SCSI)
1818				cnt += (TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F) << 1;
1819			else
1820				cnt += (TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F);
1821		}
1822		if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) {	/* if DMA xfer is pending, abort DMA xfer */
1823			TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT);
1824			/* wait Abort DMA xfer done */
1825			while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & XABT) == 0);
1826		}
1827		if ((cnt == 1) && (pCurHcb->HCS_Phase == DATA_OUT)) {
1828			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
1829			if (wait_tulip(pCurHcb) == -1) {
1830				return (-1);
1831			}
1832			cnt = 0;
1833		} else {
1834			if ((TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1) & TSS_XFER_CMP) == 0)
1835				TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
1836		}
1837	}
1838
1839	if (cnt == 0) {
1840		pCurScb->SCB_BufLen = 0;
1841		return (6);	/* Go to state 6                */
1842	}
1843	/* Update active data pointer */
1844	xcnt = (long) pCurScb->SCB_BufLen - cnt;	/* xcnt== bytes already xferred */
1845	pCurScb->SCB_BufLen = (U32) cnt;	/* cnt == bytes left to be xferred */
1846	if (pCurScb->SCB_Flags & SCF_SG) {
1847		register SG *sgp;
1848		ULONG i;
1849
1850		sgp = &pCurScb->SCB_SGList[pCurScb->SCB_SGIdx];
1851		for (i = pCurScb->SCB_SGIdx; i < pCurScb->SCB_SGMax; sgp++, i++) {
1852			xcnt -= (long) sgp->SG_Len;
1853			if (xcnt < 0) {		/* this sgp xfer half done */
1854				xcnt += (long) sgp->SG_Len;	/* xcnt == bytes xferred in this sgp */
1855				sgp->SG_Ptr += (U32) xcnt;	/* new ptr to be xfer */
1856				sgp->SG_Len -= (U32) xcnt;	/* new len to be xfer */
1857				pCurScb->SCB_BufPtr += ((U32) (i - pCurScb->SCB_SGIdx) << 3);
1858				/* new SG table ptr */
1859				pCurScb->SCB_SGLen = (BYTE) (pCurScb->SCB_SGMax - i);
1860				/* new SG table len */
1861				pCurScb->SCB_SGIdx = (WORD) i;
1862				/* for next disc and come in this loop */
1863				return (4);	/* Go to state 4                */
1864			}
1865			/* else (xcnt >= 0 , i.e. this sgp already xferred */
1866		}		/* for */
1867		return (6);	/* Go to state 6                */
1868	} else {
1869		pCurScb->SCB_BufPtr += (U32) xcnt;
1870	}
1871	return (4);		/* Go to state 4                */
1872}
1873
1874/***************************************************************************/
1875/* state after Data phase */
1876int tul_state_6(HCS * pCurHcb)
1877{
1878	SCB *pCurScb = pCurHcb->HCS_ActScb;
1879
1880#if DEBUG_STATE
1881	printk("-s6-");
1882#endif
1883	for (;;) {
1884		switch (pCurHcb->HCS_Phase) {
1885		case STATUS_IN:	/* Status phase                 */
1886			if ((tul_status_msg(pCurHcb)) == -1)
1887				return (-1);
1888			break;
1889
1890		case MSG_IN:	/* Message in phase             */
1891			pCurScb->SCB_NxtStat = 6;
1892			if ((tul_msgin(pCurHcb)) == -1)
1893				return (-1);
1894			break;
1895
1896		case MSG_OUT:	/* Message out phase            */
1897			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);		/* msg nop */
1898			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
1899			if (wait_tulip(pCurHcb) == -1)
1900				return (-1);
1901			break;
1902
1903		case DATA_IN:	/* Data in phase                */
1904			return (tul_xpad_in(pCurHcb));
1905
1906		case DATA_OUT:	/* Data out phase               */
1907			return (tul_xpad_out(pCurHcb));
1908
1909		default:
1910			return (tul_bad_seq(pCurHcb));
1911		}
1912	}
1913}
1914
1915/***************************************************************************/
1916int tul_state_7(HCS * pCurHcb)
1917{
1918	int cnt, i;
1919
1920#if DEBUG_STATE
1921	printk("-s7-");
1922#endif
1923	/* flush SCSI FIFO */
1924	cnt = TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F;
1925	if (cnt) {
1926		for (i = 0; i < cnt; i++)
1927			TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
1928	}
1929	switch (pCurHcb->HCS_Phase) {
1930	case DATA_IN:		/* Data in phase                */
1931	case DATA_OUT:		/* Data out phase               */
1932		return (tul_bad_seq(pCurHcb));
1933	default:
1934		return (6);	/* Go to state 6                */
1935	}
1936}
1937
1938/***************************************************************************/
1939int tul_xfer_data_in(HCS * pCurHcb)
1940{
1941	SCB *pCurScb = pCurHcb->HCS_ActScb;
1942
1943	if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DOUT) {
1944		return (6);	/* wrong direction */
1945	}
1946	TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, pCurScb->SCB_BufLen);
1947
1948	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_DMA_IN);	/* 7/25/95 */
1949
1950	if (pCurScb->SCB_Flags & SCF_SG) {	/* S/G xfer */
1951		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, ((ULONG) pCurScb->SCB_SGLen) << 3);
1952		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
1953		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_SG_IN);
1954	} else {
1955		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, pCurScb->SCB_BufLen);
1956		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
1957		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_IN);
1958	}
1959	pCurScb->SCB_NxtStat = 0x5;
1960	return (0);		/* return to OS, wait xfer done , let jas_isr come in */
1961}
1962
1963
1964/***************************************************************************/
1965int tul_xfer_data_out(HCS * pCurHcb)
1966{
1967	SCB *pCurScb = pCurHcb->HCS_ActScb;
1968
1969	if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DIN) {
1970		return (6);	/* wrong direction */
1971	}
1972	TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, pCurScb->SCB_BufLen);
1973	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_DMA_OUT);
1974
1975	if (pCurScb->SCB_Flags & SCF_SG) {	/* S/G xfer */
1976		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, ((ULONG) pCurScb->SCB_SGLen) << 3);
1977		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
1978		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_SG_OUT);
1979	} else {
1980		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, pCurScb->SCB_BufLen);
1981		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
1982		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_OUT);
1983	}
1984
1985	pCurScb->SCB_NxtStat = 0x5;
1986	return (0);		/* return to OS, wait xfer done , let jas_isr come in */
1987}
1988
1989
1990/***************************************************************************/
1991int tul_xpad_in(HCS * pCurHcb)
1992{
1993	SCB *pCurScb = pCurHcb->HCS_ActScb;
1994	TCS *pCurTcb = pCurHcb->HCS_ActTcs;
1995
1996	if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) {
1997		pCurScb->SCB_HaStat = HOST_DO_DU;	/* over run             */
1998	}
1999	for (;;) {
2000		if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI)
2001			TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 2);
2002		else
2003			TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
2004
2005		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
2006		if ((wait_tulip(pCurHcb)) == -1) {
2007			return (-1);
2008		}
2009		if (pCurHcb->HCS_Phase != DATA_IN) {
2010			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
2011			return (6);
2012		}
2013		TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
2014	}
2015}
2016
2017int tul_xpad_out(HCS * pCurHcb)
2018{
2019	SCB *pCurScb = pCurHcb->HCS_ActScb;
2020	TCS *pCurTcb = pCurHcb->HCS_ActTcs;
2021
2022	if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) {
2023		pCurScb->SCB_HaStat = HOST_DO_DU;	/* over run             */
2024	}
2025	for (;;) {
2026		if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI)
2027			TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 2);
2028		else
2029			TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
2030
2031		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 0);
2032		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
2033		if ((wait_tulip(pCurHcb)) == -1) {
2034			return (-1);
2035		}
2036		if (pCurHcb->HCS_Phase != DATA_OUT) {	/* Disable wide CPU to allow read 16 bits */
2037			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);
2038			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
2039			return (6);
2040		}
2041	}
2042}
2043
2044
2045/***************************************************************************/
2046int tul_status_msg(HCS * pCurHcb)
2047{				/* status & MSG_IN */
2048	SCB *pCurScb = pCurHcb->HCS_ActScb;
2049	BYTE msg;
2050
2051	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_CMD_COMP);
2052	if ((wait_tulip(pCurHcb)) == -1) {
2053		return (-1);
2054	}
2055	/* get status */
2056	pCurScb->SCB_TaStat = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
2057
2058	if (pCurHcb->HCS_Phase == MSG_OUT) {
2059		if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {
2060			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_PARITY);
2061		} else {
2062			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);
2063		}
2064		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
2065		return (wait_tulip(pCurHcb));
2066	}
2067	if (pCurHcb->HCS_Phase == MSG_IN) {
2068		msg = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
2069		if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {	/* Parity error                 */
2070			if ((tul_msgin_accept(pCurHcb)) == -1)
2071				return (-1);
2072			if (pCurHcb->HCS_Phase != MSG_OUT)
2073				return (tul_bad_seq(pCurHcb));
2074			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_PARITY);
2075			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
2076			return (wait_tulip(pCurHcb));
2077		}
2078		if (msg == 0) {	/* Command complete             */
2079
2080			if ((pCurScb->SCB_TaStat & 0x18) == 0x10) {	/* No link support              */
2081				return (tul_bad_seq(pCurHcb));
2082			}
2083			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
2084			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
2085			return tul_wait_done_disc(pCurHcb);
2086
2087		}
2088		if ((msg == MSG_LINK_COMP) || (msg == MSG_LINK_FLAG)) {
2089			if ((pCurScb->SCB_TaStat & 0x18) == 0x10)
2090				return (tul_msgin_accept(pCurHcb));
2091		}
2092	}
2093	return (tul_bad_seq(pCurHcb));
2094}
2095
2096
2097/***************************************************************************/
2098/* scsi bus free */
2099int int_tul_busfree(HCS * pCurHcb)
2100{
2101	SCB *pCurScb = pCurHcb->HCS_ActScb;
2102
2103	if (pCurScb != NULL) {
2104		if (pCurScb->SCB_Status & SCB_SELECT) {		/* selection timeout */
2105			tul_unlink_pend_scb(pCurHcb, pCurScb);
2106			pCurScb->SCB_HaStat = HOST_SEL_TOUT;
2107			tul_append_done_scb(pCurHcb, pCurScb);
2108		} else {	/* Unexpected bus free          */
2109			tul_unlink_busy_scb(pCurHcb, pCurScb);
2110			pCurScb->SCB_HaStat = HOST_BUS_FREE;
2111			tul_append_done_scb(pCurHcb, pCurScb);
2112		}
2113		pCurHcb->HCS_ActScb = NULL;
2114		pCurHcb->HCS_ActTcs = NULL;
2115	}
2116	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);		/* Flush SCSI FIFO  */
2117	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
2118	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);	/* Enable HW reselect       */
2119	return (-1);
2120}
2121
2122
2123/***************************************************************************/
2124/* scsi bus reset */
2125int int_tul_scsi_rst(HCS * pCurHcb)
2126{
2127	SCB *pCurScb;
2128	int i;
2129
2130	/* if DMA xfer is pending, abort DMA xfer */
2131	if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & 0x01) {
2132		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO);
2133		/* wait Abort DMA xfer done */
2134		while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & 0x04) == 0);
2135		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
2136	}
2137	/* Abort all active & disconnected scb */
2138	while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {
2139		pCurScb->SCB_HaStat = HOST_BAD_PHAS;
2140		tul_append_done_scb(pCurHcb, pCurScb);
2141	}
2142	pCurHcb->HCS_ActScb = NULL;
2143	pCurHcb->HCS_ActTcs = NULL;
2144
2145	/* clr sync nego. done flag */
2146	for (i = 0; i < pCurHcb->HCS_MaxTar; i++) {
2147		pCurHcb->HCS_Tcs[i].TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
2148	}
2149	return (-1);
2150}
2151
2152
2153/***************************************************************************/
2154/* scsi reselection */
2155int int_tul_resel(HCS * pCurHcb)
2156{
2157	SCB *pCurScb;
2158	TCS *pCurTcb;
2159	BYTE tag, msg = 0;
2160	BYTE tar, lun;
2161
2162	if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) {
2163		if (pCurScb->SCB_Status & SCB_SELECT) {		/* if waiting for selection complete */
2164			pCurScb->SCB_Status &= ~SCB_SELECT;
2165		}
2166		pCurHcb->HCS_ActScb = NULL;
2167	}
2168	/* --------- get target id---------------------- */
2169	tar = TUL_RD(pCurHcb->HCS_Base, TUL_SBusId);
2170	/* ------ get LUN from Identify message----------- */
2171	lun = TUL_RD(pCurHcb->HCS_Base, TUL_SIdent) & 0x0F;
2172	/* 07/22/98 from 0x1F -> 0x0F */
2173	pCurTcb = &pCurHcb->HCS_Tcs[tar];
2174	pCurHcb->HCS_ActTcs = pCurTcb;
2175	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0);
2176	TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurTcb->TCS_JS_Period);
2177
2178
2179	/* ------------- tag queueing ? ------------------- */
2180	if (pCurTcb->TCS_DrvFlags & TCF_DRV_EN_TAG) {
2181		if ((tul_msgin_accept(pCurHcb)) == -1)
2182			return (-1);
2183		if (pCurHcb->HCS_Phase != MSG_IN)
2184			goto no_tag;
2185		TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
2186		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
2187		if ((wait_tulip(pCurHcb)) == -1)
2188			return (-1);
2189		msg = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);	/* Read Tag Message    */
2190
2191		if ((msg < MSG_STAG) || (msg > MSG_OTAG))	/* Is simple Tag      */
2192			goto no_tag;
2193
2194		if ((tul_msgin_accept(pCurHcb)) == -1)
2195			return (-1);
2196
2197		if (pCurHcb->HCS_Phase != MSG_IN)
2198			goto no_tag;
2199
2200		TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
2201		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
2202		if ((wait_tulip(pCurHcb)) == -1)
2203			return (-1);
2204		tag = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);	/* Read Tag ID       */
2205		pCurScb = pCurHcb->HCS_Scb + tag;
2206		if ((pCurScb->SCB_Target != tar) || (pCurScb->SCB_Lun != lun)) {
2207			return tul_msgout_abort_tag(pCurHcb);
2208		}
2209		if (pCurScb->SCB_Status != SCB_BUSY) {	/* 03/24/95             */
2210			return tul_msgout_abort_tag(pCurHcb);
2211		}
2212		pCurHcb->HCS_ActScb = pCurScb;
2213		if ((tul_msgin_accept(pCurHcb)) == -1)
2214			return (-1);
2215	} else {		/* No tag               */
2216	      no_tag:
2217		if ((pCurScb = tul_find_busy_scb(pCurHcb, tar | (lun << 8))) == NULL) {
2218			return tul_msgout_abort_targ(pCurHcb);
2219		}
2220		pCurHcb->HCS_ActScb = pCurScb;
2221		if (!(pCurTcb->TCS_DrvFlags & TCF_DRV_EN_TAG)) {
2222			if ((tul_msgin_accept(pCurHcb)) == -1)
2223				return (-1);
2224		}
2225	}
2226	return 0;
2227}
2228
2229
2230/***************************************************************************/
2231int int_tul_bad_seq(HCS * pCurHcb)
2232{				/* target wrong phase           */
2233	SCB *pCurScb;
2234	int i;
2235
2236	tul_reset_scsi(pCurHcb, 10);
2237
2238	while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {
2239		pCurScb->SCB_HaStat = HOST_BAD_PHAS;
2240		tul_append_done_scb(pCurHcb, pCurScb);
2241	}
2242	for (i = 0; i < pCurHcb->HCS_MaxTar; i++) {
2243		pCurHcb->HCS_Tcs[i].TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);;
2244	}
2245	return (-1);
2246}
2247
2248
2249/***************************************************************************/
2250int tul_msgout_abort_targ(HCS * pCurHcb)
2251{
2252
2253	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
2254	if (tul_msgin_accept(pCurHcb) == -1)
2255		return (-1);
2256	if (pCurHcb->HCS_Phase != MSG_OUT)
2257		return (tul_bad_seq(pCurHcb));
2258
2259	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_ABORT);
2260	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
2261
2262	return tul_wait_disc(pCurHcb);
2263}
2264
2265/***************************************************************************/
2266int tul_msgout_abort_tag(HCS * pCurHcb)
2267{
2268
2269	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
2270	if (tul_msgin_accept(pCurHcb) == -1)
2271		return (-1);
2272	if (pCurHcb->HCS_Phase != MSG_OUT)
2273		return (tul_bad_seq(pCurHcb));
2274
2275	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_ABORT_TAG);
2276	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
2277
2278	return tul_wait_disc(pCurHcb);
2279
2280}
2281
2282/***************************************************************************/
2283int tul_msgin(HCS * pCurHcb)
2284{
2285	TCS *pCurTcb;
2286
2287	for (;;) {
2288
2289		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
2290
2291		TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
2292		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
2293		if ((wait_tulip(pCurHcb)) == -1)
2294			return (-1);
2295
2296		switch (TUL_RD(pCurHcb->HCS_Base, TUL_SFifo)) {
2297		case MSG_DISC:	/* Disconnect msg */
2298			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
2299
2300			return tul_wait_disc(pCurHcb);
2301
2302		case MSG_SDP:
2303		case MSG_RESTORE:
2304		case MSG_NOP:
2305			tul_msgin_accept(pCurHcb);
2306			break;
2307
2308		case MSG_REJ:	/* Clear ATN first              */
2309			TUL_WR(pCurHcb->HCS_Base + TUL_SSignal,
2310			       (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)));
2311			pCurTcb = pCurHcb->HCS_ActTcs;
2312			if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {	/* do sync nego */
2313				TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
2314			}
2315			tul_msgin_accept(pCurHcb);
2316			break;
2317
2318		case MSG_EXTEND:	/* extended msg */
2319			tul_msgin_extend(pCurHcb);
2320			break;
2321
2322		case MSG_IGNOREWIDE:
2323			tul_msgin_accept(pCurHcb);
2324			break;
2325
2326			/* get */
2327			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
2328			if (wait_tulip(pCurHcb) == -1)
2329				return -1;
2330
2331			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 0);	/* put pad  */
2332			TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);	/* get IGNORE field */
2333			TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);	/* get pad */
2334
2335			tul_msgin_accept(pCurHcb);
2336			break;
2337
2338		case MSG_COMP:
2339			{
2340				TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
2341				TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
2342				return tul_wait_done_disc(pCurHcb);
2343			}
2344		default:
2345			tul_msgout_reject(pCurHcb);
2346			break;
2347		}
2348		if (pCurHcb->HCS_Phase != MSG_IN)
2349			return (pCurHcb->HCS_Phase);
2350	}
2351	/* statement won't reach here */
2352}
2353
2354
2355
2356
2357/***************************************************************************/
2358int tul_msgout_reject(HCS * pCurHcb)
2359{
2360
2361	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
2362
2363	if ((tul_msgin_accept(pCurHcb)) == -1)
2364		return (-1);
2365
2366	if (pCurHcb->HCS_Phase == MSG_OUT) {
2367		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_REJ);		/* Msg reject           */
2368		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
2369		return (wait_tulip(pCurHcb));
2370	}
2371	return (pCurHcb->HCS_Phase);
2372}
2373
2374
2375
2376/***************************************************************************/
2377int tul_msgout_ide(HCS * pCurHcb)
2378{
2379	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_IDE);		/* Initiator Detected Error */
2380	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
2381	return (wait_tulip(pCurHcb));
2382}
2383
2384
2385/***************************************************************************/
2386int tul_msgin_extend(HCS * pCurHcb)
2387{
2388	BYTE len, idx;
2389
2390	if (tul_msgin_accept(pCurHcb) != MSG_IN)
2391		return (pCurHcb->HCS_Phase);
2392
2393	/* Get extended msg length      */
2394	TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
2395	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
2396	if (wait_tulip(pCurHcb) == -1)
2397		return (-1);
2398
2399	len = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
2400	pCurHcb->HCS_Msg[0] = len;
2401	for (idx = 1; len != 0; len--) {
2402
2403		if ((tul_msgin_accept(pCurHcb)) != MSG_IN)
2404			return (pCurHcb->HCS_Phase);
2405		TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
2406		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
2407		if (wait_tulip(pCurHcb) == -1)
2408			return (-1);
2409		pCurHcb->HCS_Msg[idx++] = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
2410	}
2411	if (pCurHcb->HCS_Msg[1] == 1) {		/* if it's synchronous data transfer request */
2412		if (pCurHcb->HCS_Msg[0] != 3)	/* if length is not right */
2413			return (tul_msgout_reject(pCurHcb));
2414		if (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_SYNC_NEGO) {	/* Set OFFSET=0 to do async, nego back */
2415			pCurHcb->HCS_Msg[3] = 0;
2416		} else {
2417			if ((tul_msgin_sync(pCurHcb) == 0) &&
2418			    (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_SYNC_DONE)) {
2419				tul_sync_done(pCurHcb);
2420				return (tul_msgin_accept(pCurHcb));
2421			}
2422		}
2423
2424		TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
2425		if ((tul_msgin_accept(pCurHcb)) != MSG_OUT)
2426			return (pCurHcb->HCS_Phase);
2427		/* sync msg out */
2428		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
2429
2430		tul_sync_done(pCurHcb);
2431
2432		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
2433		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);
2434		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);
2435		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[2]);
2436		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[3]);
2437
2438		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
2439		return (wait_tulip(pCurHcb));
2440	}
2441	if ((pCurHcb->HCS_Msg[0] != 2) || (pCurHcb->HCS_Msg[1] != 3))
2442		return (tul_msgout_reject(pCurHcb));
2443	/* if it's WIDE DATA XFER REQ   */
2444	if (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_WDTR) {
2445		pCurHcb->HCS_Msg[2] = 0;
2446	} else {
2447		if (pCurHcb->HCS_Msg[2] > 2)	/* > 32 bits            */
2448			return (tul_msgout_reject(pCurHcb));
2449		if (pCurHcb->HCS_Msg[2] == 2) {		/* == 32                */
2450			pCurHcb->HCS_Msg[2] = 1;
2451		} else {
2452			if ((pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_WDTR) == 0) {
2453				wdtr_done(pCurHcb);
2454				if ((pCurHcb->HCS_ActTcs->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0)
2455					TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
2456				return (tul_msgin_accept(pCurHcb));
2457			}
2458		}
2459	}
2460	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
2461
2462	if (tul_msgin_accept(pCurHcb) != MSG_OUT)
2463		return (pCurHcb->HCS_Phase);
2464	/* WDTR msg out                 */
2465	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
2466	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 2);
2467	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);
2468	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[2]);
2469	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
2470	return (wait_tulip(pCurHcb));
2471}
2472
2473/***************************************************************************/
2474int tul_msgin_sync(HCS * pCurHcb)
2475{
2476	char default_period;
2477
2478	default_period = tul_rate_tbl[pCurHcb->HCS_ActTcs->TCS_Flags & TCF_SCSI_RATE];
2479	if (pCurHcb->HCS_Msg[3] > MAX_OFFSET) {
2480		pCurHcb->HCS_Msg[3] = MAX_OFFSET;
2481		if (pCurHcb->HCS_Msg[2] < default_period) {
2482			pCurHcb->HCS_Msg[2] = default_period;
2483			return 1;
2484		}
2485		if (pCurHcb->HCS_Msg[2] >= 59) {	/* Change to async              */
2486			pCurHcb->HCS_Msg[3] = 0;
2487		}
2488		return 1;
2489	}
2490	/* offset requests asynchronous transfers ? */
2491	if (pCurHcb->HCS_Msg[3] == 0) {
2492		return 0;
2493	}
2494	if (pCurHcb->HCS_Msg[2] < default_period) {
2495		pCurHcb->HCS_Msg[2] = default_period;
2496		return 1;
2497	}
2498	if (pCurHcb->HCS_Msg[2] >= 59) {
2499		pCurHcb->HCS_Msg[3] = 0;
2500		return 1;
2501	}
2502	return 0;
2503}
2504
2505
2506/***************************************************************************/
2507int wdtr_done(HCS * pCurHcb)
2508{
2509	pCurHcb->HCS_ActTcs->TCS_Flags &= ~TCF_SYNC_DONE;
2510	pCurHcb->HCS_ActTcs->TCS_Flags |= TCF_WDTR_DONE;
2511
2512	pCurHcb->HCS_ActTcs->TCS_JS_Period = 0;
2513	if (pCurHcb->HCS_Msg[2]) {	/* if 16 bit */
2514		pCurHcb->HCS_ActTcs->TCS_JS_Period |= TSC_WIDE_SCSI;
2515	}
2516	pCurHcb->HCS_ActTcs->TCS_SConfig0 &= ~TSC_ALT_PERIOD;
2517	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_ActTcs->TCS_SConfig0);
2518	TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurHcb->HCS_ActTcs->TCS_JS_Period);
2519
2520	return 1;
2521}
2522
2523/***************************************************************************/
2524int tul_sync_done(HCS * pCurHcb)
2525{
2526	int i;
2527
2528	pCurHcb->HCS_ActTcs->TCS_Flags |= TCF_SYNC_DONE;
2529
2530	if (pCurHcb->HCS_Msg[3]) {
2531		pCurHcb->HCS_ActTcs->TCS_JS_Period |= pCurHcb->HCS_Msg[3];
2532		for (i = 0; i < 8; i++) {
2533			if (tul_rate_tbl[i] >= pCurHcb->HCS_Msg[2])	/* pick the big one */
2534				break;
2535		}
2536		pCurHcb->HCS_ActTcs->TCS_JS_Period |= (i << 4);
2537		pCurHcb->HCS_ActTcs->TCS_SConfig0 |= TSC_ALT_PERIOD;
2538	}
2539	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_ActTcs->TCS_SConfig0);
2540	TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurHcb->HCS_ActTcs->TCS_JS_Period);
2541
2542	return (-1);
2543}
2544
2545
2546int tul_post_scsi_rst(HCS * pCurHcb)
2547{
2548	SCB *pCurScb;
2549	TCS *pCurTcb;
2550	int i;
2551
2552	pCurHcb->HCS_ActScb = 0;
2553	pCurHcb->HCS_ActTcs = 0;
2554	pCurHcb->HCS_Flags = 0;
2555
2556	while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {
2557		pCurScb->SCB_HaStat = HOST_BAD_PHAS;
2558		tul_append_done_scb(pCurHcb, pCurScb);
2559	}
2560	/* clear sync done flag         */
2561	pCurTcb = &pCurHcb->HCS_Tcs[0];
2562	for (i = 0; i < pCurHcb->HCS_MaxTar; pCurTcb++, i++) {
2563		pCurTcb->TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
2564		/* Initialize the sync. xfer register values to an asyn xfer */
2565		pCurTcb->TCS_JS_Period = 0;
2566		pCurTcb->TCS_SConfig0 = pCurHcb->HCS_SConf1;
2567		pCurHcb->HCS_ActTags[0] = 0;	/* 07/22/98 */
2568		pCurHcb->HCS_Tcs[i].TCS_Flags &= ~TCF_BUSY;	/* 07/22/98 */
2569	}			/* for */
2570
2571	return (-1);
2572}
2573
2574/***************************************************************************/
2575void tul_select_atn_stop(HCS * pCurHcb, SCB * pCurScb)
2576{
2577	pCurScb->SCB_Status |= SCB_SELECT;
2578	pCurScb->SCB_NxtStat = 0x1;
2579	pCurHcb->HCS_ActScb = pCurScb;
2580	pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
2581	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SELATNSTOP);
2582	return;
2583}
2584
2585
2586/***************************************************************************/
2587void tul_select_atn(HCS * pCurHcb, SCB * pCurScb)
2588{
2589	int i;
2590
2591	pCurScb->SCB_Status |= SCB_SELECT;
2592	pCurScb->SCB_NxtStat = 0x2;
2593
2594	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident);
2595	for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++)
2596		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]);
2597	pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
2598	pCurHcb->HCS_ActScb = pCurScb;
2599	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SEL_ATN);
2600	return;
2601}
2602
2603/***************************************************************************/
2604void tul_select_atn3(HCS * pCurHcb, SCB * pCurScb)
2605{
2606	int i;
2607
2608	pCurScb->SCB_Status |= SCB_SELECT;
2609	pCurScb->SCB_NxtStat = 0x2;
2610
2611	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident);
2612	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagMsg);
2613	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagId);
2614	for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++)
2615		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]);
2616	pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
2617	pCurHcb->HCS_ActScb = pCurScb;
2618	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SEL_ATN3);
2619	return;
2620}
2621
2622/***************************************************************************/
2623/* SCSI Bus Device Reset */
2624int tul_bus_device_reset(HCS * pCurHcb)
2625{
2626	SCB *pCurScb = pCurHcb->HCS_ActScb;
2627	TCS *pCurTcb = pCurHcb->HCS_ActTcs;
2628	SCB *pTmpScb, *pPrevScb;
2629	BYTE tar;
2630
2631	if (pCurHcb->HCS_Phase != MSG_OUT) {
2632		return (int_tul_bad_seq(pCurHcb));	/* Unexpected phase             */
2633	}
2634	tul_unlink_pend_scb(pCurHcb, pCurScb);
2635	tul_release_scb(pCurHcb, pCurScb);
2636
2637
2638	tar = pCurScb->SCB_Target;	/* target                       */
2639	pCurTcb->TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE | TCF_BUSY);
2640	/* clr sync. nego & WDTR flags  07/22/98 */
2641
2642	/* abort all SCB with same target */
2643	pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;	/* Check Busy queue */
2644	while (pTmpScb != NULL) {
2645
2646		if (pTmpScb->SCB_Target == tar) {
2647			/* unlink it */
2648			if (pTmpScb == pCurHcb->HCS_FirstBusy) {
2649				if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
2650					pCurHcb->HCS_LastBusy = NULL;
2651			} else {
2652				pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
2653				if (pTmpScb == pCurHcb->HCS_LastBusy)
2654					pCurHcb->HCS_LastBusy = pPrevScb;
2655			}
2656			pTmpScb->SCB_HaStat = HOST_ABORTED;
2657			tul_append_done_scb(pCurHcb, pTmpScb);
2658		}
2659		/* Previous haven't change      */
2660		else {
2661			pPrevScb = pTmpScb;
2662		}
2663		pTmpScb = pTmpScb->SCB_NxtScb;
2664	}
2665
2666	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_DEVRST);
2667	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
2668
2669	return tul_wait_disc(pCurHcb);
2670
2671}
2672
2673/***************************************************************************/
2674int tul_msgin_accept(HCS * pCurHcb)
2675{
2676	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
2677	return (wait_tulip(pCurHcb));
2678}
2679
2680/***************************************************************************/
2681int wait_tulip(HCS * pCurHcb)
2682{
2683
2684	while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0))
2685		 & TSS_INT_PENDING));
2686
2687	pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
2688	pCurHcb->HCS_Phase = pCurHcb->HCS_JSStatus0 & TSS_PH_MASK;
2689	pCurHcb->HCS_JSStatus1 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1);
2690
2691	if (pCurHcb->HCS_JSInt & TSS_RESEL_INT) {	/* if SCSI bus reset detected   */
2692		return (int_tul_resel(pCurHcb));
2693	}
2694	if (pCurHcb->HCS_JSInt & TSS_SEL_TIMEOUT) {	/* if selected/reselected timeout interrupt */
2695		return (int_tul_busfree(pCurHcb));
2696	}
2697	if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {	/* if SCSI bus reset detected   */
2698		return (int_tul_scsi_rst(pCurHcb));
2699	}
2700	if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {	/* BUS disconnection            */
2701		if (pCurHcb->HCS_Flags & HCF_EXPECT_DONE_DISC) {
2702			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);		/* Flush SCSI FIFO  */
2703			tul_unlink_busy_scb(pCurHcb, pCurHcb->HCS_ActScb);
2704			pCurHcb->HCS_ActScb->SCB_HaStat = 0;
2705			tul_append_done_scb(pCurHcb, pCurHcb->HCS_ActScb);
2706			pCurHcb->HCS_ActScb = NULL;
2707			pCurHcb->HCS_ActTcs = NULL;
2708			pCurHcb->HCS_Flags &= ~HCF_EXPECT_DONE_DISC;
2709			TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
2710			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);	/* Enable HW reselect       */
2711			return (-1);
2712		}
2713		if (pCurHcb->HCS_Flags & HCF_EXPECT_DISC) {
2714			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);		/* Flush SCSI FIFO  */
2715			pCurHcb->HCS_ActScb = NULL;
2716			pCurHcb->HCS_ActTcs = NULL;
2717			pCurHcb->HCS_Flags &= ~HCF_EXPECT_DISC;
2718			TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
2719			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);	/* Enable HW reselect       */
2720			return (-1);
2721		}
2722		return (int_tul_busfree(pCurHcb));
2723	}
2724	if (pCurHcb->HCS_JSInt & (TSS_FUNC_COMP | TSS_BUS_SERV)) {
2725		return (pCurHcb->HCS_Phase);
2726	}
2727	return (pCurHcb->HCS_Phase);
2728}
2729/***************************************************************************/
2730int tul_wait_disc(HCS * pCurHcb)
2731{
2732
2733	while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0))
2734		 & TSS_INT_PENDING));
2735
2736
2737	pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
2738
2739	if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {	/* if SCSI bus reset detected   */
2740		return (int_tul_scsi_rst(pCurHcb));
2741	}
2742	if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {	/* BUS disconnection            */
2743		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);		/* Flush SCSI FIFO  */
2744		TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
2745		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);	/* Enable HW reselect       */
2746		pCurHcb->HCS_ActScb = NULL;
2747		return (-1);
2748	}
2749	return (tul_bad_seq(pCurHcb));
2750}
2751
2752/***************************************************************************/
2753int tul_wait_done_disc(HCS * pCurHcb)
2754{
2755
2756
2757	while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0))
2758		 & TSS_INT_PENDING));
2759
2760	pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
2761
2762
2763	if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {	/* if SCSI bus reset detected   */
2764		return (int_tul_scsi_rst(pCurHcb));
2765	}
2766	if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {	/* BUS disconnection            */
2767		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);		/* Flush SCSI FIFO  */
2768		TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
2769		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);	/* Enable HW reselect       */
2770		tul_unlink_busy_scb(pCurHcb, pCurHcb->HCS_ActScb);
2771
2772		tul_append_done_scb(pCurHcb, pCurHcb->HCS_ActScb);
2773		pCurHcb->HCS_ActScb = NULL;
2774		return (-1);
2775	}
2776	return (tul_bad_seq(pCurHcb));
2777}
2778
2779/**************************** EOF *********************************/
2780