^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700    1) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700    2)  * Adaptec AIC79xx device driver for Linux.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700    3)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700    4)  * $Id: //depot/aic7xxx/linux/drivers/scsi/aic7xxx/aic79xx_osm.c#171 $
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700    5)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700    6)  * --------------------------------------------------------------------------
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700    7)  * Copyright (c) 1994-2000 Justin T. Gibbs.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700    8)  * Copyright (c) 1997-1999 Doug Ledford
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700    9)  * Copyright (c) 2000-2003 Adaptec Inc.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   10)  * All rights reserved.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   11)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   12)  * Redistribution and use in source and binary forms, with or without
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   13)  * modification, are permitted provided that the following conditions
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   14)  * are met:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   15)  * 1. Redistributions of source code must retain the above copyright
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   16)  *    notice, this list of conditions, and the following disclaimer,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   17)  *    without modification.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   18)  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   19)  *    substantially similar to the "NO WARRANTY" disclaimer below
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   20)  *    ("Disclaimer") and any redistribution must be conditioned upon
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   21)  *    including a substantially similar Disclaimer requirement for further
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   22)  *    binary redistribution.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   23)  * 3. Neither the names of the above-listed copyright holders nor the names
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   24)  *    of any contributors may be used to endorse or promote products derived
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   25)  *    from this software without specific prior written permission.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   26)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   27)  * Alternatively, this software may be distributed under the terms of the
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   28)  * GNU General Public License ("GPL") version 2 as published by the Free
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   29)  * Software Foundation.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   30)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   31)  * NO WARRANTY
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   32)  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   33)  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   34)  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   35)  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   36)  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   37)  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   38)  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   39)  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   40)  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   41)  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   42)  * POSSIBILITY OF SUCH DAMAGES.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   43)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   44) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   45) #include "aic79xx_osm.h"
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   46) #include "aic79xx_inline.h"
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   47) #include <scsi/scsicam.h>
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   48) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200   49) static struct scsi_transport_template *ahd_linux_transport_template = NULL;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200   50) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   51) #include <linux/init.h>		/* __setup */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   52) #include <linux/mm.h>		/* For fetching system memory size */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200   53) #include <linux/blkdev.h>		/* For block_size() */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   54) #include <linux/delay.h>	/* For ssleep/msleep */
017560fca496f (Jeff Garzik        2005-10-24 18:04:36 -0400   55) #include <linux/device.h>
5a0e3ad6af866 (Tejun Heo          2010-03-24 17:04:11 +0900   56) #include <linux/slab.h>
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   57) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   58) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   59)  * Bucket size for counting good commands in between bad ones.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   60)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   61) #define AHD_LINUX_ERR_THRESH	1000
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   62) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   63) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   64)  * Set this to the delay in seconds after SCSI bus reset.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   65)  * Note, we honor this only for the initial bus reset.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   66)  * The scsi error recovery code performs its own bus settle
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   67)  * delay handling for error recovery actions.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   68)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   69) #ifdef CONFIG_AIC79XX_RESET_DELAY_MS
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   70) #define AIC79XX_RESET_DELAY CONFIG_AIC79XX_RESET_DELAY_MS
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   71) #else
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   72) #define AIC79XX_RESET_DELAY 5000
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   73) #endif
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   74) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   75) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   76)  * To change the default number of tagged transactions allowed per-device,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   77)  * add a line to the lilo.conf file like:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   78)  * append="aic79xx=verbose,tag_info:{{32,32,32,32},{32,32,32,32}}"
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   79)  * which will result in the first four devices on the first two
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   80)  * controllers being set to a tagged queue depth of 32.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   81)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   82)  * The tag_commands is an array of 16 to allow for wide and twin adapters.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   83)  * Twin adapters will use indexes 0-7 for channel 0, and indexes 8-15
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   84)  * for channel 1.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   85)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   86) typedef struct {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   87) 	uint16_t tag_commands[16];	/* Allow for wide/twin adapters. */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   88) } adapter_tag_info_t;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   89) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   90) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   91)  * Modify this as you see fit for your system.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   92)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   93)  * 0			tagged queuing disabled
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   94)  * 1 <= n <= 253	n == max tags ever dispatched.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   95)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   96)  * The driver will throttle the number of commands dispatched to a
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   97)  * device if it returns queue full.  For devices with a fixed maximum
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   98)  * queue depth, the driver will eventually determine this depth and
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   99)  * lock it in (a console message is printed to indicate that a lock
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  100)  * has occurred).  On some devices, queue full is returned for a temporary
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  101)  * resource shortage.  These devices will return queue full at varying
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  102)  * depths.  The driver will throttle back when the queue fulls occur and
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  103)  * attempt to slowly increase the depth over time as the device recovers
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  104)  * from the resource shortage.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  105)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  106)  * In this example, the first line will disable tagged queueing for all
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  107)  * the devices on the first probed aic79xx adapter.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  108)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  109)  * The second line enables tagged queueing with 4 commands/LUN for IDs
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  110)  * (0, 2-11, 13-15), disables tagged queueing for ID 12, and tells the
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  111)  * driver to attempt to use up to 64 tags for ID 1.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  112)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  113)  * The third line is the same as the first line.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  114)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  115)  * The fourth line disables tagged queueing for devices 0 and 3.  It
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  116)  * enables tagged queueing for the other IDs, with 16 commands/LUN
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  117)  * for IDs 1 and 4, 127 commands/LUN for ID 8, and 4 commands/LUN for
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  118)  * IDs 2, 5-7, and 9-15.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  119)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  120) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  121) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  122)  * NOTE: The below structure is for reference only, the actual structure
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  123)  *       to modify in order to change things is just below this comment block.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  124) adapter_tag_info_t aic79xx_tag_info[] =
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  125) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  126) 	{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  127) 	{{4, 64, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 4, 4, 4}},
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  128) 	{{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}},
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  129) 	{{0, 16, 4, 0, 16, 4, 4, 4, 127, 4, 4, 4, 4, 4, 4, 4}}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  130) };
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  131) */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  132) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  133) #ifdef CONFIG_AIC79XX_CMDS_PER_DEVICE
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  134) #define AIC79XX_CMDS_PER_DEVICE CONFIG_AIC79XX_CMDS_PER_DEVICE
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  135) #else
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  136) #define AIC79XX_CMDS_PER_DEVICE AHD_MAX_QUEUE
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  137) #endif
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  138) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  139) #define AIC79XX_CONFIGED_TAG_COMMANDS {					\
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  140) 	AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE,		\
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  141) 	AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE,		\
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  142) 	AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE,		\
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  143) 	AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE,		\
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  144) 	AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE,		\
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  145) 	AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE,		\
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  146) 	AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE,		\
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  147) 	AIC79XX_CMDS_PER_DEVICE, AIC79XX_CMDS_PER_DEVICE		\
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  148) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  149) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  150) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  151)  * By default, use the number of commands specified by
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  152)  * the users kernel configuration.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  153)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  154) static adapter_tag_info_t aic79xx_tag_info[] =
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  155) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  156) 	{AIC79XX_CONFIGED_TAG_COMMANDS},
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  157) 	{AIC79XX_CONFIGED_TAG_COMMANDS},
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  158) 	{AIC79XX_CONFIGED_TAG_COMMANDS},
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  159) 	{AIC79XX_CONFIGED_TAG_COMMANDS},
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  160) 	{AIC79XX_CONFIGED_TAG_COMMANDS},
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  161) 	{AIC79XX_CONFIGED_TAG_COMMANDS},
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  162) 	{AIC79XX_CONFIGED_TAG_COMMANDS},
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  163) 	{AIC79XX_CONFIGED_TAG_COMMANDS},
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  164) 	{AIC79XX_CONFIGED_TAG_COMMANDS},
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  165) 	{AIC79XX_CONFIGED_TAG_COMMANDS},
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  166) 	{AIC79XX_CONFIGED_TAG_COMMANDS},
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  167) 	{AIC79XX_CONFIGED_TAG_COMMANDS},
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  168) 	{AIC79XX_CONFIGED_TAG_COMMANDS},
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  169) 	{AIC79XX_CONFIGED_TAG_COMMANDS},
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  170) 	{AIC79XX_CONFIGED_TAG_COMMANDS},
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  171) 	{AIC79XX_CONFIGED_TAG_COMMANDS}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  172) };
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  173) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  174) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  175)  * The I/O cell on the chip is very configurable in respect to its analog
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  176)  * characteristics.  Set the defaults here; they can be overriden with
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  177)  * the proper insmod parameters.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  178)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  179) struct ahd_linux_iocell_opts
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  180) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  181) 	uint8_t	precomp;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  182) 	uint8_t	slewrate;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  183) 	uint8_t amplitude;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  184) };
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  185) #define AIC79XX_DEFAULT_PRECOMP		0xFF
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  186) #define AIC79XX_DEFAULT_SLEWRATE	0xFF
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  187) #define AIC79XX_DEFAULT_AMPLITUDE	0xFF
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  188) #define AIC79XX_DEFAULT_IOOPTS			\
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  189) {						\
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  190) 	AIC79XX_DEFAULT_PRECOMP,		\
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  191) 	AIC79XX_DEFAULT_SLEWRATE,		\
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  192) 	AIC79XX_DEFAULT_AMPLITUDE		\
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  193) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  194) #define AIC79XX_PRECOMP_INDEX	0
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  195) #define AIC79XX_SLEWRATE_INDEX	1
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  196) #define AIC79XX_AMPLITUDE_INDEX	2
980b306a29772 (Denys Vlasenko     2008-04-25 04:36:01 +0200  197) static const struct ahd_linux_iocell_opts aic79xx_iocell_info[] =
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  198) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  199) 	AIC79XX_DEFAULT_IOOPTS,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  200) 	AIC79XX_DEFAULT_IOOPTS,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  201) 	AIC79XX_DEFAULT_IOOPTS,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  202) 	AIC79XX_DEFAULT_IOOPTS,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  203) 	AIC79XX_DEFAULT_IOOPTS,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  204) 	AIC79XX_DEFAULT_IOOPTS,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  205) 	AIC79XX_DEFAULT_IOOPTS,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  206) 	AIC79XX_DEFAULT_IOOPTS,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  207) 	AIC79XX_DEFAULT_IOOPTS,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  208) 	AIC79XX_DEFAULT_IOOPTS,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  209) 	AIC79XX_DEFAULT_IOOPTS,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  210) 	AIC79XX_DEFAULT_IOOPTS,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  211) 	AIC79XX_DEFAULT_IOOPTS,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  212) 	AIC79XX_DEFAULT_IOOPTS,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  213) 	AIC79XX_DEFAULT_IOOPTS,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  214) 	AIC79XX_DEFAULT_IOOPTS
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  215) };
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  216) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  217) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  218)  * There should be a specific return value for this in scsi.h, but
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  219)  * it seems that most drivers ignore it.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  220)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  221) #define DID_UNDERFLOW   DID_ERROR
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  222) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  223) void
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  224) ahd_print_path(struct ahd_softc *ahd, struct scb *scb)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  225) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  226) 	printk("(scsi%d:%c:%d:%d): ",
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  227) 	       ahd->platform_data->host->host_no,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  228) 	       scb != NULL ? SCB_GET_CHANNEL(ahd, scb) : 'X',
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  229) 	       scb != NULL ? SCB_GET_TARGET(ahd, scb) : -1,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  230) 	       scb != NULL ? SCB_GET_LUN(scb) : -1);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  231) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  232) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  233) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  234)  * XXX - these options apply unilaterally to _all_ adapters
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  235)  *       cards in the system.  This should be fixed.  Exceptions to this
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  236)  *       rule are noted in the comments.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  237)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  238) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  239) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  240)  * Skip the scsi bus reset.  Non 0 make us skip the reset at startup.  This
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  241)  * has no effect on any later resets that might occur due to things like
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  242)  * SCSI bus timeouts.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  243)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  244) static uint32_t aic79xx_no_reset;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  245) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  246) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  247)  * Should we force EXTENDED translation on a controller.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  248)  *     0 == Use whatever is in the SEEPROM or default to off
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  249)  *     1 == Use whatever is in the SEEPROM or default to on
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  250)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  251) static uint32_t aic79xx_extended;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  252) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  253) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  254)  * PCI bus parity checking of the Adaptec controllers.  This is somewhat
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  255)  * dubious at best.  To my knowledge, this option has never actually
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  256)  * solved a PCI parity problem, but on certain machines with broken PCI
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  257)  * chipset configurations, it can generate tons of false error messages.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  258)  * It's included in the driver for completeness.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  259)  *   0	   = Shut off PCI parity check
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  260)  *   non-0 = Enable PCI parity check
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  261)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  262)  * NOTE: you can't actually pass -1 on the lilo prompt.  So, to set this
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  263)  * variable to -1 you would actually want to simply pass the variable
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  264)  * name without a number.  That will invert the 0 which will result in
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  265)  * -1.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  266)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  267) static uint32_t aic79xx_pci_parity = ~0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  268) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  269) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  270)  * There are lots of broken chipsets in the world.  Some of them will
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  271)  * violate the PCI spec when we issue byte sized memory writes to our
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  272)  * controller.  I/O mapped register access, if allowed by the given
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  273)  * platform, will work in almost all cases.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  274)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  275) uint32_t aic79xx_allow_memio = ~0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  276) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  277) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  278)  * So that we can set how long each device is given as a selection timeout.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  279)  * The table of values goes like this:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  280)  *   0 - 256ms
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  281)  *   1 - 128ms
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  282)  *   2 - 64ms
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  283)  *   3 - 32ms
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  284)  * We default to 256ms because some older devices need a longer time
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  285)  * to respond to initial selection.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  286)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  287) static uint32_t aic79xx_seltime;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  288) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  289) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  290)  * Certain devices do not perform any aging on commands.  Should the
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  291)  * device be saturated by commands in one portion of the disk, it is
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  292)  * possible for transactions on far away sectors to never be serviced.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  293)  * To handle these devices, we can periodically send an ordered tag to
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  294)  * force all outstanding transactions to be serviced prior to a new
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  295)  * transaction.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  296)  */
289fe5b1f99c5 (Adrian Bunk        2006-10-20 14:47:57 -0700  297) static uint32_t aic79xx_periodic_otag;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  298) 
3fb086126462c (Hannes Reinecke    2006-01-24 10:44:38 +0100  299) /* Some storage boxes are using an LSI chip which has a bug making it
3fb086126462c (Hannes Reinecke    2006-01-24 10:44:38 +0100  300)  * impossible to use aic79xx Rev B chip in 320 speeds.  The following
3fb086126462c (Hannes Reinecke    2006-01-24 10:44:38 +0100  301)  * storage boxes have been reported to be buggy:
3fb086126462c (Hannes Reinecke    2006-01-24 10:44:38 +0100  302)  * EonStor 3U 16-Bay: U16U-G3A3
3fb086126462c (Hannes Reinecke    2006-01-24 10:44:38 +0100  303)  * EonStor 2U 12-Bay: U12U-G3A3
3fb086126462c (Hannes Reinecke    2006-01-24 10:44:38 +0100  304)  * SentinelRAID: 2500F R5 / R6
3fb086126462c (Hannes Reinecke    2006-01-24 10:44:38 +0100  305)  * SentinelRAID: 2500F R1
3fb086126462c (Hannes Reinecke    2006-01-24 10:44:38 +0100  306)  * SentinelRAID: 2500F/1500F
3fb086126462c (Hannes Reinecke    2006-01-24 10:44:38 +0100  307)  * SentinelRAID: 150F
3fb086126462c (Hannes Reinecke    2006-01-24 10:44:38 +0100  308)  * 
3fb086126462c (Hannes Reinecke    2006-01-24 10:44:38 +0100  309)  * To get around this LSI bug, you can set your board to 160 mode
3fb086126462c (Hannes Reinecke    2006-01-24 10:44:38 +0100  310)  * or you can enable the SLOWCRC bit.
3fb086126462c (Hannes Reinecke    2006-01-24 10:44:38 +0100  311)  */
3fb086126462c (Hannes Reinecke    2006-01-24 10:44:38 +0100  312) uint32_t aic79xx_slowcrc;
3fb086126462c (Hannes Reinecke    2006-01-24 10:44:38 +0100  313) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  314) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  315)  * Module information and settable options.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  316)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  317) static char *aic79xx = NULL;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  318) 
64624d4f46d5e (Hannes Reinecke    2007-10-19 10:32:29 +0200  319) MODULE_AUTHOR("Maintainer: Hannes Reinecke <hare@suse.de>");
64624d4f46d5e (Hannes Reinecke    2007-10-19 10:32:29 +0200  320) MODULE_DESCRIPTION("Adaptec AIC790X U320 SCSI Host Bus Adapter driver");
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  321) MODULE_LICENSE("Dual BSD/GPL");
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  322) MODULE_VERSION(AIC79XX_DRIVER_VERSION);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  323) module_param(aic79xx, charp, 0444);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  324) MODULE_PARM_DESC(aic79xx,
2b6ee9b529546 (Randy Dunlap       2006-08-14 23:09:23 -0700  325) "period-delimited options string:\n"
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  326) "	verbose			Enable verbose/diagnostic logging\n"
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  327) "	allow_memio		Allow device registers to be memory mapped\n"
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  328) "	debug			Bitmask of debug values to enable\n"
b1c118121ae37 (Joe Perches        2008-02-03 17:28:22 +0200  329) "	no_reset		Suppress initial bus resets\n"
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  330) "	extended		Enable extended geometry on all controllers\n"
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  331) "	periodic_otag		Send an ordered tagged transaction\n"
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  332) "				periodically to prevent tag starvation.\n"
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  333) "				This may be required by some older disk\n"
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  334) "				or drives/RAID arrays.\n"
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  335) "	tag_info:<tag_str>	Set per-target tag depth\n"
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  336) "	global_tag_depth:<int>	Global tag depth for all targets on all buses\n"
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  337) "	slewrate:<slewrate_list>Set the signal slew rate (0-15).\n"
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  338) "	precomp:<pcomp_list>	Set the signal precompensation (0-7).\n"
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  339) "	amplitude:<int>		Set the signal amplitude (0-7).\n"
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  340) "	seltime:<int>		Selection Timeout:\n"
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  341) "				(0/256ms,1/128ms,2/64ms,3/32ms)\n"
3fb086126462c (Hannes Reinecke    2006-01-24 10:44:38 +0100  342) "	slowcrc			Turn on the SLOWCRC bit (Rev B only)\n"		 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  343) "\n"
970e2486492aa (Lucas De Marchi    2012-03-30 13:37:16 -0700  344) "	Sample modprobe configuration file:\n"
970e2486492aa (Lucas De Marchi    2012-03-30 13:37:16 -0700  345) "	#	Enable verbose logging\n"
970e2486492aa (Lucas De Marchi    2012-03-30 13:37:16 -0700  346) "	#	Set tag depth on Controller 2/Target 2 to 10 tags\n"
970e2486492aa (Lucas De Marchi    2012-03-30 13:37:16 -0700  347) "	#	Shorten the selection timeout to 128ms\n"
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  348) "\n"
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  349) "	options aic79xx 'aic79xx=verbose.tag_info:{{}.{}.{..10}}.seltime:1'\n"
2b6ee9b529546 (Randy Dunlap       2006-08-14 23:09:23 -0700  350) );
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  351) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  352) static void ahd_linux_handle_scsi_status(struct ahd_softc *,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  353) 					 struct scsi_device *,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  354) 					 struct scb *);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  355) static void ahd_linux_queue_cmd_complete(struct ahd_softc *ahd,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  356) 					 struct scsi_cmnd *cmd);
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  357) static int ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  358) static void ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  359) static u_int ahd_linux_user_tagdepth(struct ahd_softc *ahd,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  360) 				     struct ahd_devinfo *devinfo);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  361) static void ahd_linux_device_queue_depth(struct scsi_device *);
60a1321384029 (Hannes Reinecke    2005-07-22 16:42:28 +0200  362) static int ahd_linux_run_command(struct ahd_softc*,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  363) 				 struct ahd_linux_device *,
60a1321384029 (Hannes Reinecke    2005-07-22 16:42:28 +0200  364) 				 struct scsi_cmnd *);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  365) static void ahd_linux_setup_tag_info_global(char *p);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  366) static int  aic79xx_setup(char *c);
e3e0ca5143d7a (Adrian Bunk        2007-03-26 21:59:29 -0800  367) static void ahd_freeze_simq(struct ahd_softc *ahd);
e3e0ca5143d7a (Adrian Bunk        2007-03-26 21:59:29 -0800  368) static void ahd_release_simq(struct ahd_softc *ahd);
85a46523ff68a (Christoph Hellwig  2005-08-15 13:28:46 +0200  369) 
85a46523ff68a (Christoph Hellwig  2005-08-15 13:28:46 +0200  370) static int ahd_linux_unit;
85a46523ff68a (Christoph Hellwig  2005-08-15 13:28:46 +0200  371) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  372) 
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  373) /************************** OS Utility Wrappers *******************************/
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  374) void ahd_delay(long);
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  375) void
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  376) ahd_delay(long usec)
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  377) {
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  378) 	/*
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  379) 	 * udelay on Linux can have problems for
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  380) 	 * multi-millisecond waits.  Wait at most
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  381) 	 * 1024us per call.
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  382) 	 */
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  383) 	while (usec > 0) {
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  384) 		udelay(usec % 1024);
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  385) 		usec -= 1024;
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  386) 	}
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  387) }
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  388) 
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  389) 
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  390) /***************************** Low Level I/O **********************************/
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  391) uint8_t ahd_inb(struct ahd_softc * ahd, long port);
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  392) void ahd_outb(struct ahd_softc * ahd, long port, uint8_t val);
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  393) void ahd_outw_atomic(struct ahd_softc * ahd,
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  394) 				     long port, uint16_t val);
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  395) void ahd_outsb(struct ahd_softc * ahd, long port,
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  396) 			       uint8_t *, int count);
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  397) void ahd_insb(struct ahd_softc * ahd, long port,
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  398) 			       uint8_t *, int count);
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  399) 
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  400) uint8_t
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  401) ahd_inb(struct ahd_softc * ahd, long port)
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  402) {
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  403) 	uint8_t x;
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  404) 
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  405) 	if (ahd->tags[0] == BUS_SPACE_MEMIO) {
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  406) 		x = readb(ahd->bshs[0].maddr + port);
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  407) 	} else {
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  408) 		x = inb(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF));
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  409) 	}
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  410) 	mb();
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  411) 	return (x);
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  412) }
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  413) 
d1d7b19d43318 (Denys Vlasenko     2008-04-25 04:34:49 +0200  414) #if 0 /* unused */
d1d7b19d43318 (Denys Vlasenko     2008-04-25 04:34:49 +0200  415) static uint16_t
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  416) ahd_inw_atomic(struct ahd_softc * ahd, long port)
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  417) {
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  418) 	uint8_t x;
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  419) 
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  420) 	if (ahd->tags[0] == BUS_SPACE_MEMIO) {
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  421) 		x = readw(ahd->bshs[0].maddr + port);
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  422) 	} else {
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  423) 		x = inw(ahd->bshs[(port) >> 8].ioport + ((port) & 0xFF));
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  424) 	}
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  425) 	mb();
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  426) 	return (x);
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  427) }
d1d7b19d43318 (Denys Vlasenko     2008-04-25 04:34:49 +0200  428) #endif
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  429) 
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  430) void
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  431) ahd_outb(struct ahd_softc * ahd, long port, uint8_t val)
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  432) {
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  433) 	if (ahd->tags[0] == BUS_SPACE_MEMIO) {
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  434) 		writeb(val, ahd->bshs[0].maddr + port);
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  435) 	} else {
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  436) 		outb(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF));
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  437) 	}
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  438) 	mb();
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  439) }
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  440) 
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  441) void
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  442) ahd_outw_atomic(struct ahd_softc * ahd, long port, uint16_t val)
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  443) {
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  444) 	if (ahd->tags[0] == BUS_SPACE_MEMIO) {
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  445) 		writew(val, ahd->bshs[0].maddr + port);
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  446) 	} else {
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  447) 		outw(val, ahd->bshs[(port) >> 8].ioport + (port & 0xFF));
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  448) 	}
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  449) 	mb();
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  450) }
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  451) 
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  452) void
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  453) ahd_outsb(struct ahd_softc * ahd, long port, uint8_t *array, int count)
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  454) {
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  455) 	int i;
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  456) 
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  457) 	/*
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  458) 	 * There is probably a more efficient way to do this on Linux
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  459) 	 * but we don't use this for anything speed critical and this
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  460) 	 * should work.
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  461) 	 */
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  462) 	for (i = 0; i < count; i++)
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  463) 		ahd_outb(ahd, port, *array++);
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  464) }
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  465) 
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  466) void
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  467) ahd_insb(struct ahd_softc * ahd, long port, uint8_t *array, int count)
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  468) {
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  469) 	int i;
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  470) 
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  471) 	/*
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  472) 	 * There is probably a more efficient way to do this on Linux
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  473) 	 * but we don't use this for anything speed critical and this
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  474) 	 * should work.
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  475) 	 */
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  476) 	for (i = 0; i < count; i++)
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  477) 		*array++ = ahd_inb(ahd, port);
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  478) }
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  479) 
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  480) /******************************* PCI Routines *********************************/
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  481) uint32_t
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  482) ahd_pci_read_config(ahd_dev_softc_t pci, int reg, int width)
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  483) {
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  484) 	switch (width) {
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  485) 	case 1:
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  486) 	{
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  487) 		uint8_t retval;
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  488) 
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  489) 		pci_read_config_byte(pci, reg, &retval);
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  490) 		return (retval);
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  491) 	}
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  492) 	case 2:
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  493) 	{
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  494) 		uint16_t retval;
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  495) 		pci_read_config_word(pci, reg, &retval);
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  496) 		return (retval);
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  497) 	}
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  498) 	case 4:
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  499) 	{
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  500) 		uint32_t retval;
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  501) 		pci_read_config_dword(pci, reg, &retval);
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  502) 		return (retval);
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  503) 	}
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  504) 	default:
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  505) 		panic("ahd_pci_read_config: Read size too big");
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  506) 		/* NOTREACHED */
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  507) 		return (0);
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  508) 	}
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  509) }
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  510) 
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  511) void
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  512) ahd_pci_write_config(ahd_dev_softc_t pci, int reg, uint32_t value, int width)
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  513) {
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  514) 	switch (width) {
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  515) 	case 1:
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  516) 		pci_write_config_byte(pci, reg, value);
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  517) 		break;
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  518) 	case 2:
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  519) 		pci_write_config_word(pci, reg, value);
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  520) 		break;
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  521) 	case 4:
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  522) 		pci_write_config_dword(pci, reg, value);
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  523) 		break;
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  524) 	default:
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  525) 		panic("ahd_pci_write_config: Write size too big");
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  526) 		/* NOTREACHED */
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  527) 	}
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  528) }
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  529) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  530) /****************************** Inlines ***************************************/
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  531) static void ahd_linux_unmap_scb(struct ahd_softc*, struct scb*);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  532) 
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  533) static void
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  534) ahd_linux_unmap_scb(struct ahd_softc *ahd, struct scb *scb)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  535) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  536) 	struct scsi_cmnd *cmd;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  537) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  538) 	cmd = scb->io_ctx;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  539) 	ahd_sync_sglist(ahd, scb, BUS_DMASYNC_POSTWRITE);
4c688fc7df618 (FUJITA Tomonori    2007-05-26 02:02:34 +0900  540) 	scsi_dma_unmap(cmd);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  541) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  542) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  543) /******************************** Macros **************************************/
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  544) #define BUILD_SCSIID(ahd, cmd)						\
422c0d61d591c (Jeff Garzik        2005-10-24 18:05:09 -0400  545) 	(((scmd_id(cmd) << TID_SHIFT) & TID) | (ahd)->our_id)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  546) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  547) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  548)  * Return a string describing the driver.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  549)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  550) static const char *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  551) ahd_linux_info(struct Scsi_Host *host)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  552) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  553) 	static char buffer[512];
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  554) 	char	ahd_info[256];
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  555) 	char   *bp;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  556) 	struct ahd_softc *ahd;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  557) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  558) 	bp = &buffer[0];
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  559) 	ahd = *(struct ahd_softc **)host->hostdata;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  560) 	memset(bp, 0, sizeof(buffer));
980b306a29772 (Denys Vlasenko     2008-04-25 04:36:01 +0200  561) 	strcpy(bp, "Adaptec AIC79XX PCI-X SCSI HBA DRIVER, Rev " AIC79XX_DRIVER_VERSION "\n"
980b306a29772 (Denys Vlasenko     2008-04-25 04:36:01 +0200  562) 			"        <");
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  563) 	strcat(bp, ahd->description);
980b306a29772 (Denys Vlasenko     2008-04-25 04:36:01 +0200  564) 	strcat(bp, ">\n"
980b306a29772 (Denys Vlasenko     2008-04-25 04:36:01 +0200  565) 			"        ");
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  566) 	ahd_controller_info(ahd, ahd_info);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  567) 	strcat(bp, ahd_info);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  568) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  569) 	return (bp);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  570) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  571) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  572) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  573)  * Queue an SCB to the controller.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  574)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  575) static int
f281233d3eba1 (Jeff Garzik        2010-11-16 02:10:29 -0500  576) ahd_linux_queue_lck(struct scsi_cmnd * cmd, void (*scsi_done) (struct scsi_cmnd *))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  577) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  578) 	struct	 ahd_softc *ahd;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  579) 	struct	 ahd_linux_device *dev = scsi_transport_device_data(cmd->device);
4065a413d7684 (Christoph Hellwig  2005-10-31 20:05:01 +0100  580) 	int rtn = SCSI_MLQUEUE_HOST_BUSY;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  581) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  582) 	ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  583) 
7b22da38b64a3 (Hannes Reinecke    2006-03-08 12:56:14 +0100  584) 	cmd->scsi_done = scsi_done;
7b22da38b64a3 (Hannes Reinecke    2006-03-08 12:56:14 +0100  585) 	cmd->result = CAM_REQ_INPROG << 16;
7b22da38b64a3 (Hannes Reinecke    2006-03-08 12:56:14 +0100  586) 	rtn = ahd_linux_run_command(ahd, dev, cmd);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  587) 
4065a413d7684 (Christoph Hellwig  2005-10-31 20:05:01 +0100  588) 	return rtn;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  589) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  590) 
f281233d3eba1 (Jeff Garzik        2010-11-16 02:10:29 -0500  591) static DEF_SCSI_QCMD(ahd_linux_queue)
f281233d3eba1 (Jeff Garzik        2010-11-16 02:10:29 -0500  592) 
be0d67680d524 (Denys Vlasenko     2008-03-23 04:41:22 +0100  593) static struct scsi_target **
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  594) ahd_linux_target_in_softc(struct scsi_target *starget)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  595) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  596) 	struct	ahd_softc *ahd =
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  597) 		*((struct ahd_softc **)dev_to_shost(&starget->dev)->hostdata);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  598) 	unsigned int target_offset;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  599) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  600) 	target_offset = starget->id;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  601) 	if (starget->channel != 0)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  602) 		target_offset += 8;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  603) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  604) 	return &ahd->platform_data->starget[target_offset];
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  605) }
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  606) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  607) static int
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  608) ahd_linux_target_alloc(struct scsi_target *starget)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  609) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  610) 	struct	ahd_softc *ahd =
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  611) 		*((struct ahd_softc **)dev_to_shost(&starget->dev)->hostdata);
986a25f96accc (Hannes Reinecke    2006-03-08 12:59:35 +0100  612) 	struct seeprom_config *sc = ahd->seep_config;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  613) 	unsigned long flags;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  614) 	struct scsi_target **ahd_targp = ahd_linux_target_in_softc(starget);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  615) 	struct ahd_devinfo devinfo;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  616) 	struct ahd_initiator_tinfo *tinfo;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  617) 	struct ahd_tmode_tstate *tstate;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  618) 	char channel = starget->channel + 'A';
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  619) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  620) 	ahd_lock(ahd, &flags);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  621) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  622) 	BUG_ON(*ahd_targp != NULL);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  623) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  624) 	*ahd_targp = starget;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  625) 
986a25f96accc (Hannes Reinecke    2006-03-08 12:59:35 +0100  626) 	if (sc) {
986a25f96accc (Hannes Reinecke    2006-03-08 12:59:35 +0100  627) 		int flags = sc->device_flags[starget->id];
986a25f96accc (Hannes Reinecke    2006-03-08 12:59:35 +0100  628) 
986a25f96accc (Hannes Reinecke    2006-03-08 12:59:35 +0100  629) 		tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
986a25f96accc (Hannes Reinecke    2006-03-08 12:59:35 +0100  630) 					    starget->id, &tstate);
986a25f96accc (Hannes Reinecke    2006-03-08 12:59:35 +0100  631) 
986a25f96accc (Hannes Reinecke    2006-03-08 12:59:35 +0100  632) 		if ((flags  & CFPACKETIZED) == 0) {
ea4431906d866 (James Bottomley    2009-06-13 12:19:05 -0500  633) 			/* don't negotiate packetized (IU) transfers */
ea4431906d866 (James Bottomley    2009-06-13 12:19:05 -0500  634) 			spi_max_iu(starget) = 0;
986a25f96accc (Hannes Reinecke    2006-03-08 12:59:35 +0100  635) 		} else {
986a25f96accc (Hannes Reinecke    2006-03-08 12:59:35 +0100  636) 			if ((ahd->features & AHD_RTI) == 0)
986a25f96accc (Hannes Reinecke    2006-03-08 12:59:35 +0100  637) 				spi_rti(starget) = 0;
986a25f96accc (Hannes Reinecke    2006-03-08 12:59:35 +0100  638) 		}
986a25f96accc (Hannes Reinecke    2006-03-08 12:59:35 +0100  639) 
986a25f96accc (Hannes Reinecke    2006-03-08 12:59:35 +0100  640) 		if ((flags & CFQAS) == 0)
ea4431906d866 (James Bottomley    2009-06-13 12:19:05 -0500  641) 			spi_max_qas(starget) = 0;
986a25f96accc (Hannes Reinecke    2006-03-08 12:59:35 +0100  642) 
986a25f96accc (Hannes Reinecke    2006-03-08 12:59:35 +0100  643) 		/* Transinfo values have been set to BIOS settings */
986a25f96accc (Hannes Reinecke    2006-03-08 12:59:35 +0100  644) 		spi_max_width(starget) = (flags & CFWIDEB) ? 1 : 0;
986a25f96accc (Hannes Reinecke    2006-03-08 12:59:35 +0100  645) 		spi_min_period(starget) = tinfo->user.period;
986a25f96accc (Hannes Reinecke    2006-03-08 12:59:35 +0100  646) 		spi_max_offset(starget) = tinfo->user.offset;
986a25f96accc (Hannes Reinecke    2006-03-08 12:59:35 +0100  647) 	}
986a25f96accc (Hannes Reinecke    2006-03-08 12:59:35 +0100  648) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  649) 	tinfo = ahd_fetch_transinfo(ahd, channel, ahd->our_id,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  650) 				    starget->id, &tstate);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  651) 	ahd_compile_devinfo(&devinfo, ahd->our_id, starget->id,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  652) 			    CAM_LUN_WILDCARD, channel,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  653) 			    ROLE_INITIATOR);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  654) 	ahd_set_syncrate(ahd, &devinfo, 0, 0, 0,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  655) 			 AHD_TRANS_GOAL, /*paused*/FALSE);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  656) 	ahd_set_width(ahd, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  657) 		      AHD_TRANS_GOAL, /*paused*/FALSE);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  658) 	ahd_unlock(ahd, &flags);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  659) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  660) 	return 0;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  661) }
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  662) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  663) static void
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  664) ahd_linux_target_destroy(struct scsi_target *starget)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  665) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  666) 	struct scsi_target **ahd_targp = ahd_linux_target_in_softc(starget);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  667) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  668) 	*ahd_targp = NULL;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  669) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  670) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  671) static int
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  672) ahd_linux_slave_alloc(struct scsi_device *sdev)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  673) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  674) 	struct	ahd_softc *ahd =
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  675) 		*((struct ahd_softc **)sdev->host->hostdata);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  676) 	struct ahd_linux_device *dev;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  677) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  678) 	if (bootverbose)
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300  679) 		printk("%s: Slave Alloc %d\n", ahd_name(ahd), sdev->id);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  680) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  681) 	dev = scsi_transport_device_data(sdev);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  682) 	memset(dev, 0, sizeof(*dev));
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  683) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  684) 	/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  685) 	 * We start out life using untagged
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  686) 	 * transactions of which we allow one.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  687) 	 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  688) 	dev->openings = 1;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  689) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  690) 	/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  691) 	 * Set maxtags to 0.  This will be changed if we
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  692) 	 * later determine that we are dealing with
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  693) 	 * a tagged queuing capable device.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  694) 	 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  695) 	dev->maxtags = 0;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  696) 	
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  697) 	return (0);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  698) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  699) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  700) static int
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  701) ahd_linux_slave_configure(struct scsi_device *sdev)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  702) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  703) 	struct	ahd_softc *ahd;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  704) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  705) 	ahd = *((struct ahd_softc **)sdev->host->hostdata);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  706) 	if (bootverbose)
017560fca496f (Jeff Garzik        2005-10-24 18:04:36 -0400  707) 		sdev_printk(KERN_INFO, sdev, "Slave Configure\n");
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  708) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  709) 	ahd_linux_device_queue_depth(sdev);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  710) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  711) 	/* Initial Domain Validation */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  712) 	if (!spi_initial_dv(sdev->sdev_target))
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  713) 		spi_dv_device(sdev);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  714) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  715) 	return 0;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  716) }
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  717) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  718) #if defined(__i386__)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  719) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  720)  * Return the disk geometry for the given SCSI device.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  721)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  722) static int
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  723) ahd_linux_biosparam(struct scsi_device *sdev, struct block_device *bdev,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  724) 		    sector_t capacity, int geom[])
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  725) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  726) 	int	 heads;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  727) 	int	 sectors;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  728) 	int	 cylinders;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  729) 	int	 extended;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  730) 	struct	 ahd_softc *ahd;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  731) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  732) 	ahd = *((struct ahd_softc **)sdev->host->hostdata);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  733) 
a10183d744fb4 (Christoph Hellwig  2020-03-24 08:25:17 +0100  734) 	if (scsi_partsize(bdev, capacity, geom))
a10183d744fb4 (Christoph Hellwig  2020-03-24 08:25:17 +0100  735) 		return 0;
a10183d744fb4 (Christoph Hellwig  2020-03-24 08:25:17 +0100  736) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  737) 	heads = 64;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  738) 	sectors = 32;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  739) 	cylinders = aic_sector_div(capacity, heads, sectors);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  740) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  741) 	if (aic79xx_extended != 0)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  742) 		extended = 1;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  743) 	else
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  744) 		extended = (ahd->flags & AHD_EXTENDED_TRANS_A) != 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  745) 	if (extended && cylinders >= 1024) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  746) 		heads = 255;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  747) 		sectors = 63;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  748) 		cylinders = aic_sector_div(capacity, heads, sectors);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  749) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  750) 	geom[0] = heads;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  751) 	geom[1] = sectors;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  752) 	geom[2] = cylinders;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  753) 	return (0);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  754) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  755) #endif
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  756) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  757) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  758)  * Abort the current SCSI command(s).
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  759)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  760) static int
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  761) ahd_linux_abort(struct scsi_cmnd *cmd)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  762) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  763) 	int error;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  764) 	
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  765) 	error = ahd_linux_queue_abort_cmd(cmd);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  766) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  767) 	return error;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  768) }
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  769) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  770) /*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  771)  * Attempt to send a target reset message to the device that timed out.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  772)  */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  773) static int
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  774) ahd_linux_dev_reset(struct scsi_cmnd *cmd)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  775) {
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  776) 	struct ahd_softc *ahd;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  777) 	struct ahd_linux_device *dev;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  778) 	struct scb *reset_scb;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  779) 	u_int  cdb_byte;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  780) 	int    retval = SUCCESS;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  781) 	int    paused;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  782) 	int    wait;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  783) 	struct	ahd_initiator_tinfo *tinfo;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  784) 	struct	ahd_tmode_tstate *tstate;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  785) 	unsigned long flags;
6e9a4738c9fad (Peter Zijlstra     2006-09-30 23:28:10 -0700  786) 	DECLARE_COMPLETION_ONSTACK(done);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  787) 
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  788) 	reset_scb = NULL;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  789) 	paused = FALSE;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  790) 	wait = FALSE;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  791) 	ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  792) 
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  793) 	scmd_printk(KERN_INFO, cmd,
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  794) 		    "Attempting to queue a TARGET RESET message:");
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  795) 
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300  796) 	printk("CDB:");
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  797) 	for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++)
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300  798) 		printk(" 0x%x", cmd->cmnd[cdb_byte]);
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300  799) 	printk("\n");
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  800) 
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  801) 	/*
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  802) 	 * Determine if we currently own this command.
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  803) 	 */
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  804) 	dev = scsi_transport_device_data(cmd->device);
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  805) 
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  806) 	if (dev == NULL) {
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  807) 		/*
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  808) 		 * No target device for this command exists,
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  809) 		 * so we must not still own the command.
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  810) 		 */
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  811) 		scmd_printk(KERN_INFO, cmd, "Is not an active device\n");
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  812) 		return SUCCESS;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  813) 	}
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  814) 
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  815) 	/*
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  816) 	 * Generate us a new SCB
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  817) 	 */
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  818) 	reset_scb = ahd_get_scb(ahd, AHD_NEVER_COL_IDX);
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  819) 	if (!reset_scb) {
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  820) 		scmd_printk(KERN_INFO, cmd, "No SCB available\n");
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  821) 		return FAILED;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  822) 	}
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  823) 
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  824) 	tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  825) 				    cmd->device->id, &tstate);
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  826) 	reset_scb->io_ctx = cmd;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  827) 	reset_scb->platform_data->dev = dev;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  828) 	reset_scb->sg_count = 0;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  829) 	ahd_set_residual(reset_scb, 0);
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  830) 	ahd_set_sense_residual(reset_scb, 0);
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  831) 	reset_scb->platform_data->xfer_len = 0;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  832) 	reset_scb->hscb->control = 0;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  833) 	reset_scb->hscb->scsiid = BUILD_SCSIID(ahd,cmd);
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  834) 	reset_scb->hscb->lun = cmd->device->lun;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  835) 	reset_scb->hscb->cdb_len = 0;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  836) 	reset_scb->hscb->task_management = SIU_TASKMGMT_LUN_RESET;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  837) 	reset_scb->flags |= SCB_DEVICE_RESET|SCB_RECOVERY_SCB|SCB_ACTIVE;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  838) 	if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  839) 		reset_scb->flags |= SCB_PACKETIZED;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  840) 	} else {
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  841) 		reset_scb->hscb->control |= MK_MESSAGE;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  842) 	}
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  843) 	dev->openings--;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  844) 	dev->active++;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  845) 	dev->commands_issued++;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  846) 
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  847) 	ahd_lock(ahd, &flags);
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  848) 
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  849) 	LIST_INSERT_HEAD(&ahd->pending_scbs, reset_scb, pending_links);
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  850) 	ahd_queue_scb(ahd, reset_scb);
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  851) 
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  852) 	ahd->platform_data->eh_done = &done;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  853) 	ahd_unlock(ahd, &flags);
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  854) 
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300  855) 	printk("%s: Device reset code sleeping\n", ahd_name(ahd));
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  856) 	if (!wait_for_completion_timeout(&done, 5 * HZ)) {
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  857) 		ahd_lock(ahd, &flags);
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  858) 		ahd->platform_data->eh_done = NULL;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  859) 		ahd_unlock(ahd, &flags);
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300  860) 		printk("%s: Device reset timer expired (active %d)\n",
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  861) 		       ahd_name(ahd), dev->active);
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  862) 		retval = FAILED;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  863) 	}
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300  864) 	printk("%s: Device reset returning 0x%x\n", ahd_name(ahd), retval);
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  865) 
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100  866) 	return (retval);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  867) }
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  868) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  869) /*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  870)  * Reset the SCSI bus.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  871)  */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  872) static int
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  873) ahd_linux_bus_reset(struct scsi_cmnd *cmd)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  874) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  875) 	struct ahd_softc *ahd;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  876) 	int    found;
f41b5cec9bd6f (Hannes Reinecke    2006-04-03 08:19:34 +0200  877) 	unsigned long flags;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  878) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  879) 	ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  880) #ifdef AHD_DEBUG
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  881) 	if ((ahd_debug & AHD_SHOW_RECOVERY) != 0)
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300  882) 		printk("%s: Bus reset called for cmd %p\n",
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  883) 		       ahd_name(ahd), cmd);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  884) #endif
f41b5cec9bd6f (Hannes Reinecke    2006-04-03 08:19:34 +0200  885) 	ahd_lock(ahd, &flags);
f41b5cec9bd6f (Hannes Reinecke    2006-04-03 08:19:34 +0200  886) 
422c0d61d591c (Jeff Garzik        2005-10-24 18:05:09 -0400  887) 	found = ahd_reset_channel(ahd, scmd_channel(cmd) + 'A',
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  888) 				  /*initiate reset*/TRUE);
f41b5cec9bd6f (Hannes Reinecke    2006-04-03 08:19:34 +0200  889) 	ahd_unlock(ahd, &flags);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  890) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  891) 	if (bootverbose)
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300  892) 		printk("%s: SCSI bus reset delivered. "
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  893) 		       "%d SCBs aborted.\n", ahd_name(ahd), found);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  894) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  895) 	return (SUCCESS);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  896) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  897) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  898) struct scsi_host_template aic79xx_driver_template = {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  899) 	.module			= THIS_MODULE,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  900) 	.name			= "aic79xx",
85a46523ff68a (Christoph Hellwig  2005-08-15 13:28:46 +0200  901) 	.proc_name		= "aic79xx",
f6f83a6c92107 (Al Viro            2013-03-31 03:59:17 -0400  902) 	.show_info		= ahd_linux_show_info,
f6f83a6c92107 (Al Viro            2013-03-31 03:59:17 -0400  903) 	.write_info	 	= ahd_proc_write_seeprom,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  904) 	.info			= ahd_linux_info,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  905) 	.queuecommand		= ahd_linux_queue,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  906) 	.eh_abort_handler	= ahd_linux_abort,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  907) 	.eh_device_reset_handler = ahd_linux_dev_reset,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  908) 	.eh_bus_reset_handler	= ahd_linux_bus_reset,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  909) #if defined(__i386__)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  910) 	.bios_param		= ahd_linux_biosparam,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  911) #endif
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  912) 	.can_queue		= AHD_MAX_QUEUE,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  913) 	.this_id		= -1,
80f1443c66de3 (Hannes Reinecke    2006-10-06 09:22:41 +0200  914) 	.max_sectors		= 8192,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  915) 	.cmd_per_lun		= 2,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  916) 	.slave_alloc		= ahd_linux_slave_alloc,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  917) 	.slave_configure	= ahd_linux_slave_configure,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  918) 	.target_alloc		= ahd_linux_target_alloc,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  919) 	.target_destroy		= ahd_linux_target_destroy,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  920) };
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  921) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  922) /******************************** Bus DMA *************************************/
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  923) int
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  924) ahd_dma_tag_create(struct ahd_softc *ahd, bus_dma_tag_t parent,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  925) 		   bus_size_t alignment, bus_size_t boundary,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  926) 		   dma_addr_t lowaddr, dma_addr_t highaddr,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  927) 		   bus_dma_filter_t *filter, void *filterarg,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  928) 		   bus_size_t maxsize, int nsegments,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  929) 		   bus_size_t maxsegsz, int flags, bus_dma_tag_t *ret_tag)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  930) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  931) 	bus_dma_tag_t dmat;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  932) 
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300  933) 	dmat = kmalloc(sizeof(*dmat), GFP_ATOMIC);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  934) 	if (dmat == NULL)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  935) 		return (ENOMEM);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  936) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  937) 	/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  938) 	 * Linux is very simplistic about DMA memory.  For now don't
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  939) 	 * maintain all specification information.  Once Linux supplies
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  940) 	 * better facilities for doing these operations, or the
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  941) 	 * needs of this particular driver change, we might need to do
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  942) 	 * more here.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  943) 	 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  944) 	dmat->alignment = alignment;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  945) 	dmat->boundary = boundary;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  946) 	dmat->maxsize = maxsize;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  947) 	*ret_tag = dmat;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  948) 	return (0);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  949) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  950) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  951) void
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  952) ahd_dma_tag_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  953) {
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300  954) 	kfree(dmat);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  955) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  956) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  957) int
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  958) ahd_dmamem_alloc(struct ahd_softc *ahd, bus_dma_tag_t dmat, void** vaddr,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  959) 		 int flags, bus_dmamap_t *mapp)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  960) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  961) 	*vaddr = pci_alloc_consistent(ahd->dev_softc,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  962) 				      dmat->maxsize, mapp);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  963) 	if (*vaddr == NULL)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  964) 		return (ENOMEM);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  965) 	return(0);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  966) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  967) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  968) void
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  969) ahd_dmamem_free(struct ahd_softc *ahd, bus_dma_tag_t dmat,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  970) 		void* vaddr, bus_dmamap_t map)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  971) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  972) 	pci_free_consistent(ahd->dev_softc, dmat->maxsize,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  973) 			    vaddr, map);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  974) }
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  975) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  976) int
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  977) ahd_dmamap_load(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  978) 		void *buf, bus_size_t buflen, bus_dmamap_callback_t *cb,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  979) 		void *cb_arg, int flags)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  980) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  981) 	/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  982) 	 * Assume for now that this will only be used during
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  983) 	 * initialization and not for per-transaction buffer mapping.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  984) 	 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  985) 	bus_dma_segment_t stack_sg;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  986) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  987) 	stack_sg.ds_addr = map;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  988) 	stack_sg.ds_len = dmat->maxsize;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  989) 	cb(cb_arg, &stack_sg, /*nseg*/1, /*error*/0);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  990) 	return (0);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  991) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  992) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  993) void
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  994) ahd_dmamap_destroy(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  995) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  996) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  997) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  998) int
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200  999) ahd_dmamap_unload(struct ahd_softc *ahd, bus_dma_tag_t dmat, bus_dmamap_t map)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1000) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1001) 	/* Nothing to do */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1002) 	return (0);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1003) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1004) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1005) /********************* Platform Dependent Functions ***************************/
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1006) static void
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1007) ahd_linux_setup_iocell_info(u_long index, int instance, int targ, int32_t value)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1008) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1009) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1010) 	if ((instance >= 0)
6391a11375de5 (Tobias Klauser     2006-06-08 22:23:48 -0700 1011) 	 && (instance < ARRAY_SIZE(aic79xx_iocell_info))) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1012) 		uint8_t *iocell_info;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1013) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1014) 		iocell_info = (uint8_t*)&aic79xx_iocell_info[instance];
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1015) 		iocell_info[index] = value & 0xFFFF;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1016) 		if (bootverbose)
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 1017) 			printk("iocell[%d:%ld] = %d\n", instance, index, value);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1018) 	}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1019) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1020) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1021) static void
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1022) ahd_linux_setup_tag_info_global(char *p)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1023) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1024) 	int tags, i, j;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1025) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1026) 	tags = simple_strtoul(p + 1, NULL, 0) & 0xff;
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 1027) 	printk("Setting Global Tags= %d\n", tags);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1028) 
6391a11375de5 (Tobias Klauser     2006-06-08 22:23:48 -0700 1029) 	for (i = 0; i < ARRAY_SIZE(aic79xx_tag_info); i++) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1030) 		for (j = 0; j < AHD_NUM_TARGETS; j++) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1031) 			aic79xx_tag_info[i].tag_commands[j] = tags;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1032) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1033) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1034) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1035) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1036) static void
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1037) ahd_linux_setup_tag_info(u_long arg, int instance, int targ, int32_t value)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1038) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1039) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1040) 	if ((instance >= 0) && (targ >= 0)
6391a11375de5 (Tobias Klauser     2006-06-08 22:23:48 -0700 1041) 	 && (instance < ARRAY_SIZE(aic79xx_tag_info))
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1042) 	 && (targ < AHD_NUM_TARGETS)) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1043) 		aic79xx_tag_info[instance].tag_commands[targ] = value & 0x1FF;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1044) 		if (bootverbose)
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 1045) 			printk("tag_info[%d:%d] = %d\n", instance, targ, value);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1046) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1047) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1048) 
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1049) static char *
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1050) ahd_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth,
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1051) 		       void (*callback)(u_long, int, int, int32_t),
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1052) 		       u_long callback_arg)
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1053) {
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1054) 	char	*tok_end;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1055) 	char	*tok_end2;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1056) 	int      i;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1057) 	int      instance;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1058) 	int	 targ;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1059) 	int	 done;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1060) 	char	 tok_list[] = {'.', ',', '{', '}', '\0'};
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1061) 
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1062) 	/* All options use a ':' name/arg separator */
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1063) 	if (*opt_arg != ':')
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1064) 		return (opt_arg);
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1065) 	opt_arg++;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1066) 	instance = -1;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1067) 	targ = -1;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1068) 	done = FALSE;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1069) 	/*
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1070) 	 * Restore separator that may be in
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1071) 	 * the middle of our option argument.
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1072) 	 */
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1073) 	tok_end = strchr(opt_arg, '\0');
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1074) 	if (tok_end < end)
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1075) 		*tok_end = ',';
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1076) 	while (!done) {
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1077) 		switch (*opt_arg) {
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1078) 		case '{':
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1079) 			if (instance == -1) {
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1080) 				instance = 0;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1081) 			} else {
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1082) 				if (depth > 1) {
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1083) 					if (targ == -1)
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1084) 						targ = 0;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1085) 				} else {
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 1086) 					printk("Malformed Option %s\n",
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1087) 					       opt_name);
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1088) 					done = TRUE;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1089) 				}
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1090) 			}
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1091) 			opt_arg++;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1092) 			break;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1093) 		case '}':
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1094) 			if (targ != -1)
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1095) 				targ = -1;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1096) 			else if (instance != -1)
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1097) 				instance = -1;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1098) 			opt_arg++;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1099) 			break;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1100) 		case ',':
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1101) 		case '.':
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1102) 			if (instance == -1)
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1103) 				done = TRUE;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1104) 			else if (targ >= 0)
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1105) 				targ++;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1106) 			else if (instance >= 0)
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1107) 				instance++;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1108) 			opt_arg++;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1109) 			break;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1110) 		case '\0':
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1111) 			done = TRUE;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1112) 			break;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1113) 		default:
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1114) 			tok_end = end;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1115) 			for (i = 0; tok_list[i]; i++) {
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1116) 				tok_end2 = strchr(opt_arg, tok_list[i]);
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1117) 				if ((tok_end2) && (tok_end2 < tok_end))
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1118) 					tok_end = tok_end2;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1119) 			}
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1120) 			callback(callback_arg, instance, targ,
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1121) 				 simple_strtol(opt_arg, NULL, 0));
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1122) 			opt_arg = tok_end;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1123) 			break;
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1124) 		}
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1125) 	}
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1126) 	return (opt_arg);
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1127) }
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1128) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1129) /*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1130)  * Handle Linux boot parameters. This routine allows for assigning a value
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1131)  * to a parameter with a ':' between the parameter and the value.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1132)  * ie. aic79xx=stpwlev:1,extended
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1133)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1134) static int
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1135) aic79xx_setup(char *s)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1136) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1137) 	int	i, n;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1138) 	char   *p;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1139) 	char   *end;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1140) 
980b306a29772 (Denys Vlasenko     2008-04-25 04:36:01 +0200 1141) 	static const struct {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1142) 		const char *name;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1143) 		uint32_t *flag;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1144) 	} options[] = {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1145) 		{ "extended", &aic79xx_extended },
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1146) 		{ "no_reset", &aic79xx_no_reset },
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1147) 		{ "verbose", &aic79xx_verbose },
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1148) 		{ "allow_memio", &aic79xx_allow_memio},
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1149) #ifdef AHD_DEBUG
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1150) 		{ "debug", &ahd_debug },
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1151) #endif
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1152) 		{ "periodic_otag", &aic79xx_periodic_otag },
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1153) 		{ "pci_parity", &aic79xx_pci_parity },
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1154) 		{ "seltime", &aic79xx_seltime },
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1155) 		{ "tag_info", NULL },
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1156) 		{ "global_tag_depth", NULL},
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1157) 		{ "slewrate", NULL },
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1158) 		{ "precomp", NULL },
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1159) 		{ "amplitude", NULL },
3fb086126462c (Hannes Reinecke    2006-01-24 10:44:38 +0100 1160) 		{ "slowcrc", &aic79xx_slowcrc },
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1161) 	};
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1162) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1163) 	end = strchr(s, '\0');
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1164) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1165) 	/*
6391a11375de5 (Tobias Klauser     2006-06-08 22:23:48 -0700 1166) 	 * XXX ia64 gcc isn't smart enough to know that ARRAY_SIZE
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1167) 	 * will never be 0 in this case.
6391a11375de5 (Tobias Klauser     2006-06-08 22:23:48 -0700 1168) 	 */
6391a11375de5 (Tobias Klauser     2006-06-08 22:23:48 -0700 1169) 	n = 0;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1170) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1171) 	while ((p = strsep(&s, ",.")) != NULL) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1172) 		if (*p == '\0')
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1173) 			continue;
6391a11375de5 (Tobias Klauser     2006-06-08 22:23:48 -0700 1174) 		for (i = 0; i < ARRAY_SIZE(options); i++) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1175) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1176) 			n = strlen(options[i].name);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1177) 			if (strncmp(options[i].name, p, n) == 0)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1178) 				break;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1179) 		}
6391a11375de5 (Tobias Klauser     2006-06-08 22:23:48 -0700 1180) 		if (i == ARRAY_SIZE(options))
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1181) 			continue;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1182) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1183) 		if (strncmp(p, "global_tag_depth", n) == 0) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1184) 			ahd_linux_setup_tag_info_global(p + n);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1185) 		} else if (strncmp(p, "tag_info", n) == 0) {
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1186) 			s = ahd_parse_brace_option("tag_info", p + n, end,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1187) 			    2, ahd_linux_setup_tag_info, 0);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1188) 		} else if (strncmp(p, "slewrate", n) == 0) {
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1189) 			s = ahd_parse_brace_option("slewrate",
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1190) 			    p + n, end, 1, ahd_linux_setup_iocell_info,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1191) 			    AIC79XX_SLEWRATE_INDEX);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1192) 		} else if (strncmp(p, "precomp", n) == 0) {
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1193) 			s = ahd_parse_brace_option("precomp",
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1194) 			    p + n, end, 1, ahd_linux_setup_iocell_info,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1195) 			    AIC79XX_PRECOMP_INDEX);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1196) 		} else if (strncmp(p, "amplitude", n) == 0) {
1ff927306e08b (Christoph Hellwig  2005-08-19 18:57:13 +0200 1197) 			s = ahd_parse_brace_option("amplitude",
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1198) 			    p + n, end, 1, ahd_linux_setup_iocell_info,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1199) 			    AIC79XX_AMPLITUDE_INDEX);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1200) 		} else if (p[n] == ':') {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1201) 			*(options[i].flag) = simple_strtoul(p + n + 1, NULL, 0);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1202) 		} else if (!strncmp(p, "verbose", n)) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1203) 			*(options[i].flag) = 1;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1204) 		} else {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1205) 			*(options[i].flag) ^= 0xFFFFFFFF;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1206) 		}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1207) 	}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1208) 	return 1;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1209) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1210) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1211) __setup("aic79xx=", aic79xx_setup);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1212) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1213) uint32_t aic79xx_verbose;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1214) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1215) int
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1216) ahd_linux_register_host(struct ahd_softc *ahd, struct scsi_host_template *template)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1217) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1218) 	char	buf[80];
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1219) 	struct	Scsi_Host *host;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1220) 	char	*new_name;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1221) 	u_long	s;
e7a1ca1d27e20 (Jesper Juhl        2005-12-14 19:27:28 +0100 1222) 	int	retval;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1223) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1224) 	template->name = ahd->description;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1225) 	host = scsi_host_alloc(template, sizeof(struct ahd_softc *));
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1226) 	if (host == NULL)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1227) 		return (ENOMEM);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1228) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1229) 	*((struct ahd_softc **)host->hostdata) = ahd;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1230) 	ahd->platform_data->host = host;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1231) 	host->can_queue = AHD_MAX_QUEUE;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1232) 	host->cmd_per_lun = 2;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1233) 	host->sg_tablesize = AHD_NSEG;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1234) 	host->this_id = ahd->our_id;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1235) 	host->irq = ahd->platform_data->irq;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1236) 	host->max_id = (ahd->features & AHD_WIDE) ? 16 : 8;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1237) 	host->max_lun = AHD_NUM_LUNS;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1238) 	host->max_channel = 0;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1239) 	host->sg_tablesize = AHD_NSEG;
eb221849540b7 (Hannes Reinecke    2006-01-30 16:10:31 +0100 1240) 	ahd_lock(ahd, &s);
85a46523ff68a (Christoph Hellwig  2005-08-15 13:28:46 +0200 1241) 	ahd_set_unit(ahd, ahd_linux_unit++);
eb221849540b7 (Hannes Reinecke    2006-01-30 16:10:31 +0100 1242) 	ahd_unlock(ahd, &s);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1243) 	sprintf(buf, "scsi%d", host->host_no);
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 1244) 	new_name = kmalloc(strlen(buf) + 1, GFP_ATOMIC);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1245) 	if (new_name != NULL) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1246) 		strcpy(new_name, buf);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1247) 		ahd_set_name(ahd, new_name);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1248) 	}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1249) 	host->unique_id = ahd->unit;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1250) 	ahd_linux_initialize_scsi_bus(ahd);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1251) 	ahd_intr_enable(ahd, TRUE);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1252) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1253) 	host->transportt = ahd_linux_transport_template;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1254) 
e7a1ca1d27e20 (Jesper Juhl        2005-12-14 19:27:28 +0100 1255) 	retval = scsi_add_host(host, &ahd->dev_softc->dev);
e7a1ca1d27e20 (Jesper Juhl        2005-12-14 19:27:28 +0100 1256) 	if (retval) {
e7a1ca1d27e20 (Jesper Juhl        2005-12-14 19:27:28 +0100 1257) 		printk(KERN_WARNING "aic79xx: scsi_add_host failed\n");
e7a1ca1d27e20 (Jesper Juhl        2005-12-14 19:27:28 +0100 1258) 		scsi_host_put(host);
e7a1ca1d27e20 (Jesper Juhl        2005-12-14 19:27:28 +0100 1259) 		return retval;
e7a1ca1d27e20 (Jesper Juhl        2005-12-14 19:27:28 +0100 1260) 	}
e7a1ca1d27e20 (Jesper Juhl        2005-12-14 19:27:28 +0100 1261) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1262) 	scsi_scan_host(host);
e7a1ca1d27e20 (Jesper Juhl        2005-12-14 19:27:28 +0100 1263) 	return 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1264) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1265) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1266) /*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1267)  * Place the SCSI bus into a known state by either resetting it,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1268)  * or forcing transfer negotiations on the next command to any
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1269)  * target.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1270)  */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1271) static void
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1272) ahd_linux_initialize_scsi_bus(struct ahd_softc *ahd)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1273) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1274) 	u_int target_id;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1275) 	u_int numtarg;
eb221849540b7 (Hannes Reinecke    2006-01-30 16:10:31 +0100 1276) 	unsigned long s;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1277) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1278) 	target_id = 0;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1279) 	numtarg = 0;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1280) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1281) 	if (aic79xx_no_reset != 0)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1282) 		ahd->flags &= ~AHD_RESET_BUS_A;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1283) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1284) 	if ((ahd->flags & AHD_RESET_BUS_A) != 0)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1285) 		ahd_reset_channel(ahd, 'A', /*initiate_reset*/TRUE);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1286) 	else
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1287) 		numtarg = (ahd->features & AHD_WIDE) ? 16 : 8;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1288) 
eb221849540b7 (Hannes Reinecke    2006-01-30 16:10:31 +0100 1289) 	ahd_lock(ahd, &s);
eb221849540b7 (Hannes Reinecke    2006-01-30 16:10:31 +0100 1290) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1291) 	/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1292) 	 * Force negotiation to async for all targets that
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1293) 	 * will not see an initial bus reset.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1294) 	 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1295) 	for (; target_id < numtarg; target_id++) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1296) 		struct ahd_devinfo devinfo;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1297) 		struct ahd_initiator_tinfo *tinfo;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1298) 		struct ahd_tmode_tstate *tstate;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1299) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1300) 		tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1301) 					    target_id, &tstate);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1302) 		ahd_compile_devinfo(&devinfo, ahd->our_id, target_id,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1303) 				    CAM_LUN_WILDCARD, 'A', ROLE_INITIATOR);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1304) 		ahd_update_neg_request(ahd, &devinfo, tstate,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1305) 				       tinfo, AHD_NEG_ALWAYS);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1306) 	}
eb221849540b7 (Hannes Reinecke    2006-01-30 16:10:31 +0100 1307) 	ahd_unlock(ahd, &s);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1308) 	/* Give the bus some time to recover */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1309) 	if ((ahd->flags & AHD_RESET_BUS_A) != 0) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1310) 		ahd_freeze_simq(ahd);
eb221849540b7 (Hannes Reinecke    2006-01-30 16:10:31 +0100 1311) 		msleep(AIC79XX_RESET_DELAY);
eb221849540b7 (Hannes Reinecke    2006-01-30 16:10:31 +0100 1312) 		ahd_release_simq(ahd);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1313) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1314) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1315) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1316) int
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1317) ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1318) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1319) 	ahd->platform_data =
114fc1d9a8cc7 (Michael Opdenacker 2015-03-26 17:51:46 -0700 1320) 	    kzalloc(sizeof(struct ahd_platform_data), GFP_ATOMIC);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1321) 	if (ahd->platform_data == NULL)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1322) 		return (ENOMEM);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1323) 	ahd->platform_data->irq = AHD_LINUX_NOIRQ;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1324) 	ahd_lockinit(ahd);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1325) 	ahd->seltime = (aic79xx_seltime & 0x3) << 4;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1326) 	return (0);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1327) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1328) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1329) void
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1330) ahd_platform_free(struct ahd_softc *ahd)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1331) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1332) 	struct scsi_target *starget;
f89d0a4e1d011 (Hannes Reinecke    2006-06-22 11:45:00 +0200 1333) 	int i;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1334) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1335) 	if (ahd->platform_data != NULL) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1336) 		/* destroy all of the device and target objects */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1337) 		for (i = 0; i < AHD_NUM_TARGETS; i++) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1338) 			starget = ahd->platform_data->starget[i];
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1339) 			if (starget != NULL) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1340) 				ahd->platform_data->starget[i] = NULL;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1341) 			}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1342) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1343) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1344) 		if (ahd->platform_data->irq != AHD_LINUX_NOIRQ)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1345) 			free_irq(ahd->platform_data->irq, ahd);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1346) 		if (ahd->tags[0] == BUS_SPACE_PIO
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1347) 		 && ahd->bshs[0].ioport != 0)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1348) 			release_region(ahd->bshs[0].ioport, 256);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1349) 		if (ahd->tags[1] == BUS_SPACE_PIO
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1350) 		 && ahd->bshs[1].ioport != 0)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1351) 			release_region(ahd->bshs[1].ioport, 256);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1352) 		if (ahd->tags[0] == BUS_SPACE_MEMIO
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1353) 		 && ahd->bshs[0].maddr != NULL) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1354) 			iounmap(ahd->bshs[0].maddr);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1355) 			release_mem_region(ahd->platform_data->mem_busaddr,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1356) 					   0x1000);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1357) 		}
97af50f60ff12 (James Bottomley    2005-10-02 15:22:35 -0500 1358) 		if (ahd->platform_data->host)
97af50f60ff12 (James Bottomley    2005-10-02 15:22:35 -0500 1359) 			scsi_host_put(ahd->platform_data->host);
97af50f60ff12 (James Bottomley    2005-10-02 15:22:35 -0500 1360) 
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 1361) 		kfree(ahd->platform_data);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1362) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1363) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1364) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1365) void
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1366) ahd_platform_init(struct ahd_softc *ahd)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1367) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1368) 	/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1369) 	 * Lookup and commit any modified IO Cell options.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1370) 	 */
6391a11375de5 (Tobias Klauser     2006-06-08 22:23:48 -0700 1371) 	if (ahd->unit < ARRAY_SIZE(aic79xx_iocell_info)) {
980b306a29772 (Denys Vlasenko     2008-04-25 04:36:01 +0200 1372) 		const struct ahd_linux_iocell_opts *iocell_opts;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1373) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1374) 		iocell_opts = &aic79xx_iocell_info[ahd->unit];
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1375) 		if (iocell_opts->precomp != AIC79XX_DEFAULT_PRECOMP)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1376) 			AHD_SET_PRECOMP(ahd, iocell_opts->precomp);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1377) 		if (iocell_opts->slewrate != AIC79XX_DEFAULT_SLEWRATE)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1378) 			AHD_SET_SLEWRATE(ahd, iocell_opts->slewrate);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1379) 		if (iocell_opts->amplitude != AIC79XX_DEFAULT_AMPLITUDE)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1380) 			AHD_SET_AMPLITUDE(ahd, iocell_opts->amplitude);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1381) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1382) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1383) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1384) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1385) void
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1386) ahd_platform_freeze_devq(struct ahd_softc *ahd, struct scb *scb)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1387) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1388) 	ahd_platform_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb),
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1389) 				SCB_GET_CHANNEL(ahd, scb),
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1390) 				SCB_GET_LUN(scb), SCB_LIST_NULL,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1391) 				ROLE_UNKNOWN, CAM_REQUEUE_REQ);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1392) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1393) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1394) void
f89d0a4e1d011 (Hannes Reinecke    2006-06-22 11:45:00 +0200 1395) ahd_platform_set_tags(struct ahd_softc *ahd, struct scsi_device *sdev,
f89d0a4e1d011 (Hannes Reinecke    2006-06-22 11:45:00 +0200 1396) 		      struct ahd_devinfo *devinfo, ahd_queue_alg alg)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1397) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1398) 	struct ahd_linux_device *dev;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1399) 	int was_queuing;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1400) 	int now_queuing;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1401) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1402) 	if (sdev == NULL)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1403) 		return;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1404) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1405) 	dev = scsi_transport_device_data(sdev);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1406) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1407) 	if (dev == NULL)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1408) 		return;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1409) 	was_queuing = dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1410) 	switch (alg) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1411) 	default:
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1412) 	case AHD_QUEUE_NONE:
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1413) 		now_queuing = 0;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1414) 		break; 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1415) 	case AHD_QUEUE_BASIC:
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1416) 		now_queuing = AHD_DEV_Q_BASIC;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1417) 		break;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1418) 	case AHD_QUEUE_TAGGED:
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1419) 		now_queuing = AHD_DEV_Q_TAGGED;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1420) 		break;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1421) 	}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1422) 	if ((dev->flags & AHD_DEV_FREEZE_TIL_EMPTY) == 0
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1423) 	 && (was_queuing != now_queuing)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1424) 	 && (dev->active != 0)) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1425) 		dev->flags |= AHD_DEV_FREEZE_TIL_EMPTY;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1426) 		dev->qfrozen++;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1427) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1428) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1429) 	dev->flags &= ~(AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED|AHD_DEV_PERIODIC_OTAG);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1430) 	if (now_queuing) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1431) 		u_int usertags;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1432) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1433) 		usertags = ahd_linux_user_tagdepth(ahd, devinfo);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1434) 		if (!was_queuing) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1435) 			/*
25985edcedea6 (Lucas De Marchi    2011-03-30 22:57:33 -0300 1436) 			 * Start out aggressively and allow our
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1437) 			 * dynamic queue depth algorithm to take
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1438) 			 * care of the rest.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1439) 			 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1440) 			dev->maxtags = usertags;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1441) 			dev->openings = dev->maxtags - dev->active;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1442) 		}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1443) 		if (dev->maxtags == 0) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1444) 			/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1445) 			 * Queueing is disabled by the user.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1446) 			 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1447) 			dev->openings = 1;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1448) 		} else if (alg == AHD_QUEUE_TAGGED) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1449) 			dev->flags |= AHD_DEV_Q_TAGGED;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1450) 			if (aic79xx_periodic_otag != 0)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1451) 				dev->flags |= AHD_DEV_PERIODIC_OTAG;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1452) 		} else
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1453) 			dev->flags |= AHD_DEV_Q_BASIC;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1454) 	} else {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1455) 		/* We can only have one opening. */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1456) 		dev->maxtags = 0;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1457) 		dev->openings =  1 - dev->active;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1458) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1459) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1460) 	switch ((dev->flags & (AHD_DEV_Q_BASIC|AHD_DEV_Q_TAGGED))) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1461) 	case AHD_DEV_Q_BASIC:
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1462) 	case AHD_DEV_Q_TAGGED:
db5ed4dfd5dd0 (Christoph Hellwig  2014-11-13 15:08:42 +0100 1463) 		scsi_change_queue_depth(sdev,
2ecb204d07ac8 (Christoph Hellwig  2014-11-03 14:09:02 +0100 1464) 				dev->openings + dev->active);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1465) 		break;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1466) 	default:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1467) 		/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1468) 		 * We allow the OS to queue 2 untagged transactions to
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1469) 		 * us at any time even though we can only execute them
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1470) 		 * serially on the controller/device.  This should
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1471) 		 * remove some latency.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1472) 		 */
db5ed4dfd5dd0 (Christoph Hellwig  2014-11-13 15:08:42 +0100 1473) 		scsi_change_queue_depth(sdev, 1);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1474) 		break;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1475) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1476) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1477) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1478) int
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1479) ahd_platform_abort_scbs(struct ahd_softc *ahd, int target, char channel,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1480) 			int lun, u_int tag, role_t role, uint32_t status)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1481) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1482) 	return 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1483) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1484) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1485) static u_int
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1486) ahd_linux_user_tagdepth(struct ahd_softc *ahd, struct ahd_devinfo *devinfo)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1487) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1488) 	static int warned_user;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1489) 	u_int tags;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1490) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1491) 	tags = 0;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1492) 	if ((ahd->user_discenable & devinfo->target_mask) != 0) {
6391a11375de5 (Tobias Klauser     2006-06-08 22:23:48 -0700 1493) 		if (ahd->unit >= ARRAY_SIZE(aic79xx_tag_info)) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1494) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1495) 			if (warned_user == 0) {
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 1496) 				printk(KERN_WARNING
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1497) "aic79xx: WARNING: Insufficient tag_info instances\n"
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1498) "aic79xx: for installed controllers.  Using defaults\n"
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1499) "aic79xx: Please update the aic79xx_tag_info array in\n"
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1500) "aic79xx: the aic79xx_osm.c source file.\n");
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1501) 				warned_user++;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1502) 			}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1503) 			tags = AHD_MAX_QUEUE;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1504) 		} else {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1505) 			adapter_tag_info_t *tag_info;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1506) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1507) 			tag_info = &aic79xx_tag_info[ahd->unit];
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1508) 			tags = tag_info->tag_commands[devinfo->target_offset];
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1509) 			if (tags > AHD_MAX_QUEUE)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1510) 				tags = AHD_MAX_QUEUE;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1511) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1512) 	}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1513) 	return (tags);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1514) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1515) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1516) /*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1517)  * Determines the queue depth for a given device.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1518)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1519) static void
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1520) ahd_linux_device_queue_depth(struct scsi_device *sdev)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1521) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1522) 	struct	ahd_devinfo devinfo;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1523) 	u_int	tags;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1524) 	struct ahd_softc *ahd = *((struct ahd_softc **)sdev->host->hostdata);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1525) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1526) 	ahd_compile_devinfo(&devinfo,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1527) 			    ahd->our_id,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1528) 			    sdev->sdev_target->id, sdev->lun,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1529) 			    sdev->sdev_target->channel == 0 ? 'A' : 'B',
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1530) 			    ROLE_INITIATOR);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1531) 	tags = ahd_linux_user_tagdepth(ahd, &devinfo);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1532) 	if (tags != 0 && sdev->tagged_supported != 0) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1533) 
f89d0a4e1d011 (Hannes Reinecke    2006-06-22 11:45:00 +0200 1534) 		ahd_platform_set_tags(ahd, sdev, &devinfo, AHD_QUEUE_TAGGED);
f89d0a4e1d011 (Hannes Reinecke    2006-06-22 11:45:00 +0200 1535) 		ahd_send_async(ahd, devinfo.channel, devinfo.target,
f89d0a4e1d011 (Hannes Reinecke    2006-06-22 11:45:00 +0200 1536) 			       devinfo.lun, AC_TRANSFER_NEG);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1537) 		ahd_print_devinfo(ahd, &devinfo);
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 1538) 		printk("Tagged Queuing enabled.  Depth %d\n", tags);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1539) 	} else {
f89d0a4e1d011 (Hannes Reinecke    2006-06-22 11:45:00 +0200 1540) 		ahd_platform_set_tags(ahd, sdev, &devinfo, AHD_QUEUE_NONE);
f89d0a4e1d011 (Hannes Reinecke    2006-06-22 11:45:00 +0200 1541) 		ahd_send_async(ahd, devinfo.channel, devinfo.target,
f89d0a4e1d011 (Hannes Reinecke    2006-06-22 11:45:00 +0200 1542) 			       devinfo.lun, AC_TRANSFER_NEG);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1543) 	}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1544) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1545) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1546) static int
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1547) ahd_linux_run_command(struct ahd_softc *ahd, struct ahd_linux_device *dev,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1548) 		      struct scsi_cmnd *cmd)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1549) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1550) 	struct	 scb *scb;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1551) 	struct	 hardware_scb *hscb;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1552) 	struct	 ahd_initiator_tinfo *tinfo;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1553) 	struct	 ahd_tmode_tstate *tstate;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1554) 	u_int	 col_idx;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1555) 	uint16_t mask;
7b22da38b64a3 (Hannes Reinecke    2006-03-08 12:56:14 +0100 1556) 	unsigned long flags;
4c688fc7df618 (FUJITA Tomonori    2007-05-26 02:02:34 +0900 1557) 	int nseg;
7b22da38b64a3 (Hannes Reinecke    2006-03-08 12:56:14 +0100 1558) 
2505873afe510 (FUJITA Tomonori    2008-03-09 22:50:40 +0900 1559) 	nseg = scsi_dma_map(cmd);
2505873afe510 (FUJITA Tomonori    2008-03-09 22:50:40 +0900 1560) 	if (nseg < 0)
2505873afe510 (FUJITA Tomonori    2008-03-09 22:50:40 +0900 1561) 		return SCSI_MLQUEUE_HOST_BUSY;
2505873afe510 (FUJITA Tomonori    2008-03-09 22:50:40 +0900 1562) 
7b22da38b64a3 (Hannes Reinecke    2006-03-08 12:56:14 +0100 1563) 	ahd_lock(ahd, &flags);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1564) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1565) 	/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1566) 	 * Get an scb to use.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1567) 	 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1568) 	tinfo = ahd_fetch_transinfo(ahd, 'A', ahd->our_id,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1569) 				    cmd->device->id, &tstate);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1570) 	if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) == 0
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1571) 	 || (tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1572) 		col_idx = AHD_NEVER_COL_IDX;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1573) 	} else {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1574) 		col_idx = AHD_BUILD_COL_IDX(cmd->device->id,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1575) 					    cmd->device->lun);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1576) 	}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1577) 	if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1578) 		ahd->flags |= AHD_RESOURCE_SHORTAGE;
7b22da38b64a3 (Hannes Reinecke    2006-03-08 12:56:14 +0100 1579) 		ahd_unlock(ahd, &flags);
2505873afe510 (FUJITA Tomonori    2008-03-09 22:50:40 +0900 1580) 		scsi_dma_unmap(cmd);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1581) 		return SCSI_MLQUEUE_HOST_BUSY;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1582) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1583) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1584) 	scb->io_ctx = cmd;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1585) 	scb->platform_data->dev = dev;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1586) 	hscb = scb->hscb;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1587) 	cmd->host_scribble = (char *)scb;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1588) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1589) 	/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1590) 	 * Fill out basics of the HSCB.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1591) 	 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1592) 	hscb->control = 0;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1593) 	hscb->scsiid = BUILD_SCSIID(ahd, cmd);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1594) 	hscb->lun = cmd->device->lun;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1595) 	scb->hscb->task_management = 0;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1596) 	mask = SCB_GET_TARGET_MASK(ahd, scb);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1597) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1598) 	if ((ahd->user_discenable & mask) != 0)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1599) 		hscb->control |= DISCENB;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1600) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1601) 	if ((tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ) != 0)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1602) 		scb->flags |= SCB_PACKETIZED;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1603) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1604) 	if ((tstate->auto_negotiate & mask) != 0) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1605) 		scb->flags |= SCB_AUTO_NEGOTIATE;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1606) 		scb->hscb->control |= MK_MESSAGE;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1607) 	}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1608) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1609) 	if ((dev->flags & (AHD_DEV_Q_TAGGED|AHD_DEV_Q_BASIC)) != 0) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1610) 		if (dev->commands_since_idle_or_otag == AHD_OTAG_THRESH
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1611) 		 && (dev->flags & AHD_DEV_Q_TAGGED) != 0) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1612) 			hscb->control |= MSG_ORDERED_TASK;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1613) 			dev->commands_since_idle_or_otag = 0;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1614) 		} else {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1615) 			hscb->control |= MSG_SIMPLE_TASK;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1616) 		}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1617) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1618) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1619) 	hscb->cdb_len = cmd->cmd_len;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1620) 	memcpy(hscb->shared_data.idata.cdb, cmd->cmnd, hscb->cdb_len);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1621) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1622) 	scb->platform_data->xfer_len = 0;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1623) 	ahd_set_residual(scb, 0);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1624) 	ahd_set_sense_residual(scb, 0);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1625) 	scb->sg_count = 0;
4c688fc7df618 (FUJITA Tomonori    2007-05-26 02:02:34 +0900 1626) 
4c688fc7df618 (FUJITA Tomonori    2007-05-26 02:02:34 +0900 1627) 	if (nseg > 0) {
4c688fc7df618 (FUJITA Tomonori    2007-05-26 02:02:34 +0900 1628) 		void *sg = scb->sg_list;
4c688fc7df618 (FUJITA Tomonori    2007-05-26 02:02:34 +0900 1629) 		struct scatterlist *cur_seg;
4c688fc7df618 (FUJITA Tomonori    2007-05-26 02:02:34 +0900 1630) 		int i;
4c688fc7df618 (FUJITA Tomonori    2007-05-26 02:02:34 +0900 1631) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1632) 		scb->platform_data->xfer_len = 0;
4c688fc7df618 (FUJITA Tomonori    2007-05-26 02:02:34 +0900 1633) 
4c688fc7df618 (FUJITA Tomonori    2007-05-26 02:02:34 +0900 1634) 		scsi_for_each_sg(cmd, cur_seg, nseg, i) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1635) 			dma_addr_t addr;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1636) 			bus_size_t len;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1637) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1638) 			addr = sg_dma_address(cur_seg);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1639) 			len = sg_dma_len(cur_seg);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1640) 			scb->platform_data->xfer_len += len;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1641) 			sg = ahd_sg_setup(ahd, scb, sg, addr, len,
4c688fc7df618 (FUJITA Tomonori    2007-05-26 02:02:34 +0900 1642) 					  i == (nseg - 1));
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1643) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1644) 	}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1645) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1646) 	LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1647) 	dev->openings--;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1648) 	dev->active++;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1649) 	dev->commands_issued++;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1650) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1651) 	if ((dev->flags & AHD_DEV_PERIODIC_OTAG) != 0)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1652) 		dev->commands_since_idle_or_otag++;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1653) 	scb->flags |= SCB_ACTIVE;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1654) 	ahd_queue_scb(ahd, scb);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1655) 
7b22da38b64a3 (Hannes Reinecke    2006-03-08 12:56:14 +0100 1656) 	ahd_unlock(ahd, &flags);
7b22da38b64a3 (Hannes Reinecke    2006-03-08 12:56:14 +0100 1657) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1658) 	return 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1659) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1660) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1661) /*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1662)  * SCSI controller interrupt handler.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1663)  */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1664) irqreturn_t
7d12e780e003f (David Howells      2006-10-05 14:55:46 +0100 1665) ahd_linux_isr(int irq, void *dev_id)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1666) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1667) 	struct	ahd_softc *ahd;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1668) 	u_long	flags;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1669) 	int	ours;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1670) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1671) 	ahd = (struct ahd_softc *) dev_id;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1672) 	ahd_lock(ahd, &flags); 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1673) 	ours = ahd_intr(ahd);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1674) 	ahd_unlock(ahd, &flags);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1675) 	return IRQ_RETVAL(ours);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1676) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1677) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1678) void
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1679) ahd_send_async(struct ahd_softc *ahd, char channel,
f89d0a4e1d011 (Hannes Reinecke    2006-06-22 11:45:00 +0200 1680) 	       u_int target, u_int lun, ac_code code)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1681) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1682) 	switch (code) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1683) 	case AC_TRANSFER_NEG:
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1684) 	{
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1685) 		struct  scsi_target *starget;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1686) 		struct	ahd_initiator_tinfo *tinfo;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1687) 		struct	ahd_tmode_tstate *tstate;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1688) 		unsigned int target_ppr_options;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1689) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1690) 		BUG_ON(target == CAM_TARGET_WILDCARD);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1691) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1692) 		tinfo = ahd_fetch_transinfo(ahd, channel, ahd->our_id,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1693) 					    target, &tstate);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1694) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1695) 		/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1696) 		 * Don't bother reporting results while
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1697) 		 * negotiations are still pending.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1698) 		 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1699) 		if (tinfo->curr.period != tinfo->goal.period
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1700) 		 || tinfo->curr.width != tinfo->goal.width
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1701) 		 || tinfo->curr.offset != tinfo->goal.offset
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1702) 		 || tinfo->curr.ppr_options != tinfo->goal.ppr_options)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1703) 			if (bootverbose == 0)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1704) 				break;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1705) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1706) 		/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1707) 		 * Don't bother reporting results that
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1708) 		 * are identical to those last reported.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1709) 		 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1710) 		starget = ahd->platform_data->starget[target];
fc789a9399485 (James Bottomley    2005-08-05 16:24:54 -0500 1711) 		if (starget == NULL)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1712) 			break;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1713) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1714) 		target_ppr_options =
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1715) 			(spi_dt(starget) ? MSG_EXT_PPR_DT_REQ : 0)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1716) 			+ (spi_qas(starget) ? MSG_EXT_PPR_QAS_REQ : 0)
3f40d7d6eaade (James Bottomley    2005-08-03 13:25:10 -0500 1717) 			+ (spi_iu(starget) ?  MSG_EXT_PPR_IU_REQ : 0)
3f40d7d6eaade (James Bottomley    2005-08-03 13:25:10 -0500 1718) 			+ (spi_rd_strm(starget) ? MSG_EXT_PPR_RD_STRM : 0)
3f40d7d6eaade (James Bottomley    2005-08-03 13:25:10 -0500 1719) 			+ (spi_pcomp_en(starget) ? MSG_EXT_PPR_PCOMP_EN : 0)
3f40d7d6eaade (James Bottomley    2005-08-03 13:25:10 -0500 1720) 			+ (spi_rti(starget) ? MSG_EXT_PPR_RTI : 0)
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 1721) 			+ (spi_wr_flow(starget) ? MSG_EXT_PPR_WR_FLOW : 0)
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 1722) 			+ (spi_hold_mcs(starget) ? MSG_EXT_PPR_HOLD_MCS : 0);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1723) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1724) 		if (tinfo->curr.period == spi_period(starget)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1725) 		    && tinfo->curr.width == spi_width(starget)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1726) 		    && tinfo->curr.offset == spi_offset(starget)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1727) 		 && tinfo->curr.ppr_options == target_ppr_options)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1728) 			if (bootverbose == 0)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1729) 				break;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1730) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1731) 		spi_period(starget) = tinfo->curr.period;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1732) 		spi_width(starget) = tinfo->curr.width;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1733) 		spi_offset(starget) = tinfo->curr.offset;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 1734) 		spi_dt(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_DT_REQ ? 1 : 0;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 1735) 		spi_qas(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_QAS_REQ ? 1 : 0;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 1736) 		spi_iu(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_IU_REQ ? 1 : 0;
3f40d7d6eaade (James Bottomley    2005-08-03 13:25:10 -0500 1737) 		spi_rd_strm(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_RD_STRM ? 1 : 0;
3f40d7d6eaade (James Bottomley    2005-08-03 13:25:10 -0500 1738) 		spi_pcomp_en(starget) =  tinfo->curr.ppr_options & MSG_EXT_PPR_PCOMP_EN ? 1 : 0;
3f40d7d6eaade (James Bottomley    2005-08-03 13:25:10 -0500 1739) 		spi_rti(starget) =  tinfo->curr.ppr_options &  MSG_EXT_PPR_RTI ? 1 : 0;
3f40d7d6eaade (James Bottomley    2005-08-03 13:25:10 -0500 1740) 		spi_wr_flow(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_WR_FLOW ? 1 : 0;
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 1741) 		spi_hold_mcs(starget) = tinfo->curr.ppr_options & MSG_EXT_PPR_HOLD_MCS ? 1 : 0;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1742) 		spi_display_xfer_agreement(starget);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1743) 		break;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1744) 	}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1745)         case AC_SENT_BDR:
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1746) 	{
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1747) 		WARN_ON(lun != CAM_LUN_WILDCARD);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1748) 		scsi_report_device_reset(ahd->platform_data->host,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1749) 					 channel - 'A', target);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1750) 		break;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1751) 	}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1752)         case AC_BUS_RESET:
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1753) 		if (ahd->platform_data->host != NULL) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1754) 			scsi_report_bus_reset(ahd->platform_data->host,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1755) 					      channel - 'A');
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1756) 		}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1757)                 break;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1758)         default:
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1759)                 panic("ahd_send_async: Unexpected async event");
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1760)         }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1761) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1762) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1763) /*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1764)  * Calls the higher level scsi done function and frees the scb.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1765)  */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1766) void
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1767) ahd_done(struct ahd_softc *ahd, struct scb *scb)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1768) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1769) 	struct scsi_cmnd *cmd;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1770) 	struct	  ahd_linux_device *dev;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1771) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1772) 	if ((scb->flags & SCB_ACTIVE) == 0) {
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 1773) 		printk("SCB %d done'd twice\n", SCB_GET_TAG(scb));
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1774) 		ahd_dump_card_state(ahd);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1775) 		panic("Stopping for safety");
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1776) 	}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1777) 	LIST_REMOVE(scb, pending_links);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1778) 	cmd = scb->io_ctx;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1779) 	dev = scb->platform_data->dev;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1780) 	dev->active--;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1781) 	dev->openings++;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1782) 	if ((cmd->result & (CAM_DEV_QFRZN << 16)) != 0) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1783) 		cmd->result &= ~(CAM_DEV_QFRZN << 16);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1784) 		dev->qfrozen--;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1785) 	}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1786) 	ahd_linux_unmap_scb(ahd, scb);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1787) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1788) 	/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1789) 	 * Guard against stale sense data.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1790) 	 * The Linux mid-layer assumes that sense
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1791) 	 * was retrieved anytime the first byte of
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1792) 	 * the sense buffer looks "sane".
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1793) 	 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1794) 	cmd->sense_buffer[0] = 0;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1795) 	if (ahd_get_transaction_status(scb) == CAM_REQ_INPROG) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1796) 		uint32_t amount_xferred;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1797) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1798) 		amount_xferred =
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1799) 		    ahd_get_transfer_length(scb) - ahd_get_residual(scb);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1800) 		if ((scb->flags & SCB_TRANSMISSION_ERROR) != 0) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1801) #ifdef AHD_DEBUG
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1802) 			if ((ahd_debug & AHD_SHOW_MISC) != 0) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1803) 				ahd_print_path(ahd, scb);
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 1804) 				printk("Set CAM_UNCOR_PARITY\n");
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1805) 			}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1806) #endif
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1807) 			ahd_set_transaction_status(scb, CAM_UNCOR_PARITY);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1808) #ifdef AHD_REPORT_UNDERFLOWS
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1809) 		/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1810) 		 * This code is disabled by default as some
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1811) 		 * clients of the SCSI system do not properly
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1812) 		 * initialize the underflow parameter.  This
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1813) 		 * results in spurious termination of commands
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1814) 		 * that complete as expected (e.g. underflow is
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1815) 		 * allowed as command can return variable amounts
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1816) 		 * of data.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1817) 		 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1818) 		} else if (amount_xferred < scb->io_ctx->underflow) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1819) 			u_int i;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1820) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1821) 			ahd_print_path(ahd, scb);
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 1822) 			printk("CDB:");
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1823) 			for (i = 0; i < scb->io_ctx->cmd_len; i++)
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 1824) 				printk(" 0x%x", scb->io_ctx->cmnd[i]);
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 1825) 			printk("\n");
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1826) 			ahd_print_path(ahd, scb);
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 1827) 			printk("Saw underflow (%ld of %ld bytes). "
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1828) 			       "Treated as error\n",
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1829) 				ahd_get_residual(scb),
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1830) 				ahd_get_transfer_length(scb));
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1831) 			ahd_set_transaction_status(scb, CAM_DATA_RUN_ERR);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1832) #endif
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1833) 		} else {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1834) 			ahd_set_transaction_status(scb, CAM_REQ_CMP);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1835) 		}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1836) 	} else if (ahd_get_transaction_status(scb) == CAM_SCSI_STATUS_ERROR) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1837) 		ahd_linux_handle_scsi_status(ahd, cmd->device, scb);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1838) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1839) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1840) 	if (dev->openings == 1
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1841) 	 && ahd_get_transaction_status(scb) == CAM_REQ_CMP
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1842) 	 && ahd_get_scsi_status(scb) != SCSI_STATUS_QUEUE_FULL)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1843) 		dev->tag_success_count++;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1844) 	/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1845) 	 * Some devices deal with temporary internal resource
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1846) 	 * shortages by returning queue full.  When the queue
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1847) 	 * full occurrs, we throttle back.  Slowly try to get
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1848) 	 * back to our previous queue depth.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1849) 	 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1850) 	if ((dev->openings + dev->active) < dev->maxtags
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1851) 	 && dev->tag_success_count > AHD_TAG_SUCCESS_INTERVAL) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1852) 		dev->tag_success_count = 0;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1853) 		dev->openings++;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1854) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1855) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1856) 	if (dev->active == 0)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1857) 		dev->commands_since_idle_or_otag = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1858) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1859) 	if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 1860) 		printk("Recovery SCB completes\n");
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1861) 		if (ahd_get_transaction_status(scb) == CAM_BDR_SENT
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1862) 		 || ahd_get_transaction_status(scb) == CAM_REQ_ABORTED)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1863) 			ahd_set_transaction_status(scb, CAM_CMD_TIMEOUT);
7b22da38b64a3 (Hannes Reinecke    2006-03-08 12:56:14 +0100 1864) 
7b22da38b64a3 (Hannes Reinecke    2006-03-08 12:56:14 +0100 1865) 		if (ahd->platform_data->eh_done)
7b22da38b64a3 (Hannes Reinecke    2006-03-08 12:56:14 +0100 1866) 			complete(ahd->platform_data->eh_done);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1867) 	}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1868) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1869) 	ahd_free_scb(ahd, scb);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1870) 	ahd_linux_queue_cmd_complete(ahd, cmd);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1871) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1872) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1873) static void
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1874) ahd_linux_handle_scsi_status(struct ahd_softc *ahd,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1875) 			     struct scsi_device *sdev, struct scb *scb)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1876) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1877) 	struct	ahd_devinfo devinfo;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1878) 	struct ahd_linux_device *dev = scsi_transport_device_data(sdev);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1879) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1880) 	ahd_compile_devinfo(&devinfo,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1881) 			    ahd->our_id,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1882) 			    sdev->sdev_target->id, sdev->lun,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1883) 			    sdev->sdev_target->channel == 0 ? 'A' : 'B',
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1884) 			    ROLE_INITIATOR);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1885) 	
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1886) 	/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1887) 	 * We don't currently trust the mid-layer to
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1888) 	 * properly deal with queue full or busy.  So,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1889) 	 * when one occurs, we tell the mid-layer to
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1890) 	 * unconditionally requeue the command to us
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1891) 	 * so that we can retry it ourselves.  We also
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1892) 	 * implement our own throttling mechanism so
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1893) 	 * we don't clobber the device with too many
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1894) 	 * commands.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1895) 	 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1896) 	switch (ahd_get_scsi_status(scb)) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1897) 	default:
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1898) 		break;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1899) 	case SCSI_STATUS_CHECK_COND:
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1900) 	case SCSI_STATUS_CMD_TERMINATED:
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1901) 	{
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1902) 		struct scsi_cmnd *cmd;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1903) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1904) 		/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1905) 		 * Copy sense information to the OS's cmd
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1906) 		 * structure if it is available.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1907) 		 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1908) 		cmd = scb->io_ctx;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1909) 		if ((scb->flags & (SCB_SENSE|SCB_PKT_SENSE)) != 0) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1910) 			struct scsi_status_iu_header *siu;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1911) 			u_int sense_size;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1912) 			u_int sense_offset;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1913) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1914) 			if (scb->flags & SCB_SENSE) {
6d07cb71fdacc (Amol Lad           2006-10-20 14:48:40 -0700 1915) 				sense_size = min(sizeof(struct scsi_sense_data)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1916) 					       - ahd_get_sense_residual(scb),
b80ca4f7ee36c (FUJITA Tomonori    2008-01-13 15:46:13 +0900 1917) 						 (u_long)SCSI_SENSE_BUFFERSIZE);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1918) 				sense_offset = 0;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1919) 			} else {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1920) 				/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1921) 				 * Copy only the sense data into the provided
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1922) 				 * buffer.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1923) 				 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1924) 				siu = (struct scsi_status_iu_header *)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1925) 				    scb->sense_data;
6d07cb71fdacc (Amol Lad           2006-10-20 14:48:40 -0700 1926) 				sense_size = min_t(size_t,
6d07cb71fdacc (Amol Lad           2006-10-20 14:48:40 -0700 1927) 						scsi_4btoul(siu->sense_length),
b80ca4f7ee36c (FUJITA Tomonori    2008-01-13 15:46:13 +0900 1928) 						SCSI_SENSE_BUFFERSIZE);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1929) 				sense_offset = SIU_SENSE_OFFSET(siu);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1930) 			}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1931) 
b80ca4f7ee36c (FUJITA Tomonori    2008-01-13 15:46:13 +0900 1932) 			memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1933) 			memcpy(cmd->sense_buffer,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1934) 			       ahd_get_sense_buf(ahd, scb)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1935) 			       + sense_offset, sense_size);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1936) 			cmd->result |= (DRIVER_SENSE << 24);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1937) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1938) #ifdef AHD_DEBUG
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1939) 			if (ahd_debug & AHD_SHOW_SENSE) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1940) 				int i;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1941) 
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 1942) 				printk("Copied %d bytes of sense data at %d:",
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1943) 				       sense_size, sense_offset);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1944) 				for (i = 0; i < sense_size; i++) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1945) 					if ((i & 0xF) == 0)
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 1946) 						printk("\n");
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 1947) 					printk("0x%x ", cmd->sense_buffer[i]);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1948) 				}
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 1949) 				printk("\n");
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1950) 			}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1951) #endif
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1952) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1953) 		break;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1954) 	}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1955) 	case SCSI_STATUS_QUEUE_FULL:
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1956) 		/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1957) 		 * By the time the core driver has returned this
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1958) 		 * command, all other commands that were queued
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1959) 		 * to us but not the device have been returned.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1960) 		 * This ensures that dev->active is equal to
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1961) 		 * the number of commands actually queued to
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1962) 		 * the device.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1963) 		 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1964) 		dev->tag_success_count = 0;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1965) 		if (dev->active != 0) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1966) 			/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1967) 			 * Drop our opening count to the number
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1968) 			 * of commands currently outstanding.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1969) 			 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1970) 			dev->openings = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1971) #ifdef AHD_DEBUG
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1972) 			if ((ahd_debug & AHD_SHOW_QFULL) != 0) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1973) 				ahd_print_path(ahd, scb);
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 1974) 				printk("Dropping tag count to %d\n",
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1975) 				       dev->active);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1976) 			}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1977) #endif
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1978) 			if (dev->active == dev->tags_on_last_queuefull) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1979) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1980) 				dev->last_queuefull_same_count++;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1981) 				/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1982) 				 * If we repeatedly see a queue full
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1983) 				 * at the same queue depth, this
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1984) 				 * device has a fixed number of tag
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1985) 				 * slots.  Lock in this tag depth
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1986) 				 * so we stop seeing queue fulls from
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1987) 				 * this device.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1988) 				 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1989) 				if (dev->last_queuefull_same_count
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1990) 				 == AHD_LOCK_TAGS_COUNT) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1991) 					dev->maxtags = dev->active;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1992) 					ahd_print_path(ahd, scb);
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 1993) 					printk("Locking max tag count at %d\n",
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1994) 					       dev->active);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1995) 				}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1996) 			} else {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1997) 				dev->tags_on_last_queuefull = dev->active;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 1998) 				dev->last_queuefull_same_count = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 1999) 			}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2000) 			ahd_set_transaction_status(scb, CAM_REQUEUE_REQ);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2001) 			ahd_set_scsi_status(scb, SCSI_STATUS_OK);
f89d0a4e1d011 (Hannes Reinecke    2006-06-22 11:45:00 +0200 2002) 			ahd_platform_set_tags(ahd, sdev, &devinfo,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2003) 				     (dev->flags & AHD_DEV_Q_BASIC)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2004) 				   ? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2005) 			break;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2006) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2007) 		/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2008) 		 * Drop down to a single opening, and treat this
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2009) 		 * as if the target returned BUSY SCSI status.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2010) 		 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2011) 		dev->openings = 1;
f89d0a4e1d011 (Hannes Reinecke    2006-06-22 11:45:00 +0200 2012) 		ahd_platform_set_tags(ahd, sdev, &devinfo,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2013) 			     (dev->flags & AHD_DEV_Q_BASIC)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2014) 			   ? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2015) 		ahd_set_scsi_status(scb, SCSI_STATUS_BUSY);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2016) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2017) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2018) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2019) static void
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2020) ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2021) {
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2022) 	int status;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2023) 	int new_status = DID_OK;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2024) 	int do_fallback = 0;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2025) 	int scsi_status;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2026) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2027) 	/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2028) 	 * Map CAM error codes into Linux Error codes.  We
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2029) 	 * avoid the conversion so that the DV code has the
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2030) 	 * full error information available when making
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2031) 	 * state change decisions.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2032) 	 */
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2033) 
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2034) 	status = ahd_cmd_get_transaction_status(cmd);
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2035) 	switch (status) {
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2036) 	case CAM_REQ_INPROG:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2037) 	case CAM_REQ_CMP:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2038) 		new_status = DID_OK;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2039) 		break;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2040) 	case CAM_AUTOSENSE_FAIL:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2041) 		new_status = DID_ERROR;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2042) 		/* Fallthrough */
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2043) 	case CAM_SCSI_STATUS_ERROR:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2044) 		scsi_status = ahd_cmd_get_scsi_status(cmd);
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2045) 
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2046) 		switch(scsi_status) {
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2047) 		case SCSI_STATUS_CMD_TERMINATED:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2048) 		case SCSI_STATUS_CHECK_COND:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2049) 			if ((cmd->result >> 24) != DRIVER_SENSE) {
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2050) 				do_fallback = 1;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2051) 			} else {
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2052) 				struct scsi_sense_data *sense;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2053) 				
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2054) 				sense = (struct scsi_sense_data *)
c1c9ce52c8674 (FUJITA Tomonori    2008-01-27 12:41:09 +0900 2055) 					cmd->sense_buffer;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2056) 				if (sense->extra_len >= 5 &&
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2057) 				    (sense->add_sense_code == 0x47
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2058) 				     || sense->add_sense_code == 0x48))
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2059) 					do_fallback = 1;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2060) 			}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2061) 			break;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2062) 		default:
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2063) 			break;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2064) 		}
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2065) 		break;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2066) 	case CAM_REQ_ABORTED:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2067) 		new_status = DID_ABORT;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2068) 		break;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2069) 	case CAM_BUSY:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2070) 		new_status = DID_BUS_BUSY;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2071) 		break;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2072) 	case CAM_REQ_INVALID:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2073) 	case CAM_PATH_INVALID:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2074) 		new_status = DID_BAD_TARGET;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2075) 		break;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2076) 	case CAM_SEL_TIMEOUT:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2077) 		new_status = DID_NO_CONNECT;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2078) 		break;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2079) 	case CAM_SCSI_BUS_RESET:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2080) 	case CAM_BDR_SENT:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2081) 		new_status = DID_RESET;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2082) 		break;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2083) 	case CAM_UNCOR_PARITY:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2084) 		new_status = DID_PARITY;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2085) 		do_fallback = 1;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2086) 		break;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2087) 	case CAM_CMD_TIMEOUT:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2088) 		new_status = DID_TIME_OUT;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2089) 		do_fallback = 1;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2090) 		break;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2091) 	case CAM_REQ_CMP_ERR:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2092) 	case CAM_UNEXP_BUSFREE:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2093) 	case CAM_DATA_RUN_ERR:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2094) 		new_status = DID_ERROR;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2095) 		do_fallback = 1;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2096) 		break;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2097) 	case CAM_UA_ABORT:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2098) 	case CAM_NO_HBA:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2099) 	case CAM_SEQUENCE_FAIL:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2100) 	case CAM_CCB_LEN_ERR:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2101) 	case CAM_PROVIDE_FAIL:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2102) 	case CAM_REQ_TERMIO:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2103) 	case CAM_UNREC_HBA_ERROR:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2104) 	case CAM_REQ_TOO_BIG:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2105) 		new_status = DID_ERROR;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2106) 		break;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2107) 	case CAM_REQUEUE_REQ:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2108) 		new_status = DID_REQUEUE;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2109) 		break;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2110) 	default:
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2111) 		/* We should never get here */
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2112) 		new_status = DID_ERROR;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2113) 		break;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2114) 	}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2115) 
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2116) 	if (do_fallback) {
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 2117) 		printk("%s: device overrun (status %x) on %d:%d:%d\n",
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2118) 		       ahd_name(ahd), status, cmd->device->channel,
9cb78c16f5dad (Hannes Reinecke    2014-06-25 15:27:36 +0200 2119) 		       cmd->device->id, (u8)cmd->device->lun);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2120) 	}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2121) 
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2122) 	ahd_cmd_set_transaction_status(cmd, new_status);
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2123) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2124) 	cmd->scsi_done(cmd);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2125) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2126) 
e3e0ca5143d7a (Adrian Bunk        2007-03-26 21:59:29 -0800 2127) static void
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2128) ahd_freeze_simq(struct ahd_softc *ahd)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2129) {
7b22da38b64a3 (Hannes Reinecke    2006-03-08 12:56:14 +0100 2130) 	scsi_block_requests(ahd->platform_data->host);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2131) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2132) 
e3e0ca5143d7a (Adrian Bunk        2007-03-26 21:59:29 -0800 2133) static void
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2134) ahd_release_simq(struct ahd_softc *ahd)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2135) {
7b22da38b64a3 (Hannes Reinecke    2006-03-08 12:56:14 +0100 2136) 	scsi_unblock_requests(ahd->platform_data->host);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2137) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2138) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2139) static int
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2140) ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2141) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2142) 	struct ahd_softc *ahd;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2143) 	struct ahd_linux_device *dev;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2144) 	struct scb *pending_scb;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2145) 	u_int  saved_scbptr;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2146) 	u_int  active_scbptr;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2147) 	u_int  last_phase;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2148) 	u_int  saved_scsiid;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2149) 	u_int  cdb_byte;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2150) 	int    retval;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2151) 	int    was_paused;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2152) 	int    paused;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2153) 	int    wait;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2154) 	int    disconnected;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2155) 	ahd_mode_state saved_modes;
4065a413d7684 (Christoph Hellwig  2005-10-31 20:05:01 +0100 2156) 	unsigned long flags;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2157) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2158) 	pending_scb = NULL;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2159) 	paused = FALSE;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2160) 	wait = FALSE;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2161) 	ahd = *(struct ahd_softc **)cmd->device->host->hostdata;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2162) 
017560fca496f (Jeff Garzik        2005-10-24 18:04:36 -0400 2163) 	scmd_printk(KERN_INFO, cmd,
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2164) 		    "Attempting to queue an ABORT message:");
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2165) 
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 2166) 	printk("CDB:");
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2167) 	for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++)
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 2168) 		printk(" 0x%x", cmd->cmnd[cdb_byte]);
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 2169) 	printk("\n");
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2170) 
4065a413d7684 (Christoph Hellwig  2005-10-31 20:05:01 +0100 2171) 	ahd_lock(ahd, &flags);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2172) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2173) 	/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2174) 	 * First determine if we currently own this command.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2175) 	 * Start by searching the device queue.  If not found
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2176) 	 * there, check the pending_scb list.  If not found
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2177) 	 * at all, and the system wanted us to just abort the
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2178) 	 * command, return success.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2179) 	 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2180) 	dev = scsi_transport_device_data(cmd->device);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2181) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2182) 	if (dev == NULL) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2183) 		/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2184) 		 * No target device for this command exists,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2185) 		 * so we must not still own the command.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2186) 		 */
017560fca496f (Jeff Garzik        2005-10-24 18:04:36 -0400 2187) 		scmd_printk(KERN_INFO, cmd, "Is not an active device\n");
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2188) 		retval = SUCCESS;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2189) 		goto no_cmd;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2190) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2191) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2192) 	/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2193) 	 * See if we can find a matching cmd in the pending list.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2194) 	 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2195) 	LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2196) 		if (pending_scb->io_ctx == cmd)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2197) 			break;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2198) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2199) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2200) 	if (pending_scb == NULL) {
017560fca496f (Jeff Garzik        2005-10-24 18:04:36 -0400 2201) 		scmd_printk(KERN_INFO, cmd, "Command not found\n");
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2202) 		goto no_cmd;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2203) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2204) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2205) 	if ((pending_scb->flags & SCB_RECOVERY_SCB) != 0) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2206) 		/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2207) 		 * We can't queue two recovery actions using the same SCB
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2208) 		 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2209) 		retval = FAILED;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2210) 		goto  done;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2211) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2212) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2213) 	/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2214) 	 * Ensure that the card doesn't do anything
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2215) 	 * behind our back.  Also make sure that we
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2216) 	 * didn't "just" miss an interrupt that would
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2217) 	 * affect this cmd.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2218) 	 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2219) 	was_paused = ahd_is_paused(ahd);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2220) 	ahd_pause_and_flushwork(ahd);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2221) 	paused = TRUE;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2222) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2223) 	if ((pending_scb->flags & SCB_ACTIVE) == 0) {
017560fca496f (Jeff Garzik        2005-10-24 18:04:36 -0400 2224) 		scmd_printk(KERN_INFO, cmd, "Command already completed\n");
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2225) 		goto no_cmd;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2226) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2227) 
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 2228) 	printk("%s: At time of recovery, card was %spaused\n",
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2229) 	       ahd_name(ahd), was_paused ? "" : "not ");
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2230) 	ahd_dump_card_state(ahd);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2231) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2232) 	disconnected = TRUE;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2233) 	if (ahd_search_qinfifo(ahd, cmd->device->id, 
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2234) 			       cmd->device->channel + 'A',
9cb78c16f5dad (Hannes Reinecke    2014-06-25 15:27:36 +0200 2235) 			       cmd->device->lun,
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2236) 			       pending_scb->hscb->tag,
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2237) 			       ROLE_INITIATOR, CAM_REQ_ABORTED,
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2238) 			       SEARCH_COMPLETE) > 0) {
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 2239) 		printk("%s:%d:%d:%d: Cmd aborted from QINFIFO\n",
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2240) 		       ahd_name(ahd), cmd->device->channel, 
9cb78c16f5dad (Hannes Reinecke    2014-06-25 15:27:36 +0200 2241) 		       cmd->device->id, (u8)cmd->device->lun);
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2242) 		retval = SUCCESS;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2243) 		goto done;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2244) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2245) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2246) 	saved_modes = ahd_save_modes(ahd);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2247) 	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2248) 	last_phase = ahd_inb(ahd, LASTPHASE);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2249) 	saved_scbptr = ahd_get_scbptr(ahd);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2250) 	active_scbptr = saved_scbptr;
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2251) 	if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2252) 		struct scb *bus_scb;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2253) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2254) 		bus_scb = ahd_lookup_scb(ahd, active_scbptr);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2255) 		if (bus_scb == pending_scb)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2256) 			disconnected = FALSE;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2257) 	}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2258) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2259) 	/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2260) 	 * At this point, pending_scb is the scb associated with the
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2261) 	 * passed in command.  That command is currently active on the
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2262) 	 * bus or is in the disconnected state.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2263) 	 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2264) 	saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2265) 	if (last_phase != P_BUSFREE
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2266) 	    && SCB_GET_TAG(pending_scb) == active_scbptr) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2267) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2268) 		/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2269) 		 * We're active on the bus, so assert ATN
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2270) 		 * and hope that the target responds.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2271) 		 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2272) 		pending_scb = ahd_lookup_scb(ahd, active_scbptr);
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2273) 		pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2274) 		ahd_outb(ahd, MSG_OUT, HOST_MSG);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2275) 		ahd_outb(ahd, SCSISIGO, last_phase|ATNO);
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2276) 		scmd_printk(KERN_INFO, cmd, "Device is active, asserting ATN\n");
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2277) 		wait = TRUE;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2278) 	} else if (disconnected) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2279) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2280) 		/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2281) 		 * Actually re-queue this SCB in an attempt
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2282) 		 * to select the device before it reconnects.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2283) 		 */
6902f41610d63 (Hannes Reinecke    2006-03-08 12:58:16 +0100 2284) 		pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2285) 		ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb));
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2286) 		pending_scb->hscb->cdb_len = 0;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2287) 		pending_scb->hscb->task_attribute = 0;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2288) 		pending_scb->hscb->task_management = SIU_TASKMGMT_ABORT_TASK;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2289) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2290) 		if ((pending_scb->flags & SCB_PACKETIZED) != 0) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2291) 			/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2292) 			 * Mark the SCB has having an outstanding
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2293) 			 * task management function.  Should the command
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2294) 			 * complete normally before the task management
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2295) 			 * function can be sent, the host will be notified
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2296) 			 * to abort our requeued SCB.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2297) 			 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2298) 			ahd_outb(ahd, SCB_TASK_MANAGEMENT,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2299) 				 pending_scb->hscb->task_management);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2300) 		} else {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2301) 			/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2302) 			 * If non-packetized, set the MK_MESSAGE control
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2303) 			 * bit indicating that we desire to send a message.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2304) 			 * We also set the disconnected flag since there is
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2305) 			 * no guarantee that our SCB control byte matches
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2306) 			 * the version on the card.  We don't want the
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2307) 			 * sequencer to abort the command thinking an
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2308) 			 * unsolicited reselection occurred.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2309) 			 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2310) 			pending_scb->hscb->control |= MK_MESSAGE|DISCONNECTED;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2311) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2312) 			/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2313) 			 * The sequencer will never re-reference the
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2314) 			 * in-core SCB.  To make sure we are notified
b71a8eb0fa64e (Uwe Kleine-König   2009-10-06 12:42:51 +0200 2315) 			 * during reselection, set the MK_MESSAGE flag in
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2316) 			 * the card's copy of the SCB.
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2317) 			 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2318) 			ahd_outb(ahd, SCB_CONTROL,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2319) 				 ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2320) 		}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2321) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2322) 		/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2323) 		 * Clear out any entries in the QINFIFO first
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2324) 		 * so we are the next SCB for this target
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2325) 		 * to run.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2326) 		 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2327) 		ahd_search_qinfifo(ahd, cmd->device->id,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2328) 				   cmd->device->channel + 'A', cmd->device->lun,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2329) 				   SCB_LIST_NULL, ROLE_INITIATOR,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2330) 				   CAM_REQUEUE_REQ, SEARCH_COMPLETE);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2331) 		ahd_qinfifo_requeue_tail(ahd, pending_scb);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2332) 		ahd_set_scbptr(ahd, saved_scbptr);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2333) 		ahd_print_path(ahd, pending_scb);
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 2334) 		printk("Device is disconnected, re-queuing SCB\n");
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2335) 		wait = TRUE;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2336) 	} else {
017560fca496f (Jeff Garzik        2005-10-24 18:04:36 -0400 2337) 		scmd_printk(KERN_INFO, cmd, "Unable to deliver message\n");
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2338) 		retval = FAILED;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2339) 		goto done;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2340) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2341) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2342) no_cmd:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2343) 	/*
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2344) 	 * Our assumption is that if we don't have the command, no
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2345) 	 * recovery action was required, so we return success.  Again,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2346) 	 * the semantics of the mid-layer recovery engine are not
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2347) 	 * well defined, so this may change in time.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2348) 	 */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2349) 	retval = SUCCESS;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2350) done:
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2351) 	if (paused)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2352) 		ahd_unpause(ahd);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2353) 	if (wait) {
6e9a4738c9fad (Peter Zijlstra     2006-09-30 23:28:10 -0700 2354) 		DECLARE_COMPLETION_ONSTACK(done);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2355) 
7b22da38b64a3 (Hannes Reinecke    2006-03-08 12:56:14 +0100 2356) 		ahd->platform_data->eh_done = &done;
4065a413d7684 (Christoph Hellwig  2005-10-31 20:05:01 +0100 2357) 		ahd_unlock(ahd, &flags);
4065a413d7684 (Christoph Hellwig  2005-10-31 20:05:01 +0100 2358) 
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 2359) 		printk("%s: Recovery code sleeping\n", ahd_name(ahd));
7b22da38b64a3 (Hannes Reinecke    2006-03-08 12:56:14 +0100 2360) 		if (!wait_for_completion_timeout(&done, 5 * HZ)) {
7b22da38b64a3 (Hannes Reinecke    2006-03-08 12:56:14 +0100 2361) 			ahd_lock(ahd, &flags);
7b22da38b64a3 (Hannes Reinecke    2006-03-08 12:56:14 +0100 2362) 			ahd->platform_data->eh_done = NULL;
7b22da38b64a3 (Hannes Reinecke    2006-03-08 12:56:14 +0100 2363) 			ahd_unlock(ahd, &flags);
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 2364) 			printk("%s: Timer Expired (active %d)\n",
11668bb673c41 (Hannes Reinecke    2006-01-12 12:08:06 +0100 2365) 			       ahd_name(ahd), dev->active);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2366) 			retval = FAILED;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2367) 		}
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 2368) 		printk("Recovery code awake\n");
eb221849540b7 (Hannes Reinecke    2006-01-30 16:10:31 +0100 2369) 	} else
eb221849540b7 (Hannes Reinecke    2006-01-30 16:10:31 +0100 2370) 		ahd_unlock(ahd, &flags);
eb221849540b7 (Hannes Reinecke    2006-01-30 16:10:31 +0100 2371) 
7b22da38b64a3 (Hannes Reinecke    2006-03-08 12:56:14 +0100 2372) 	if (retval != SUCCESS)
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 2373) 		printk("%s: Command abort returning 0x%x\n",
7b22da38b64a3 (Hannes Reinecke    2006-03-08 12:56:14 +0100 2374) 		       ahd_name(ahd), retval);
7b22da38b64a3 (Hannes Reinecke    2006-03-08 12:56:14 +0100 2375) 
7b22da38b64a3 (Hannes Reinecke    2006-03-08 12:56:14 +0100 2376) 	return retval;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2377) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2378) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2379) static void ahd_linux_set_width(struct scsi_target *starget, int width)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2380) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2381) 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2382) 	struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2383) 	struct ahd_devinfo devinfo;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2384) 	unsigned long flags;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2385) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2386) 	ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2387) 			    starget->channel + 'A', ROLE_INITIATOR);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2388) 	ahd_lock(ahd, &flags);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2389) 	ahd_set_width(ahd, &devinfo, width, AHD_TRANS_GOAL, FALSE);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2390) 	ahd_unlock(ahd, &flags);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2391) }
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2392) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2393) static void ahd_linux_set_period(struct scsi_target *starget, int period)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2394) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2395) 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2396) 	struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2397) 	struct ahd_tmode_tstate *tstate;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2398) 	struct ahd_initiator_tinfo *tinfo 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2399) 		= ahd_fetch_transinfo(ahd,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2400) 				      starget->channel + 'A',
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2401) 				      shost->this_id, starget->id, &tstate);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2402) 	struct ahd_devinfo devinfo;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2403) 	unsigned int ppr_options = tinfo->goal.ppr_options;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2404) 	unsigned int dt;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2405) 	unsigned long flags;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2406) 	unsigned long offset = tinfo->goal.offset;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2407) 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2408) #ifdef AHD_DEBUG
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2409) 	if ((ahd_debug & AHD_SHOW_DV) != 0)
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 2410) 		printk("%s: set period to %d\n", ahd_name(ahd), period);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2411) #endif
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2412) 	if (offset == 0)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2413) 		offset = MAX_OFFSET;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2414) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2415) 	if (period < 8)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2416) 		period = 8;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2417) 	if (period < 10) {
0f82cb9211f80 (James Bottomley    2007-07-26 17:13:10 -0400 2418) 		if (spi_max_width(starget)) {
0f82cb9211f80 (James Bottomley    2007-07-26 17:13:10 -0400 2419) 			ppr_options |= MSG_EXT_PPR_DT_REQ;
0f82cb9211f80 (James Bottomley    2007-07-26 17:13:10 -0400 2420) 			if (period == 8)
0f82cb9211f80 (James Bottomley    2007-07-26 17:13:10 -0400 2421) 				ppr_options |= MSG_EXT_PPR_IU_REQ;
0f82cb9211f80 (James Bottomley    2007-07-26 17:13:10 -0400 2422) 		} else
0f82cb9211f80 (James Bottomley    2007-07-26 17:13:10 -0400 2423) 			period = 10;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2424) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2425) 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2426) 	dt = ppr_options & MSG_EXT_PPR_DT_REQ;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2427) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2428) 	ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2429) 			    starget->channel + 'A', ROLE_INITIATOR);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2430) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2431) 	/* all PPR requests apart from QAS require wide transfers */
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2432) 	if (ppr_options & ~MSG_EXT_PPR_QAS_REQ) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2433) 		if (spi_width(starget) == 0)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2434) 			ppr_options &= MSG_EXT_PPR_QAS_REQ;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2435) 	}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2436) 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2437) 	ahd_find_syncrate(ahd, &period, &ppr_options,
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2438) 			  dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2439) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2440) 	ahd_lock(ahd, &flags);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2441) 	ahd_set_syncrate(ahd, &devinfo, period, offset,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2442) 			 ppr_options, AHD_TRANS_GOAL, FALSE);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2443) 	ahd_unlock(ahd, &flags);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2444) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2445) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2446) static void ahd_linux_set_offset(struct scsi_target *starget, int offset)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2447) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2448) 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2449) 	struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2450) 	struct ahd_tmode_tstate *tstate;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2451) 	struct ahd_initiator_tinfo *tinfo 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2452) 		= ahd_fetch_transinfo(ahd,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2453) 				      starget->channel + 'A',
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2454) 				      shost->this_id, starget->id, &tstate);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2455) 	struct ahd_devinfo devinfo;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2456) 	unsigned int ppr_options = 0;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2457) 	unsigned int period = 0;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2458) 	unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2459) 	unsigned long flags;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2460) 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2461) #ifdef AHD_DEBUG
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2462) 	if ((ahd_debug & AHD_SHOW_DV) != 0)
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 2463) 		printk("%s: set offset to %d\n", ahd_name(ahd), offset);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2464) #endif
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2465) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2466) 	ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2467) 			    starget->channel + 'A', ROLE_INITIATOR);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2468) 	if (offset != 0) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2469) 		period = tinfo->goal.period;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2470) 		ppr_options = tinfo->goal.ppr_options;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2471) 		ahd_find_syncrate(ahd, &period, &ppr_options, 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2472) 				  dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2473) 	}
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2474) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2475) 	ahd_lock(ahd, &flags);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2476) 	ahd_set_syncrate(ahd, &devinfo, period, offset, ppr_options,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2477) 			 AHD_TRANS_GOAL, FALSE);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2478) 	ahd_unlock(ahd, &flags);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2479) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2480) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2481) static void ahd_linux_set_dt(struct scsi_target *starget, int dt)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2482) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2483) 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2484) 	struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2485) 	struct ahd_tmode_tstate *tstate;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2486) 	struct ahd_initiator_tinfo *tinfo 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2487) 		= ahd_fetch_transinfo(ahd,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2488) 				      starget->channel + 'A',
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2489) 				      shost->this_id, starget->id, &tstate);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2490) 	struct ahd_devinfo devinfo;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2491) 	unsigned int ppr_options = tinfo->goal.ppr_options
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2492) 		& ~MSG_EXT_PPR_DT_REQ;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2493) 	unsigned int period = tinfo->goal.period;
52b5cfb355b2b (Hannes Reinecke    2005-08-04 09:16:59 +0200 2494) 	unsigned int width = tinfo->goal.width;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2495) 	unsigned long flags;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2496) 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2497) #ifdef AHD_DEBUG
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2498) 	if ((ahd_debug & AHD_SHOW_DV) != 0)
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 2499) 		printk("%s: %s DT\n", ahd_name(ahd),
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2500) 		       dt ? "enabling" : "disabling");
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2501) #endif
0f82cb9211f80 (James Bottomley    2007-07-26 17:13:10 -0400 2502) 	if (dt && spi_max_width(starget)) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2503) 		ppr_options |= MSG_EXT_PPR_DT_REQ;
52b5cfb355b2b (Hannes Reinecke    2005-08-04 09:16:59 +0200 2504) 		if (!width)
52b5cfb355b2b (Hannes Reinecke    2005-08-04 09:16:59 +0200 2505) 			ahd_linux_set_width(starget, 1);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2506) 	} else {
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2507) 		if (period <= 9)
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2508) 			period = 10; /* If resetting DT, period must be >= 25ns */
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2509) 		/* IU is invalid without DT set */
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2510) 		ppr_options &= ~MSG_EXT_PPR_IU_REQ;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2511) 	}
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2512) 	ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2513) 			    starget->channel + 'A', ROLE_INITIATOR);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2514) 	ahd_find_syncrate(ahd, &period, &ppr_options,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2515) 			  dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2516) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2517) 	ahd_lock(ahd, &flags);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2518) 	ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2519) 			 ppr_options, AHD_TRANS_GOAL, FALSE);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2520) 	ahd_unlock(ahd, &flags);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2521) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2522) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2523) static void ahd_linux_set_qas(struct scsi_target *starget, int qas)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2524) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2525) 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2526) 	struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2527) 	struct ahd_tmode_tstate *tstate;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2528) 	struct ahd_initiator_tinfo *tinfo 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2529) 		= ahd_fetch_transinfo(ahd,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2530) 				      starget->channel + 'A',
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2531) 				      shost->this_id, starget->id, &tstate);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2532) 	struct ahd_devinfo devinfo;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2533) 	unsigned int ppr_options = tinfo->goal.ppr_options
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2534) 		& ~MSG_EXT_PPR_QAS_REQ;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2535) 	unsigned int period = tinfo->goal.period;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2536) 	unsigned int dt;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2537) 	unsigned long flags;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2538) 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2539) #ifdef AHD_DEBUG
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2540) 	if ((ahd_debug & AHD_SHOW_DV) != 0)
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 2541) 		printk("%s: %s QAS\n", ahd_name(ahd),
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2542) 		       qas ? "enabling" : "disabling");
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2543) #endif
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2544) 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2545) 	if (qas) {
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2546) 		ppr_options |= MSG_EXT_PPR_QAS_REQ; 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2547) 	}
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2548) 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2549) 	dt = ppr_options & MSG_EXT_PPR_DT_REQ;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2550) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2551) 	ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2552) 			    starget->channel + 'A', ROLE_INITIATOR);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2553) 	ahd_find_syncrate(ahd, &period, &ppr_options,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2554) 			  dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2555) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2556) 	ahd_lock(ahd, &flags);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2557) 	ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2558) 			 ppr_options, AHD_TRANS_GOAL, FALSE);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2559) 	ahd_unlock(ahd, &flags);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2560) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2561) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2562) static void ahd_linux_set_iu(struct scsi_target *starget, int iu)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2563) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2564) 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2565) 	struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2566) 	struct ahd_tmode_tstate *tstate;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2567) 	struct ahd_initiator_tinfo *tinfo 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2568) 		= ahd_fetch_transinfo(ahd,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2569) 				      starget->channel + 'A',
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2570) 				      shost->this_id, starget->id, &tstate);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2571) 	struct ahd_devinfo devinfo;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2572) 	unsigned int ppr_options = tinfo->goal.ppr_options
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2573) 		& ~MSG_EXT_PPR_IU_REQ;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2574) 	unsigned int period = tinfo->goal.period;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2575) 	unsigned int dt;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2576) 	unsigned long flags;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2577) 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2578) #ifdef AHD_DEBUG
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2579) 	if ((ahd_debug & AHD_SHOW_DV) != 0)
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 2580) 		printk("%s: %s IU\n", ahd_name(ahd),
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2581) 		       iu ? "enabling" : "disabling");
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2582) #endif
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2583) 
0f82cb9211f80 (James Bottomley    2007-07-26 17:13:10 -0400 2584) 	if (iu && spi_max_width(starget)) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2585) 		ppr_options |= MSG_EXT_PPR_IU_REQ;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2586) 		ppr_options |= MSG_EXT_PPR_DT_REQ; /* IU requires DT */
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2587) 	}
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2588) 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2589) 	dt = ppr_options & MSG_EXT_PPR_DT_REQ;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2590) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2591) 	ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2592) 			    starget->channel + 'A', ROLE_INITIATOR);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2593) 	ahd_find_syncrate(ahd, &period, &ppr_options,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2594) 			  dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2595) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2596) 	ahd_lock(ahd, &flags);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2597) 	ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2598) 			 ppr_options, AHD_TRANS_GOAL, FALSE);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2599) 	ahd_unlock(ahd, &flags);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2600) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2601) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2602) static void ahd_linux_set_rd_strm(struct scsi_target *starget, int rdstrm)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2603) {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2604) 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2605) 	struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2606) 	struct ahd_tmode_tstate *tstate;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2607) 	struct ahd_initiator_tinfo *tinfo 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2608) 		= ahd_fetch_transinfo(ahd,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2609) 				      starget->channel + 'A',
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2610) 				      shost->this_id, starget->id, &tstate);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2611) 	struct ahd_devinfo devinfo;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2612) 	unsigned int ppr_options = tinfo->goal.ppr_options
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2613) 		& ~MSG_EXT_PPR_RD_STRM;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2614) 	unsigned int period = tinfo->goal.period;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2615) 	unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2616) 	unsigned long flags;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2617) 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2618) #ifdef AHD_DEBUG
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2619) 	if ((ahd_debug & AHD_SHOW_DV) != 0)
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 2620) 		printk("%s: %s Read Streaming\n", ahd_name(ahd),
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2621) 		       rdstrm  ? "enabling" : "disabling");
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2622) #endif
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2623) 
0f82cb9211f80 (James Bottomley    2007-07-26 17:13:10 -0400 2624) 	if (rdstrm && spi_max_width(starget))
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2625) 		ppr_options |= MSG_EXT_PPR_RD_STRM;
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2626) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2627) 	ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2628) 			    starget->channel + 'A', ROLE_INITIATOR);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2629) 	ahd_find_syncrate(ahd, &period, &ppr_options,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2630) 			  dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2631) 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2632) 	ahd_lock(ahd, &flags);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2633) 	ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2634) 			 ppr_options, AHD_TRANS_GOAL, FALSE);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2635) 	ahd_unlock(ahd, &flags);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2636) }
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2637) 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2638) static void ahd_linux_set_wr_flow(struct scsi_target *starget, int wrflow)
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2639) {
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2640) 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2641) 	struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2642) 	struct ahd_tmode_tstate *tstate;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2643) 	struct ahd_initiator_tinfo *tinfo 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2644) 		= ahd_fetch_transinfo(ahd,
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2645) 				      starget->channel + 'A',
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2646) 				      shost->this_id, starget->id, &tstate);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2647) 	struct ahd_devinfo devinfo;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2648) 	unsigned int ppr_options = tinfo->goal.ppr_options
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2649) 		& ~MSG_EXT_PPR_WR_FLOW;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2650) 	unsigned int period = tinfo->goal.period;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2651) 	unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2652) 	unsigned long flags;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2653) 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2654) #ifdef AHD_DEBUG
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2655) 	if ((ahd_debug & AHD_SHOW_DV) != 0)
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 2656) 		printk("%s: %s Write Flow Control\n", ahd_name(ahd),
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2657) 		       wrflow ? "enabling" : "disabling");
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2658) #endif
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2659) 
0f82cb9211f80 (James Bottomley    2007-07-26 17:13:10 -0400 2660) 	if (wrflow && spi_max_width(starget))
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2661) 		ppr_options |= MSG_EXT_PPR_WR_FLOW;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2662) 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2663) 	ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2664) 			    starget->channel + 'A', ROLE_INITIATOR);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2665) 	ahd_find_syncrate(ahd, &period, &ppr_options,
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2666) 			  dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2667) 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2668) 	ahd_lock(ahd, &flags);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2669) 	ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2670) 			 ppr_options, AHD_TRANS_GOAL, FALSE);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2671) 	ahd_unlock(ahd, &flags);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2672) }
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2673) 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2674) static void ahd_linux_set_rti(struct scsi_target *starget, int rti)
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2675) {
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2676) 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2677) 	struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2678) 	struct ahd_tmode_tstate *tstate;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2679) 	struct ahd_initiator_tinfo *tinfo 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2680) 		= ahd_fetch_transinfo(ahd,
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2681) 				      starget->channel + 'A',
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2682) 				      shost->this_id, starget->id, &tstate);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2683) 	struct ahd_devinfo devinfo;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2684) 	unsigned int ppr_options = tinfo->goal.ppr_options
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2685) 		& ~MSG_EXT_PPR_RTI;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2686) 	unsigned int period = tinfo->goal.period;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2687) 	unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2688) 	unsigned long flags;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2689) 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2690) 	if ((ahd->features & AHD_RTI) == 0) {
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2691) #ifdef AHD_DEBUG
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2692) 		if ((ahd_debug & AHD_SHOW_DV) != 0)
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 2693) 			printk("%s: RTI not available\n", ahd_name(ahd));
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2694) #endif
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2695) 		return;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2696) 	}
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2697) 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2698) #ifdef AHD_DEBUG
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2699) 	if ((ahd_debug & AHD_SHOW_DV) != 0)
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 2700) 		printk("%s: %s RTI\n", ahd_name(ahd),
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2701) 		       rti ? "enabling" : "disabling");
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2702) #endif
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2703) 
0f82cb9211f80 (James Bottomley    2007-07-26 17:13:10 -0400 2704) 	if (rti && spi_max_width(starget))
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2705) 		ppr_options |= MSG_EXT_PPR_RTI;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2706) 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2707) 	ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2708) 			    starget->channel + 'A', ROLE_INITIATOR);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2709) 	ahd_find_syncrate(ahd, &period, &ppr_options,
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2710) 			  dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2711) 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2712) 	ahd_lock(ahd, &flags);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2713) 	ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2714) 			 ppr_options, AHD_TRANS_GOAL, FALSE);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2715) 	ahd_unlock(ahd, &flags);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2716) }
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2717) 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2718) static void ahd_linux_set_pcomp_en(struct scsi_target *starget, int pcomp)
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2719) {
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2720) 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2721) 	struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2722) 	struct ahd_tmode_tstate *tstate;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2723) 	struct ahd_initiator_tinfo *tinfo 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2724) 		= ahd_fetch_transinfo(ahd,
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2725) 				      starget->channel + 'A',
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2726) 				      shost->this_id, starget->id, &tstate);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2727) 	struct ahd_devinfo devinfo;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2728) 	unsigned int ppr_options = tinfo->goal.ppr_options
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2729) 		& ~MSG_EXT_PPR_PCOMP_EN;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2730) 	unsigned int period = tinfo->goal.period;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2731) 	unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2732) 	unsigned long flags;
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2733) 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2734) #ifdef AHD_DEBUG
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2735) 	if ((ahd_debug & AHD_SHOW_DV) != 0)
48813cf989eb8 (Pekka Enberg       2010-07-14 13:12:57 +0300 2736) 		printk("%s: %s Precompensation\n", ahd_name(ahd),
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2737) 		       pcomp ? "Enable" : "Disable");
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2738) #endif
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2739) 
0f82cb9211f80 (James Bottomley    2007-07-26 17:13:10 -0400 2740) 	if (pcomp && spi_max_width(starget)) {
843822ad63188 (Hannes Reinecke    2006-10-23 15:24:23 +0200 2741) 		uint8_t precomp;
843822ad63188 (Hannes Reinecke    2006-10-23 15:24:23 +0200 2742) 
843822ad63188 (Hannes Reinecke    2006-10-23 15:24:23 +0200 2743) 		if (ahd->unit < ARRAY_SIZE(aic79xx_iocell_info)) {
980b306a29772 (Denys Vlasenko     2008-04-25 04:36:01 +0200 2744) 			const struct ahd_linux_iocell_opts *iocell_opts;
843822ad63188 (Hannes Reinecke    2006-10-23 15:24:23 +0200 2745) 
843822ad63188 (Hannes Reinecke    2006-10-23 15:24:23 +0200 2746) 			iocell_opts = &aic79xx_iocell_info[ahd->unit];
843822ad63188 (Hannes Reinecke    2006-10-23 15:24:23 +0200 2747) 			precomp = iocell_opts->precomp;
843822ad63188 (Hannes Reinecke    2006-10-23 15:24:23 +0200 2748) 		} else {
843822ad63188 (Hannes Reinecke    2006-10-23 15:24:23 +0200 2749) 			precomp = AIC79XX_DEFAULT_PRECOMP;
843822ad63188 (Hannes Reinecke    2006-10-23 15:24:23 +0200 2750) 		}
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2751) 		ppr_options |= MSG_EXT_PPR_PCOMP_EN;
843822ad63188 (Hannes Reinecke    2006-10-23 15:24:23 +0200 2752) 		AHD_SET_PRECOMP(ahd, precomp);
843822ad63188 (Hannes Reinecke    2006-10-23 15:24:23 +0200 2753) 	} else {
843822ad63188 (Hannes Reinecke    2006-10-23 15:24:23 +0200 2754) 		AHD_SET_PRECOMP(ahd, 0);
843822ad63188 (Hannes Reinecke    2006-10-23 15:24:23 +0200 2755) 	}
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2756) 
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2757) 	ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2758) 			    starget->channel + 'A', ROLE_INITIATOR);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2759) 	ahd_find_syncrate(ahd, &period, &ppr_options,
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2760) 			  dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2761) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2762) 	ahd_lock(ahd, &flags);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2763) 	ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2764) 			 ppr_options, AHD_TRANS_GOAL, FALSE);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2765) 	ahd_unlock(ahd, &flags);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2766) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2767) 
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2768) static void ahd_linux_set_hold_mcs(struct scsi_target *starget, int hold)
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2769) {
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2770) 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2771) 	struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2772) 	struct ahd_tmode_tstate *tstate;
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2773) 	struct ahd_initiator_tinfo *tinfo 
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2774) 		= ahd_fetch_transinfo(ahd,
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2775) 				      starget->channel + 'A',
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2776) 				      shost->this_id, starget->id, &tstate);
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2777) 	struct ahd_devinfo devinfo;
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2778) 	unsigned int ppr_options = tinfo->goal.ppr_options
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2779) 		& ~MSG_EXT_PPR_HOLD_MCS;
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2780) 	unsigned int period = tinfo->goal.period;
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2781) 	unsigned int dt = ppr_options & MSG_EXT_PPR_DT_REQ;
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2782) 	unsigned long flags;
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2783) 
0f82cb9211f80 (James Bottomley    2007-07-26 17:13:10 -0400 2784) 	if (hold && spi_max_width(starget))
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2785) 		ppr_options |= MSG_EXT_PPR_HOLD_MCS;
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2786) 
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2787) 	ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2788) 			    starget->channel + 'A', ROLE_INITIATOR);
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2789) 	ahd_find_syncrate(ahd, &period, &ppr_options,
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2790) 			  dt ? AHD_SYNCRATE_MAX : AHD_SYNCRATE_ULTRA2);
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2791) 
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2792) 	ahd_lock(ahd, &flags);
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2793) 	ahd_set_syncrate(ahd, &devinfo, period, tinfo->goal.offset,
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2794) 			 ppr_options, AHD_TRANS_GOAL, FALSE);
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2795) 	ahd_unlock(ahd, &flags);
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2796) }
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2797) 
d6b9ccbbeb625 (Hannes Reinecke    2006-10-23 15:26:37 +0200 2798) static void ahd_linux_get_signalling(struct Scsi_Host *shost)
d6b9ccbbeb625 (Hannes Reinecke    2006-10-23 15:26:37 +0200 2799) {
d6b9ccbbeb625 (Hannes Reinecke    2006-10-23 15:26:37 +0200 2800) 	struct ahd_softc *ahd = *(struct ahd_softc **)shost->hostdata;
d6b9ccbbeb625 (Hannes Reinecke    2006-10-23 15:26:37 +0200 2801) 	unsigned long flags;
d6b9ccbbeb625 (Hannes Reinecke    2006-10-23 15:26:37 +0200 2802) 	u8 mode;
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2803) 
d6b9ccbbeb625 (Hannes Reinecke    2006-10-23 15:26:37 +0200 2804) 	ahd_lock(ahd, &flags);
d6b9ccbbeb625 (Hannes Reinecke    2006-10-23 15:26:37 +0200 2805) 	ahd_pause(ahd);
d6b9ccbbeb625 (Hannes Reinecke    2006-10-23 15:26:37 +0200 2806) 	mode = ahd_inb(ahd, SBLKCTL);
d6b9ccbbeb625 (Hannes Reinecke    2006-10-23 15:26:37 +0200 2807) 	ahd_unpause(ahd);
d6b9ccbbeb625 (Hannes Reinecke    2006-10-23 15:26:37 +0200 2808) 	ahd_unlock(ahd, &flags);
d6b9ccbbeb625 (Hannes Reinecke    2006-10-23 15:26:37 +0200 2809) 
d6b9ccbbeb625 (Hannes Reinecke    2006-10-23 15:26:37 +0200 2810) 	if (mode & ENAB40)
d6b9ccbbeb625 (Hannes Reinecke    2006-10-23 15:26:37 +0200 2811) 		spi_signalling(shost) = SPI_SIGNAL_LVD;
d6b9ccbbeb625 (Hannes Reinecke    2006-10-23 15:26:37 +0200 2812) 	else if (mode & ENAB20)
d6b9ccbbeb625 (Hannes Reinecke    2006-10-23 15:26:37 +0200 2813) 		spi_signalling(shost) = SPI_SIGNAL_SE;
d6b9ccbbeb625 (Hannes Reinecke    2006-10-23 15:26:37 +0200 2814) 	else
d6b9ccbbeb625 (Hannes Reinecke    2006-10-23 15:26:37 +0200 2815) 		spi_signalling(shost) = SPI_SIGNAL_UNKNOWN;
d6b9ccbbeb625 (Hannes Reinecke    2006-10-23 15:26:37 +0200 2816) }
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2817) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2818) static struct spi_function_template ahd_linux_transport_functions = {
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2819) 	.set_offset	= ahd_linux_set_offset,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2820) 	.show_offset	= 1,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2821) 	.set_period	= ahd_linux_set_period,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2822) 	.show_period	= 1,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2823) 	.set_width	= ahd_linux_set_width,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2824) 	.show_width	= 1,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2825) 	.set_dt		= ahd_linux_set_dt,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2826) 	.show_dt	= 1,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2827) 	.set_iu		= ahd_linux_set_iu,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2828) 	.show_iu	= 1,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2829) 	.set_qas	= ahd_linux_set_qas,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2830) 	.show_qas	= 1,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2831) 	.set_rd_strm	= ahd_linux_set_rd_strm,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2832) 	.show_rd_strm	= 1,
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2833) 	.set_wr_flow	= ahd_linux_set_wr_flow,
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2834) 	.show_wr_flow	= 1,
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2835) 	.set_rti	= ahd_linux_set_rti,
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2836) 	.show_rti	= 1,
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2837) 	.set_pcomp_en	= ahd_linux_set_pcomp_en,
a4b53a11806f5 (Hannes Reinecke    2005-08-01 09:52:56 +0200 2838) 	.show_pcomp_en	= 1,
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2839) 	.set_hold_mcs	= ahd_linux_set_hold_mcs,
88ff29a4a5a8c (James Bottomley    2005-08-03 15:59:04 -0500 2840) 	.show_hold_mcs	= 1,
d6b9ccbbeb625 (Hannes Reinecke    2006-10-23 15:26:37 +0200 2841) 	.get_signalling = ahd_linux_get_signalling,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2842) };
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2843) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2844) static int __init
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2845) ahd_linux_init(void)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2846) {
85a46523ff68a (Christoph Hellwig  2005-08-15 13:28:46 +0200 2847) 	int	error = 0;
85a46523ff68a (Christoph Hellwig  2005-08-15 13:28:46 +0200 2848) 
85a46523ff68a (Christoph Hellwig  2005-08-15 13:28:46 +0200 2849) 	/*
85a46523ff68a (Christoph Hellwig  2005-08-15 13:28:46 +0200 2850) 	 * If we've been passed any parameters, process them now.
85a46523ff68a (Christoph Hellwig  2005-08-15 13:28:46 +0200 2851) 	 */
85a46523ff68a (Christoph Hellwig  2005-08-15 13:28:46 +0200 2852) 	if (aic79xx)
85a46523ff68a (Christoph Hellwig  2005-08-15 13:28:46 +0200 2853) 		aic79xx_setup(aic79xx);
85a46523ff68a (Christoph Hellwig  2005-08-15 13:28:46 +0200 2854) 
85a46523ff68a (Christoph Hellwig  2005-08-15 13:28:46 +0200 2855) 	ahd_linux_transport_template =
85a46523ff68a (Christoph Hellwig  2005-08-15 13:28:46 +0200 2856) 		spi_attach_transport(&ahd_linux_transport_functions);
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2857) 	if (!ahd_linux_transport_template)
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2858) 		return -ENODEV;
85a46523ff68a (Christoph Hellwig  2005-08-15 13:28:46 +0200 2859) 
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2860) 	scsi_transport_reserve_device(ahd_linux_transport_template,
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2861) 				      sizeof(struct ahd_linux_device));
a80b3424d9fde (James Bottomley    2005-08-08 19:06:50 -0500 2862) 
85a46523ff68a (Christoph Hellwig  2005-08-15 13:28:46 +0200 2863) 	error = ahd_linux_pci_init();
85a46523ff68a (Christoph Hellwig  2005-08-15 13:28:46 +0200 2864) 	if (error)
85a46523ff68a (Christoph Hellwig  2005-08-15 13:28:46 +0200 2865) 		spi_release_transport(ahd_linux_transport_template);
85a46523ff68a (Christoph Hellwig  2005-08-15 13:28:46 +0200 2866) 	return error;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2867) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2868) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2869) static void __exit
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2870) ahd_linux_exit(void)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2871) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2872) 	ahd_linux_pci_exit();
73a2546210077 (Hannes Reinecke    2005-07-22 16:44:04 +0200 2873) 	spi_release_transport(ahd_linux_transport_template);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2874) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2875) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2876) module_init(ahd_linux_init);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 2877) module_exit(ahd_linux_exit);