OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [scsi/] [i91uscsi.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
/**************************************************************************
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 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*10 milliseconds */
222
        unsigned long the_time = jiffies + amount;      /* 0.01 seconds per jiffy */
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 * 100);
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 *********************************/

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.