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