linux-old/drivers/scsi/i91uscsi.c
<<
>>
Prefs
   1/**************************************************************************
   2 * Initio 9100 device driver for Linux.
   3 *
   4 * Copyright (c) 1994-1998 Initio Corporation
   5 * Copyright (c) 1998 Bas Vermeulen <bvermeul@blackstar.xs4all.nl>
   6 * All rights reserved.
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; either version 2, or (at your option)
  11 * any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; see the file COPYING.  If not, write to
  20 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  21 *
  22 * --------------------------------------------------------------------------
  23 *
  24 * Redistribution and use in source and binary forms, with or without
  25 * modification, are permitted provided that the following conditions
  26 * are met:
  27 * 1. Redistributions of source code must retain the above copyright
  28 *    notice, this list of conditions, and the following disclaimer,
  29 *    without modification, immediately at the beginning of the file.
  30 * 2. Redistributions in binary form must reproduce the above copyright
  31 *    notice, this list of conditions and the following disclaimer in the
  32 *    documentation and/or other materials provided with the distribution.
  33 * 3. The name of the author may not be used to endorse or promote products
  34 *    derived from this software without specific prior written permission.
  35 *
  36 * Where this Software is combined with software released under the terms of 
  37 * the GNU General Public License ("GPL") and the terms of the GPL would require the 
  38 * combined work to also be released under the terms of the GPL, the terms
  39 * and conditions of this License will apply in addition to those of the
  40 * GPL with the exception of any terms or conditions of this License that
  41 * conflict with, or are expressly prohibited by, the GPL.
  42 *
  43 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  46 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  47 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  53 * SUCH DAMAGE.
  54 *
  55 ************************************************************************
  56    Module: i91uscsi.c
  57    Description: PCI I/F for INI-910 SCSI Bus Master Controller
  58    Revision History:
  59        11/09/94 Tim Chen, Initiali Version 0.90A
  60        01/17/95 TC, release ver 1.01
  61        02/09/95 TC  modify ReadPCIConfig, try both mechanisms;
  62        02/15/95 TC  add support for INI-9100W
  63        06/04/96 HC, Change to fit LINUX from jaspci.c
  64        11/18/96 HC, Port for tulip
  65        07/08/98 hc, Support 0002134A
  66        07/23/98 wh, Change the abort_srb routine.
  67        09/16/98 hl, Support ALPHA, Rewrite the returnNumberAdapters    <01>
  68        12/09/98 bv, Removed unused code, changed tul_se2_wait to
  69                     use udelay(30) and tul_do_pause to enable 
  70                     interrupts for >= 2.1.95
  71        12/13/98 bv, Use spinlocks instead of cli() for serialized
  72                     access to HCS_Semaph, HCS_FirstAvail and HCS_LastAvail
  73                     members of the HCS structure.
  74        01/09/98 bv, Fix a deadlock on SMP system.
  75**********************************************************************/
  76
  77#define DEBUG_INTERRUPT 0
  78#define DEBUG_QUEUE     0
  79#define DEBUG_STATE     0
  80#define INT_DISC        0
  81
  82
  83#ifndef CVT_LINUX_VERSION
  84#define CVT_LINUX_VERSION(V,P,S)        (V * 65536 + P * 256 + S)
  85#endif
  86
  87#ifndef LINUX_VERSION_CODE
  88#include <linux/version.h>
  89#endif
  90
  91#include <linux/sched.h>
  92#include <linux/delay.h>
  93#include <linux/blk.h>
  94#include <asm/io.h>
  95
  96#include "i91uscsi.h"
  97
  98/*--- external functions --*/
  99static void tul_se2_wait(void);
 100
 101/*--- forward refrence ---*/
 102static SCB *tul_find_busy_scb(HCS * pCurHcb, WORD tarlun);
 103static SCB *tul_find_done_scb(HCS * pCurHcb);
 104
 105static int tulip_main(HCS * pCurHcb);
 106
 107static int tul_next_state(HCS * pCurHcb);
 108static int tul_state_1(HCS * pCurHcb);
 109static int tul_state_2(HCS * pCurHcb);
 110static int tul_state_3(HCS * pCurHcb);
 111static int tul_state_4(HCS * pCurHcb);
 112static int tul_state_5(HCS * pCurHcb);
 113static int tul_state_6(HCS * pCurHcb);
 114static int tul_state_7(HCS * pCurHcb);
 115static int tul_xfer_data_in(HCS * pCurHcb);
 116static int tul_xfer_data_out(HCS * pCurHcb);
 117static int tul_xpad_in(HCS * pCurHcb);
 118static int tul_xpad_out(HCS * pCurHcb);
 119static int tul_status_msg(HCS * pCurHcb);
 120
 121static int tul_msgin(HCS * pCurHcb);
 122static int tul_msgin_sync(HCS * pCurHcb);
 123static int tul_msgin_accept(HCS * pCurHcb);
 124static int tul_msgout_reject(HCS * pCurHcb);
 125static int tul_msgin_extend(HCS * pCurHcb);
 126
 127static int tul_msgout_ide(HCS * pCurHcb);
 128static int tul_msgout_abort_targ(HCS * pCurHcb);
 129static int tul_msgout_abort_tag(HCS * pCurHcb);
 130
 131static int tul_bus_device_reset(HCS * pCurHcb);
 132static void tul_select_atn(HCS * pCurHcb, SCB * pCurScb);
 133static void tul_select_atn3(HCS * pCurHcb, SCB * pCurScb);
 134static void tul_select_atn_stop(HCS * pCurHcb, SCB * pCurScb);
 135static int int_tul_busfree(HCS * pCurHcb);
 136int int_tul_scsi_rst(HCS * pCurHcb);
 137static int int_tul_bad_seq(HCS * pCurHcb);
 138static int int_tul_resel(HCS * pCurHcb);
 139static int tul_sync_done(HCS * pCurHcb);
 140static int wdtr_done(HCS * pCurHcb);
 141static int wait_tulip(HCS * pCurHcb);
 142static int tul_wait_done_disc(HCS * pCurHcb);
 143static int tul_wait_disc(HCS * pCurHcb);
 144static void tulip_scsi(HCS * pCurHcb);
 145static int tul_post_scsi_rst(HCS * pCurHcb);
 146
 147static void tul_se2_ew_en(WORD CurBase);
 148static void tul_se2_ew_ds(WORD CurBase);
 149static int tul_se2_rd_all(WORD CurBase);
 150static void tul_se2_update_all(WORD CurBase);   /* setup default pattern */
 151static void tul_read_eeprom(WORD CurBase);
 152
 153                                /* ---- EXTERNAL VARIABLES ---- */
 154HCS tul_hcs[MAX_SUPPORTED_ADAPTERS];
 155                                /* ---- INTERNAL VARIABLES ---- */
 156static INI_ADPT_STRUCT i91u_adpt[MAX_SUPPORTED_ADAPTERS];
 157
 158/*NVRAM nvram, *nvramp = &nvram; */
 159static NVRAM i91unvram;
 160static NVRAM *i91unvramp;
 161
 162
 163
 164static UCHAR i91udftNvRam[64] =
 165{
 166/*----------- header -----------*/
 167        0x25, 0xc9,             /* Signature    */
 168        0x40,                   /* Size         */
 169        0x01,                   /* Revision     */
 170        /* -- Host Adapter Structure -- */
 171        0x95,                   /* ModelByte0   */
 172        0x00,                   /* ModelByte1   */
 173        0x00,                   /* ModelInfo    */
 174        0x01,                   /* NumOfCh      */
 175        NBC1_DEFAULT,           /* BIOSConfig1  */
 176        0,                      /* BIOSConfig2  */
 177        0,                      /* HAConfig1    */
 178        0,                      /* HAConfig2    */
 179        /* SCSI channel 0 and target Structure  */
 180        7,                      /* SCSIid       */
 181        NCC1_DEFAULT,           /* SCSIconfig1  */
 182        0,                      /* SCSIconfig2  */
 183        0x10,                   /* NumSCSItarget */
 184
 185        NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
 186        NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
 187        NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
 188        NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
 189
 190        /* SCSI channel 1 and target Structure  */
 191        7,                      /* SCSIid       */
 192        NCC1_DEFAULT,           /* SCSIconfig1  */
 193        0,                      /* SCSIconfig2  */
 194        0x10,                   /* NumSCSItarget */
 195
 196        NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
 197        NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
 198        NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
 199        NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
 200        0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 201        0, 0};                  /*      - CheckSum -            */
 202
 203
 204static UCHAR tul_rate_tbl[8] =  /* fast 20      */
 205{
 206                                /* nanosecond devide by 4 */
 207        12,                     /* 50ns,  20M   */
 208        18,                     /* 75ns,  13.3M */
 209        25,                     /* 100ns, 10M   */
 210        31,                     /* 125ns, 8M    */
 211        37,                     /* 150ns, 6.6M  */
 212        43,                     /* 175ns, 5.7M  */
 213        50,                     /* 200ns, 5M    */
 214        62                      /* 250ns, 4M    */
 215};
 216
 217extern int tul_num_ch;
 218
 219
 220static void tul_do_pause(unsigned amount)
 221{                               /* Pause for amount jiffies */
 222        unsigned long the_time = jiffies + amount;
 223
 224#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
 225        while (time_before_eq(jiffies, the_time));
 226#else
 227        while (jiffies < the_time);
 228#endif
 229}
 230
 231/*-- forward reference --*/
 232
 233/*******************************************************************
 234        Use memeory refresh time        ~ 15us * 2
 235********************************************************************/
 236void tul_se2_wait()
 237{
 238#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******************************************************************/
 301void 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******************************************************************/
 332void 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*************************************************************************/
 344void 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*******************************************************************/
 357USHORT 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*******************************************************************/
 388void 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************************************************************************/
 430int 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************************************************************************/
 458void 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**************************************************************************/
 487void 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
 504int 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
 536void 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
 550void 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/***************************************************************************/
 562void 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/***************************************************************************/
 571int tul_reset_scsi(HCS * pCurHcb, int seconds)
 572{
 573        TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_BUS);
 574
 575        while (!((pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt)) & TSS_SCSIRST_INT));
 576        /* reset tulip chip */
 577
 578        TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, 0);
 579
 580        /* Stall for a while, wait for target's firmware ready,make it 2 sec ! */
 581        /* SONY 5200 tape drive won't work if only stall for 1 sec */
 582        tul_do_pause(seconds * HZ);
 583
 584        TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
 585
 586        return (SCSI_RESET_SUCCESS);
 587}
 588
 589/***************************************************************************/
 590int init_tulip(HCS * pCurHcb, SCB * scbp, int tul_num_scb, BYTE * pbBiosAdr, int seconds)
 591{
 592        int i;
 593        BYTE *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 = & (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/***************************************************************************/
 712SCB *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/***************************************************************************/
 740void 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/***************************************************************************/
 771void 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/***************************************************************************/
 789void 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/***************************************************************************/
 805SCB *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/***************************************************************************/
 836SCB *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/***************************************************************************/
 853void 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/***************************************************************************/
 881void 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/***************************************************************************/
 903SCB *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/***************************************************************************/
 924void 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/***************************************************************************/
 957SCB *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/***************************************************************************/
 979void 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/***************************************************************************/
 998SCB *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/***************************************************************************/
1015int 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/***************************************************************************/
1142int 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/************************************************************************/
1162int 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
1262int 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/************************************************************************/
1314void 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/***************************************************************************/
1360int 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/***************************************************************************/
1381int 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/***************************************************************************/
1467void 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/***************************************************************************/
1575int 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 */
1616int 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 */
1670int 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 */
1693int 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/***************************************************************************/
1759int 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 */
1819int 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 */
1905int 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/***************************************************************************/
1945int 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/***************************************************************************/
1968int 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/***************************************************************************/
1994int 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/***************************************************************************/
2020int 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
2046int 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/***************************************************************************/
2075int 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 */
2128int 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 */
2154int 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 */
2184int 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/***************************************************************************/
2260int 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/***************************************************************************/
2279int 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/***************************************************************************/
2295int 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/***************************************************************************/
2312int 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/***************************************************************************/
2387int 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/***************************************************************************/
2406int 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/***************************************************************************/
2415int 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/***************************************************************************/
2503int 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/***************************************************************************/
2536int 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/***************************************************************************/
2553int 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
2575int 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/***************************************************************************/
2604void 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/***************************************************************************/
2616void 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/***************************************************************************/
2633void 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 */
2653int 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/***************************************************************************/
2703int 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/***************************************************************************/
2710int 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/***************************************************************************/
2759int 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/***************************************************************************/
2782int 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 *********************************/
2809
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.