^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 1996 John Shifflett, GeoLog Consulting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * john@geolog.com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * jshiffle@netcom.com
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Drew Eckhardt's excellent 'Generic NCR5380' sources from Linux-PC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * provided much of the inspiration and some of the code for this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * driver. Everything I know about Amiga DMA was gleaned from careful
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * reading of Hamish Mcdonald's original wd33c93 driver; in fact, I
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * borrowed shamelessly from all over that source. Thanks Hamish!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * _This_ driver is (I feel) an improvement over the old one in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * several respects:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * - Target Disconnection/Reconnection is now supported. Any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * system with more than one device active on the SCSI bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * will benefit from this. The driver defaults to what I
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * call 'adaptive disconnect' - meaning that each command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * is evaluated individually as to whether or not it should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * be run with the option to disconnect/reselect (if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * device chooses), or as a "SCSI-bus-hog".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * - Synchronous data transfers are now supported. Because of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * a few devices that choke after telling the driver that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * they can do sync transfers, we don't automatically use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * this faster protocol - it can be enabled via the command-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * line on a device-by-device basis.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * - Runtime operating parameters can now be specified through
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * the 'amiboot' or the 'insmod' command line. For amiboot do:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * "amiboot [usual stuff] wd33c93=blah,blah,blah"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * The defaults should be good for most people. See the comment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * for 'setup_strings' below for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * - The old driver relied exclusively on what the Western Digital
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * docs call "Combination Level 2 Commands", which are a great
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * idea in that the CPU is relieved of a lot of interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * overhead. However, by accepting a certain (user-settable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) * amount of additional interrupts, this driver achieves
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * better control over the SCSI bus, and data transfers are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * almost as fast while being much easier to define, track,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * and debug.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * TODO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * more speed. linked commands.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * People with bug reports, wish-lists, complaints, comments,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) * or improvements are asked to pah-leeez email me (John Shifflett)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * at john@geolog.com or jshiffle@netcom.com! I'm anxious to get
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * this thing into as good a shape as possible, and I'm positive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) * there are lots of lurking bugs and "Stupid Places".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * Updates:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * Added support for pre -A chips, which don't have advanced features
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * and will generate CSR_RESEL rather than CSR_RESEL_AM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * Richard Hirst <richard@sleepie.demon.co.uk> August 2000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * Added support for Burst Mode DMA and Fast SCSI. Enabled the use of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * default_sx_per for asynchronous data transfers. Added adjustment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * of transfer periods in sx_table to the actual input-clock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * peter fuerst <post@pfrst.de> February 2007
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #include <linux/blkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #include <scsi/scsi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #include <scsi/scsi_cmnd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #include <scsi/scsi_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #include <scsi/scsi_host.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #include "wd33c93.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define optimum_sx_per(hostdata) (hostdata)->sx_table[1].period_ns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define WD33C93_VERSION "1.26++"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define WD33C93_DATE "10/Feb/2007"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) MODULE_AUTHOR("John Shifflett");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) MODULE_DESCRIPTION("Generic WD33C93 SCSI driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * 'setup_strings' is a single string used to pass operating parameters and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * settings from the kernel/module command-line to the driver. 'setup_args[]'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * is an array of strings that define the compile-time default values for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * these settings. If Linux boots with an amiboot or insmod command-line,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * those settings are combined with 'setup_args[]'. Note that amiboot
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * command-lines are prefixed with "wd33c93=" while insmod uses a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * "setup_strings=" prefix. The driver recognizes the following keywords
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * (lower case required) and arguments:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * - nosync:bitmask -bitmask is a byte where the 1st 7 bits correspond with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * the 7 possible SCSI devices. Set a bit to negotiate for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * asynchronous transfers on that device. To maintain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * backwards compatibility, a command-line such as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * "wd33c93=255" will be automatically translated to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * "wd33c93=nosync:0xff".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * - nodma:x -x = 1 to disable DMA, x = 0 to enable it. Argument is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * optional - if not present, same as "nodma:1".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * - period:ns -ns is the minimum # of nanoseconds in a SCSI data transfer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * period. Default is 500; acceptable values are 250 - 1000.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * - disconnect:x -x = 0 to never allow disconnects, 2 to always allow them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * x = 1 does 'adaptive' disconnects, which is the default
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * and generally the best choice.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * - debug:x -If 'DEBUGGING_ON' is defined, x is a bit mask that causes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * various types of debug output to printed - see the DB_xxx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * defines in wd33c93.h
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * - clock:x -x = clock input in MHz for WD33c93 chip. Normal values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * would be from 8 through 20. Default is 8.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * - burst:x -x = 1 to use Burst Mode (or Demand-Mode) DMA, x = 0 to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * Single Byte DMA, which is the default. Argument is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * optional - if not present, same as "burst:1".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) * - fast:x -x = 1 to enable Fast SCSI, which is only effective with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * input-clock divisor 4 (WD33C93_FS_16_20), x = 0 to disable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * it, which is the default. Argument is optional - if not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * present, same as "fast:1".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * - next -No argument. Used to separate blocks of keywords when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * there's more than one host adapter in the system.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * Syntax Notes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * - Numeric arguments can be decimal or the '0x' form of hex notation. There
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * _must_ be a colon between a keyword and its numeric argument, with no
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * spaces.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * - Keywords are separated by commas, no spaces, in the standard kernel
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * command-line manner.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * - A keyword in the 'nth' comma-separated command-line member will overwrite
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * the 'nth' element of setup_args[]. A blank command-line member (in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * other words, a comma with no preceding keyword) will _not_ overwrite
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * the corresponding setup_args[] element.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) * - If a keyword is used more than once, the first one applies to the first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * SCSI host found, the second to the second card, etc, unless the 'next'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * keyword is used to change the order.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * Some amiboot examples (for insmod, use 'setup_strings' instead of 'wd33c93'):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * - wd33c93=nosync:255
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * - wd33c93=nodma
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * - wd33c93=nodma:1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * - wd33c93=disconnect:2,nosync:0x08,period:250
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * - wd33c93=debug:0x1c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) /* Normally, no defaults are specified */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static char *setup_args[] = { "", "", "", "", "", "", "", "", "", "" };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) static char *setup_strings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) module_param(setup_strings, charp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static void wd33c93_execute(struct Scsi_Host *instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) #ifdef CONFIG_WD33C93_PIO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) static inline uchar
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) read_wd33c93(const wd33c93_regs regs, uchar reg_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) uchar data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) outb(reg_num, regs.SASR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) data = inb(regs.SCMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) return data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) static inline unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) read_wd33c93_count(const wd33c93_regs regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) unsigned long value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) outb(WD_TRANSFER_COUNT_MSB, regs.SASR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) value = inb(regs.SCMD) << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) value |= inb(regs.SCMD) << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) value |= inb(regs.SCMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static inline uchar
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) read_aux_stat(const wd33c93_regs regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) return inb(regs.SASR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) write_wd33c93(const wd33c93_regs regs, uchar reg_num, uchar value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) outb(reg_num, regs.SASR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) outb(value, regs.SCMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) write_wd33c93_count(const wd33c93_regs regs, unsigned long value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) outb(WD_TRANSFER_COUNT_MSB, regs.SASR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) outb((value >> 16) & 0xff, regs.SCMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) outb((value >> 8) & 0xff, regs.SCMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) outb( value & 0xff, regs.SCMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) #define write_wd33c93_cmd(regs, cmd) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) write_wd33c93((regs), WD_COMMAND, (cmd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) write_wd33c93_cdb(const wd33c93_regs regs, uint len, uchar cmnd[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) outb(WD_CDB_1, regs.SASR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) for (i=0; i<len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) outb(cmnd[i], regs.SCMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) #else /* CONFIG_WD33C93_PIO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) static inline uchar
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) read_wd33c93(const wd33c93_regs regs, uchar reg_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) *regs.SASR = reg_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return (*regs.SCMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) read_wd33c93_count(const wd33c93_regs regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) unsigned long value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) *regs.SASR = WD_TRANSFER_COUNT_MSB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) value = *regs.SCMD << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) value |= *regs.SCMD << 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) value |= *regs.SCMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) static inline uchar
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) read_aux_stat(const wd33c93_regs regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return *regs.SASR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) write_wd33c93(const wd33c93_regs regs, uchar reg_num, uchar value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) *regs.SASR = reg_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) *regs.SCMD = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) write_wd33c93_count(const wd33c93_regs regs, unsigned long value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) *regs.SASR = WD_TRANSFER_COUNT_MSB;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) *regs.SCMD = value >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) *regs.SCMD = value >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) *regs.SCMD = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) write_wd33c93_cmd(const wd33c93_regs regs, uchar cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) *regs.SASR = WD_COMMAND;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) *regs.SCMD = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) write_wd33c93_cdb(const wd33c93_regs regs, uint len, uchar cmnd[])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) *regs.SASR = WD_CDB_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) for (i = 0; i < len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) *regs.SCMD = cmnd[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) #endif /* CONFIG_WD33C93_PIO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) static inline uchar
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) read_1_byte(const wd33c93_regs regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) uchar asr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) uchar x = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) write_wd33c93_cmd(regs, WD_CMD_TRANS_INFO | 0x80);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) asr = read_aux_stat(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if (asr & ASR_DBR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) x = read_wd33c93(regs, WD_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) } while (!(asr & ASR_INT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) round_period(unsigned int period, const struct sx_period *sx_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) int x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) for (x = 1; sx_table[x].period_ns; x++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if ((period <= sx_table[x - 0].period_ns) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) (period > sx_table[x - 1].period_ns)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) return x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) * Calculate Synchronous Transfer Register value from SDTR code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) static uchar
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) calc_sync_xfer(unsigned int period, unsigned int offset, unsigned int fast,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) const struct sx_period *sx_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /* When doing Fast SCSI synchronous data transfers, the corresponding
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) * value in 'sx_table' is two times the actually used transfer period.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) uchar result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if (offset && fast) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) fast = STR_FSS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) period *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) fast = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) period *= 4; /* convert SDTR code to ns */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) result = sx_table[round_period(period,sx_table)].reg_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) result |= (offset < OPTIMUM_SX_OFF) ? offset : OPTIMUM_SX_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) result |= fast;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) * Calculate SDTR code bytes [3],[4] from period and offset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) calc_sync_msg(unsigned int period, unsigned int offset, unsigned int fast,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) uchar msg[2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) /* 'period' is a "normal"-mode value, like the ones in 'sx_table'. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) * actually used transfer period for Fast SCSI synchronous data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) * transfers is half that value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) period /= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (offset && fast)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) period /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) msg[0] = period;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) msg[1] = offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) wd33c93_queuecommand_lck(struct scsi_cmnd *cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) void (*done)(struct scsi_cmnd *))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) struct WD33C93_hostdata *hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) struct scsi_cmnd *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) hostdata = (struct WD33C93_hostdata *) cmd->device->host->hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) DB(DB_QUEUE_COMMAND,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) printk("Q-%d-%02x( ", cmd->device->id, cmd->cmnd[0]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) /* Set up a few fields in the scsi_cmnd structure for our own use:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) * - host_scribble is the pointer to the next cmd in the input queue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) * - scsi_done points to the routine we call when a cmd is finished
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) * - result is what you'd expect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) cmd->host_scribble = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) cmd->scsi_done = done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) cmd->result = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) /* We use the Scsi_Pointer structure that's included with each command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) * as a scratchpad (as it's intended to be used!). The handy thing about
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) * the SCp.xxx fields is that they're always associated with a given
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) * cmd, and are preserved across disconnect-reselect. This means we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) * can pretty much ignore SAVE_POINTERS and RESTORE_POINTERS messages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) * if we keep all the critical pointers and counters in SCp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) * - SCp.ptr is the pointer into the RAM buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * - SCp.this_residual is the size of that buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) * - SCp.buffer points to the current scatter-gather buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) * - SCp.buffers_residual tells us how many S.G. buffers there are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) * - SCp.have_data_in is not used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) * - SCp.sent_command is not used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) * - SCp.phase records this command's SRCID_ER bit setting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) if (scsi_bufflen(cmd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) cmd->SCp.buffer = scsi_sglist(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) cmd->SCp.buffers_residual = scsi_sg_count(cmd) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) cmd->SCp.this_residual = cmd->SCp.buffer->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) cmd->SCp.buffer = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) cmd->SCp.buffers_residual = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) cmd->SCp.ptr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) cmd->SCp.this_residual = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) /* WD docs state that at the conclusion of a "LEVEL2" command, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * status byte can be retrieved from the LUN register. Apparently,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * this is the case only for *uninterrupted* LEVEL2 commands! If
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) * there are any unexpected phases entered, even if they are 100%
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * legal (different devices may choose to do things differently),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * the LEVEL2 command sequence is exited. This often occurs prior
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) * to receiving the status byte, in which case the driver does a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) * status phase interrupt and gets the status byte on its own.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) * While such a command can then be "resumed" (ie restarted to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) * finish up as a LEVEL2 command), the LUN register will NOT be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) * a valid status byte at the command's conclusion, and we must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) * use the byte obtained during the earlier interrupt. Here, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) * preset SCp.Status to an illegal value (0xff) so that when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) * this command finally completes, we can tell where the actual
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * status byte is stored.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) cmd->SCp.Status = ILLEGAL_STATUS_BYTE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) * Add the cmd to the end of 'input_Q'. Note that REQUEST SENSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) * commands are added to the head of the queue so that the desired
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) * sense data is not lost before REQUEST_SENSE executes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) spin_lock_irq(&hostdata->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) if (!(hostdata->input_Q) || (cmd->cmnd[0] == REQUEST_SENSE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) cmd->host_scribble = (uchar *) hostdata->input_Q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) hostdata->input_Q = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) } else { /* find the end of the queue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) for (tmp = (struct scsi_cmnd *) hostdata->input_Q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) tmp->host_scribble;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) tmp = (struct scsi_cmnd *) tmp->host_scribble) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) tmp->host_scribble = (uchar *) cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) /* We know that there's at least one command in 'input_Q' now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) * Go see if any of them are runnable!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) wd33c93_execute(cmd->device->host);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) DB(DB_QUEUE_COMMAND, printk(")Q "))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) spin_unlock_irq(&hostdata->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) DEF_SCSI_QCMD(wd33c93_queuecommand)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) * This routine attempts to start a scsi command. If the host_card is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) * already connected, we give up immediately. Otherwise, look through
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) * the input_Q, using the first command we find that's intended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) * for a currently non-busy target/lun.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) * wd33c93_execute() is always called with interrupts disabled or from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * the wd33c93_intr itself, which means that a wd33c93 interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) * cannot occur while we are in here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) wd33c93_execute(struct Scsi_Host *instance)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) struct WD33C93_hostdata *hostdata =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) (struct WD33C93_hostdata *) instance->hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) const wd33c93_regs regs = hostdata->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) struct scsi_cmnd *cmd, *prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) DB(DB_EXECUTE, printk("EX("))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (hostdata->selecting || hostdata->connected) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) DB(DB_EXECUTE, printk(")EX-0 "))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) * Search through the input_Q for a command destined
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) * for an idle target/lun.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) cmd = (struct scsi_cmnd *) hostdata->input_Q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) while (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if (!(hostdata->busy[cmd->device->id] &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) (1 << (cmd->device->lun & 0xff))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) prev = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) cmd = (struct scsi_cmnd *) cmd->host_scribble;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) /* quit if queue empty or all possible targets are busy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) if (!cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) DB(DB_EXECUTE, printk(")EX-1 "))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) /* remove command from queue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (prev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) prev->host_scribble = cmd->host_scribble;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) hostdata->input_Q = (struct scsi_cmnd *) cmd->host_scribble;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) #ifdef PROC_STATISTICS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) hostdata->cmd_cnt[cmd->device->id]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) * Start the selection process
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) if (cmd->sc_data_direction == DMA_TO_DEVICE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) write_wd33c93(regs, WD_DESTINATION_ID, cmd->device->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) write_wd33c93(regs, WD_DESTINATION_ID, cmd->device->id | DSTID_DPD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) /* Now we need to figure out whether or not this command is a good
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) * candidate for disconnect/reselect. We guess to the best of our
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) * ability, based on a set of hierarchical rules. When several
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) * devices are operating simultaneously, disconnects are usually
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) * an advantage. In a single device system, or if only 1 device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) * is being accessed, transfers usually go faster if disconnects
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) * are not allowed:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) * + Commands should NEVER disconnect if hostdata->disconnect =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) * DIS_NEVER (this holds for tape drives also), and ALWAYS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) * disconnect if hostdata->disconnect = DIS_ALWAYS.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) * + Tape drive commands should always be allowed to disconnect.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) * + Disconnect should be allowed if disconnected_Q isn't empty.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) * + Commands should NOT disconnect if input_Q is empty.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) * + Disconnect should be allowed if there are commands in input_Q
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) * for a different target/lun. In this case, the other commands
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) * should be made disconnect-able, if not already.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) * I know, I know - this code would flunk me out of any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) * "C Programming 101" class ever offered. But it's easy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) * to change around and experiment with for now.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) cmd->SCp.phase = 0; /* assume no disconnect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (hostdata->disconnect == DIS_NEVER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) goto no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if (hostdata->disconnect == DIS_ALWAYS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) goto yes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) if (cmd->device->type == 1) /* tape drive? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) goto yes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) if (hostdata->disconnected_Q) /* other commands disconnected? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) goto yes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (!(hostdata->input_Q)) /* input_Q empty? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) goto no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) for (prev = (struct scsi_cmnd *) hostdata->input_Q; prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) prev = (struct scsi_cmnd *) prev->host_scribble) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if ((prev->device->id != cmd->device->id) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) (prev->device->lun != cmd->device->lun)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) for (prev = (struct scsi_cmnd *) hostdata->input_Q; prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) prev = (struct scsi_cmnd *) prev->host_scribble)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) prev->SCp.phase = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) goto yes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) goto no;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) yes:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) cmd->SCp.phase = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) #ifdef PROC_STATISTICS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) hostdata->disc_allowed_cnt[cmd->device->id]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) no:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) write_wd33c93(regs, WD_SOURCE_ID, ((cmd->SCp.phase) ? SRCID_ER : 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) write_wd33c93(regs, WD_TARGET_LUN, (u8)cmd->device->lun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) hostdata->sync_xfer[cmd->device->id]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) hostdata->busy[cmd->device->id] |= (1 << (cmd->device->lun & 0xFF));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) if ((hostdata->level2 == L2_NONE) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) (hostdata->sync_stat[cmd->device->id] == SS_UNSET)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) * Do a 'Select-With-ATN' command. This will end with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) * one of the following interrupts:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) * CSR_RESEL_AM: failure - can try again later.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) * CSR_TIMEOUT: failure - give up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) * CSR_SELECT: success - proceed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) hostdata->selecting = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) /* Every target has its own synchronous transfer setting, kept in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) * sync_xfer array, and a corresponding status byte in sync_stat[].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) * Each target's sync_stat[] entry is initialized to SX_UNSET, and its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) * sync_xfer[] entry is initialized to the default/safe value. SS_UNSET
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) * means that the parameters are undetermined as yet, and that we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) * need to send an SDTR message to this device after selection is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) * complete: We set SS_FIRST to tell the interrupt routine to do so.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) * If we've been asked not to try synchronous transfers on this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) * target (and _all_ luns within it), we'll still send the SDTR message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) * later, but at that time we'll negotiate for async by specifying a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) * sync fifo depth of 0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) if (hostdata->sync_stat[cmd->device->id] == SS_UNSET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) hostdata->sync_stat[cmd->device->id] = SS_FIRST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) hostdata->state = S_SELECTING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) write_wd33c93_count(regs, 0); /* guarantee a DATA_PHASE interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) write_wd33c93_cmd(regs, WD_CMD_SEL_ATN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) * Do a 'Select-With-ATN-Xfer' command. This will end with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) * one of the following interrupts:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) * CSR_RESEL_AM: failure - can try again later.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) * CSR_TIMEOUT: failure - give up.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) * anything else: success - proceed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) hostdata->connected = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) write_wd33c93(regs, WD_COMMAND_PHASE, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) /* copy command_descriptor_block into WD chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) * (take advantage of auto-incrementing)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) write_wd33c93_cdb(regs, cmd->cmd_len, cmd->cmnd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) /* The wd33c93 only knows about Group 0, 1, and 5 commands when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) * it's doing a 'select-and-transfer'. To be safe, we write the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) * size of the CDB into the OWN_ID register for every case. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) * way there won't be problems with vendor-unique, audio, etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) write_wd33c93(regs, WD_OWN_ID, cmd->cmd_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) /* When doing a non-disconnect command with DMA, we can save
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) * ourselves a DATA phase interrupt later by setting everything
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) * up ahead of time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if ((cmd->SCp.phase == 0) && (hostdata->no_dma == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) if (hostdata->dma_setup(cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) (cmd->sc_data_direction == DMA_TO_DEVICE) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) DATA_OUT_DIR : DATA_IN_DIR))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) write_wd33c93_count(regs, 0); /* guarantee a DATA_PHASE interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) write_wd33c93_count(regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) cmd->SCp.this_residual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) write_wd33c93(regs, WD_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) CTRL_IDI | CTRL_EDI | hostdata->dma_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) hostdata->dma = D_DMA_RUNNING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) write_wd33c93_count(regs, 0); /* guarantee a DATA_PHASE interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) hostdata->state = S_RUNNING_LEVEL2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) write_wd33c93_cmd(regs, WD_CMD_SEL_ATN_XFER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * Since the SCSI bus can handle only 1 connection at a time,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * we get out of here now. If the selection fails, or when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) * the command disconnects, we'll come back to this routine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) * to search the input_Q again...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) DB(DB_EXECUTE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) printk("%s)EX-2 ", (cmd->SCp.phase) ? "d:" : ""))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) transfer_pio(const wd33c93_regs regs, uchar * buf, int cnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) int data_in_dir, struct WD33C93_hostdata *hostdata)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) uchar asr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) DB(DB_TRANSFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) printk("(%p,%d,%s:", buf, cnt, data_in_dir ? "in" : "out"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) write_wd33c93_count(regs, cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) write_wd33c93_cmd(regs, WD_CMD_TRANS_INFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) if (data_in_dir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) asr = read_aux_stat(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) if (asr & ASR_DBR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) *buf++ = read_wd33c93(regs, WD_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) } while (!(asr & ASR_INT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) asr = read_aux_stat(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (asr & ASR_DBR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) write_wd33c93(regs, WD_DATA, *buf++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) } while (!(asr & ASR_INT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) /* Note: we are returning with the interrupt UN-cleared.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) * Since (presumably) an entire I/O operation has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) * completed, the bus phase is probably different, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) * the interrupt routine will discover this when it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) * responds to the uncleared int.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) transfer_bytes(const wd33c93_regs regs, struct scsi_cmnd *cmd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) int data_in_dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) struct WD33C93_hostdata *hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) unsigned long length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) hostdata = (struct WD33C93_hostdata *) cmd->device->host->hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) /* Normally, you'd expect 'this_residual' to be non-zero here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) * In a series of scatter-gather transfers, however, this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) * routine will usually be called with 'this_residual' equal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) * to 0 and 'buffers_residual' non-zero. This means that a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) * previous transfer completed, clearing 'this_residual', and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) * now we need to setup the next scatter-gather buffer as the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) * source or destination for THIS transfer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) cmd->SCp.buffer = sg_next(cmd->SCp.buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) --cmd->SCp.buffers_residual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) cmd->SCp.this_residual = cmd->SCp.buffer->length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) cmd->SCp.ptr = sg_virt(cmd->SCp.buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (!cmd->SCp.this_residual) /* avoid bogus setups */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) hostdata->sync_xfer[cmd->device->id]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) /* 'hostdata->no_dma' is TRUE if we don't even want to try DMA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) * Update 'this_residual' and 'ptr' after 'transfer_pio()' returns.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) if (hostdata->no_dma || hostdata->dma_setup(cmd, data_in_dir)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) #ifdef PROC_STATISTICS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) hostdata->pio_cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) transfer_pio(regs, (uchar *) cmd->SCp.ptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) cmd->SCp.this_residual, data_in_dir, hostdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) length = cmd->SCp.this_residual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) cmd->SCp.this_residual = read_wd33c93_count(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) cmd->SCp.ptr += (length - cmd->SCp.this_residual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) /* We are able to do DMA (in fact, the Amiga hardware is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) * already going!), so start up the wd33c93 in DMA mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) * We set 'hostdata->dma' = D_DMA_RUNNING so that when the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) * transfer completes and causes an interrupt, we're
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) * reminded to tell the Amiga to shut down its end. We'll
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) * postpone the updating of 'this_residual' and 'ptr'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) * until then.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) #ifdef PROC_STATISTICS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) hostdata->dma_cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | hostdata->dma_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) write_wd33c93_count(regs, cmd->SCp.this_residual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if ((hostdata->level2 >= L2_DATA) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) (hostdata->level2 == L2_BASIC && cmd->SCp.phase == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) write_wd33c93(regs, WD_COMMAND_PHASE, 0x45);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) write_wd33c93_cmd(regs, WD_CMD_SEL_ATN_XFER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) hostdata->state = S_RUNNING_LEVEL2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) write_wd33c93_cmd(regs, WD_CMD_TRANS_INFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) hostdata->dma = D_DMA_RUNNING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) wd33c93_intr(struct Scsi_Host *instance)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) struct WD33C93_hostdata *hostdata =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) (struct WD33C93_hostdata *) instance->hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) const wd33c93_regs regs = hostdata->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) struct scsi_cmnd *patch, *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) uchar asr, sr, phs, id, lun, *ucp, msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) unsigned long length, flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) asr = read_aux_stat(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) if (!(asr & ASR_INT) || (asr & ASR_BSY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) spin_lock_irqsave(&hostdata->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) #ifdef PROC_STATISTICS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) hostdata->int_cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) cmd = (struct scsi_cmnd *) hostdata->connected; /* assume we're connected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) sr = read_wd33c93(regs, WD_SCSI_STATUS); /* clear the interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) phs = read_wd33c93(regs, WD_COMMAND_PHASE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) DB(DB_INTR, printk("{%02x:%02x-", asr, sr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) /* After starting a DMA transfer, the next interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) * is guaranteed to be in response to completion of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) * the transfer. Since the Amiga DMA hardware runs in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) * in an open-ended fashion, it needs to be told when
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) * to stop; do that here if D_DMA_RUNNING is true.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) * Also, we have to update 'this_residual' and 'ptr'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) * based on the contents of the TRANSFER_COUNT register,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) * in case the device decided to do an intermediate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) * disconnect (a device may do this if it has to do a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) * seek, or just to be nice and let other devices have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) * some bus time during long transfers). After doing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) * whatever is needed, we go on and service the WD3393
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) * interrupt normally.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) if (hostdata->dma == D_DMA_RUNNING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) DB(DB_TRANSFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) printk("[%p/%d:", cmd->SCp.ptr, cmd->SCp.this_residual))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) hostdata->dma_stop(cmd->device->host, cmd, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) hostdata->dma = D_DMA_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) length = cmd->SCp.this_residual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) cmd->SCp.this_residual = read_wd33c93_count(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) cmd->SCp.ptr += (length - cmd->SCp.this_residual);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) DB(DB_TRANSFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) printk("%p/%d]", cmd->SCp.ptr, cmd->SCp.this_residual))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) /* Respond to the specific WD3393 interrupt - there are quite a few! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) switch (sr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) case CSR_TIMEOUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) DB(DB_INTR, printk("TIMEOUT"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) if (hostdata->state == S_RUNNING_LEVEL2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) hostdata->connected = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) cmd = (struct scsi_cmnd *) hostdata->selecting; /* get a valid cmd */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) hostdata->selecting = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) cmd->result = DID_NO_CONNECT << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) hostdata->state = S_UNCONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) cmd->scsi_done(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) /* From esp.c:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) * There is a window of time within the scsi_done() path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) * of execution where interrupts are turned back on full
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) * blast and left that way. During that time we could
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) * reconnect to a disconnected command, then we'd bomb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) * out below. We could also end up executing two commands
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) * at _once_. ...just so you know why the restore_flags()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) * is here...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) spin_unlock_irqrestore(&hostdata->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) /* We are not connected to a target - check to see if there
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) * are commands waiting to be executed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) wd33c93_execute(instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) /* Note: this interrupt should not occur in a LEVEL2 command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) case CSR_SELECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) DB(DB_INTR, printk("SELECT"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) hostdata->connected = cmd =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) (struct scsi_cmnd *) hostdata->selecting;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) hostdata->selecting = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) /* construct an IDENTIFY message with correct disconnect bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) hostdata->outgoing_msg[0] = IDENTIFY(0, cmd->device->lun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) if (cmd->SCp.phase)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) hostdata->outgoing_msg[0] |= 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) if (hostdata->sync_stat[cmd->device->id] == SS_FIRST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) hostdata->sync_stat[cmd->device->id] = SS_WAITING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) /* Tack on a 2nd message to ask about synchronous transfers. If we've
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) * been asked to do only asynchronous transfers on this device, we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) * request a fifo depth of 0, which is equivalent to async - should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) * solve the problems some people have had with GVP's Guru ROM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) hostdata->outgoing_msg[1] = EXTENDED_MESSAGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) hostdata->outgoing_msg[2] = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) hostdata->outgoing_msg[3] = EXTENDED_SDTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) if (hostdata->no_sync & (1 << cmd->device->id)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) calc_sync_msg(hostdata->default_sx_per, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) 0, hostdata->outgoing_msg + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) calc_sync_msg(optimum_sx_per(hostdata),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) OPTIMUM_SX_OFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) hostdata->fast,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) hostdata->outgoing_msg + 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) hostdata->outgoing_len = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) #ifdef SYNC_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) ucp = hostdata->outgoing_msg + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) printk(" sending SDTR %02x03%02x%02x%02x ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) ucp[0], ucp[2], ucp[3], ucp[4]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) hostdata->outgoing_len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) hostdata->state = S_CONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) spin_unlock_irqrestore(&hostdata->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) case CSR_XFER_DONE | PHS_DATA_IN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) case CSR_UNEXP | PHS_DATA_IN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) case CSR_SRV_REQ | PHS_DATA_IN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) DB(DB_INTR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) printk("IN-%d.%d", cmd->SCp.this_residual,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) cmd->SCp.buffers_residual))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) transfer_bytes(regs, cmd, DATA_IN_DIR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) if (hostdata->state != S_RUNNING_LEVEL2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) hostdata->state = S_CONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) spin_unlock_irqrestore(&hostdata->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) case CSR_XFER_DONE | PHS_DATA_OUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) case CSR_UNEXP | PHS_DATA_OUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) case CSR_SRV_REQ | PHS_DATA_OUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) DB(DB_INTR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) printk("OUT-%d.%d", cmd->SCp.this_residual,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) cmd->SCp.buffers_residual))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) transfer_bytes(regs, cmd, DATA_OUT_DIR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) if (hostdata->state != S_RUNNING_LEVEL2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) hostdata->state = S_CONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) spin_unlock_irqrestore(&hostdata->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) /* Note: this interrupt should not occur in a LEVEL2 command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) case CSR_XFER_DONE | PHS_COMMAND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) case CSR_UNEXP | PHS_COMMAND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) case CSR_SRV_REQ | PHS_COMMAND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) DB(DB_INTR, printk("CMND-%02x", cmd->cmnd[0]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) transfer_pio(regs, cmd->cmnd, cmd->cmd_len, DATA_OUT_DIR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) hostdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) hostdata->state = S_CONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) spin_unlock_irqrestore(&hostdata->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) case CSR_XFER_DONE | PHS_STATUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) case CSR_UNEXP | PHS_STATUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) case CSR_SRV_REQ | PHS_STATUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) DB(DB_INTR, printk("STATUS="))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) cmd->SCp.Status = read_1_byte(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) DB(DB_INTR, printk("%02x", cmd->SCp.Status))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) if (hostdata->level2 >= L2_BASIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) sr = read_wd33c93(regs, WD_SCSI_STATUS); /* clear interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) udelay(7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) hostdata->state = S_RUNNING_LEVEL2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) write_wd33c93(regs, WD_COMMAND_PHASE, 0x50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) write_wd33c93_cmd(regs, WD_CMD_SEL_ATN_XFER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) hostdata->state = S_CONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) spin_unlock_irqrestore(&hostdata->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) case CSR_XFER_DONE | PHS_MESS_IN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) case CSR_UNEXP | PHS_MESS_IN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) case CSR_SRV_REQ | PHS_MESS_IN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) DB(DB_INTR, printk("MSG_IN="))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) msg = read_1_byte(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) sr = read_wd33c93(regs, WD_SCSI_STATUS); /* clear interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) udelay(7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) hostdata->incoming_msg[hostdata->incoming_ptr] = msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) if (hostdata->incoming_msg[0] == EXTENDED_MESSAGE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) msg = EXTENDED_MESSAGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) hostdata->incoming_ptr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) cmd->SCp.Message = msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) switch (msg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) case COMMAND_COMPLETE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) DB(DB_INTR, printk("CCMP"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) hostdata->state = S_PRE_CMP_DISC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) case SAVE_POINTERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) DB(DB_INTR, printk("SDP"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) hostdata->state = S_CONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) case RESTORE_POINTERS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) DB(DB_INTR, printk("RDP"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) if (hostdata->level2 >= L2_BASIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) write_wd33c93(regs, WD_COMMAND_PHASE, 0x45);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) write_wd33c93_cmd(regs, WD_CMD_SEL_ATN_XFER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) hostdata->state = S_RUNNING_LEVEL2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) hostdata->state = S_CONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) case DISCONNECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) DB(DB_INTR, printk("DIS"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) cmd->device->disconnect = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) hostdata->state = S_PRE_TMP_DISC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) case MESSAGE_REJECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) DB(DB_INTR, printk("REJ"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) #ifdef SYNC_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) printk("-REJ-");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) if (hostdata->sync_stat[cmd->device->id] == SS_WAITING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) hostdata->sync_stat[cmd->device->id] = SS_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) /* we want default_sx_per, not DEFAULT_SX_PER */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) hostdata->sync_xfer[cmd->device->id] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) calc_sync_xfer(hostdata->default_sx_per
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) / 4, 0, 0, hostdata->sx_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) hostdata->state = S_CONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) case EXTENDED_MESSAGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) DB(DB_INTR, printk("EXT"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) ucp = hostdata->incoming_msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) #ifdef SYNC_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) printk("%02x", ucp[hostdata->incoming_ptr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) /* Is this the last byte of the extended message? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) if ((hostdata->incoming_ptr >= 2) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) (hostdata->incoming_ptr == (ucp[1] + 1))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) switch (ucp[2]) { /* what's the EXTENDED code? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) case EXTENDED_SDTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) /* default to default async period */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) id = calc_sync_xfer(hostdata->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) default_sx_per / 4, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) 0, hostdata->sx_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) if (hostdata->sync_stat[cmd->device->id] !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) SS_WAITING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) /* A device has sent an unsolicited SDTR message; rather than go
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) * through the effort of decoding it and then figuring out what
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) * our reply should be, we're just gonna say that we have a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) * synchronous fifo depth of 0. This will result in asynchronous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) * transfers - not ideal but so much easier.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) * Actually, this is OK because it assures us that if we don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) * specifically ask for sync transfers, we won't do any.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) write_wd33c93_cmd(regs, WD_CMD_ASSERT_ATN); /* want MESS_OUT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) hostdata->outgoing_msg[0] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) EXTENDED_MESSAGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) hostdata->outgoing_msg[1] = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) hostdata->outgoing_msg[2] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) EXTENDED_SDTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) calc_sync_msg(hostdata->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) default_sx_per, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) 0, hostdata->outgoing_msg + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) hostdata->outgoing_len = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) if (ucp[4]) /* well, sync transfer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) id = calc_sync_xfer(ucp[3], ucp[4],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) hostdata->fast,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) hostdata->sx_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) else if (ucp[3]) /* very unlikely... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) id = calc_sync_xfer(ucp[3], ucp[4],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) 0, hostdata->sx_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) hostdata->sync_xfer[cmd->device->id] = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) #ifdef SYNC_DEBUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) printk(" sync_xfer=%02x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) hostdata->sync_xfer[cmd->device->id]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) hostdata->sync_stat[cmd->device->id] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) SS_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) write_wd33c93_cmd(regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) WD_CMD_NEGATE_ACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) hostdata->state = S_CONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) case EXTENDED_WDTR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) write_wd33c93_cmd(regs, WD_CMD_ASSERT_ATN); /* want MESS_OUT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) printk("sending WDTR ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) hostdata->outgoing_msg[0] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) EXTENDED_MESSAGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) hostdata->outgoing_msg[1] = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) hostdata->outgoing_msg[2] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) EXTENDED_WDTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) hostdata->outgoing_msg[3] = 0; /* 8 bit transfer width */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) hostdata->outgoing_len = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) write_wd33c93_cmd(regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) WD_CMD_NEGATE_ACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) hostdata->state = S_CONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) write_wd33c93_cmd(regs, WD_CMD_ASSERT_ATN); /* want MESS_OUT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) printk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) ("Rejecting Unknown Extended Message(%02x). ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) ucp[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) hostdata->outgoing_msg[0] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) MESSAGE_REJECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) hostdata->outgoing_len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) write_wd33c93_cmd(regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) WD_CMD_NEGATE_ACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) hostdata->state = S_CONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) hostdata->incoming_ptr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) /* We need to read more MESS_IN bytes for the extended message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) hostdata->incoming_ptr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) hostdata->state = S_CONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) printk("Rejecting Unknown Message(%02x) ", msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) write_wd33c93_cmd(regs, WD_CMD_ASSERT_ATN); /* want MESS_OUT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) hostdata->outgoing_msg[0] = MESSAGE_REJECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) hostdata->outgoing_len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) hostdata->state = S_CONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) spin_unlock_irqrestore(&hostdata->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) /* Note: this interrupt will occur only after a LEVEL2 command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) case CSR_SEL_XFER_DONE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) /* Make sure that reselection is enabled at this point - it may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) * have been turned off for the command that just completed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) write_wd33c93(regs, WD_SOURCE_ID, SRCID_ER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) if (phs == 0x60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) DB(DB_INTR, printk("SX-DONE"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) cmd->SCp.Message = COMMAND_COMPLETE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) lun = read_wd33c93(regs, WD_TARGET_LUN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) DB(DB_INTR, printk(":%d.%d", cmd->SCp.Status, lun))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) hostdata->connected = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) hostdata->state = S_UNCONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) if (cmd->SCp.Status == ILLEGAL_STATUS_BYTE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) cmd->SCp.Status = lun;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) if (cmd->cmnd[0] == REQUEST_SENSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) && cmd->SCp.Status != GOOD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) cmd->result =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) (cmd->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) result & 0x00ffff) | (DID_ERROR << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) cmd->result =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) cmd->SCp.Status | (cmd->SCp.Message << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) cmd->scsi_done(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) /* We are no longer connected to a target - check to see if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) * there are commands waiting to be executed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) spin_unlock_irqrestore(&hostdata->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) wd33c93_execute(instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) printk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) ("%02x:%02x:%02x: Unknown SEL_XFER_DONE phase!!---",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) asr, sr, phs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) spin_unlock_irqrestore(&hostdata->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) /* Note: this interrupt will occur only after a LEVEL2 command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) case CSR_SDP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) DB(DB_INTR, printk("SDP"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) hostdata->state = S_RUNNING_LEVEL2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) write_wd33c93(regs, WD_COMMAND_PHASE, 0x41);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) write_wd33c93_cmd(regs, WD_CMD_SEL_ATN_XFER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) spin_unlock_irqrestore(&hostdata->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) case CSR_XFER_DONE | PHS_MESS_OUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) case CSR_UNEXP | PHS_MESS_OUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) case CSR_SRV_REQ | PHS_MESS_OUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) DB(DB_INTR, printk("MSG_OUT="))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) /* To get here, we've probably requested MESSAGE_OUT and have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) * already put the correct bytes in outgoing_msg[] and filled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) * in outgoing_len. We simply send them out to the SCSI bus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) * Sometimes we get MESSAGE_OUT phase when we're not expecting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) * it - like when our SDTR message is rejected by a target. Some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) * targets send the REJECT before receiving all of the extended
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) * message, and then seem to go back to MESSAGE_OUT for a byte
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) * or two. Not sure why, or if I'm doing something wrong to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) * cause this to happen. Regardless, it seems that sending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) * NOP messages in these situations results in no harm and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) * makes everyone happy.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) if (hostdata->outgoing_len == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) hostdata->outgoing_len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) hostdata->outgoing_msg[0] = NOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) transfer_pio(regs, hostdata->outgoing_msg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) hostdata->outgoing_len, DATA_OUT_DIR, hostdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) DB(DB_INTR, printk("%02x", hostdata->outgoing_msg[0]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) hostdata->outgoing_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) hostdata->state = S_CONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) spin_unlock_irqrestore(&hostdata->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) case CSR_UNEXP_DISC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) /* I think I've seen this after a request-sense that was in response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) * to an error condition, but not sure. We certainly need to do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) * something when we get this interrupt - the question is 'what?'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) * Let's think positively, and assume some command has finished
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) * in a legal manner (like a command that provokes a request-sense),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) * so we treat it as a normal command-complete-disconnect.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) /* Make sure that reselection is enabled at this point - it may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) * have been turned off for the command that just completed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) write_wd33c93(regs, WD_SOURCE_ID, SRCID_ER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) if (cmd == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) printk(" - Already disconnected! ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) hostdata->state = S_UNCONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) spin_unlock_irqrestore(&hostdata->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) DB(DB_INTR, printk("UNEXP_DISC"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) hostdata->connected = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) hostdata->state = S_UNCONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) cmd->result =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) (cmd->result & 0x00ffff) | (DID_ERROR << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) cmd->scsi_done(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) /* We are no longer connected to a target - check to see if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) * there are commands waiting to be executed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) /* look above for comments on scsi_done() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) spin_unlock_irqrestore(&hostdata->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) wd33c93_execute(instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) case CSR_DISC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) /* Make sure that reselection is enabled at this point - it may
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) * have been turned off for the command that just completed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) write_wd33c93(regs, WD_SOURCE_ID, SRCID_ER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) DB(DB_INTR, printk("DISC"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) if (cmd == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) printk(" - Already disconnected! ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) hostdata->state = S_UNCONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) switch (hostdata->state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) case S_PRE_CMP_DISC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) hostdata->connected = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) hostdata->state = S_UNCONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) DB(DB_INTR, printk(":%d", cmd->SCp.Status))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) if (cmd->cmnd[0] == REQUEST_SENSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) && cmd->SCp.Status != GOOD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) cmd->result =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) (cmd->
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) result & 0x00ffff) | (DID_ERROR << 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) cmd->result =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) cmd->SCp.Status | (cmd->SCp.Message << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) cmd->scsi_done(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) case S_PRE_TMP_DISC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) case S_RUNNING_LEVEL2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) cmd->host_scribble = (uchar *) hostdata->disconnected_Q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) hostdata->disconnected_Q = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) hostdata->connected = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) hostdata->state = S_UNCONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) #ifdef PROC_STATISTICS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) hostdata->disc_done_cnt[cmd->device->id]++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) printk("*** Unexpected DISCONNECT interrupt! ***");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) hostdata->state = S_UNCONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) /* We are no longer connected to a target - check to see if
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) * there are commands waiting to be executed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) spin_unlock_irqrestore(&hostdata->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) wd33c93_execute(instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) case CSR_RESEL_AM:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) case CSR_RESEL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) DB(DB_INTR, printk("RESEL%s", sr == CSR_RESEL_AM ? "_AM" : ""))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) /* Old chips (pre -A ???) don't have advanced features and will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) * generate CSR_RESEL. In that case we have to extract the LUN the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) * hard way (see below).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) * First we have to make sure this reselection didn't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) * happen during Arbitration/Selection of some other device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) * If yes, put losing command back on top of input_Q.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) if (hostdata->level2 <= L2_NONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) if (hostdata->selecting) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) cmd = (struct scsi_cmnd *) hostdata->selecting;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) hostdata->selecting = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) cmd->host_scribble =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) (uchar *) hostdata->input_Q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) hostdata->input_Q = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) if (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) if (phs == 0x00) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) hostdata->busy[cmd->device->id] &=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) ~(1 << (cmd->device->lun & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) cmd->host_scribble =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) (uchar *) hostdata->input_Q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) hostdata->input_Q = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) printk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) ("---%02x:%02x:%02x-TROUBLE: Intrusive ReSelect!---",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) asr, sr, phs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) while (1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) printk("\r");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) /* OK - find out which device reselected us. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) id = read_wd33c93(regs, WD_SOURCE_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) id &= SRCID_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) /* and extract the lun from the ID message. (Note that we don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) * bother to check for a valid message here - I guess this is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) * not the right way to go, but...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) if (sr == CSR_RESEL_AM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) lun = read_wd33c93(regs, WD_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) if (hostdata->level2 < L2_RESELECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) lun &= 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) /* Old chip; wait for msgin phase to pick up the LUN. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) for (lun = 255; lun; lun--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) if ((asr = read_aux_stat(regs)) & ASR_INT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) if (!(asr & ASR_INT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) printk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) ("wd33c93: Reselected without IDENTIFY\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) lun = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) /* Verify this is a change to MSG_IN and read the message */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) sr = read_wd33c93(regs, WD_SCSI_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) udelay(7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) if (sr == (CSR_ABORT | PHS_MESS_IN) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) sr == (CSR_UNEXP | PHS_MESS_IN) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) sr == (CSR_SRV_REQ | PHS_MESS_IN)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) /* Got MSG_IN, grab target LUN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) lun = read_1_byte(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) /* Now we expect a 'paused with ACK asserted' int.. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) asr = read_aux_stat(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) if (!(asr & ASR_INT)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) udelay(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) asr = read_aux_stat(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) if (!(asr & ASR_INT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) printk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) ("wd33c93: No int after LUN on RESEL (%02x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) asr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) sr = read_wd33c93(regs, WD_SCSI_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) udelay(7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) if (sr != CSR_MSGIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) printk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) ("wd33c93: Not paused with ACK on RESEL (%02x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) sr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) lun &= 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) write_wd33c93_cmd(regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) WD_CMD_NEGATE_ACK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) printk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) ("wd33c93: Not MSG_IN on reselect (%02x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) sr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) lun = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) /* Now we look for the command that's reconnecting. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) cmd = (struct scsi_cmnd *) hostdata->disconnected_Q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) patch = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) while (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) if (id == cmd->device->id && lun == (u8)cmd->device->lun)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) patch = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) cmd = (struct scsi_cmnd *) cmd->host_scribble;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) /* Hmm. Couldn't find a valid command.... What to do? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) if (!cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) printk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) ("---TROUBLE: target %d.%d not in disconnect queue---",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) id, (u8)lun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) spin_unlock_irqrestore(&hostdata->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) /* Ok, found the command - now start it up again. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) if (patch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) patch->host_scribble = cmd->host_scribble;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) hostdata->disconnected_Q =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) (struct scsi_cmnd *) cmd->host_scribble;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) hostdata->connected = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) /* We don't need to worry about 'initialize_SCp()' or 'hostdata->busy[]'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) * because these things are preserved over a disconnect.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) * But we DO need to fix the DPD bit so it's correct for this command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) if (cmd->sc_data_direction == DMA_TO_DEVICE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) write_wd33c93(regs, WD_DESTINATION_ID, cmd->device->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) write_wd33c93(regs, WD_DESTINATION_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) cmd->device->id | DSTID_DPD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) if (hostdata->level2 >= L2_RESELECT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) write_wd33c93_count(regs, 0); /* we want a DATA_PHASE interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) write_wd33c93(regs, WD_COMMAND_PHASE, 0x45);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) write_wd33c93_cmd(regs, WD_CMD_SEL_ATN_XFER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) hostdata->state = S_RUNNING_LEVEL2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) hostdata->state = S_CONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) spin_unlock_irqrestore(&hostdata->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) printk("--UNKNOWN INTERRUPT:%02x:%02x:%02x--", asr, sr, phs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) spin_unlock_irqrestore(&hostdata->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) DB(DB_INTR, printk("} "))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) reset_wd33c93(struct Scsi_Host *instance)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) struct WD33C93_hostdata *hostdata =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) (struct WD33C93_hostdata *) instance->hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) const wd33c93_regs regs = hostdata->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) uchar sr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) #ifdef CONFIG_SGI_IP22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) int busycount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) extern void sgiwd93_reset(unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) /* wait 'til the chip gets some time for us */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) while ((read_aux_stat(regs) & ASR_BSY) && busycount++ < 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) udelay (10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) * there are scsi devices out there, which manage to lock up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) * the wd33c93 in a busy condition. In this state it won't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) * accept the reset command. The only way to solve this is to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) * give the chip a hardware reset (if possible). The code below
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) * does this for the SGI Indy, where this is possible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) /* still busy ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) if (read_aux_stat(regs) & ASR_BSY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) sgiwd93_reset(instance->base); /* yeah, give it the hard one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) write_wd33c93(regs, WD_OWN_ID, OWNID_EAF | OWNID_RAF |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) instance->this_id | hostdata->clock_freq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) calc_sync_xfer(hostdata->default_sx_per / 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) DEFAULT_SX_OFF, 0, hostdata->sx_table));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) write_wd33c93(regs, WD_COMMAND, WD_CMD_RESET);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) #ifdef CONFIG_MVME147_SCSI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) udelay(25); /* The old wd33c93 on MVME147 needs this, at least */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) while (!(read_aux_stat(regs) & ASR_INT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) sr = read_wd33c93(regs, WD_SCSI_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) hostdata->microcode = read_wd33c93(regs, WD_CDB_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) if (sr == 0x00)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) hostdata->chip = C_WD33C93;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) else if (sr == 0x01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) write_wd33c93(regs, WD_QUEUE_TAG, 0xa5); /* any random number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548) sr = read_wd33c93(regs, WD_QUEUE_TAG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) if (sr == 0xa5) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) hostdata->chip = C_WD33C93B;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) write_wd33c93(regs, WD_QUEUE_TAG, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) hostdata->chip = C_WD33C93A;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) hostdata->chip = C_UNKNOWN_CHIP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) if (hostdata->chip != C_WD33C93B) /* Fast SCSI unavailable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) hostdata->fast = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) write_wd33c93(regs, WD_TIMEOUT_PERIOD, TIMEOUT_PERIOD_VALUE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) write_wd33c93(regs, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) wd33c93_host_reset(struct scsi_cmnd * SCpnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) struct Scsi_Host *instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) struct WD33C93_hostdata *hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) instance = SCpnt->device->host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) spin_lock_irq(instance->host_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) hostdata = (struct WD33C93_hostdata *) instance->hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) printk("scsi%d: reset. ", instance->host_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) disable_irq(instance->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) hostdata->dma_stop(instance, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) for (i = 0; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) hostdata->busy[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) hostdata->sync_xfer[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) 0, hostdata->sx_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) hostdata->sync_stat[i] = SS_UNSET; /* using default sync values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) hostdata->input_Q = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) hostdata->selecting = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) hostdata->connected = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) hostdata->disconnected_Q = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) hostdata->state = S_UNCONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) hostdata->dma = D_DMA_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) hostdata->incoming_ptr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) hostdata->outgoing_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) reset_wd33c93(instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) SCpnt->result = DID_RESET << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) enable_irq(instance->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) spin_unlock_irq(instance->host_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) return SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) wd33c93_abort(struct scsi_cmnd * cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) struct Scsi_Host *instance;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) struct WD33C93_hostdata *hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) wd33c93_regs regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) struct scsi_cmnd *tmp, *prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) disable_irq(cmd->device->host->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) instance = cmd->device->host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) hostdata = (struct WD33C93_hostdata *) instance->hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) regs = hostdata->regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) * Case 1 : If the command hasn't been issued yet, we simply remove it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) * from the input_Q.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) tmp = (struct scsi_cmnd *) hostdata->input_Q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) prev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) while (tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) if (tmp == cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) if (prev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) prev->host_scribble = cmd->host_scribble;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) hostdata->input_Q =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) (struct scsi_cmnd *) cmd->host_scribble;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) cmd->host_scribble = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) cmd->result = DID_ABORT << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) printk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) ("scsi%d: Abort - removing command from input_Q. ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) instance->host_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) enable_irq(cmd->device->host->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) cmd->scsi_done(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) return SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) prev = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) tmp = (struct scsi_cmnd *) tmp->host_scribble;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) * Case 2 : If the command is connected, we're going to fail the abort
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) * and let the high level SCSI driver retry at a later time or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) * issue a reset.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) * Timeouts, and therefore aborted commands, will be highly unlikely
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) * and handling them cleanly in this situation would make the common
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) * case of noresets less efficient, and would pollute our code. So,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) * we fail.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) if (hostdata->connected == cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) uchar sr, asr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) unsigned long timeout;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) printk("scsi%d: Aborting connected command - ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) instance->host_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) printk("stopping DMA - ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) if (hostdata->dma == D_DMA_RUNNING) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) hostdata->dma_stop(instance, cmd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) hostdata->dma = D_DMA_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) printk("sending wd33c93 ABORT command - ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) write_wd33c93(regs, WD_CONTROL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) CTRL_IDI | CTRL_EDI | CTRL_POLLED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) write_wd33c93_cmd(regs, WD_CMD_ABORT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) /* Now we have to attempt to flush out the FIFO... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) printk("flushing fifo - ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) timeout = 1000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) asr = read_aux_stat(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) if (asr & ASR_DBR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) read_wd33c93(regs, WD_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) } while (!(asr & ASR_INT) && timeout-- > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) sr = read_wd33c93(regs, WD_SCSI_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) printk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) ("asr=%02x, sr=%02x, %ld bytes un-transferred (timeout=%ld) - ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) asr, sr, read_wd33c93_count(regs), timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) * Abort command processed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) * Still connected.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) * We must disconnect.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) printk("sending wd33c93 DISCONNECT command - ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) write_wd33c93_cmd(regs, WD_CMD_DISCONNECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) timeout = 1000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) asr = read_aux_stat(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) while ((asr & ASR_CIP) && timeout-- > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) asr = read_aux_stat(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) sr = read_wd33c93(regs, WD_SCSI_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) printk("asr=%02x, sr=%02x.", asr, sr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) hostdata->connected = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) hostdata->state = S_UNCONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) cmd->result = DID_ABORT << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) /* sti();*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) wd33c93_execute(instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) enable_irq(cmd->device->host->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) cmd->scsi_done(cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) return SUCCESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) * Case 3: If the command is currently disconnected from the bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) * we're not going to expend much effort here: Let's just return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) * an ABORT_SNOOZE and hope for the best...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) tmp = (struct scsi_cmnd *) hostdata->disconnected_Q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) while (tmp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) if (tmp == cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) printk
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) ("scsi%d: Abort - command found on disconnected_Q - ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) instance->host_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) printk("Abort SNOOZE. ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) enable_irq(cmd->device->host->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) return FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) tmp = (struct scsi_cmnd *) tmp->host_scribble;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) * Case 4 : If we reached this point, the command was not found in any of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) * the queues.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) * We probably reached this point because of an unlikely race condition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) * between the command completing successfully and the abortion code,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) * so we won't panic, but we will notify the user in case something really
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) * broke.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) /* sti();*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) wd33c93_execute(instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) enable_irq(cmd->device->host->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) printk("scsi%d: warning : SCSI command probably completed successfully"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) " before abortion. ", instance->host_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) return FAILED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) #define MAX_WD33C93_HOSTS 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) #define MAX_SETUP_ARGS ARRAY_SIZE(setup_args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) #define SETUP_BUFFER_SIZE 200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) static char setup_buffer[SETUP_BUFFER_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) static char setup_used[MAX_SETUP_ARGS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) static int done_setup = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) wd33c93_setup(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) char *p1, *p2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) /* The kernel does some processing of the command-line before calling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) * this function: If it begins with any decimal or hex number arguments,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) * ints[0] = how many numbers found and ints[1] through [n] are the values
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) * themselves. str points to where the non-numeric arguments (if any)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) * start: We do our own parsing of those. We construct synthetic 'nosync'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) * keywords out of numeric args (to maintain compatibility with older
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) * versions) and then add the rest of the arguments.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) p1 = setup_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) *p1 = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) if (str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) strncpy(p1, str, SETUP_BUFFER_SIZE - strlen(setup_buffer));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) setup_buffer[SETUP_BUFFER_SIZE - 1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) p1 = setup_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782) while (*p1 && (i < MAX_SETUP_ARGS)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) p2 = strchr(p1, ',');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) if (p2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) *p2 = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) if (p1 != p2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) setup_args[i] = p1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) p1 = p2 + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) setup_args[i] = p1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) for (i = 0; i < MAX_SETUP_ARGS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) setup_used[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) done_setup = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) __setup("wd33c93=", wd33c93_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) /* check_setup_args() returns index if key found, 0 if not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) check_setup_args(char *key, int *flags, int *val, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) int x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) char *cp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) for (x = 0; x < MAX_SETUP_ARGS; x++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) if (setup_used[x])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) if (!strncmp(setup_args[x], key, strlen(key)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) if (!strncmp(setup_args[x], "next", strlen("next")))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) if (x == MAX_SETUP_ARGS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) setup_used[x] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) cp = setup_args[x] + strlen(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) *val = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) if (*cp != ':')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) return ++x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) cp++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) if ((*cp >= '0') && (*cp <= '9')) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) *val = simple_strtoul(cp, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) return ++x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) * Calculate internal data-transfer-clock cycle from input-clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) * frequency (/MHz) and fill 'sx_table'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) * The original driver used to rely on a fixed sx_table, containing periods
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) * for (only) the lower limits of the respective input-clock-frequency ranges
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) * (8-10/12-15/16-20 MHz). Although it seems, that no problems occurred with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) * this setting so far, it might be desirable to adjust the transfer periods
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) * closer to the really attached, possibly 25% higher, input-clock, since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) * - the wd33c93 may really use a significant shorter period, than it has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) * negotiated (eg. thrashing the target, which expects 4/8MHz, with 5/10MHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) * instead).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) * - the wd33c93 may ask the target for a lower transfer rate, than the target
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) * is capable of (eg. negotiating for an assumed minimum of 252ns instead of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) * possible 200ns, which indeed shows up in tests as an approx. 10% lower
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) * transfer rate).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) static inline unsigned int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) round_4(unsigned int x)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) switch (x & 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) case 1: --x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) case 2: ++x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858) case 3: ++x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) return x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) calc_sx_table(unsigned int mhz, struct sx_period sx_table[9])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) unsigned int d, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) if (mhz < 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) d = 2; /* divisor for 8-10 MHz input-clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) else if (mhz < 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) d = 3; /* divisor for 12-15 MHz input-clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) d = 4; /* divisor for 16-20 MHz input-clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) d = (100000 * d) / 2 / mhz; /* 100 x DTCC / nanosec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) sx_table[0].period_ns = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) sx_table[0].reg_value = 0x20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) for (i = 1; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) sx_table[i].period_ns = round_4((i+1)*d / 100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) sx_table[i].reg_value = (i+1)*0x10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) sx_table[7].reg_value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) sx_table[8].period_ns = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) sx_table[8].reg_value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) * check and, maybe, map an init- or "clock:"- argument.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) static uchar
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) set_clk_freq(int freq, int *mhz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) int x = freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) if (WD33C93_FS_8_10 == freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) freq = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) else if (WD33C93_FS_12_15 == freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) freq = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) else if (WD33C93_FS_16_20 == freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) freq = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) else if (freq > 7 && freq < 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) x = WD33C93_FS_8_10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) else if (freq > 11 && freq < 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) x = WD33C93_FS_12_15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) else if (freq > 15 && freq < 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905) x = WD33C93_FS_16_20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) /* Hmm, wouldn't it be safer to assume highest freq here? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) x = WD33C93_FS_8_10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) freq = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) *mhz = freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) return x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) * to be used with the resync: fast: ... options
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) static inline void set_resync ( struct WD33C93_hostdata *hd, int mask )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) for (i = 0; i < 8; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) if (mask & (1 << i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) hd->sync_stat[i] = SS_UNSET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) wd33c93_init(struct Scsi_Host *instance, const wd33c93_regs regs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) dma_setup_t setup, dma_stop_t stop, int clock_freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) struct WD33C93_hostdata *hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) int flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) char buf[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) if (!done_setup && setup_strings)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) wd33c93_setup(setup_strings);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) hostdata = (struct WD33C93_hostdata *) instance->hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) hostdata->regs = regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) hostdata->clock_freq = set_clk_freq(clock_freq, &i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) calc_sx_table(i, hostdata->sx_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) hostdata->dma_setup = setup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) hostdata->dma_stop = stop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) hostdata->dma_bounce_buffer = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) hostdata->dma_bounce_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) for (i = 0; i < 8; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) hostdata->busy[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950) hostdata->sync_xfer[i] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) calc_sync_xfer(DEFAULT_SX_PER / 4, DEFAULT_SX_OFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) 0, hostdata->sx_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) hostdata->sync_stat[i] = SS_UNSET; /* using default sync values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) #ifdef PROC_STATISTICS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) hostdata->cmd_cnt[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) hostdata->disc_allowed_cnt[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) hostdata->disc_done_cnt[i] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) hostdata->input_Q = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) hostdata->selecting = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) hostdata->connected = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) hostdata->disconnected_Q = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) hostdata->state = S_UNCONNECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) hostdata->dma = D_DMA_OFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) hostdata->level2 = L2_BASIC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) hostdata->disconnect = DIS_ADAPTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) hostdata->args = DEBUG_DEFAULTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) hostdata->incoming_ptr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) hostdata->outgoing_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) hostdata->default_sx_per = DEFAULT_SX_PER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) hostdata->no_dma = 0; /* default is DMA enabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) #ifdef PROC_INTERFACE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) hostdata->proc = PR_VERSION | PR_INFO | PR_STATISTICS |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976) PR_CONNECTED | PR_INPUTQ | PR_DISCQ | PR_STOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) #ifdef PROC_STATISTICS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) hostdata->dma_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) hostdata->pio_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) hostdata->int_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) if (check_setup_args("clock", &flags, &val, buf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) hostdata->clock_freq = set_clk_freq(val, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) calc_sx_table(val, hostdata->sx_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) if (check_setup_args("nosync", &flags, &val, buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) hostdata->no_sync = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) if (check_setup_args("nodma", &flags, &val, buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) hostdata->no_dma = (val == -1) ? 1 : val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) if (check_setup_args("period", &flags, &val, buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) hostdata->default_sx_per =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) hostdata->sx_table[round_period((unsigned int) val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) hostdata->sx_table)].period_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) if (check_setup_args("disconnect", &flags, &val, buf)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) if ((val >= DIS_NEVER) && (val <= DIS_ALWAYS))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) hostdata->disconnect = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) hostdata->disconnect = DIS_ADAPTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) if (check_setup_args("level2", &flags, &val, buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) hostdata->level2 = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) if (check_setup_args("debug", &flags, &val, buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) hostdata->args = val & DB_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013) if (check_setup_args("burst", &flags, &val, buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) hostdata->dma_mode = val ? CTRL_BURST:CTRL_DMA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) if (WD33C93_FS_16_20 == hostdata->clock_freq /* divisor 4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017) && check_setup_args("fast", &flags, &val, buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) hostdata->fast = !!val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) if ((i = check_setup_args("next", &flags, &val, buf))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021) while (i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) setup_used[--i] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) #ifdef PROC_INTERFACE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025) if (check_setup_args("proc", &flags, &val, buf))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) hostdata->proc = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) spin_lock_irq(&hostdata->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030) reset_wd33c93(instance);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) spin_unlock_irq(&hostdata->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) printk("wd33c93-%d: chip=%s/%d no_sync=0x%x no_dma=%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) instance->host_no,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) (hostdata->chip == C_WD33C93) ? "WD33c93" : (hostdata->chip ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) C_WD33C93A) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) "WD33c93A" : (hostdata->chip ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038) C_WD33C93B) ? "WD33c93B" : "unknown",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) hostdata->microcode, hostdata->no_sync, hostdata->no_dma);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) #ifdef DEBUGGING_ON
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) printk(" debug_flags=0x%02x\n", hostdata->args);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) printk(" debugging=OFF\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) printk(" setup_args=");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) for (i = 0; i < MAX_SETUP_ARGS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047) printk("%s,", setup_args[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) printk(" Version %s - %s\n", WD33C93_VERSION, WD33C93_DATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) int wd33c93_write_info(struct Scsi_Host *instance, char *buf, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) #ifdef PROC_INTERFACE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) char *bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) struct WD33C93_hostdata *hd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) int x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059) hd = (struct WD33C93_hostdata *) instance->hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061) /* We accept the following
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) * keywords (same format as command-line, but arguments are not optional):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) * debug
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) * disconnect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) * period
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) * resync
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) * proc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) * nodma
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069) * level2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) * burst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) * fast
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072) * nosync
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075) buf[len] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) for (bp = buf; *bp; ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) while (',' == *bp || ' ' == *bp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) ++bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) if (!strncmp(bp, "debug:", 6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) hd->args = simple_strtoul(bp+6, &bp, 0) & DB_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) } else if (!strncmp(bp, "disconnect:", 11)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082) x = simple_strtoul(bp+11, &bp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) if (x < DIS_NEVER || x > DIS_ALWAYS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) x = DIS_ADAPTIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) hd->disconnect = x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) } else if (!strncmp(bp, "period:", 7)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087) x = simple_strtoul(bp+7, &bp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) hd->default_sx_per =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) hd->sx_table[round_period((unsigned int) x,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) hd->sx_table)].period_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) } else if (!strncmp(bp, "resync:", 7)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) set_resync(hd, (int)simple_strtoul(bp+7, &bp, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) } else if (!strncmp(bp, "proc:", 5)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) hd->proc = simple_strtoul(bp+5, &bp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) } else if (!strncmp(bp, "nodma:", 6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) hd->no_dma = simple_strtoul(bp+6, &bp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) } else if (!strncmp(bp, "level2:", 7)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098) hd->level2 = simple_strtoul(bp+7, &bp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) } else if (!strncmp(bp, "burst:", 6)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100) hd->dma_mode =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) simple_strtol(bp+6, &bp, 0) ? CTRL_BURST:CTRL_DMA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) } else if (!strncmp(bp, "fast:", 5)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) x = !!simple_strtol(bp+5, &bp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) if (x != hd->fast)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2105) set_resync(hd, 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2106) hd->fast = x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2107) } else if (!strncmp(bp, "nosync:", 7)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2108) x = simple_strtoul(bp+7, &bp, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2109) set_resync(hd, x ^ hd->no_sync);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2110) hd->no_sync = x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2111) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2112) break; /* unknown keyword,syntax-error,... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2115) return len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2116) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2117) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2118) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2121) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2122) wd33c93_show_info(struct seq_file *m, struct Scsi_Host *instance)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2124) #ifdef PROC_INTERFACE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2125) struct WD33C93_hostdata *hd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2126) struct scsi_cmnd *cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2127) int x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2129) hd = (struct WD33C93_hostdata *) instance->hostdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2131) spin_lock_irq(&hd->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2132) if (hd->proc & PR_VERSION)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2133) seq_printf(m, "\nVersion %s - %s.",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2134) WD33C93_VERSION, WD33C93_DATE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2136) if (hd->proc & PR_INFO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2137) seq_printf(m, "\nclock_freq=%02x no_sync=%02x no_dma=%d"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2138) " dma_mode=%02x fast=%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2139) hd->clock_freq, hd->no_sync, hd->no_dma, hd->dma_mode, hd->fast);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2140) seq_puts(m, "\nsync_xfer[] = ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2141) for (x = 0; x < 7; x++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2142) seq_printf(m, "\t%02x", hd->sync_xfer[x]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2143) seq_puts(m, "\nsync_stat[] = ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2144) for (x = 0; x < 7; x++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2145) seq_printf(m, "\t%02x", hd->sync_stat[x]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2147) #ifdef PROC_STATISTICS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2148) if (hd->proc & PR_STATISTICS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2149) seq_puts(m, "\ncommands issued: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2150) for (x = 0; x < 7; x++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2151) seq_printf(m, "\t%ld", hd->cmd_cnt[x]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2152) seq_puts(m, "\ndisconnects allowed:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2153) for (x = 0; x < 7; x++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2154) seq_printf(m, "\t%ld", hd->disc_allowed_cnt[x]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2155) seq_puts(m, "\ndisconnects done: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2156) for (x = 0; x < 7; x++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2157) seq_printf(m, "\t%ld", hd->disc_done_cnt[x]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2158) seq_printf(m,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2159) "\ninterrupts: %ld, DATA_PHASE ints: %ld DMA, %ld PIO",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2160) hd->int_cnt, hd->dma_cnt, hd->pio_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2162) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2163) if (hd->proc & PR_CONNECTED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2164) seq_puts(m, "\nconnected: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2165) if (hd->connected) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2166) cmd = (struct scsi_cmnd *) hd->connected;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2167) seq_printf(m, " %d:%llu(%02x)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2168) cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2171) if (hd->proc & PR_INPUTQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2172) seq_puts(m, "\ninput_Q: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2173) cmd = (struct scsi_cmnd *) hd->input_Q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2174) while (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2175) seq_printf(m, " %d:%llu(%02x)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2176) cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2177) cmd = (struct scsi_cmnd *) cmd->host_scribble;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2180) if (hd->proc & PR_DISCQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2181) seq_puts(m, "\ndisconnected_Q:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2182) cmd = (struct scsi_cmnd *) hd->disconnected_Q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2183) while (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2184) seq_printf(m, " %d:%llu(%02x)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2185) cmd->device->id, cmd->device->lun, cmd->cmnd[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2186) cmd = (struct scsi_cmnd *) cmd->host_scribble;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2189) seq_putc(m, '\n');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2190) spin_unlock_irq(&hd->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2191) #endif /* PROC_INTERFACE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2192) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2195) EXPORT_SYMBOL(wd33c93_host_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2196) EXPORT_SYMBOL(wd33c93_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2197) EXPORT_SYMBOL(wd33c93_abort);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2198) EXPORT_SYMBOL(wd33c93_queuecommand);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2199) EXPORT_SYMBOL(wd33c93_intr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2200) EXPORT_SYMBOL(wd33c93_show_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2201) EXPORT_SYMBOL(wd33c93_write_info);