| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1 | /* | 
 | 2 |  * sbp2.c - SBP-2 protocol driver for IEEE-1394 | 
 | 3 |  * | 
 | 4 |  * Copyright (C) 2000 James Goodwin, Filanet Corporation (www.filanet.com) | 
 | 5 |  * jamesg@filanet.com (JSG) | 
 | 6 |  * | 
 | 7 |  * Copyright (C) 2003 Ben Collins <bcollins@debian.org> | 
 | 8 |  * | 
 | 9 |  * This program is free software; you can redistribute it and/or modify | 
 | 10 |  * it under the terms of the GNU General Public License as published by | 
 | 11 |  * the Free Software Foundation; either version 2 of the License, or | 
 | 12 |  * (at your option) any later version. | 
 | 13 |  * | 
 | 14 |  * This program is distributed in the hope that it will be useful, | 
 | 15 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 | 16 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 | 17 |  * GNU General Public License for more details. | 
 | 18 |  * | 
 | 19 |  * You should have received a copy of the GNU General Public License | 
 | 20 |  * along with this program; if not, write to the Free Software Foundation, | 
 | 21 |  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 
 | 22 |  */ | 
 | 23 |  | 
 | 24 | /* | 
 | 25 |  * Brief Description: | 
 | 26 |  * | 
 | 27 |  * This driver implements the Serial Bus Protocol 2 (SBP-2) over IEEE-1394 | 
 | 28 |  * under Linux. The SBP-2 driver is implemented as an IEEE-1394 high-level | 
 | 29 |  * driver. It also registers as a SCSI lower-level driver in order to accept | 
 | 30 |  * SCSI commands for transport using SBP-2. | 
 | 31 |  * | 
 | 32 |  * You may access any attached SBP-2 storage devices as if they were SCSI | 
 | 33 |  * devices (e.g. mount /dev/sda1,  fdisk, mkfs, etc.). | 
 | 34 |  * | 
 | 35 |  * Current Issues: | 
 | 36 |  * | 
 | 37 |  *	- Error Handling: SCSI aborts and bus reset requests are handled somewhat | 
 | 38 |  *	  but the code needs additional debugging. | 
 | 39 |  */ | 
 | 40 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 41 | #include <linux/kernel.h> | 
 | 42 | #include <linux/list.h> | 
 | 43 | #include <linux/string.h> | 
| Stefan Richter | 24d3bf8 | 2006-05-15 22:04:59 +0200 | [diff] [blame] | 44 | #include <linux/stringify.h> | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 45 | #include <linux/slab.h> | 
 | 46 | #include <linux/interrupt.h> | 
 | 47 | #include <linux/fs.h> | 
 | 48 | #include <linux/poll.h> | 
 | 49 | #include <linux/module.h> | 
 | 50 | #include <linux/moduleparam.h> | 
 | 51 | #include <linux/types.h> | 
 | 52 | #include <linux/delay.h> | 
 | 53 | #include <linux/sched.h> | 
 | 54 | #include <linux/blkdev.h> | 
 | 55 | #include <linux/smp_lock.h> | 
 | 56 | #include <linux/init.h> | 
 | 57 | #include <linux/pci.h> | 
 | 58 |  | 
 | 59 | #include <asm/current.h> | 
 | 60 | #include <asm/uaccess.h> | 
 | 61 | #include <asm/io.h> | 
 | 62 | #include <asm/byteorder.h> | 
 | 63 | #include <asm/atomic.h> | 
 | 64 | #include <asm/system.h> | 
 | 65 | #include <asm/scatterlist.h> | 
 | 66 |  | 
 | 67 | #include <scsi/scsi.h> | 
 | 68 | #include <scsi/scsi_cmnd.h> | 
 | 69 | #include <scsi/scsi_dbg.h> | 
 | 70 | #include <scsi/scsi_device.h> | 
 | 71 | #include <scsi/scsi_host.h> | 
 | 72 |  | 
 | 73 | #include "csr1212.h" | 
 | 74 | #include "ieee1394.h" | 
 | 75 | #include "ieee1394_types.h" | 
 | 76 | #include "ieee1394_core.h" | 
 | 77 | #include "nodemgr.h" | 
 | 78 | #include "hosts.h" | 
 | 79 | #include "highlevel.h" | 
 | 80 | #include "ieee1394_transactions.h" | 
 | 81 | #include "sbp2.h" | 
 | 82 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 83 | /* | 
 | 84 |  * Module load parameter definitions | 
 | 85 |  */ | 
 | 86 |  | 
 | 87 | /* | 
 | 88 |  * Change max_speed on module load if you have a bad IEEE-1394 | 
 | 89 |  * controller that has trouble running 2KB packets at 400mb. | 
 | 90 |  * | 
 | 91 |  * NOTE: On certain OHCI parts I have seen short packets on async transmit | 
 | 92 |  * (probably due to PCI latency/throughput issues with the part). You can | 
 | 93 |  * bump down the speed if you are running into problems. | 
 | 94 |  */ | 
 | 95 | static int max_speed = IEEE1394_SPEED_MAX; | 
 | 96 | module_param(max_speed, int, 0644); | 
| Jody McIntyre | 2bab359 | 2005-09-30 11:59:07 -0700 | [diff] [blame] | 97 | MODULE_PARM_DESC(max_speed, "Force max speed (3 = 800mb, 2 = 400mb, 1 = 200mb, 0 = 100mb)"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 98 |  | 
 | 99 | /* | 
 | 100 |  * Set serialize_io to 1 if you'd like only one scsi command sent | 
 | 101 |  * down to us at a time (debugging). This might be necessary for very | 
 | 102 |  * badly behaved sbp2 devices. | 
| Jody McIntyre | 2bab359 | 2005-09-30 11:59:07 -0700 | [diff] [blame] | 103 |  * | 
 | 104 |  * TODO: Make this configurable per device. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 105 |  */ | 
| Jody McIntyre | 2bab359 | 2005-09-30 11:59:07 -0700 | [diff] [blame] | 106 | static int serialize_io = 1; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 107 | module_param(serialize_io, int, 0444); | 
| Jody McIntyre | 2bab359 | 2005-09-30 11:59:07 -0700 | [diff] [blame] | 108 | MODULE_PARM_DESC(serialize_io, "Serialize I/O coming from scsi drivers (default = 1, faster = 0)"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 109 |  | 
 | 110 | /* | 
 | 111 |  * Bump up max_sectors if you'd like to support very large sized | 
 | 112 |  * transfers. Please note that some older sbp2 bridge chips are broken for | 
 | 113 |  * transfers greater or equal to 128KB.  Default is a value of 255 | 
 | 114 |  * sectors, or just under 128KB (at 512 byte sector size). I can note that | 
 | 115 |  * the Oxsemi sbp2 chipsets have no problems supporting very large | 
 | 116 |  * transfer sizes. | 
 | 117 |  */ | 
 | 118 | static int max_sectors = SBP2_MAX_SECTORS; | 
 | 119 | module_param(max_sectors, int, 0444); | 
| Stefan Richter | 24d3bf8 | 2006-05-15 22:04:59 +0200 | [diff] [blame] | 120 | MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported (default = " | 
 | 121 | 		 __stringify(SBP2_MAX_SECTORS) ")"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 122 |  | 
 | 123 | /* | 
 | 124 |  * Exclusive login to sbp2 device? In most cases, the sbp2 driver should | 
 | 125 |  * do an exclusive login, as it's generally unsafe to have two hosts | 
 | 126 |  * talking to a single sbp2 device at the same time (filesystem coherency, | 
 | 127 |  * etc.). If you're running an sbp2 device that supports multiple logins, | 
 | 128 |  * and you're either running read-only filesystems or some sort of special | 
| Ben Collins | 20f4578 | 2006-06-12 18:13:11 -0400 | [diff] [blame] | 129 |  * filesystem supporting multiple hosts, e.g. OpenGFS, Oracle Cluster | 
 | 130 |  * File System, or Lustre, then set exclusive_login to zero. | 
 | 131 |  * | 
 | 132 |  * So far only bridges from Oxford Semiconductor are known to support | 
 | 133 |  * concurrent logins. Depending on firmware, four or two concurrent logins | 
 | 134 |  * are possible on OXFW911 and newer Oxsemi bridges. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 135 |  */ | 
 | 136 | static int exclusive_login = 1; | 
 | 137 | module_param(exclusive_login, int, 0644); | 
 | 138 | MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device (default = 1)"); | 
 | 139 |  | 
 | 140 | /* | 
| Stefan Richter | 24d3bf8 | 2006-05-15 22:04:59 +0200 | [diff] [blame] | 141 |  * If any of the following workarounds is required for your device to work, | 
 | 142 |  * please submit the kernel messages logged by sbp2 to the linux1394-devel | 
 | 143 |  * mailing list. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 144 |  * | 
| Stefan Richter | 24d3bf8 | 2006-05-15 22:04:59 +0200 | [diff] [blame] | 145 |  * - 128kB max transfer | 
 | 146 |  *   Limit transfer size. Necessary for some old bridges. | 
 | 147 |  * | 
 | 148 |  * - 36 byte inquiry | 
 | 149 |  *   When scsi_mod probes the device, let the inquiry command look like that | 
 | 150 |  *   from MS Windows. | 
 | 151 |  * | 
 | 152 |  * - skip mode page 8 | 
 | 153 |  *   Suppress sending of mode_sense for mode page 8 if the device pretends to | 
 | 154 |  *   support the SCSI Primary Block commands instead of Reduced Block Commands. | 
| Stefan Richter | e9a1c52 | 2006-05-15 22:06:37 +0200 | [diff] [blame] | 155 |  * | 
 | 156 |  * - fix capacity | 
 | 157 |  *   Tell sd_mod to correct the last sector number reported by read_capacity. | 
 | 158 |  *   Avoids access beyond actual disk limits on devices with an off-by-one bug. | 
 | 159 |  *   Don't use this with devices which don't have this bug. | 
| Stefan Richter | 679c0cd | 2006-05-15 22:08:09 +0200 | [diff] [blame] | 160 |  * | 
 | 161 |  * - override internal blacklist | 
 | 162 |  *   Instead of adding to the built-in blacklist, use only the workarounds | 
 | 163 |  *   specified in the module load parameter. | 
 | 164 |  *   Useful if a blacklist entry interfered with a non-broken device. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 165 |  */ | 
| Stefan Richter | 24d3bf8 | 2006-05-15 22:04:59 +0200 | [diff] [blame] | 166 | static int sbp2_default_workarounds; | 
 | 167 | module_param_named(workarounds, sbp2_default_workarounds, int, 0644); | 
 | 168 | MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0" | 
 | 169 | 	", 128kB max transfer = " __stringify(SBP2_WORKAROUND_128K_MAX_TRANS) | 
 | 170 | 	", 36 byte inquiry = "    __stringify(SBP2_WORKAROUND_INQUIRY_36) | 
 | 171 | 	", skip mode page 8 = "   __stringify(SBP2_WORKAROUND_MODE_SENSE_8) | 
| Stefan Richter | e9a1c52 | 2006-05-15 22:06:37 +0200 | [diff] [blame] | 172 | 	", fix capacity = "       __stringify(SBP2_WORKAROUND_FIX_CAPACITY) | 
| Stefan Richter | 679c0cd | 2006-05-15 22:08:09 +0200 | [diff] [blame] | 173 | 	", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE) | 
| Stefan Richter | 24d3bf8 | 2006-05-15 22:04:59 +0200 | [diff] [blame] | 174 | 	", or a combination)"); | 
 | 175 |  | 
 | 176 | /* legacy parameter */ | 
| Ben Collins | 1934b8b | 2005-07-09 20:01:23 -0400 | [diff] [blame] | 177 | static int force_inquiry_hack; | 
| Stefan Richter | a80614d | 2006-02-14 22:04:19 -0500 | [diff] [blame] | 178 | module_param(force_inquiry_hack, int, 0644); | 
| Stefan Richter | 24d3bf8 | 2006-05-15 22:04:59 +0200 | [diff] [blame] | 179 | MODULE_PARM_DESC(force_inquiry_hack, "Deprecated, use 'workarounds'"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 180 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 181 | /* | 
 | 182 |  * Export information about protocols/devices supported by this driver. | 
 | 183 |  */ | 
 | 184 | static struct ieee1394_device_id sbp2_id_table[] = { | 
 | 185 | 	{ | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 186 | 	 .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, | 
 | 187 | 	 .specifier_id = SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff, | 
 | 188 | 	 .version = SBP2_SW_VERSION_ENTRY & 0xffffff}, | 
 | 189 | 	{} | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 190 | }; | 
 | 191 |  | 
 | 192 | MODULE_DEVICE_TABLE(ieee1394, sbp2_id_table); | 
 | 193 |  | 
 | 194 | /* | 
 | 195 |  * Debug levels, configured via kernel config, or enable here. | 
 | 196 |  */ | 
 | 197 |  | 
| Olaf Hering | 44456d3 | 2005-07-27 11:45:17 -0700 | [diff] [blame] | 198 | #define CONFIG_IEEE1394_SBP2_DEBUG 0 | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 199 | /* #define CONFIG_IEEE1394_SBP2_DEBUG_ORBS */ | 
 | 200 | /* #define CONFIG_IEEE1394_SBP2_DEBUG_DMA */ | 
 | 201 | /* #define CONFIG_IEEE1394_SBP2_DEBUG 1 */ | 
 | 202 | /* #define CONFIG_IEEE1394_SBP2_DEBUG 2 */ | 
 | 203 | /* #define CONFIG_IEEE1394_SBP2_PACKET_DUMP */ | 
 | 204 |  | 
 | 205 | #ifdef CONFIG_IEEE1394_SBP2_DEBUG_ORBS | 
 | 206 | #define SBP2_ORB_DEBUG(fmt, args...)	HPSB_ERR("sbp2(%s): "fmt, __FUNCTION__, ## args) | 
 | 207 | static u32 global_outstanding_command_orbs = 0; | 
 | 208 | #define outstanding_orb_incr global_outstanding_command_orbs++ | 
 | 209 | #define outstanding_orb_decr global_outstanding_command_orbs-- | 
 | 210 | #else | 
 | 211 | #define SBP2_ORB_DEBUG(fmt, args...) | 
 | 212 | #define outstanding_orb_incr | 
 | 213 | #define outstanding_orb_decr | 
 | 214 | #endif | 
 | 215 |  | 
 | 216 | #ifdef CONFIG_IEEE1394_SBP2_DEBUG_DMA | 
 | 217 | #define SBP2_DMA_ALLOC(fmt, args...) \ | 
 | 218 | 	HPSB_ERR("sbp2(%s)alloc(%d): "fmt, __FUNCTION__, \ | 
 | 219 | 		 ++global_outstanding_dmas, ## args) | 
 | 220 | #define SBP2_DMA_FREE(fmt, args...) \ | 
 | 221 | 	HPSB_ERR("sbp2(%s)free(%d): "fmt, __FUNCTION__, \ | 
 | 222 | 		 --global_outstanding_dmas, ## args) | 
 | 223 | static u32 global_outstanding_dmas = 0; | 
 | 224 | #else | 
 | 225 | #define SBP2_DMA_ALLOC(fmt, args...) | 
 | 226 | #define SBP2_DMA_FREE(fmt, args...) | 
 | 227 | #endif | 
 | 228 |  | 
 | 229 | #if CONFIG_IEEE1394_SBP2_DEBUG >= 2 | 
 | 230 | #define SBP2_DEBUG(fmt, args...)	HPSB_ERR("sbp2: "fmt, ## args) | 
 | 231 | #define SBP2_INFO(fmt, args...)		HPSB_ERR("sbp2: "fmt, ## args) | 
 | 232 | #define SBP2_NOTICE(fmt, args...)	HPSB_ERR("sbp2: "fmt, ## args) | 
 | 233 | #define SBP2_WARN(fmt, args...)		HPSB_ERR("sbp2: "fmt, ## args) | 
 | 234 | #elif CONFIG_IEEE1394_SBP2_DEBUG == 1 | 
 | 235 | #define SBP2_DEBUG(fmt, args...)	HPSB_DEBUG("sbp2: "fmt, ## args) | 
 | 236 | #define SBP2_INFO(fmt, args...)		HPSB_INFO("sbp2: "fmt, ## args) | 
 | 237 | #define SBP2_NOTICE(fmt, args...)	HPSB_NOTICE("sbp2: "fmt, ## args) | 
 | 238 | #define SBP2_WARN(fmt, args...)		HPSB_WARN("sbp2: "fmt, ## args) | 
 | 239 | #else | 
 | 240 | #define SBP2_DEBUG(fmt, args...) | 
 | 241 | #define SBP2_INFO(fmt, args...)		HPSB_INFO("sbp2: "fmt, ## args) | 
 | 242 | #define SBP2_NOTICE(fmt, args...)       HPSB_NOTICE("sbp2: "fmt, ## args) | 
 | 243 | #define SBP2_WARN(fmt, args...)         HPSB_WARN("sbp2: "fmt, ## args) | 
 | 244 | #endif | 
 | 245 |  | 
 | 246 | #define SBP2_ERR(fmt, args...)		HPSB_ERR("sbp2: "fmt, ## args) | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 247 | #define SBP2_DEBUG_ENTER()		SBP2_DEBUG("%s", __FUNCTION__) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 248 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 249 | /* | 
 | 250 |  * Globals | 
 | 251 |  */ | 
 | 252 |  | 
 | 253 | static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id, | 
 | 254 | 					   u32 status); | 
 | 255 |  | 
 | 256 | static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, | 
 | 257 | 				      u32 scsi_status, struct scsi_cmnd *SCpnt, | 
 | 258 | 				      void (*done)(struct scsi_cmnd *)); | 
 | 259 |  | 
 | 260 | static struct scsi_host_template scsi_driver_template; | 
 | 261 |  | 
 | 262 | static const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xA, 0xB, 0xC }; | 
 | 263 |  | 
 | 264 | static void sbp2_host_reset(struct hpsb_host *host); | 
 | 265 |  | 
 | 266 | static int sbp2_probe(struct device *dev); | 
 | 267 | static int sbp2_remove(struct device *dev); | 
 | 268 | static int sbp2_update(struct unit_directory *ud); | 
 | 269 |  | 
 | 270 | static struct hpsb_highlevel sbp2_highlevel = { | 
 | 271 | 	.name =		SBP2_DEVICE_NAME, | 
 | 272 | 	.host_reset =	sbp2_host_reset, | 
 | 273 | }; | 
 | 274 |  | 
 | 275 | static struct hpsb_address_ops sbp2_ops = { | 
 | 276 | 	.write = sbp2_handle_status_write | 
 | 277 | }; | 
 | 278 |  | 
 | 279 | #ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA | 
 | 280 | static struct hpsb_address_ops sbp2_physdma_ops = { | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 281 | 	.read = sbp2_handle_physdma_read, | 
 | 282 | 	.write = sbp2_handle_physdma_write, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 283 | }; | 
 | 284 | #endif | 
 | 285 |  | 
 | 286 | static struct hpsb_protocol_driver sbp2_driver = { | 
 | 287 | 	.name		= "SBP2 Driver", | 
 | 288 | 	.id_table	= sbp2_id_table, | 
 | 289 | 	.update		= sbp2_update, | 
 | 290 | 	.driver		= { | 
 | 291 | 		.name		= SBP2_DEVICE_NAME, | 
 | 292 | 		.bus		= &ieee1394_bus_type, | 
 | 293 | 		.probe		= sbp2_probe, | 
 | 294 | 		.remove		= sbp2_remove, | 
 | 295 | 	}, | 
 | 296 | }; | 
 | 297 |  | 
| Stefan Richter | a80614d | 2006-02-14 22:04:19 -0500 | [diff] [blame] | 298 | /* | 
| Stefan Richter | 24d3bf8 | 2006-05-15 22:04:59 +0200 | [diff] [blame] | 299 |  * List of devices with known bugs. | 
 | 300 |  * | 
 | 301 |  * The firmware_revision field, masked with 0xffff00, is the best indicator | 
 | 302 |  * for the type of bridge chip of a device.  It yields a few false positives | 
 | 303 |  * but this did not break correctly behaving devices so far. | 
| Stefan Richter | a80614d | 2006-02-14 22:04:19 -0500 | [diff] [blame] | 304 |  */ | 
| Stefan Richter | 24d3bf8 | 2006-05-15 22:04:59 +0200 | [diff] [blame] | 305 | static const struct { | 
 | 306 | 	u32 firmware_revision; | 
| Stefan Richter | e9a1c52 | 2006-05-15 22:06:37 +0200 | [diff] [blame] | 307 | 	u32 model_id; | 
| Stefan Richter | 24d3bf8 | 2006-05-15 22:04:59 +0200 | [diff] [blame] | 308 | 	unsigned workarounds; | 
 | 309 | } sbp2_workarounds_table[] = { | 
| Ben Collins | 4b9a334 | 2006-06-12 18:10:18 -0400 | [diff] [blame] | 310 | 	/* DViCO Momobay CX-1 with TSB42AA9 bridge */ { | 
| Stefan Richter | 24d3bf8 | 2006-05-15 22:04:59 +0200 | [diff] [blame] | 311 | 		.firmware_revision	= 0x002800, | 
| Ben Collins | 4b9a334 | 2006-06-12 18:10:18 -0400 | [diff] [blame] | 312 | 		.model_id		= 0x001010, | 
| Stefan Richter | 24d3bf8 | 2006-05-15 22:04:59 +0200 | [diff] [blame] | 313 | 		.workarounds		= SBP2_WORKAROUND_INQUIRY_36 | | 
 | 314 | 					  SBP2_WORKAROUND_MODE_SENSE_8, | 
 | 315 | 	}, | 
 | 316 | 	/* Initio bridges, actually only needed for some older ones */ { | 
 | 317 | 		.firmware_revision	= 0x000200, | 
 | 318 | 		.workarounds		= SBP2_WORKAROUND_INQUIRY_36, | 
 | 319 | 	}, | 
 | 320 | 	/* Symbios bridge */ { | 
 | 321 | 		.firmware_revision	= 0xa0b800, | 
 | 322 | 		.workarounds		= SBP2_WORKAROUND_128K_MAX_TRANS, | 
| Stefan Richter | e9a1c52 | 2006-05-15 22:06:37 +0200 | [diff] [blame] | 323 | 	}, | 
 | 324 | 	/* | 
 | 325 | 	 * Note about the following Apple iPod blacklist entries: | 
 | 326 | 	 * | 
 | 327 | 	 * There are iPods (2nd gen, 3rd gen) with model_id==0.  Since our | 
 | 328 | 	 * matching logic treats 0 as a wildcard, we cannot match this ID | 
 | 329 | 	 * without rewriting the matching routine.  Fortunately these iPods | 
 | 330 | 	 * do not feature the read_capacity bug according to one report. | 
 | 331 | 	 * Read_capacity behaviour as well as model_id could change due to | 
 | 332 | 	 * Apple-supplied firmware updates though. | 
 | 333 | 	 */ | 
 | 334 | 	/* iPod 4th generation */ { | 
 | 335 | 		.firmware_revision	= 0x0a2700, | 
 | 336 | 		.model_id		= 0x000021, | 
 | 337 | 		.workarounds		= SBP2_WORKAROUND_FIX_CAPACITY, | 
 | 338 | 	}, | 
 | 339 | 	/* iPod mini */ { | 
 | 340 | 		.firmware_revision	= 0x0a2700, | 
 | 341 | 		.model_id		= 0x000023, | 
 | 342 | 		.workarounds		= SBP2_WORKAROUND_FIX_CAPACITY, | 
 | 343 | 	}, | 
 | 344 | 	/* iPod Photo */ { | 
 | 345 | 		.firmware_revision	= 0x0a2700, | 
 | 346 | 		.model_id		= 0x00007e, | 
 | 347 | 		.workarounds		= SBP2_WORKAROUND_FIX_CAPACITY, | 
| Stefan Richter | 24d3bf8 | 2006-05-15 22:04:59 +0200 | [diff] [blame] | 348 | 	} | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 349 | }; | 
 | 350 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 351 | /************************************** | 
 | 352 |  * General utility functions | 
 | 353 |  **************************************/ | 
 | 354 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 355 | #ifndef __BIG_ENDIAN | 
 | 356 | /* | 
 | 357 |  * Converts a buffer from be32 to cpu byte ordering. Length is in bytes. | 
 | 358 |  */ | 
 | 359 | static __inline__ void sbp2util_be32_to_cpu_buffer(void *buffer, int length) | 
 | 360 | { | 
 | 361 | 	u32 *temp = buffer; | 
 | 362 |  | 
 | 363 | 	for (length = (length >> 2); length--; ) | 
 | 364 | 		temp[length] = be32_to_cpu(temp[length]); | 
 | 365 |  | 
 | 366 | 	return; | 
 | 367 | } | 
 | 368 |  | 
 | 369 | /* | 
 | 370 |  * Converts a buffer from cpu to be32 byte ordering. Length is in bytes. | 
 | 371 |  */ | 
 | 372 | static __inline__ void sbp2util_cpu_to_be32_buffer(void *buffer, int length) | 
 | 373 | { | 
 | 374 | 	u32 *temp = buffer; | 
 | 375 |  | 
 | 376 | 	for (length = (length >> 2); length--; ) | 
 | 377 | 		temp[length] = cpu_to_be32(temp[length]); | 
 | 378 |  | 
 | 379 | 	return; | 
 | 380 | } | 
 | 381 | #else /* BIG_ENDIAN */ | 
 | 382 | /* Why waste the cpu cycles? */ | 
 | 383 | #define sbp2util_be32_to_cpu_buffer(x,y) | 
 | 384 | #define sbp2util_cpu_to_be32_buffer(x,y) | 
 | 385 | #endif | 
 | 386 |  | 
 | 387 | #ifdef CONFIG_IEEE1394_SBP2_PACKET_DUMP | 
 | 388 | /* | 
 | 389 |  * Debug packet dump routine. Length is in bytes. | 
 | 390 |  */ | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 391 | static void sbp2util_packet_dump(void *buffer, int length, char *dump_name, | 
 | 392 | 				 u32 dump_phys_addr) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 393 | { | 
 | 394 | 	int i; | 
 | 395 | 	unsigned char *dump = buffer; | 
 | 396 |  | 
 | 397 | 	if (!dump || !length || !dump_name) | 
 | 398 | 		return; | 
 | 399 |  | 
 | 400 | 	if (dump_phys_addr) | 
 | 401 | 		printk("[%s, 0x%x]", dump_name, dump_phys_addr); | 
 | 402 | 	else | 
 | 403 | 		printk("[%s]", dump_name); | 
 | 404 | 	for (i = 0; i < length; i++) { | 
 | 405 | 		if (i > 0x3f) { | 
 | 406 | 			printk("\n   ..."); | 
 | 407 | 			break; | 
 | 408 | 		} | 
 | 409 | 		if ((i & 0x3) == 0) | 
 | 410 | 			printk("  "); | 
 | 411 | 		if ((i & 0xf) == 0) | 
 | 412 | 			printk("\n   "); | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 413 | 		printk("%02x ", (int)dump[i]); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 414 | 	} | 
 | 415 | 	printk("\n"); | 
 | 416 |  | 
 | 417 | 	return; | 
 | 418 | } | 
 | 419 | #else | 
 | 420 | #define sbp2util_packet_dump(w,x,y,z) | 
 | 421 | #endif | 
 | 422 |  | 
 | 423 | /* | 
 | 424 |  * Goofy routine that basically does a down_timeout function. | 
 | 425 |  */ | 
 | 426 | static int sbp2util_down_timeout(atomic_t *done, int timeout) | 
 | 427 | { | 
 | 428 | 	int i; | 
 | 429 |  | 
 | 430 | 	for (i = timeout; (i > 0 && atomic_read(done) == 0); i-= HZ/10) { | 
 | 431 | 		if (msleep_interruptible(100))	/* 100ms */ | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 432 | 			return 1; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 433 | 	} | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 434 | 	return (i > 0) ? 0 : 1; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 435 | } | 
 | 436 |  | 
 | 437 | /* Free's an allocated packet */ | 
 | 438 | static void sbp2_free_packet(struct hpsb_packet *packet) | 
 | 439 | { | 
 | 440 | 	hpsb_free_tlabel(packet); | 
 | 441 | 	hpsb_free_packet(packet); | 
 | 442 | } | 
 | 443 |  | 
 | 444 | /* This is much like hpsb_node_write(), except it ignores the response | 
 | 445 |  * subaction and returns immediately. Can be used from interrupts. | 
 | 446 |  */ | 
 | 447 | static int sbp2util_node_write_no_wait(struct node_entry *ne, u64 addr, | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 448 | 				       quadlet_t *buffer, size_t length) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 449 | { | 
 | 450 | 	struct hpsb_packet *packet; | 
 | 451 |  | 
 | 452 | 	packet = hpsb_make_writepacket(ne->host, ne->nodeid, | 
 | 453 | 				       addr, buffer, length); | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 454 | 	if (!packet) | 
 | 455 | 		return -ENOMEM; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 456 |  | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 457 | 	hpsb_set_packet_complete_task(packet, | 
 | 458 | 				      (void (*)(void *))sbp2_free_packet, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 459 | 				      packet); | 
 | 460 |  | 
 | 461 | 	hpsb_node_fill_packet(ne, packet); | 
 | 462 |  | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 463 | 	if (hpsb_send_packet(packet) < 0) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 464 | 		sbp2_free_packet(packet); | 
 | 465 | 		return -EIO; | 
 | 466 | 	} | 
 | 467 |  | 
 | 468 | 	return 0; | 
 | 469 | } | 
 | 470 |  | 
 | 471 | /* | 
 | 472 |  * This function is called to create a pool of command orbs used for | 
 | 473 |  * command processing. It is called when a new sbp2 device is detected. | 
 | 474 |  */ | 
 | 475 | static int sbp2util_create_command_orb_pool(struct scsi_id_instance_data *scsi_id) | 
 | 476 | { | 
 | 477 | 	struct sbp2scsi_host_info *hi = scsi_id->hi; | 
 | 478 | 	int i; | 
 | 479 | 	unsigned long flags, orbs; | 
 | 480 | 	struct sbp2_command_info *command; | 
 | 481 |  | 
 | 482 | 	orbs = serialize_io ? 2 : SBP2_MAX_CMDS; | 
 | 483 |  | 
 | 484 | 	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); | 
 | 485 | 	for (i = 0; i < orbs; i++) { | 
| Stefan Richter | 8551158 | 2005-11-07 06:31:45 -0500 | [diff] [blame] | 486 | 		command = kzalloc(sizeof(*command), GFP_ATOMIC); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 487 | 		if (!command) { | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 488 | 			spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, | 
 | 489 | 					       flags); | 
 | 490 | 			return -ENOMEM; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 491 | 		} | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 492 | 		command->command_orb_dma = | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 493 | 		    pci_map_single(hi->host->pdev, &command->command_orb, | 
 | 494 | 				   sizeof(struct sbp2_command_orb), | 
 | 495 | 				   PCI_DMA_BIDIRECTIONAL); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 496 | 		SBP2_DMA_ALLOC("single command orb DMA"); | 
 | 497 | 		command->sge_dma = | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 498 | 		    pci_map_single(hi->host->pdev, | 
 | 499 | 				   &command->scatter_gather_element, | 
 | 500 | 				   sizeof(command->scatter_gather_element), | 
 | 501 | 				   PCI_DMA_BIDIRECTIONAL); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 502 | 		SBP2_DMA_ALLOC("scatter_gather_element"); | 
 | 503 | 		INIT_LIST_HEAD(&command->list); | 
 | 504 | 		list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed); | 
 | 505 | 	} | 
 | 506 | 	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); | 
 | 507 | 	return 0; | 
 | 508 | } | 
 | 509 |  | 
 | 510 | /* | 
 | 511 |  * This function is called to delete a pool of command orbs. | 
 | 512 |  */ | 
 | 513 | static void sbp2util_remove_command_orb_pool(struct scsi_id_instance_data *scsi_id) | 
 | 514 | { | 
 | 515 | 	struct hpsb_host *host = scsi_id->hi->host; | 
 | 516 | 	struct list_head *lh, *next; | 
 | 517 | 	struct sbp2_command_info *command; | 
 | 518 | 	unsigned long flags; | 
 | 519 |  | 
 | 520 | 	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); | 
 | 521 | 	if (!list_empty(&scsi_id->sbp2_command_orb_completed)) { | 
 | 522 | 		list_for_each_safe(lh, next, &scsi_id->sbp2_command_orb_completed) { | 
 | 523 | 			command = list_entry(lh, struct sbp2_command_info, list); | 
 | 524 |  | 
 | 525 | 			/* Release our generic DMA's */ | 
 | 526 | 			pci_unmap_single(host->pdev, command->command_orb_dma, | 
 | 527 | 					 sizeof(struct sbp2_command_orb), | 
 | 528 | 					 PCI_DMA_BIDIRECTIONAL); | 
 | 529 | 			SBP2_DMA_FREE("single command orb DMA"); | 
 | 530 | 			pci_unmap_single(host->pdev, command->sge_dma, | 
 | 531 | 					 sizeof(command->scatter_gather_element), | 
 | 532 | 					 PCI_DMA_BIDIRECTIONAL); | 
 | 533 | 			SBP2_DMA_FREE("scatter_gather_element"); | 
 | 534 |  | 
 | 535 | 			kfree(command); | 
 | 536 | 		} | 
 | 537 | 	} | 
 | 538 | 	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); | 
 | 539 | 	return; | 
 | 540 | } | 
 | 541 |  | 
 | 542 | /* | 
 | 543 |  * This function finds the sbp2_command for a given outstanding command | 
 | 544 |  * orb.Only looks at the inuse list. | 
 | 545 |  */ | 
 | 546 | static struct sbp2_command_info *sbp2util_find_command_for_orb( | 
 | 547 | 		struct scsi_id_instance_data *scsi_id, dma_addr_t orb) | 
 | 548 | { | 
 | 549 | 	struct sbp2_command_info *command; | 
 | 550 | 	unsigned long flags; | 
 | 551 |  | 
 | 552 | 	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); | 
 | 553 | 	if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) { | 
 | 554 | 		list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) { | 
 | 555 | 			if (command->command_orb_dma == orb) { | 
 | 556 | 				spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 557 | 				return command; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 558 | 			} | 
 | 559 | 		} | 
 | 560 | 	} | 
 | 561 | 	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); | 
 | 562 |  | 
 | 563 | 	SBP2_ORB_DEBUG("could not match command orb %x", (unsigned int)orb); | 
 | 564 |  | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 565 | 	return NULL; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 566 | } | 
 | 567 |  | 
 | 568 | /* | 
 | 569 |  * This function finds the sbp2_command for a given outstanding SCpnt. | 
 | 570 |  * Only looks at the inuse list. | 
| Stefan Richter | 24c7cd0 | 2006-04-01 21:11:41 +0200 | [diff] [blame] | 571 |  * Must be called with scsi_id->sbp2_command_orb_lock held. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 572 |  */ | 
| Stefan Richter | 24c7cd0 | 2006-04-01 21:11:41 +0200 | [diff] [blame] | 573 | static struct sbp2_command_info *sbp2util_find_command_for_SCpnt( | 
 | 574 | 		struct scsi_id_instance_data *scsi_id, void *SCpnt) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 575 | { | 
 | 576 | 	struct sbp2_command_info *command; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 577 |  | 
| Stefan Richter | 24c7cd0 | 2006-04-01 21:11:41 +0200 | [diff] [blame] | 578 | 	if (!list_empty(&scsi_id->sbp2_command_orb_inuse)) | 
 | 579 | 		list_for_each_entry(command, &scsi_id->sbp2_command_orb_inuse, list) | 
 | 580 | 			if (command->Current_SCpnt == SCpnt) | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 581 | 				return command; | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 582 | 	return NULL; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 583 | } | 
 | 584 |  | 
 | 585 | /* | 
 | 586 |  * This function allocates a command orb used to send a scsi command. | 
 | 587 |  */ | 
 | 588 | static struct sbp2_command_info *sbp2util_allocate_command_orb( | 
 | 589 | 		struct scsi_id_instance_data *scsi_id, | 
 | 590 | 		struct scsi_cmnd *Current_SCpnt, | 
 | 591 | 		void (*Current_done)(struct scsi_cmnd *)) | 
 | 592 | { | 
 | 593 | 	struct list_head *lh; | 
 | 594 | 	struct sbp2_command_info *command = NULL; | 
 | 595 | 	unsigned long flags; | 
 | 596 |  | 
 | 597 | 	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); | 
 | 598 | 	if (!list_empty(&scsi_id->sbp2_command_orb_completed)) { | 
 | 599 | 		lh = scsi_id->sbp2_command_orb_completed.next; | 
 | 600 | 		list_del(lh); | 
 | 601 | 		command = list_entry(lh, struct sbp2_command_info, list); | 
 | 602 | 		command->Current_done = Current_done; | 
 | 603 | 		command->Current_SCpnt = Current_SCpnt; | 
 | 604 | 		list_add_tail(&command->list, &scsi_id->sbp2_command_orb_inuse); | 
 | 605 | 	} else { | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 606 | 		SBP2_ERR("%s: no orbs available", __FUNCTION__); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 607 | 	} | 
 | 608 | 	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 609 | 	return command; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 610 | } | 
 | 611 |  | 
 | 612 | /* Free our DMA's */ | 
 | 613 | static void sbp2util_free_command_dma(struct sbp2_command_info *command) | 
 | 614 | { | 
 | 615 | 	struct scsi_id_instance_data *scsi_id = | 
 | 616 | 		(struct scsi_id_instance_data *)command->Current_SCpnt->device->host->hostdata[0]; | 
 | 617 | 	struct hpsb_host *host; | 
 | 618 |  | 
 | 619 | 	if (!scsi_id) { | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 620 | 		SBP2_ERR("%s: scsi_id == NULL", __FUNCTION__); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 621 | 		return; | 
 | 622 | 	} | 
 | 623 |  | 
 | 624 | 	host = scsi_id->ud->ne->host; | 
 | 625 |  | 
 | 626 | 	if (command->cmd_dma) { | 
 | 627 | 		if (command->dma_type == CMD_DMA_SINGLE) { | 
 | 628 | 			pci_unmap_single(host->pdev, command->cmd_dma, | 
 | 629 | 					 command->dma_size, command->dma_dir); | 
 | 630 | 			SBP2_DMA_FREE("single bulk"); | 
 | 631 | 		} else if (command->dma_type == CMD_DMA_PAGE) { | 
 | 632 | 			pci_unmap_page(host->pdev, command->cmd_dma, | 
 | 633 | 				       command->dma_size, command->dma_dir); | 
 | 634 | 			SBP2_DMA_FREE("single page"); | 
 | 635 | 		} /* XXX: Check for CMD_DMA_NONE bug */ | 
 | 636 | 		command->dma_type = CMD_DMA_NONE; | 
 | 637 | 		command->cmd_dma = 0; | 
 | 638 | 	} | 
 | 639 |  | 
 | 640 | 	if (command->sge_buffer) { | 
 | 641 | 		pci_unmap_sg(host->pdev, command->sge_buffer, | 
 | 642 | 			     command->dma_size, command->dma_dir); | 
 | 643 | 		SBP2_DMA_FREE("scatter list"); | 
 | 644 | 		command->sge_buffer = NULL; | 
 | 645 | 	} | 
 | 646 | } | 
 | 647 |  | 
 | 648 | /* | 
 | 649 |  * This function moves a command to the completed orb list. | 
| Stefan Richter | 24c7cd0 | 2006-04-01 21:11:41 +0200 | [diff] [blame] | 650 |  * Must be called with scsi_id->sbp2_command_orb_lock held. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 651 |  */ | 
| Stefan Richter | 24c7cd0 | 2006-04-01 21:11:41 +0200 | [diff] [blame] | 652 | static void sbp2util_mark_command_completed( | 
 | 653 | 		struct scsi_id_instance_data *scsi_id, | 
 | 654 | 		struct sbp2_command_info *command) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 655 | { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 656 | 	list_del(&command->list); | 
 | 657 | 	sbp2util_free_command_dma(command); | 
 | 658 | 	list_add_tail(&command->list, &scsi_id->sbp2_command_orb_completed); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 659 | } | 
 | 660 |  | 
| Jody McIntyre | abd559b | 2005-09-30 11:59:06 -0700 | [diff] [blame] | 661 | /* | 
 | 662 |  * Is scsi_id valid? Is the 1394 node still present? | 
 | 663 |  */ | 
 | 664 | static inline int sbp2util_node_is_available(struct scsi_id_instance_data *scsi_id) | 
 | 665 | { | 
 | 666 | 	return scsi_id && scsi_id->ne && !scsi_id->ne->in_limbo; | 
 | 667 | } | 
 | 668 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 669 | /********************************************* | 
 | 670 |  * IEEE-1394 core driver stack related section | 
 | 671 |  *********************************************/ | 
 | 672 | static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud); | 
 | 673 |  | 
 | 674 | static int sbp2_probe(struct device *dev) | 
 | 675 | { | 
 | 676 | 	struct unit_directory *ud; | 
 | 677 | 	struct scsi_id_instance_data *scsi_id; | 
 | 678 |  | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 679 | 	SBP2_DEBUG_ENTER(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 680 |  | 
 | 681 | 	ud = container_of(dev, struct unit_directory, device); | 
 | 682 |  | 
 | 683 | 	/* Don't probe UD's that have the LUN flag. We'll probe the LUN(s) | 
 | 684 | 	 * instead. */ | 
 | 685 | 	if (ud->flags & UNIT_DIRECTORY_HAS_LUN_DIRECTORY) | 
 | 686 | 		return -ENODEV; | 
 | 687 |  | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 688 | 	scsi_id = sbp2_alloc_device(ud); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 689 |  | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 690 | 	if (!scsi_id) | 
 | 691 | 		return -ENOMEM; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 692 |  | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 693 | 	sbp2_parse_unit_directory(scsi_id, ud); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 694 |  | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 695 | 	return sbp2_start_device(scsi_id); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 696 | } | 
 | 697 |  | 
 | 698 | static int sbp2_remove(struct device *dev) | 
 | 699 | { | 
 | 700 | 	struct unit_directory *ud; | 
 | 701 | 	struct scsi_id_instance_data *scsi_id; | 
| Jody McIntyre | abd559b | 2005-09-30 11:59:06 -0700 | [diff] [blame] | 702 | 	struct scsi_device *sdev; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 703 |  | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 704 | 	SBP2_DEBUG_ENTER(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 705 |  | 
 | 706 | 	ud = container_of(dev, struct unit_directory, device); | 
 | 707 | 	scsi_id = ud->device.driver_data; | 
| Jody McIntyre | abd559b | 2005-09-30 11:59:06 -0700 | [diff] [blame] | 708 | 	if (!scsi_id) | 
 | 709 | 		return 0; | 
 | 710 |  | 
| Stefan Richter | bf637ec | 2006-01-31 00:13:06 -0500 | [diff] [blame] | 711 | 	if (scsi_id->scsi_host) { | 
 | 712 | 		/* Get rid of enqueued commands if there is no chance to | 
 | 713 | 		 * send them. */ | 
 | 714 | 		if (!sbp2util_node_is_available(scsi_id)) | 
 | 715 | 			sbp2scsi_complete_all_commands(scsi_id, DID_NO_CONNECT); | 
 | 716 | 		/* scsi_remove_device() will trigger shutdown functions of SCSI | 
 | 717 | 		 * highlevel drivers which would deadlock if blocked. */ | 
| Jody McIntyre | abd559b | 2005-09-30 11:59:06 -0700 | [diff] [blame] | 718 | 		scsi_unblock_requests(scsi_id->scsi_host); | 
| Stefan Richter | bf637ec | 2006-01-31 00:13:06 -0500 | [diff] [blame] | 719 | 	} | 
| Jody McIntyre | abd559b | 2005-09-30 11:59:06 -0700 | [diff] [blame] | 720 | 	sdev = scsi_id->sdev; | 
 | 721 | 	if (sdev) { | 
 | 722 | 		scsi_id->sdev = NULL; | 
 | 723 | 		scsi_remove_device(sdev); | 
 | 724 | 	} | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 725 |  | 
 | 726 | 	sbp2_logout_device(scsi_id); | 
 | 727 | 	sbp2_remove_device(scsi_id); | 
 | 728 |  | 
 | 729 | 	return 0; | 
 | 730 | } | 
 | 731 |  | 
 | 732 | static int sbp2_update(struct unit_directory *ud) | 
 | 733 | { | 
 | 734 | 	struct scsi_id_instance_data *scsi_id = ud->device.driver_data; | 
 | 735 |  | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 736 | 	SBP2_DEBUG_ENTER(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 737 |  | 
 | 738 | 	if (sbp2_reconnect_device(scsi_id)) { | 
 | 739 |  | 
 | 740 | 		/* | 
 | 741 | 		 * Ok, reconnect has failed. Perhaps we didn't | 
 | 742 | 		 * reconnect fast enough. Try doing a regular login, but | 
 | 743 | 		 * first do a logout just in case of any weirdness. | 
 | 744 | 		 */ | 
 | 745 | 		sbp2_logout_device(scsi_id); | 
 | 746 |  | 
 | 747 | 		if (sbp2_login_device(scsi_id)) { | 
 | 748 | 			/* Login failed too, just fail, and the backend | 
 | 749 | 			 * will call our sbp2_remove for us */ | 
 | 750 | 			SBP2_ERR("Failed to reconnect to sbp2 device!"); | 
 | 751 | 			return -EBUSY; | 
 | 752 | 		} | 
 | 753 | 	} | 
 | 754 |  | 
 | 755 | 	/* Set max retries to something large on the device. */ | 
 | 756 | 	sbp2_set_busy_timeout(scsi_id); | 
 | 757 |  | 
 | 758 | 	/* Do a SBP-2 fetch agent reset. */ | 
 | 759 | 	sbp2_agent_reset(scsi_id, 1); | 
 | 760 |  | 
 | 761 | 	/* Get the max speed and packet size that we can use. */ | 
 | 762 | 	sbp2_max_speed_and_size(scsi_id); | 
 | 763 |  | 
 | 764 | 	/* Complete any pending commands with busy (so they get | 
 | 765 | 	 * retried) and remove them from our queue | 
 | 766 | 	 */ | 
 | 767 | 	sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY); | 
 | 768 |  | 
 | 769 | 	/* Make sure we unblock requests (since this is likely after a bus | 
 | 770 | 	 * reset). */ | 
 | 771 | 	scsi_unblock_requests(scsi_id->scsi_host); | 
 | 772 |  | 
 | 773 | 	return 0; | 
 | 774 | } | 
 | 775 |  | 
 | 776 | /* This functions is called by the sbp2_probe, for each new device. We now | 
 | 777 |  * allocate one scsi host for each scsi_id (unit directory). */ | 
 | 778 | static struct scsi_id_instance_data *sbp2_alloc_device(struct unit_directory *ud) | 
 | 779 | { | 
 | 780 | 	struct sbp2scsi_host_info *hi; | 
 | 781 | 	struct Scsi_Host *scsi_host = NULL; | 
 | 782 | 	struct scsi_id_instance_data *scsi_id = NULL; | 
 | 783 |  | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 784 | 	SBP2_DEBUG_ENTER(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 785 |  | 
| Stefan Richter | 8551158 | 2005-11-07 06:31:45 -0500 | [diff] [blame] | 786 | 	scsi_id = kzalloc(sizeof(*scsi_id), GFP_KERNEL); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 787 | 	if (!scsi_id) { | 
 | 788 | 		SBP2_ERR("failed to create scsi_id"); | 
 | 789 | 		goto failed_alloc; | 
 | 790 | 	} | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 791 |  | 
 | 792 | 	scsi_id->ne = ud->ne; | 
 | 793 | 	scsi_id->ud = ud; | 
 | 794 | 	scsi_id->speed_code = IEEE1394_SPEED_100; | 
 | 795 | 	scsi_id->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100]; | 
| Ben Collins | 6737231 | 2006-06-12 18:15:31 -0400 | [diff] [blame] | 796 | 	scsi_id->status_fifo_addr = CSR1212_INVALID_ADDR_SPACE; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 797 | 	atomic_set(&scsi_id->sbp2_login_complete, 0); | 
 | 798 | 	INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_inuse); | 
 | 799 | 	INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed); | 
 | 800 | 	INIT_LIST_HEAD(&scsi_id->scsi_list); | 
 | 801 | 	spin_lock_init(&scsi_id->sbp2_command_orb_lock); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 802 |  | 
 | 803 | 	ud->device.driver_data = scsi_id; | 
 | 804 |  | 
 | 805 | 	hi = hpsb_get_hostinfo(&sbp2_highlevel, ud->ne->host); | 
 | 806 | 	if (!hi) { | 
 | 807 | 		hi = hpsb_create_hostinfo(&sbp2_highlevel, ud->ne->host, sizeof(*hi)); | 
 | 808 | 		if (!hi) { | 
 | 809 | 			SBP2_ERR("failed to allocate hostinfo"); | 
 | 810 | 			goto failed_alloc; | 
 | 811 | 		} | 
 | 812 | 		SBP2_DEBUG("sbp2_alloc_device: allocated hostinfo"); | 
 | 813 | 		hi->host = ud->ne->host; | 
 | 814 | 		INIT_LIST_HEAD(&hi->scsi_ids); | 
 | 815 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 816 | #ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA | 
 | 817 | 		/* Handle data movement if physical dma is not | 
| Stefan Richter | 5566405 | 2006-03-28 19:59:42 -0500 | [diff] [blame] | 818 | 		 * enabled or not supported on host controller */ | 
 | 819 | 		if (!hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host, | 
 | 820 | 					     &sbp2_physdma_ops, | 
 | 821 | 					     0x0ULL, 0xfffffffcULL)) { | 
 | 822 | 			SBP2_ERR("failed to register lower 4GB address range"); | 
 | 823 | 			goto failed_alloc; | 
 | 824 | 		} | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 825 | #endif | 
 | 826 | 	} | 
 | 827 |  | 
| Stefan Richter | 147830f | 2006-03-28 19:54:52 -0500 | [diff] [blame] | 828 | 	/* Prevent unloading of the 1394 host */ | 
 | 829 | 	if (!try_module_get(hi->host->driver->owner)) { | 
 | 830 | 		SBP2_ERR("failed to get a reference on 1394 host driver"); | 
 | 831 | 		goto failed_alloc; | 
 | 832 | 	} | 
 | 833 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 834 | 	scsi_id->hi = hi; | 
 | 835 |  | 
 | 836 | 	list_add_tail(&scsi_id->scsi_list, &hi->scsi_ids); | 
 | 837 |  | 
| Stefan Richter | 35bdddb | 2006-01-31 00:13:33 -0500 | [diff] [blame] | 838 | 	/* Register the status FIFO address range. We could use the same FIFO | 
 | 839 | 	 * for targets at different nodes. However we need different FIFOs per | 
| Stefan Richter | a54c9d3 | 2006-05-15 22:09:46 +0200 | [diff] [blame] | 840 | 	 * target in order to support multi-unit devices. | 
 | 841 | 	 * The FIFO is located out of the local host controller's physical range | 
 | 842 | 	 * but, if possible, within the posted write area. Status writes will | 
 | 843 | 	 * then be performed as unified transactions. This slightly reduces | 
 | 844 | 	 * bandwidth usage, and some Prolific based devices seem to require it. | 
 | 845 | 	 */ | 
| Stefan Richter | 35bdddb | 2006-01-31 00:13:33 -0500 | [diff] [blame] | 846 | 	scsi_id->status_fifo_addr = hpsb_allocate_and_register_addrspace( | 
 | 847 | 			&sbp2_highlevel, ud->ne->host, &sbp2_ops, | 
 | 848 | 			sizeof(struct sbp2_status_block), sizeof(quadlet_t), | 
| Ben Collins | 40ae6c5 | 2006-06-12 18:13:49 -0400 | [diff] [blame] | 849 | 			ud->ne->host->low_addr_space, CSR1212_ALL_SPACE_END); | 
| Ben Collins | 6737231 | 2006-06-12 18:15:31 -0400 | [diff] [blame] | 850 | 	if (scsi_id->status_fifo_addr == CSR1212_INVALID_ADDR_SPACE) { | 
| Stefan Richter | 35bdddb | 2006-01-31 00:13:33 -0500 | [diff] [blame] | 851 | 		SBP2_ERR("failed to allocate status FIFO address range"); | 
 | 852 | 		goto failed_alloc; | 
 | 853 | 	} | 
 | 854 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 855 | 	/* Register our host with the SCSI stack. */ | 
| Alexandre Oliva | a2ef79e | 2005-06-15 22:26:31 -0700 | [diff] [blame] | 856 | 	scsi_host = scsi_host_alloc(&scsi_driver_template, | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 857 | 				    sizeof(unsigned long)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 858 | 	if (!scsi_host) { | 
 | 859 | 		SBP2_ERR("failed to register scsi host"); | 
 | 860 | 		goto failed_alloc; | 
 | 861 | 	} | 
 | 862 |  | 
 | 863 | 	scsi_host->hostdata[0] = (unsigned long)scsi_id; | 
 | 864 |  | 
 | 865 | 	if (!scsi_add_host(scsi_host, &ud->device)) { | 
 | 866 | 		scsi_id->scsi_host = scsi_host; | 
 | 867 | 		return scsi_id; | 
 | 868 | 	} | 
 | 869 |  | 
 | 870 | 	SBP2_ERR("failed to add scsi host"); | 
 | 871 | 	scsi_host_put(scsi_host); | 
 | 872 |  | 
 | 873 | failed_alloc: | 
 | 874 | 	sbp2_remove_device(scsi_id); | 
 | 875 | 	return NULL; | 
 | 876 | } | 
 | 877 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 878 | static void sbp2_host_reset(struct hpsb_host *host) | 
 | 879 | { | 
 | 880 | 	struct sbp2scsi_host_info *hi; | 
 | 881 | 	struct scsi_id_instance_data *scsi_id; | 
 | 882 |  | 
 | 883 | 	hi = hpsb_get_hostinfo(&sbp2_highlevel, host); | 
 | 884 |  | 
 | 885 | 	if (hi) { | 
 | 886 | 		list_for_each_entry(scsi_id, &hi->scsi_ids, scsi_list) | 
 | 887 | 			scsi_block_requests(scsi_id->scsi_host); | 
 | 888 | 	} | 
 | 889 | } | 
 | 890 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 891 | /* | 
 | 892 |  * This function is where we first pull the node unique ids, and then | 
 | 893 |  * allocate memory and register a SBP-2 device. | 
 | 894 |  */ | 
 | 895 | static int sbp2_start_device(struct scsi_id_instance_data *scsi_id) | 
 | 896 | { | 
 | 897 | 	struct sbp2scsi_host_info *hi = scsi_id->hi; | 
| James Bottomley | 146f726 | 2005-09-10 12:44:09 -0500 | [diff] [blame] | 898 | 	int error; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 899 |  | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 900 | 	SBP2_DEBUG_ENTER(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 901 |  | 
 | 902 | 	/* Login FIFO DMA */ | 
 | 903 | 	scsi_id->login_response = | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 904 | 		pci_alloc_consistent(hi->host->pdev, | 
 | 905 | 				     sizeof(struct sbp2_login_response), | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 906 | 				     &scsi_id->login_response_dma); | 
 | 907 | 	if (!scsi_id->login_response) | 
 | 908 | 		goto alloc_fail; | 
 | 909 | 	SBP2_DMA_ALLOC("consistent DMA region for login FIFO"); | 
 | 910 |  | 
 | 911 | 	/* Query logins ORB DMA */ | 
 | 912 | 	scsi_id->query_logins_orb = | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 913 | 		pci_alloc_consistent(hi->host->pdev, | 
 | 914 | 				     sizeof(struct sbp2_query_logins_orb), | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 915 | 				     &scsi_id->query_logins_orb_dma); | 
 | 916 | 	if (!scsi_id->query_logins_orb) | 
 | 917 | 		goto alloc_fail; | 
 | 918 | 	SBP2_DMA_ALLOC("consistent DMA region for query logins ORB"); | 
 | 919 |  | 
 | 920 | 	/* Query logins response DMA */ | 
 | 921 | 	scsi_id->query_logins_response = | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 922 | 		pci_alloc_consistent(hi->host->pdev, | 
 | 923 | 				     sizeof(struct sbp2_query_logins_response), | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 924 | 				     &scsi_id->query_logins_response_dma); | 
 | 925 | 	if (!scsi_id->query_logins_response) | 
 | 926 | 		goto alloc_fail; | 
 | 927 | 	SBP2_DMA_ALLOC("consistent DMA region for query logins response"); | 
 | 928 |  | 
 | 929 | 	/* Reconnect ORB DMA */ | 
 | 930 | 	scsi_id->reconnect_orb = | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 931 | 		pci_alloc_consistent(hi->host->pdev, | 
 | 932 | 				     sizeof(struct sbp2_reconnect_orb), | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 933 | 				     &scsi_id->reconnect_orb_dma); | 
 | 934 | 	if (!scsi_id->reconnect_orb) | 
 | 935 | 		goto alloc_fail; | 
 | 936 | 	SBP2_DMA_ALLOC("consistent DMA region for reconnect ORB"); | 
 | 937 |  | 
 | 938 | 	/* Logout ORB DMA */ | 
 | 939 | 	scsi_id->logout_orb = | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 940 | 		pci_alloc_consistent(hi->host->pdev, | 
 | 941 | 				     sizeof(struct sbp2_logout_orb), | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 942 | 				     &scsi_id->logout_orb_dma); | 
 | 943 | 	if (!scsi_id->logout_orb) | 
 | 944 | 		goto alloc_fail; | 
 | 945 | 	SBP2_DMA_ALLOC("consistent DMA region for logout ORB"); | 
 | 946 |  | 
 | 947 | 	/* Login ORB DMA */ | 
 | 948 | 	scsi_id->login_orb = | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 949 | 		pci_alloc_consistent(hi->host->pdev, | 
 | 950 | 				     sizeof(struct sbp2_login_orb), | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 951 | 				     &scsi_id->login_orb_dma); | 
| Stefan Richter | eaceec7 | 2005-12-13 11:05:05 -0500 | [diff] [blame] | 952 | 	if (!scsi_id->login_orb) | 
 | 953 | 		goto alloc_fail; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 954 | 	SBP2_DMA_ALLOC("consistent DMA region for login ORB"); | 
 | 955 |  | 
 | 956 | 	SBP2_DEBUG("New SBP-2 device inserted, SCSI ID = %x", scsi_id->ud->id); | 
 | 957 |  | 
 | 958 | 	/* | 
 | 959 | 	 * Create our command orb pool | 
 | 960 | 	 */ | 
 | 961 | 	if (sbp2util_create_command_orb_pool(scsi_id)) { | 
 | 962 | 		SBP2_ERR("sbp2util_create_command_orb_pool failed!"); | 
 | 963 | 		sbp2_remove_device(scsi_id); | 
 | 964 | 		return -ENOMEM; | 
 | 965 | 	} | 
 | 966 |  | 
 | 967 | 	/* Schedule a timeout here. The reason is that we may be so close | 
 | 968 | 	 * to a bus reset, that the device is not available for logins. | 
 | 969 | 	 * This can happen when the bus reset is caused by the host | 
 | 970 | 	 * connected to the sbp2 device being removed. That host would | 
 | 971 | 	 * have a certain amount of time to relogin before the sbp2 device | 
 | 972 | 	 * allows someone else to login instead. One second makes sense. */ | 
 | 973 | 	msleep_interruptible(1000); | 
 | 974 | 	if (signal_pending(current)) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 975 | 		sbp2_remove_device(scsi_id); | 
 | 976 | 		return -EINTR; | 
 | 977 | 	} | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 978 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 979 | 	/* | 
 | 980 | 	 * Login to the sbp-2 device | 
 | 981 | 	 */ | 
 | 982 | 	if (sbp2_login_device(scsi_id)) { | 
 | 983 | 		/* Login failed, just remove the device. */ | 
 | 984 | 		sbp2_remove_device(scsi_id); | 
 | 985 | 		return -EBUSY; | 
 | 986 | 	} | 
 | 987 |  | 
 | 988 | 	/* | 
 | 989 | 	 * Set max retries to something large on the device | 
 | 990 | 	 */ | 
 | 991 | 	sbp2_set_busy_timeout(scsi_id); | 
 | 992 |  | 
 | 993 | 	/* | 
 | 994 | 	 * Do a SBP-2 fetch agent reset | 
 | 995 | 	 */ | 
 | 996 | 	sbp2_agent_reset(scsi_id, 1); | 
 | 997 |  | 
 | 998 | 	/* | 
 | 999 | 	 * Get the max speed and packet size that we can use | 
 | 1000 | 	 */ | 
 | 1001 | 	sbp2_max_speed_and_size(scsi_id); | 
 | 1002 |  | 
 | 1003 | 	/* Add this device to the scsi layer now */ | 
| James Bottomley | 146f726 | 2005-09-10 12:44:09 -0500 | [diff] [blame] | 1004 | 	error = scsi_add_device(scsi_id->scsi_host, 0, scsi_id->ud->id, 0); | 
 | 1005 | 	if (error) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1006 | 		SBP2_ERR("scsi_add_device failed"); | 
| Stefan Richter | dc3edd5 | 2005-12-12 23:03:30 -0500 | [diff] [blame] | 1007 | 		sbp2_logout_device(scsi_id); | 
 | 1008 | 		sbp2_remove_device(scsi_id); | 
| James Bottomley | 146f726 | 2005-09-10 12:44:09 -0500 | [diff] [blame] | 1009 | 		return error; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1010 | 	} | 
 | 1011 |  | 
 | 1012 | 	return 0; | 
| Stefan Richter | eaceec7 | 2005-12-13 11:05:05 -0500 | [diff] [blame] | 1013 |  | 
 | 1014 | alloc_fail: | 
 | 1015 | 	SBP2_ERR("Could not allocate memory for scsi_id"); | 
 | 1016 | 	sbp2_remove_device(scsi_id); | 
 | 1017 | 	return -ENOMEM; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1018 | } | 
 | 1019 |  | 
 | 1020 | /* | 
 | 1021 |  * This function removes an sbp2 device from the sbp2scsi_host_info struct. | 
 | 1022 |  */ | 
 | 1023 | static void sbp2_remove_device(struct scsi_id_instance_data *scsi_id) | 
 | 1024 | { | 
 | 1025 | 	struct sbp2scsi_host_info *hi; | 
 | 1026 |  | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 1027 | 	SBP2_DEBUG_ENTER(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1028 |  | 
 | 1029 | 	if (!scsi_id) | 
 | 1030 | 		return; | 
 | 1031 |  | 
 | 1032 | 	hi = scsi_id->hi; | 
 | 1033 |  | 
 | 1034 | 	/* This will remove our scsi device aswell */ | 
 | 1035 | 	if (scsi_id->scsi_host) { | 
 | 1036 | 		scsi_remove_host(scsi_id->scsi_host); | 
 | 1037 | 		scsi_host_put(scsi_id->scsi_host); | 
 | 1038 | 	} | 
 | 1039 |  | 
 | 1040 | 	sbp2util_remove_command_orb_pool(scsi_id); | 
 | 1041 |  | 
 | 1042 | 	list_del(&scsi_id->scsi_list); | 
 | 1043 |  | 
 | 1044 | 	if (scsi_id->login_response) { | 
 | 1045 | 		pci_free_consistent(hi->host->pdev, | 
 | 1046 | 				    sizeof(struct sbp2_login_response), | 
 | 1047 | 				    scsi_id->login_response, | 
 | 1048 | 				    scsi_id->login_response_dma); | 
 | 1049 | 		SBP2_DMA_FREE("single login FIFO"); | 
 | 1050 | 	} | 
 | 1051 |  | 
 | 1052 | 	if (scsi_id->login_orb) { | 
 | 1053 | 		pci_free_consistent(hi->host->pdev, | 
 | 1054 | 				    sizeof(struct sbp2_login_orb), | 
 | 1055 | 				    scsi_id->login_orb, | 
 | 1056 | 				    scsi_id->login_orb_dma); | 
 | 1057 | 		SBP2_DMA_FREE("single login ORB"); | 
 | 1058 | 	} | 
 | 1059 |  | 
 | 1060 | 	if (scsi_id->reconnect_orb) { | 
 | 1061 | 		pci_free_consistent(hi->host->pdev, | 
 | 1062 | 				    sizeof(struct sbp2_reconnect_orb), | 
 | 1063 | 				    scsi_id->reconnect_orb, | 
 | 1064 | 				    scsi_id->reconnect_orb_dma); | 
 | 1065 | 		SBP2_DMA_FREE("single reconnect orb"); | 
 | 1066 | 	} | 
 | 1067 |  | 
 | 1068 | 	if (scsi_id->logout_orb) { | 
 | 1069 | 		pci_free_consistent(hi->host->pdev, | 
 | 1070 | 				    sizeof(struct sbp2_logout_orb), | 
 | 1071 | 				    scsi_id->logout_orb, | 
 | 1072 | 				    scsi_id->logout_orb_dma); | 
 | 1073 | 		SBP2_DMA_FREE("single logout orb"); | 
 | 1074 | 	} | 
 | 1075 |  | 
 | 1076 | 	if (scsi_id->query_logins_orb) { | 
 | 1077 | 		pci_free_consistent(hi->host->pdev, | 
 | 1078 | 				    sizeof(struct sbp2_query_logins_orb), | 
 | 1079 | 				    scsi_id->query_logins_orb, | 
 | 1080 | 				    scsi_id->query_logins_orb_dma); | 
 | 1081 | 		SBP2_DMA_FREE("single query logins orb"); | 
 | 1082 | 	} | 
 | 1083 |  | 
 | 1084 | 	if (scsi_id->query_logins_response) { | 
 | 1085 | 		pci_free_consistent(hi->host->pdev, | 
 | 1086 | 				    sizeof(struct sbp2_query_logins_response), | 
 | 1087 | 				    scsi_id->query_logins_response, | 
 | 1088 | 				    scsi_id->query_logins_response_dma); | 
 | 1089 | 		SBP2_DMA_FREE("single query logins data"); | 
 | 1090 | 	} | 
 | 1091 |  | 
| Ben Collins | 6737231 | 2006-06-12 18:15:31 -0400 | [diff] [blame] | 1092 | 	if (scsi_id->status_fifo_addr != CSR1212_INVALID_ADDR_SPACE) | 
| Stefan Richter | 35bdddb | 2006-01-31 00:13:33 -0500 | [diff] [blame] | 1093 | 		hpsb_unregister_addrspace(&sbp2_highlevel, hi->host, | 
| Ben Collins | 6737231 | 2006-06-12 18:15:31 -0400 | [diff] [blame] | 1094 | 					  scsi_id->status_fifo_addr); | 
| Stefan Richter | 35bdddb | 2006-01-31 00:13:33 -0500 | [diff] [blame] | 1095 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1096 | 	scsi_id->ud->device.driver_data = NULL; | 
 | 1097 |  | 
| Stefan Richter | 147830f | 2006-03-28 19:54:52 -0500 | [diff] [blame] | 1098 | 	if (hi) | 
 | 1099 | 		module_put(hi->host->driver->owner); | 
 | 1100 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1101 | 	SBP2_DEBUG("SBP-2 device removed, SCSI ID = %d", scsi_id->ud->id); | 
 | 1102 |  | 
 | 1103 | 	kfree(scsi_id); | 
 | 1104 | } | 
 | 1105 |  | 
 | 1106 | #ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA | 
 | 1107 | /* | 
 | 1108 |  * This function deals with physical dma write requests (for adapters that do not support | 
 | 1109 |  * physical dma in hardware). Mostly just here for debugging... | 
 | 1110 |  */ | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1111 | static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid, | 
 | 1112 | 				     int destid, quadlet_t *data, u64 addr, | 
 | 1113 | 				     size_t length, u16 flags) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1114 | { | 
 | 1115 |  | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1116 | 	/* | 
 | 1117 | 	 * Manually put the data in the right place. | 
 | 1118 | 	 */ | 
 | 1119 | 	memcpy(bus_to_virt((u32) addr), data, length); | 
 | 1120 | 	sbp2util_packet_dump(data, length, "sbp2 phys dma write by device", | 
 | 1121 | 			     (u32) addr); | 
 | 1122 | 	return RCODE_COMPLETE; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1123 | } | 
 | 1124 |  | 
 | 1125 | /* | 
 | 1126 |  * This function deals with physical dma read requests (for adapters that do not support | 
 | 1127 |  * physical dma in hardware). Mostly just here for debugging... | 
 | 1128 |  */ | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1129 | static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid, | 
 | 1130 | 				    quadlet_t *data, u64 addr, size_t length, | 
 | 1131 | 				    u16 flags) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1132 | { | 
 | 1133 |  | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1134 | 	/* | 
 | 1135 | 	 * Grab data from memory and send a read response. | 
 | 1136 | 	 */ | 
 | 1137 | 	memcpy(data, bus_to_virt((u32) addr), length); | 
 | 1138 | 	sbp2util_packet_dump(data, length, "sbp2 phys dma read by device", | 
 | 1139 | 			     (u32) addr); | 
 | 1140 | 	return RCODE_COMPLETE; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1141 | } | 
 | 1142 | #endif | 
 | 1143 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1144 | /************************************** | 
 | 1145 |  * SBP-2 protocol related section | 
 | 1146 |  **************************************/ | 
 | 1147 |  | 
 | 1148 | /* | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1149 |  * This function queries the device for the maximum concurrent logins it | 
 | 1150 |  * supports. | 
 | 1151 |  */ | 
 | 1152 | static int sbp2_query_logins(struct scsi_id_instance_data *scsi_id) | 
 | 1153 | { | 
 | 1154 | 	struct sbp2scsi_host_info *hi = scsi_id->hi; | 
 | 1155 | 	quadlet_t data[2]; | 
 | 1156 | 	int max_logins; | 
 | 1157 | 	int active_logins; | 
 | 1158 |  | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 1159 | 	SBP2_DEBUG_ENTER(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1160 |  | 
 | 1161 | 	scsi_id->query_logins_orb->reserved1 = 0x0; | 
 | 1162 | 	scsi_id->query_logins_orb->reserved2 = 0x0; | 
 | 1163 |  | 
 | 1164 | 	scsi_id->query_logins_orb->query_response_lo = scsi_id->query_logins_response_dma; | 
 | 1165 | 	scsi_id->query_logins_orb->query_response_hi = ORB_SET_NODE_ID(hi->host->node_id); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1166 |  | 
 | 1167 | 	scsi_id->query_logins_orb->lun_misc = ORB_SET_FUNCTION(SBP2_QUERY_LOGINS_REQUEST); | 
 | 1168 | 	scsi_id->query_logins_orb->lun_misc |= ORB_SET_NOTIFY(1); | 
| Ben Collins | e309fc6 | 2005-11-07 06:31:34 -0500 | [diff] [blame] | 1169 | 	scsi_id->query_logins_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_lun); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1170 |  | 
 | 1171 | 	scsi_id->query_logins_orb->reserved_resp_length = | 
 | 1172 | 		ORB_SET_QUERY_LOGINS_RESP_LENGTH(sizeof(struct sbp2_query_logins_response)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1173 |  | 
| Stefan Richter | 35bdddb | 2006-01-31 00:13:33 -0500 | [diff] [blame] | 1174 | 	scsi_id->query_logins_orb->status_fifo_hi = | 
 | 1175 | 		ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id); | 
 | 1176 | 	scsi_id->query_logins_orb->status_fifo_lo = | 
 | 1177 | 		ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1178 |  | 
 | 1179 | 	sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb)); | 
 | 1180 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1181 | 	sbp2util_packet_dump(scsi_id->query_logins_orb, sizeof(struct sbp2_query_logins_orb), | 
 | 1182 | 			     "sbp2 query logins orb", scsi_id->query_logins_orb_dma); | 
 | 1183 |  | 
 | 1184 | 	memset(scsi_id->query_logins_response, 0, sizeof(struct sbp2_query_logins_response)); | 
 | 1185 | 	memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block)); | 
 | 1186 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1187 | 	data[0] = ORB_SET_NODE_ID(hi->host->node_id); | 
 | 1188 | 	data[1] = scsi_id->query_logins_orb_dma; | 
 | 1189 | 	sbp2util_cpu_to_be32_buffer(data, 8); | 
 | 1190 |  | 
 | 1191 | 	atomic_set(&scsi_id->sbp2_login_complete, 0); | 
 | 1192 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1193 | 	hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1194 |  | 
 | 1195 | 	if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, 2*HZ)) { | 
 | 1196 | 		SBP2_INFO("Error querying logins to SBP-2 device - timed out"); | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1197 | 		return -EIO; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1198 | 	} | 
 | 1199 |  | 
 | 1200 | 	if (scsi_id->status_block.ORB_offset_lo != scsi_id->query_logins_orb_dma) { | 
 | 1201 | 		SBP2_INFO("Error querying logins to SBP-2 device - timed out"); | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1202 | 		return -EIO; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1203 | 	} | 
 | 1204 |  | 
 | 1205 | 	if (STATUS_GET_RESP(scsi_id->status_block.ORB_offset_hi_misc) || | 
 | 1206 | 	    STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) || | 
 | 1207 | 	    STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) { | 
 | 1208 |  | 
 | 1209 | 		SBP2_INFO("Error querying logins to SBP-2 device - timed out"); | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1210 | 		return -EIO; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1211 | 	} | 
 | 1212 |  | 
 | 1213 | 	sbp2util_cpu_to_be32_buffer(scsi_id->query_logins_response, sizeof(struct sbp2_query_logins_response)); | 
 | 1214 |  | 
 | 1215 | 	SBP2_DEBUG("length_max_logins = %x", | 
 | 1216 | 		   (unsigned int)scsi_id->query_logins_response->length_max_logins); | 
 | 1217 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1218 | 	max_logins = RESPONSE_GET_MAX_LOGINS(scsi_id->query_logins_response->length_max_logins); | 
| Ben Collins | 20f4578 | 2006-06-12 18:13:11 -0400 | [diff] [blame] | 1219 | 	SBP2_INFO("Maximum concurrent logins supported: %d", max_logins); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1220 |  | 
 | 1221 | 	active_logins = RESPONSE_GET_ACTIVE_LOGINS(scsi_id->query_logins_response->length_max_logins); | 
| Ben Collins | 20f4578 | 2006-06-12 18:13:11 -0400 | [diff] [blame] | 1222 | 	SBP2_INFO("Number of active logins: %d", active_logins); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1223 |  | 
 | 1224 | 	if (active_logins >= max_logins) { | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1225 | 		return -EIO; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1226 | 	} | 
 | 1227 |  | 
 | 1228 | 	return 0; | 
 | 1229 | } | 
 | 1230 |  | 
 | 1231 | /* | 
 | 1232 |  * This function is called in order to login to a particular SBP-2 device, | 
 | 1233 |  * after a bus reset. | 
 | 1234 |  */ | 
 | 1235 | static int sbp2_login_device(struct scsi_id_instance_data *scsi_id) | 
 | 1236 | { | 
 | 1237 | 	struct sbp2scsi_host_info *hi = scsi_id->hi; | 
 | 1238 | 	quadlet_t data[2]; | 
 | 1239 |  | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 1240 | 	SBP2_DEBUG_ENTER(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1241 |  | 
 | 1242 | 	if (!scsi_id->login_orb) { | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 1243 | 		SBP2_DEBUG("%s: login_orb not alloc'd!", __FUNCTION__); | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1244 | 		return -EIO; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1245 | 	} | 
 | 1246 |  | 
 | 1247 | 	if (!exclusive_login) { | 
 | 1248 | 		if (sbp2_query_logins(scsi_id)) { | 
 | 1249 | 			SBP2_INFO("Device does not support any more concurrent logins"); | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1250 | 			return -EIO; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1251 | 		} | 
 | 1252 | 	} | 
 | 1253 |  | 
 | 1254 | 	/* Set-up login ORB, assume no password */ | 
 | 1255 | 	scsi_id->login_orb->password_hi = 0; | 
 | 1256 | 	scsi_id->login_orb->password_lo = 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1257 |  | 
 | 1258 | 	scsi_id->login_orb->login_response_lo = scsi_id->login_response_dma; | 
 | 1259 | 	scsi_id->login_orb->login_response_hi = ORB_SET_NODE_ID(hi->host->node_id); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1260 |  | 
 | 1261 | 	scsi_id->login_orb->lun_misc = ORB_SET_FUNCTION(SBP2_LOGIN_REQUEST); | 
 | 1262 | 	scsi_id->login_orb->lun_misc |= ORB_SET_RECONNECT(0);	/* One second reconnect time */ | 
 | 1263 | 	scsi_id->login_orb->lun_misc |= ORB_SET_EXCLUSIVE(exclusive_login);	/* Exclusive access to device */ | 
 | 1264 | 	scsi_id->login_orb->lun_misc |= ORB_SET_NOTIFY(1);	/* Notify us of login complete */ | 
| Ben Collins | e309fc6 | 2005-11-07 06:31:34 -0500 | [diff] [blame] | 1265 | 	scsi_id->login_orb->lun_misc |= ORB_SET_LUN(scsi_id->sbp2_lun); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1266 |  | 
 | 1267 | 	scsi_id->login_orb->passwd_resp_lengths = | 
 | 1268 | 		ORB_SET_LOGIN_RESP_LENGTH(sizeof(struct sbp2_login_response)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1269 |  | 
| Stefan Richter | 35bdddb | 2006-01-31 00:13:33 -0500 | [diff] [blame] | 1270 | 	scsi_id->login_orb->status_fifo_hi = | 
 | 1271 | 		ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id); | 
 | 1272 | 	scsi_id->login_orb->status_fifo_lo = | 
 | 1273 | 		ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1274 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1275 | 	sbp2util_cpu_to_be32_buffer(scsi_id->login_orb, sizeof(struct sbp2_login_orb)); | 
 | 1276 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1277 | 	sbp2util_packet_dump(scsi_id->login_orb, sizeof(struct sbp2_login_orb), | 
 | 1278 | 			     "sbp2 login orb", scsi_id->login_orb_dma); | 
 | 1279 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1280 | 	memset(scsi_id->login_response, 0, sizeof(struct sbp2_login_response)); | 
 | 1281 | 	memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block)); | 
 | 1282 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1283 | 	data[0] = ORB_SET_NODE_ID(hi->host->node_id); | 
 | 1284 | 	data[1] = scsi_id->login_orb_dma; | 
 | 1285 | 	sbp2util_cpu_to_be32_buffer(data, 8); | 
 | 1286 |  | 
 | 1287 | 	atomic_set(&scsi_id->sbp2_login_complete, 0); | 
 | 1288 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1289 | 	hpsb_node_write(scsi_id->ne, scsi_id->sbp2_management_agent_addr, data, 8); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1290 |  | 
 | 1291 | 	/* | 
 | 1292 | 	 * Wait for login status (up to 20 seconds)... | 
 | 1293 | 	 */ | 
 | 1294 | 	if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, 20*HZ)) { | 
 | 1295 | 		SBP2_ERR("Error logging into SBP-2 device - login timed-out"); | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1296 | 		return -EIO; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1297 | 	} | 
 | 1298 |  | 
 | 1299 | 	/* | 
 | 1300 | 	 * Sanity. Make sure status returned matches login orb. | 
 | 1301 | 	 */ | 
 | 1302 | 	if (scsi_id->status_block.ORB_offset_lo != scsi_id->login_orb_dma) { | 
 | 1303 | 		SBP2_ERR("Error logging into SBP-2 device - login timed-out"); | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1304 | 		return -EIO; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1305 | 	} | 
 | 1306 |  | 
 | 1307 | 	/* | 
 | 1308 | 	 * Check status | 
 | 1309 | 	 */ | 
 | 1310 | 	if (STATUS_GET_RESP(scsi_id->status_block.ORB_offset_hi_misc) || | 
 | 1311 | 	    STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) || | 
 | 1312 | 	    STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) { | 
 | 1313 |  | 
 | 1314 | 		SBP2_ERR("Error logging into SBP-2 device - login failed"); | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1315 | 		return -EIO; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1316 | 	} | 
 | 1317 |  | 
 | 1318 | 	/* | 
 | 1319 | 	 * Byte swap the login response, for use when reconnecting or | 
 | 1320 | 	 * logging out. | 
 | 1321 | 	 */ | 
 | 1322 | 	sbp2util_cpu_to_be32_buffer(scsi_id->login_response, sizeof(struct sbp2_login_response)); | 
 | 1323 |  | 
 | 1324 | 	/* | 
 | 1325 | 	 * Grab our command block agent address from the login response. | 
 | 1326 | 	 */ | 
 | 1327 | 	SBP2_DEBUG("command_block_agent_hi = %x", | 
 | 1328 | 		   (unsigned int)scsi_id->login_response->command_block_agent_hi); | 
 | 1329 | 	SBP2_DEBUG("command_block_agent_lo = %x", | 
 | 1330 | 		   (unsigned int)scsi_id->login_response->command_block_agent_lo); | 
 | 1331 |  | 
 | 1332 | 	scsi_id->sbp2_command_block_agent_addr = | 
 | 1333 | 		((u64)scsi_id->login_response->command_block_agent_hi) << 32; | 
 | 1334 | 	scsi_id->sbp2_command_block_agent_addr |= ((u64)scsi_id->login_response->command_block_agent_lo); | 
 | 1335 | 	scsi_id->sbp2_command_block_agent_addr &= 0x0000ffffffffffffULL; | 
 | 1336 |  | 
 | 1337 | 	SBP2_INFO("Logged into SBP-2 device"); | 
 | 1338 |  | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1339 | 	return 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1340 |  | 
 | 1341 | } | 
 | 1342 |  | 
 | 1343 | /* | 
 | 1344 |  * This function is called in order to logout from a particular SBP-2 | 
 | 1345 |  * device, usually called during driver unload. | 
 | 1346 |  */ | 
 | 1347 | static int sbp2_logout_device(struct scsi_id_instance_data *scsi_id) | 
 | 1348 | { | 
 | 1349 | 	struct sbp2scsi_host_info *hi = scsi_id->hi; | 
 | 1350 | 	quadlet_t data[2]; | 
 | 1351 | 	int error; | 
 | 1352 |  | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 1353 | 	SBP2_DEBUG_ENTER(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1354 |  | 
 | 1355 | 	/* | 
 | 1356 | 	 * Set-up logout ORB | 
 | 1357 | 	 */ | 
 | 1358 | 	scsi_id->logout_orb->reserved1 = 0x0; | 
 | 1359 | 	scsi_id->logout_orb->reserved2 = 0x0; | 
 | 1360 | 	scsi_id->logout_orb->reserved3 = 0x0; | 
 | 1361 | 	scsi_id->logout_orb->reserved4 = 0x0; | 
 | 1362 |  | 
 | 1363 | 	scsi_id->logout_orb->login_ID_misc = ORB_SET_FUNCTION(SBP2_LOGOUT_REQUEST); | 
 | 1364 | 	scsi_id->logout_orb->login_ID_misc |= ORB_SET_LOGIN_ID(scsi_id->login_response->length_login_ID); | 
 | 1365 |  | 
 | 1366 | 	/* Notify us when complete */ | 
 | 1367 | 	scsi_id->logout_orb->login_ID_misc |= ORB_SET_NOTIFY(1); | 
 | 1368 |  | 
 | 1369 | 	scsi_id->logout_orb->reserved5 = 0x0; | 
| Stefan Richter | 35bdddb | 2006-01-31 00:13:33 -0500 | [diff] [blame] | 1370 | 	scsi_id->logout_orb->status_fifo_hi = | 
 | 1371 | 		ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id); | 
 | 1372 | 	scsi_id->logout_orb->status_fifo_lo = | 
 | 1373 | 		ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1374 |  | 
 | 1375 | 	/* | 
 | 1376 | 	 * Byte swap ORB if necessary | 
 | 1377 | 	 */ | 
 | 1378 | 	sbp2util_cpu_to_be32_buffer(scsi_id->logout_orb, sizeof(struct sbp2_logout_orb)); | 
 | 1379 |  | 
 | 1380 | 	sbp2util_packet_dump(scsi_id->logout_orb, sizeof(struct sbp2_logout_orb), | 
 | 1381 | 			     "sbp2 logout orb", scsi_id->logout_orb_dma); | 
 | 1382 |  | 
 | 1383 | 	/* | 
 | 1384 | 	 * Ok, let's write to the target's management agent register | 
 | 1385 | 	 */ | 
 | 1386 | 	data[0] = ORB_SET_NODE_ID(hi->host->node_id); | 
 | 1387 | 	data[1] = scsi_id->logout_orb_dma; | 
 | 1388 | 	sbp2util_cpu_to_be32_buffer(data, 8); | 
 | 1389 |  | 
 | 1390 | 	atomic_set(&scsi_id->sbp2_login_complete, 0); | 
 | 1391 |  | 
 | 1392 | 	error = hpsb_node_write(scsi_id->ne, | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1393 | 				scsi_id->sbp2_management_agent_addr, data, 8); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1394 | 	if (error) | 
 | 1395 | 		return error; | 
 | 1396 |  | 
 | 1397 | 	/* Wait for device to logout...1 second. */ | 
 | 1398 | 	if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, HZ)) | 
 | 1399 | 		return -EIO; | 
 | 1400 |  | 
 | 1401 | 	SBP2_INFO("Logged out of SBP-2 device"); | 
 | 1402 |  | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1403 | 	return 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1404 |  | 
 | 1405 | } | 
 | 1406 |  | 
 | 1407 | /* | 
 | 1408 |  * This function is called in order to reconnect to a particular SBP-2 | 
 | 1409 |  * device, after a bus reset. | 
 | 1410 |  */ | 
 | 1411 | static int sbp2_reconnect_device(struct scsi_id_instance_data *scsi_id) | 
 | 1412 | { | 
 | 1413 | 	struct sbp2scsi_host_info *hi = scsi_id->hi; | 
 | 1414 | 	quadlet_t data[2]; | 
 | 1415 | 	int error; | 
 | 1416 |  | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 1417 | 	SBP2_DEBUG_ENTER(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1418 |  | 
 | 1419 | 	/* | 
 | 1420 | 	 * Set-up reconnect ORB | 
 | 1421 | 	 */ | 
 | 1422 | 	scsi_id->reconnect_orb->reserved1 = 0x0; | 
 | 1423 | 	scsi_id->reconnect_orb->reserved2 = 0x0; | 
 | 1424 | 	scsi_id->reconnect_orb->reserved3 = 0x0; | 
 | 1425 | 	scsi_id->reconnect_orb->reserved4 = 0x0; | 
 | 1426 |  | 
 | 1427 | 	scsi_id->reconnect_orb->login_ID_misc = ORB_SET_FUNCTION(SBP2_RECONNECT_REQUEST); | 
 | 1428 | 	scsi_id->reconnect_orb->login_ID_misc |= | 
 | 1429 | 		ORB_SET_LOGIN_ID(scsi_id->login_response->length_login_ID); | 
 | 1430 |  | 
 | 1431 | 	/* Notify us when complete */ | 
 | 1432 | 	scsi_id->reconnect_orb->login_ID_misc |= ORB_SET_NOTIFY(1); | 
 | 1433 |  | 
 | 1434 | 	scsi_id->reconnect_orb->reserved5 = 0x0; | 
| Stefan Richter | 35bdddb | 2006-01-31 00:13:33 -0500 | [diff] [blame] | 1435 | 	scsi_id->reconnect_orb->status_fifo_hi = | 
 | 1436 | 		ORB_SET_STATUS_FIFO_HI(scsi_id->status_fifo_addr, hi->host->node_id); | 
 | 1437 | 	scsi_id->reconnect_orb->status_fifo_lo = | 
 | 1438 | 		ORB_SET_STATUS_FIFO_LO(scsi_id->status_fifo_addr); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1439 |  | 
 | 1440 | 	/* | 
 | 1441 | 	 * Byte swap ORB if necessary | 
 | 1442 | 	 */ | 
 | 1443 | 	sbp2util_cpu_to_be32_buffer(scsi_id->reconnect_orb, sizeof(struct sbp2_reconnect_orb)); | 
 | 1444 |  | 
 | 1445 | 	sbp2util_packet_dump(scsi_id->reconnect_orb, sizeof(struct sbp2_reconnect_orb), | 
 | 1446 | 			     "sbp2 reconnect orb", scsi_id->reconnect_orb_dma); | 
 | 1447 |  | 
 | 1448 | 	/* | 
 | 1449 | 	 * Initialize status fifo | 
 | 1450 | 	 */ | 
 | 1451 | 	memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block)); | 
 | 1452 |  | 
 | 1453 | 	/* | 
 | 1454 | 	 * Ok, let's write to the target's management agent register | 
 | 1455 | 	 */ | 
 | 1456 | 	data[0] = ORB_SET_NODE_ID(hi->host->node_id); | 
 | 1457 | 	data[1] = scsi_id->reconnect_orb_dma; | 
 | 1458 | 	sbp2util_cpu_to_be32_buffer(data, 8); | 
 | 1459 |  | 
 | 1460 | 	atomic_set(&scsi_id->sbp2_login_complete, 0); | 
 | 1461 |  | 
 | 1462 | 	error = hpsb_node_write(scsi_id->ne, | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1463 | 				scsi_id->sbp2_management_agent_addr, data, 8); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1464 | 	if (error) | 
 | 1465 | 		return error; | 
 | 1466 |  | 
 | 1467 | 	/* | 
 | 1468 | 	 * Wait for reconnect status (up to 1 second)... | 
 | 1469 | 	 */ | 
 | 1470 | 	if (sbp2util_down_timeout(&scsi_id->sbp2_login_complete, HZ)) { | 
 | 1471 | 		SBP2_ERR("Error reconnecting to SBP-2 device - reconnect timed-out"); | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1472 | 		return -EIO; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1473 | 	} | 
 | 1474 |  | 
 | 1475 | 	/* | 
 | 1476 | 	 * Sanity. Make sure status returned matches reconnect orb. | 
 | 1477 | 	 */ | 
 | 1478 | 	if (scsi_id->status_block.ORB_offset_lo != scsi_id->reconnect_orb_dma) { | 
 | 1479 | 		SBP2_ERR("Error reconnecting to SBP-2 device - reconnect timed-out"); | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1480 | 		return -EIO; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1481 | 	} | 
 | 1482 |  | 
 | 1483 | 	/* | 
 | 1484 | 	 * Check status | 
 | 1485 | 	 */ | 
 | 1486 | 	if (STATUS_GET_RESP(scsi_id->status_block.ORB_offset_hi_misc) || | 
 | 1487 | 	    STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc) || | 
 | 1488 | 	    STATUS_GET_SBP_STATUS(scsi_id->status_block.ORB_offset_hi_misc)) { | 
 | 1489 |  | 
 | 1490 | 		SBP2_ERR("Error reconnecting to SBP-2 device - reconnect failed"); | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1491 | 		return -EIO; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1492 | 	} | 
 | 1493 |  | 
 | 1494 | 	HPSB_DEBUG("Reconnected to SBP-2 device"); | 
 | 1495 |  | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1496 | 	return 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1497 |  | 
 | 1498 | } | 
 | 1499 |  | 
 | 1500 | /* | 
 | 1501 |  * This function is called in order to set the busy timeout (number of | 
 | 1502 |  * retries to attempt) on the sbp2 device. | 
 | 1503 |  */ | 
 | 1504 | static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id) | 
 | 1505 | { | 
 | 1506 | 	quadlet_t data; | 
 | 1507 |  | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 1508 | 	SBP2_DEBUG_ENTER(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1509 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1510 | 	data = cpu_to_be32(SBP2_BUSY_TIMEOUT_VALUE); | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 1511 | 	if (hpsb_node_write(scsi_id->ne, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4)) | 
 | 1512 | 		SBP2_ERR("%s error", __FUNCTION__); | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1513 | 	return 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1514 | } | 
 | 1515 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1516 | /* | 
 | 1517 |  * This function is called to parse sbp2 device's config rom unit | 
 | 1518 |  * directory. Used to determine things like sbp2 management agent offset, | 
 | 1519 |  * and command set used (SCSI or RBC). | 
 | 1520 |  */ | 
 | 1521 | static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id, | 
 | 1522 | 				      struct unit_directory *ud) | 
 | 1523 | { | 
 | 1524 | 	struct csr1212_keyval *kv; | 
 | 1525 | 	struct csr1212_dentry *dentry; | 
 | 1526 | 	u64 management_agent_addr; | 
 | 1527 | 	u32 command_set_spec_id, command_set, unit_characteristics, | 
| Stefan Richter | 24d3bf8 | 2006-05-15 22:04:59 +0200 | [diff] [blame] | 1528 | 	    firmware_revision; | 
 | 1529 | 	unsigned workarounds; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1530 | 	int i; | 
 | 1531 |  | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 1532 | 	SBP2_DEBUG_ENTER(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1533 |  | 
 | 1534 | 	management_agent_addr = 0x0; | 
 | 1535 | 	command_set_spec_id = 0x0; | 
 | 1536 | 	command_set = 0x0; | 
 | 1537 | 	unit_characteristics = 0x0; | 
 | 1538 | 	firmware_revision = 0x0; | 
 | 1539 |  | 
 | 1540 | 	/* Handle different fields in the unit directory, based on keys */ | 
 | 1541 | 	csr1212_for_each_dir_entry(ud->ne->csr, kv, ud->ud_kv, dentry) { | 
 | 1542 | 		switch (kv->key.id) { | 
 | 1543 | 		case CSR1212_KV_ID_DEPENDENT_INFO: | 
 | 1544 | 			if (kv->key.type == CSR1212_KV_TYPE_CSR_OFFSET) { | 
 | 1545 | 				/* Save off the management agent address */ | 
 | 1546 | 				management_agent_addr = | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1547 | 				    CSR1212_REGISTER_SPACE_BASE + | 
 | 1548 | 				    (kv->value.csr_offset << 2); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1549 |  | 
 | 1550 | 				SBP2_DEBUG("sbp2_management_agent_addr = %x", | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1551 | 					   (unsigned int)management_agent_addr); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1552 | 			} else if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) { | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1553 | 				scsi_id->sbp2_lun = | 
 | 1554 | 				    ORB_SET_LUN(kv->value.immediate); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1555 | 			} | 
 | 1556 | 			break; | 
 | 1557 |  | 
 | 1558 | 		case SBP2_COMMAND_SET_SPEC_ID_KEY: | 
 | 1559 | 			/* Command spec organization */ | 
 | 1560 | 			command_set_spec_id = kv->value.immediate; | 
 | 1561 | 			SBP2_DEBUG("sbp2_command_set_spec_id = %x", | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1562 | 				   (unsigned int)command_set_spec_id); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1563 | 			break; | 
 | 1564 |  | 
 | 1565 | 		case SBP2_COMMAND_SET_KEY: | 
 | 1566 | 			/* Command set used by sbp2 device */ | 
 | 1567 | 			command_set = kv->value.immediate; | 
 | 1568 | 			SBP2_DEBUG("sbp2_command_set = %x", | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1569 | 				   (unsigned int)command_set); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1570 | 			break; | 
 | 1571 |  | 
 | 1572 | 		case SBP2_UNIT_CHARACTERISTICS_KEY: | 
 | 1573 | 			/* | 
 | 1574 | 			 * Unit characterisitcs (orb related stuff | 
 | 1575 | 			 * that I'm not yet paying attention to) | 
 | 1576 | 			 */ | 
 | 1577 | 			unit_characteristics = kv->value.immediate; | 
 | 1578 | 			SBP2_DEBUG("sbp2_unit_characteristics = %x", | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1579 | 				   (unsigned int)unit_characteristics); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1580 | 			break; | 
 | 1581 |  | 
 | 1582 | 		case SBP2_FIRMWARE_REVISION_KEY: | 
 | 1583 | 			/* Firmware revision */ | 
 | 1584 | 			firmware_revision = kv->value.immediate; | 
| Stefan Richter | 24d3bf8 | 2006-05-15 22:04:59 +0200 | [diff] [blame] | 1585 | 			SBP2_DEBUG("sbp2_firmware_revision = %x", | 
 | 1586 | 				   (unsigned int)firmware_revision); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1587 | 			break; | 
 | 1588 |  | 
 | 1589 | 		default: | 
 | 1590 | 			break; | 
 | 1591 | 		} | 
 | 1592 | 	} | 
 | 1593 |  | 
| Stefan Richter | 24d3bf8 | 2006-05-15 22:04:59 +0200 | [diff] [blame] | 1594 | 	workarounds = sbp2_default_workarounds; | 
 | 1595 | 	if (force_inquiry_hack) { | 
 | 1596 | 		SBP2_WARN("force_inquiry_hack is deprecated. " | 
 | 1597 | 			  "Use parameter 'workarounds' instead."); | 
 | 1598 | 		workarounds |= SBP2_WORKAROUND_INQUIRY_36; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1599 | 	} | 
 | 1600 |  | 
| Stefan Richter | 679c0cd | 2006-05-15 22:08:09 +0200 | [diff] [blame] | 1601 | 	if (!(workarounds & SBP2_WORKAROUND_OVERRIDE)) | 
 | 1602 | 		for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) { | 
 | 1603 | 			if (sbp2_workarounds_table[i].firmware_revision && | 
 | 1604 | 			    sbp2_workarounds_table[i].firmware_revision != | 
 | 1605 | 			    (firmware_revision & 0xffff00)) | 
 | 1606 | 				continue; | 
 | 1607 | 			if (sbp2_workarounds_table[i].model_id && | 
 | 1608 | 			    sbp2_workarounds_table[i].model_id != ud->model_id) | 
 | 1609 | 				continue; | 
 | 1610 | 			workarounds |= sbp2_workarounds_table[i].workarounds; | 
 | 1611 | 			break; | 
 | 1612 | 		} | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1613 |  | 
| Stefan Richter | 24d3bf8 | 2006-05-15 22:04:59 +0200 | [diff] [blame] | 1614 | 	if (workarounds) | 
| Stefan Richter | e9a1c52 | 2006-05-15 22:06:37 +0200 | [diff] [blame] | 1615 | 		SBP2_INFO("Workarounds for node " NODE_BUS_FMT ": 0x%x " | 
 | 1616 | 			  "(firmware_revision 0x%06x, vendor_id 0x%06x," | 
 | 1617 | 			  " model_id 0x%06x)", | 
| Stefan Richter | 24d3bf8 | 2006-05-15 22:04:59 +0200 | [diff] [blame] | 1618 | 			  NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid), | 
| Stefan Richter | e9a1c52 | 2006-05-15 22:06:37 +0200 | [diff] [blame] | 1619 | 			  workarounds, firmware_revision, | 
 | 1620 | 			  ud->vendor_id ? ud->vendor_id : ud->ne->vendor_id, | 
 | 1621 | 			  ud->model_id); | 
| Stefan Richter | 24d3bf8 | 2006-05-15 22:04:59 +0200 | [diff] [blame] | 1622 |  | 
 | 1623 | 	/* We would need one SCSI host template for each target to adjust | 
 | 1624 | 	 * max_sectors on the fly, therefore warn only. */ | 
 | 1625 | 	if (workarounds & SBP2_WORKAROUND_128K_MAX_TRANS && | 
 | 1626 | 	    (max_sectors * 512) > (128 * 1024)) | 
 | 1627 | 		SBP2_WARN("Node " NODE_BUS_FMT ": Bridge only supports 128KB " | 
 | 1628 | 			  "max transfer size. WARNING: Current max_sectors " | 
 | 1629 | 			  "setting is larger than 128KB (%d sectors)", | 
 | 1630 | 			  NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid), | 
 | 1631 | 			  max_sectors); | 
 | 1632 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1633 | 	/* If this is a logical unit directory entry, process the parent | 
 | 1634 | 	 * to get the values. */ | 
 | 1635 | 	if (ud->flags & UNIT_DIRECTORY_LUN_DIRECTORY) { | 
 | 1636 | 		struct unit_directory *parent_ud = | 
 | 1637 | 			container_of(ud->device.parent, struct unit_directory, device); | 
 | 1638 | 		sbp2_parse_unit_directory(scsi_id, parent_ud); | 
 | 1639 | 	} else { | 
 | 1640 | 		scsi_id->sbp2_management_agent_addr = management_agent_addr; | 
 | 1641 | 		scsi_id->sbp2_command_set_spec_id = command_set_spec_id; | 
 | 1642 | 		scsi_id->sbp2_command_set = command_set; | 
 | 1643 | 		scsi_id->sbp2_unit_characteristics = unit_characteristics; | 
 | 1644 | 		scsi_id->sbp2_firmware_revision = firmware_revision; | 
 | 1645 | 		scsi_id->workarounds = workarounds; | 
 | 1646 | 		if (ud->flags & UNIT_DIRECTORY_HAS_LUN) | 
| Ben Collins | e309fc6 | 2005-11-07 06:31:34 -0500 | [diff] [blame] | 1647 | 			scsi_id->sbp2_lun = ORB_SET_LUN(ud->lun); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1648 | 	} | 
 | 1649 | } | 
 | 1650 |  | 
| Ben Collins | fd23ade | 2006-06-12 18:14:14 -0400 | [diff] [blame] | 1651 | #define SBP2_PAYLOAD_TO_BYTES(p) (1 << ((p) + 2)) | 
 | 1652 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1653 | /* | 
 | 1654 |  * This function is called in order to determine the max speed and packet | 
 | 1655 |  * size we can use in our ORBs. Note, that we (the driver and host) only | 
 | 1656 |  * initiate the transaction. The SBP-2 device actually transfers the data | 
 | 1657 |  * (by reading from the DMA area we tell it). This means that the SBP-2 | 
 | 1658 |  * device decides the actual maximum data it can transfer. We just tell it | 
 | 1659 |  * the speed that it needs to use, and the max_rec the host supports, and | 
 | 1660 |  * it takes care of the rest. | 
 | 1661 |  */ | 
 | 1662 | static int sbp2_max_speed_and_size(struct scsi_id_instance_data *scsi_id) | 
 | 1663 | { | 
 | 1664 | 	struct sbp2scsi_host_info *hi = scsi_id->hi; | 
| Ben Collins | fd23ade | 2006-06-12 18:14:14 -0400 | [diff] [blame] | 1665 | 	u8 payload; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1666 |  | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 1667 | 	SBP2_DEBUG_ENTER(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1668 |  | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1669 | 	scsi_id->speed_code = | 
| Ben Collins | 647dcb5 | 2006-06-12 18:12:37 -0400 | [diff] [blame] | 1670 | 	    hi->host->speed[NODEID_TO_NODE(scsi_id->ne->nodeid)]; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1671 |  | 
 | 1672 | 	/* Bump down our speed if the user requested it */ | 
 | 1673 | 	if (scsi_id->speed_code > max_speed) { | 
 | 1674 | 		scsi_id->speed_code = max_speed; | 
 | 1675 | 		SBP2_ERR("Forcing SBP-2 max speed down to %s", | 
 | 1676 | 			 hpsb_speedto_str[scsi_id->speed_code]); | 
 | 1677 | 	} | 
 | 1678 |  | 
 | 1679 | 	/* Payload size is the lesser of what our speed supports and what | 
 | 1680 | 	 * our host supports.  */ | 
| Ben Collins | fd23ade | 2006-06-12 18:14:14 -0400 | [diff] [blame] | 1681 | 	payload = min(sbp2_speedto_max_payload[scsi_id->speed_code], | 
 | 1682 | 		      (u8) (hi->host->csr.max_rec - 1)); | 
 | 1683 |  | 
 | 1684 | 	/* If physical DMA is off, work around limitation in ohci1394: | 
 | 1685 | 	 * packet size must not exceed PAGE_SIZE */ | 
 | 1686 | 	if (scsi_id->ne->host->low_addr_space < (1ULL << 32)) | 
 | 1687 | 		while (SBP2_PAYLOAD_TO_BYTES(payload) + 24 > PAGE_SIZE && | 
 | 1688 | 		       payload) | 
 | 1689 | 			payload--; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1690 |  | 
 | 1691 | 	HPSB_DEBUG("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [%u]", | 
 | 1692 | 		   NODE_BUS_ARGS(hi->host, scsi_id->ne->nodeid), | 
 | 1693 | 		   hpsb_speedto_str[scsi_id->speed_code], | 
| Ben Collins | fd23ade | 2006-06-12 18:14:14 -0400 | [diff] [blame] | 1694 | 		   SBP2_PAYLOAD_TO_BYTES(payload)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1695 |  | 
| Ben Collins | fd23ade | 2006-06-12 18:14:14 -0400 | [diff] [blame] | 1696 | 	scsi_id->max_payload_size = payload; | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1697 | 	return 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1698 | } | 
 | 1699 |  | 
 | 1700 | /* | 
 | 1701 |  * This function is called in order to perform a SBP-2 agent reset. | 
 | 1702 |  */ | 
 | 1703 | static int sbp2_agent_reset(struct scsi_id_instance_data *scsi_id, int wait) | 
 | 1704 | { | 
 | 1705 | 	quadlet_t data; | 
 | 1706 | 	u64 addr; | 
 | 1707 | 	int retval; | 
 | 1708 |  | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 1709 | 	SBP2_DEBUG_ENTER(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1710 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1711 | 	data = ntohl(SBP2_AGENT_RESET_DATA); | 
 | 1712 | 	addr = scsi_id->sbp2_command_block_agent_addr + SBP2_AGENT_RESET_OFFSET; | 
 | 1713 |  | 
 | 1714 | 	if (wait) | 
 | 1715 | 		retval = hpsb_node_write(scsi_id->ne, addr, &data, 4); | 
 | 1716 | 	else | 
 | 1717 | 		retval = sbp2util_node_write_no_wait(scsi_id->ne, addr, &data, 4); | 
 | 1718 |  | 
 | 1719 | 	if (retval < 0) { | 
 | 1720 | 		SBP2_ERR("hpsb_node_write failed.\n"); | 
 | 1721 | 		return -EIO; | 
 | 1722 | 	} | 
 | 1723 |  | 
 | 1724 | 	/* | 
 | 1725 | 	 * Need to make sure orb pointer is written on next command | 
 | 1726 | 	 */ | 
 | 1727 | 	scsi_id->last_orb = NULL; | 
 | 1728 |  | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1729 | 	return 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1730 | } | 
 | 1731 |  | 
| Stefan Richter | cf8d2c0 | 2005-12-13 11:05:03 -0500 | [diff] [blame] | 1732 | static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb, | 
 | 1733 | 				     struct sbp2scsi_host_info *hi, | 
 | 1734 | 				     struct sbp2_command_info *command, | 
 | 1735 | 				     unsigned int scsi_use_sg, | 
 | 1736 | 				     struct scatterlist *sgpnt, | 
 | 1737 | 				     u32 orb_direction, | 
 | 1738 | 				     enum dma_data_direction dma_dir) | 
 | 1739 | { | 
 | 1740 | 	command->dma_dir = dma_dir; | 
 | 1741 | 	orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id); | 
 | 1742 | 	orb->misc |= ORB_SET_DIRECTION(orb_direction); | 
 | 1743 |  | 
 | 1744 | 	/* Special case if only one element (and less than 64KB in size) */ | 
 | 1745 | 	if ((scsi_use_sg == 1) && | 
 | 1746 | 	    (sgpnt[0].length <= SBP2_MAX_SG_ELEMENT_LENGTH)) { | 
 | 1747 |  | 
 | 1748 | 		SBP2_DEBUG("Only one s/g element"); | 
 | 1749 | 		command->dma_size = sgpnt[0].length; | 
 | 1750 | 		command->dma_type = CMD_DMA_PAGE; | 
 | 1751 | 		command->cmd_dma = pci_map_page(hi->host->pdev, | 
 | 1752 | 						sgpnt[0].page, | 
 | 1753 | 						sgpnt[0].offset, | 
 | 1754 | 						command->dma_size, | 
 | 1755 | 						command->dma_dir); | 
 | 1756 | 		SBP2_DMA_ALLOC("single page scatter element"); | 
 | 1757 |  | 
 | 1758 | 		orb->data_descriptor_lo = command->cmd_dma; | 
 | 1759 | 		orb->misc |= ORB_SET_DATA_SIZE(command->dma_size); | 
 | 1760 |  | 
 | 1761 | 	} else { | 
 | 1762 | 		struct sbp2_unrestricted_page_table *sg_element = | 
 | 1763 | 					&command->scatter_gather_element[0]; | 
 | 1764 | 		u32 sg_count, sg_len; | 
 | 1765 | 		dma_addr_t sg_addr; | 
 | 1766 | 		int i, count = pci_map_sg(hi->host->pdev, sgpnt, scsi_use_sg, | 
 | 1767 | 					  dma_dir); | 
 | 1768 |  | 
 | 1769 | 		SBP2_DMA_ALLOC("scatter list"); | 
 | 1770 |  | 
 | 1771 | 		command->dma_size = scsi_use_sg; | 
 | 1772 | 		command->sge_buffer = sgpnt; | 
 | 1773 |  | 
 | 1774 | 		/* use page tables (s/g) */ | 
 | 1775 | 		orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1); | 
 | 1776 | 		orb->data_descriptor_lo = command->sge_dma; | 
 | 1777 |  | 
 | 1778 | 		/* | 
 | 1779 | 		 * Loop through and fill out our sbp-2 page tables | 
 | 1780 | 		 * (and split up anything too large) | 
 | 1781 | 		 */ | 
 | 1782 | 		for (i = 0, sg_count = 0 ; i < count; i++, sgpnt++) { | 
 | 1783 | 			sg_len = sg_dma_len(sgpnt); | 
 | 1784 | 			sg_addr = sg_dma_address(sgpnt); | 
 | 1785 | 			while (sg_len) { | 
 | 1786 | 				sg_element[sg_count].segment_base_lo = sg_addr; | 
 | 1787 | 				if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) { | 
 | 1788 | 					sg_element[sg_count].length_segment_base_hi = | 
 | 1789 | 						PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH); | 
 | 1790 | 					sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH; | 
 | 1791 | 					sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH; | 
 | 1792 | 				} else { | 
 | 1793 | 					sg_element[sg_count].length_segment_base_hi = | 
 | 1794 | 						PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len); | 
 | 1795 | 					sg_len = 0; | 
 | 1796 | 				} | 
 | 1797 | 				sg_count++; | 
 | 1798 | 			} | 
 | 1799 | 		} | 
 | 1800 |  | 
 | 1801 | 		/* Number of page table (s/g) elements */ | 
 | 1802 | 		orb->misc |= ORB_SET_DATA_SIZE(sg_count); | 
 | 1803 |  | 
 | 1804 | 		sbp2util_packet_dump(sg_element, | 
 | 1805 | 				     (sizeof(struct sbp2_unrestricted_page_table)) * sg_count, | 
 | 1806 | 				     "sbp2 s/g list", command->sge_dma); | 
 | 1807 |  | 
 | 1808 | 		/* Byte swap page tables if necessary */ | 
 | 1809 | 		sbp2util_cpu_to_be32_buffer(sg_element, | 
 | 1810 | 					    (sizeof(struct sbp2_unrestricted_page_table)) * | 
 | 1811 | 					    sg_count); | 
 | 1812 | 	} | 
 | 1813 | } | 
 | 1814 |  | 
 | 1815 | static void sbp2_prep_command_orb_no_sg(struct sbp2_command_orb *orb, | 
 | 1816 | 					struct sbp2scsi_host_info *hi, | 
 | 1817 | 					struct sbp2_command_info *command, | 
 | 1818 | 					struct scatterlist *sgpnt, | 
 | 1819 | 					u32 orb_direction, | 
 | 1820 | 					unsigned int scsi_request_bufflen, | 
 | 1821 | 					void *scsi_request_buffer, | 
 | 1822 | 					enum dma_data_direction dma_dir) | 
 | 1823 | { | 
 | 1824 | 	command->dma_dir = dma_dir; | 
 | 1825 | 	command->dma_size = scsi_request_bufflen; | 
 | 1826 | 	command->dma_type = CMD_DMA_SINGLE; | 
 | 1827 | 	command->cmd_dma = pci_map_single(hi->host->pdev, scsi_request_buffer, | 
 | 1828 | 					  command->dma_size, command->dma_dir); | 
 | 1829 | 	orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id); | 
 | 1830 | 	orb->misc |= ORB_SET_DIRECTION(orb_direction); | 
 | 1831 |  | 
 | 1832 | 	SBP2_DMA_ALLOC("single bulk"); | 
 | 1833 |  | 
 | 1834 | 	/* | 
 | 1835 | 	 * Handle case where we get a command w/o s/g enabled (but | 
 | 1836 | 	 * check for transfers larger than 64K) | 
 | 1837 | 	 */ | 
 | 1838 | 	if (scsi_request_bufflen <= SBP2_MAX_SG_ELEMENT_LENGTH) { | 
 | 1839 |  | 
 | 1840 | 		orb->data_descriptor_lo = command->cmd_dma; | 
 | 1841 | 		orb->misc |= ORB_SET_DATA_SIZE(scsi_request_bufflen); | 
 | 1842 |  | 
 | 1843 | 	} else { | 
 | 1844 | 		struct sbp2_unrestricted_page_table *sg_element = | 
 | 1845 | 			&command->scatter_gather_element[0]; | 
 | 1846 | 		u32 sg_count, sg_len; | 
 | 1847 | 		dma_addr_t sg_addr; | 
 | 1848 |  | 
 | 1849 | 		/* | 
 | 1850 | 		 * Need to turn this into page tables, since the | 
 | 1851 | 		 * buffer is too large. | 
 | 1852 | 		 */ | 
 | 1853 | 		orb->data_descriptor_lo = command->sge_dma; | 
 | 1854 |  | 
 | 1855 | 		/* Use page tables (s/g) */ | 
 | 1856 | 		orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1); | 
 | 1857 |  | 
 | 1858 | 		/* | 
 | 1859 | 		 * fill out our sbp-2 page tables (and split up | 
 | 1860 | 		 * the large buffer) | 
 | 1861 | 		 */ | 
 | 1862 | 		sg_count = 0; | 
 | 1863 | 		sg_len = scsi_request_bufflen; | 
 | 1864 | 		sg_addr = command->cmd_dma; | 
 | 1865 | 		while (sg_len) { | 
 | 1866 | 			sg_element[sg_count].segment_base_lo = sg_addr; | 
 | 1867 | 			if (sg_len > SBP2_MAX_SG_ELEMENT_LENGTH) { | 
 | 1868 | 				sg_element[sg_count].length_segment_base_hi = | 
 | 1869 | 					PAGE_TABLE_SET_SEGMENT_LENGTH(SBP2_MAX_SG_ELEMENT_LENGTH); | 
 | 1870 | 				sg_addr += SBP2_MAX_SG_ELEMENT_LENGTH; | 
 | 1871 | 				sg_len -= SBP2_MAX_SG_ELEMENT_LENGTH; | 
 | 1872 | 			} else { | 
 | 1873 | 				sg_element[sg_count].length_segment_base_hi = | 
 | 1874 | 					PAGE_TABLE_SET_SEGMENT_LENGTH(sg_len); | 
 | 1875 | 				sg_len = 0; | 
 | 1876 | 			} | 
 | 1877 | 			sg_count++; | 
 | 1878 | 		} | 
 | 1879 |  | 
 | 1880 | 		/* Number of page table (s/g) elements */ | 
 | 1881 | 		orb->misc |= ORB_SET_DATA_SIZE(sg_count); | 
 | 1882 |  | 
 | 1883 | 		sbp2util_packet_dump(sg_element, | 
 | 1884 | 				     (sizeof(struct sbp2_unrestricted_page_table)) * sg_count, | 
 | 1885 | 				     "sbp2 s/g list", command->sge_dma); | 
 | 1886 |  | 
 | 1887 | 		/* Byte swap page tables if necessary */ | 
 | 1888 | 		sbp2util_cpu_to_be32_buffer(sg_element, | 
 | 1889 | 					    (sizeof(struct sbp2_unrestricted_page_table)) * | 
 | 1890 | 					     sg_count); | 
 | 1891 | 	} | 
 | 1892 | } | 
 | 1893 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1894 | /* | 
 | 1895 |  * This function is called to create the actual command orb and s/g list | 
 | 1896 |  * out of the scsi command itself. | 
 | 1897 |  */ | 
| Stefan Richter | cf8d2c0 | 2005-12-13 11:05:03 -0500 | [diff] [blame] | 1898 | static void sbp2_create_command_orb(struct scsi_id_instance_data *scsi_id, | 
 | 1899 | 				    struct sbp2_command_info *command, | 
 | 1900 | 				    unchar *scsi_cmd, | 
 | 1901 | 				    unsigned int scsi_use_sg, | 
 | 1902 | 				    unsigned int scsi_request_bufflen, | 
 | 1903 | 				    void *scsi_request_buffer, | 
 | 1904 | 				    enum dma_data_direction dma_dir) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1905 | { | 
 | 1906 | 	struct sbp2scsi_host_info *hi = scsi_id->hi; | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1907 | 	struct scatterlist *sgpnt = (struct scatterlist *)scsi_request_buffer; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1908 | 	struct sbp2_command_orb *command_orb = &command->command_orb; | 
| Stefan Richter | cf8d2c0 | 2005-12-13 11:05:03 -0500 | [diff] [blame] | 1909 | 	u32 orb_direction; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1910 |  | 
 | 1911 | 	/* | 
 | 1912 | 	 * Set-up our command ORB.. | 
 | 1913 | 	 * | 
 | 1914 | 	 * NOTE: We're doing unrestricted page tables (s/g), as this is | 
 | 1915 | 	 * best performance (at least with the devices I have). This means | 
 | 1916 | 	 * that data_size becomes the number of s/g elements, and | 
 | 1917 | 	 * page_size should be zero (for unrestricted). | 
 | 1918 | 	 */ | 
 | 1919 | 	command_orb->next_ORB_hi = ORB_SET_NULL_PTR(1); | 
 | 1920 | 	command_orb->next_ORB_lo = 0x0; | 
 | 1921 | 	command_orb->misc = ORB_SET_MAX_PAYLOAD(scsi_id->max_payload_size); | 
 | 1922 | 	command_orb->misc |= ORB_SET_SPEED(scsi_id->speed_code); | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1923 | 	command_orb->misc |= ORB_SET_NOTIFY(1);	/* Notify us when complete */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1924 |  | 
| Stefan Richter | 43863eb | 2005-12-12 23:03:24 -0500 | [diff] [blame] | 1925 | 	if (dma_dir == DMA_NONE) | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1926 | 		orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER; | 
| Stefan Richter | 43863eb | 2005-12-12 23:03:24 -0500 | [diff] [blame] | 1927 | 	else if (dma_dir == DMA_TO_DEVICE && scsi_request_bufflen) | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1928 | 		orb_direction = ORB_DIRECTION_WRITE_TO_MEDIA; | 
| Stefan Richter | 43863eb | 2005-12-12 23:03:24 -0500 | [diff] [blame] | 1929 | 	else if (dma_dir == DMA_FROM_DEVICE && scsi_request_bufflen) | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1930 | 		orb_direction = ORB_DIRECTION_READ_FROM_MEDIA; | 
| Stefan Richter | 43863eb | 2005-12-12 23:03:24 -0500 | [diff] [blame] | 1931 | 	else { | 
 | 1932 | 		SBP2_WARN("Falling back to DMA_NONE"); | 
 | 1933 | 		orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1934 | 	} | 
 | 1935 |  | 
| Stefan Richter | cf8d2c0 | 2005-12-13 11:05:03 -0500 | [diff] [blame] | 1936 | 	/* Set-up our pagetable stuff */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1937 | 	if (orb_direction == ORB_DIRECTION_NO_DATA_TRANSFER) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1938 | 		SBP2_DEBUG("No data transfer"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1939 | 		command_orb->data_descriptor_hi = 0x0; | 
 | 1940 | 		command_orb->data_descriptor_lo = 0x0; | 
 | 1941 | 		command_orb->misc |= ORB_SET_DIRECTION(1); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1942 | 	} else if (scsi_use_sg) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1943 | 		SBP2_DEBUG("Use scatter/gather"); | 
| Stefan Richter | cf8d2c0 | 2005-12-13 11:05:03 -0500 | [diff] [blame] | 1944 | 		sbp2_prep_command_orb_sg(command_orb, hi, command, scsi_use_sg, | 
 | 1945 | 					 sgpnt, orb_direction, dma_dir); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1946 | 	} else { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1947 | 		SBP2_DEBUG("No scatter/gather"); | 
| Stefan Richter | cf8d2c0 | 2005-12-13 11:05:03 -0500 | [diff] [blame] | 1948 | 		sbp2_prep_command_orb_no_sg(command_orb, hi, command, sgpnt, | 
 | 1949 | 					    orb_direction, scsi_request_bufflen, | 
 | 1950 | 					    scsi_request_buffer, dma_dir); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1951 | 	} | 
 | 1952 |  | 
| Stefan Richter | cf8d2c0 | 2005-12-13 11:05:03 -0500 | [diff] [blame] | 1953 | 	/* Byte swap command ORB if necessary */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1954 | 	sbp2util_cpu_to_be32_buffer(command_orb, sizeof(struct sbp2_command_orb)); | 
 | 1955 |  | 
| Stefan Richter | cf8d2c0 | 2005-12-13 11:05:03 -0500 | [diff] [blame] | 1956 | 	/* Put our scsi command in the command ORB */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1957 | 	memset(command_orb->cdb, 0, 12); | 
 | 1958 | 	memcpy(command_orb->cdb, scsi_cmd, COMMAND_SIZE(*scsi_cmd)); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1959 | } | 
 | 1960 |  | 
 | 1961 | /* | 
 | 1962 |  * This function is called in order to begin a regular SBP-2 command. | 
 | 1963 |  */ | 
 | 1964 | static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id, | 
 | 1965 | 				 struct sbp2_command_info *command) | 
 | 1966 | { | 
 | 1967 | 	struct sbp2scsi_host_info *hi = scsi_id->hi; | 
 | 1968 | 	struct sbp2_command_orb *command_orb = &command->command_orb; | 
 | 1969 | 	struct node_entry *ne = scsi_id->ne; | 
 | 1970 | 	u64 addr; | 
 | 1971 |  | 
 | 1972 | 	outstanding_orb_incr; | 
 | 1973 | 	SBP2_ORB_DEBUG("sending command orb %p, total orbs = %x", | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 1974 | 		       command_orb, global_outstanding_command_orbs); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 1975 |  | 
 | 1976 | 	pci_dma_sync_single_for_device(hi->host->pdev, command->command_orb_dma, | 
 | 1977 | 				       sizeof(struct sbp2_command_orb), | 
 | 1978 | 				       PCI_DMA_BIDIRECTIONAL); | 
 | 1979 | 	pci_dma_sync_single_for_device(hi->host->pdev, command->sge_dma, | 
 | 1980 | 				       sizeof(command->scatter_gather_element), | 
 | 1981 | 				       PCI_DMA_BIDIRECTIONAL); | 
 | 1982 | 	/* | 
 | 1983 | 	 * Check to see if there are any previous orbs to use | 
 | 1984 | 	 */ | 
 | 1985 | 	if (scsi_id->last_orb == NULL) { | 
 | 1986 | 		quadlet_t data[2]; | 
 | 1987 |  | 
 | 1988 | 		/* | 
 | 1989 | 		 * Ok, let's write to the target's management agent register | 
 | 1990 | 		 */ | 
 | 1991 | 		addr = scsi_id->sbp2_command_block_agent_addr + SBP2_ORB_POINTER_OFFSET; | 
 | 1992 | 		data[0] = ORB_SET_NODE_ID(hi->host->node_id); | 
 | 1993 | 		data[1] = command->command_orb_dma; | 
 | 1994 | 		sbp2util_cpu_to_be32_buffer(data, 8); | 
 | 1995 |  | 
 | 1996 | 		SBP2_ORB_DEBUG("write command agent, command orb %p", command_orb); | 
 | 1997 |  | 
 | 1998 | 		if (sbp2util_node_write_no_wait(ne, addr, data, 8) < 0) { | 
 | 1999 | 			SBP2_ERR("sbp2util_node_write_no_wait failed.\n"); | 
 | 2000 | 			return -EIO; | 
 | 2001 | 		} | 
 | 2002 |  | 
 | 2003 | 		SBP2_ORB_DEBUG("write command agent complete"); | 
 | 2004 |  | 
 | 2005 | 		scsi_id->last_orb = command_orb; | 
 | 2006 | 		scsi_id->last_orb_dma = command->command_orb_dma; | 
 | 2007 |  | 
 | 2008 | 	} else { | 
 | 2009 | 		quadlet_t data; | 
 | 2010 |  | 
 | 2011 | 		/* | 
 | 2012 | 		 * We have an orb already sent (maybe or maybe not | 
 | 2013 | 		 * processed) that we can append this orb to. So do so, | 
 | 2014 | 		 * and ring the doorbell. Have to be very careful | 
 | 2015 | 		 * modifying these next orb pointers, as they are accessed | 
 | 2016 | 		 * both by the sbp2 device and us. | 
 | 2017 | 		 */ | 
 | 2018 | 		scsi_id->last_orb->next_ORB_lo = | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2019 | 		    cpu_to_be32(command->command_orb_dma); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2020 | 		/* Tells hardware that this pointer is valid */ | 
 | 2021 | 		scsi_id->last_orb->next_ORB_hi = 0x0; | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2022 | 		pci_dma_sync_single_for_device(hi->host->pdev, | 
 | 2023 | 					       scsi_id->last_orb_dma, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2024 | 					       sizeof(struct sbp2_command_orb), | 
 | 2025 | 					       PCI_DMA_BIDIRECTIONAL); | 
 | 2026 |  | 
 | 2027 | 		/* | 
 | 2028 | 		 * Ring the doorbell | 
 | 2029 | 		 */ | 
 | 2030 | 		data = cpu_to_be32(command->command_orb_dma); | 
 | 2031 | 		addr = scsi_id->sbp2_command_block_agent_addr + SBP2_DOORBELL_OFFSET; | 
 | 2032 |  | 
 | 2033 | 		SBP2_ORB_DEBUG("ring doorbell, command orb %p", command_orb); | 
 | 2034 |  | 
 | 2035 | 		if (sbp2util_node_write_no_wait(ne, addr, &data, 4) < 0) { | 
 | 2036 | 			SBP2_ERR("sbp2util_node_write_no_wait failed"); | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2037 | 			return -EIO; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2038 | 		} | 
 | 2039 |  | 
 | 2040 | 		scsi_id->last_orb = command_orb; | 
 | 2041 | 		scsi_id->last_orb_dma = command->command_orb_dma; | 
 | 2042 |  | 
 | 2043 | 	} | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2044 | 	return 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2045 | } | 
 | 2046 |  | 
 | 2047 | /* | 
 | 2048 |  * This function is called in order to begin a regular SBP-2 command. | 
 | 2049 |  */ | 
 | 2050 | static int sbp2_send_command(struct scsi_id_instance_data *scsi_id, | 
 | 2051 | 			     struct scsi_cmnd *SCpnt, | 
 | 2052 | 			     void (*done)(struct scsi_cmnd *)) | 
 | 2053 | { | 
 | 2054 | 	unchar *cmd = (unchar *) SCpnt->cmnd; | 
 | 2055 | 	unsigned int request_bufflen = SCpnt->request_bufflen; | 
 | 2056 | 	struct sbp2_command_info *command; | 
 | 2057 |  | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 2058 | 	SBP2_DEBUG_ENTER(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2059 | 	SBP2_DEBUG("SCSI transfer size = %x", request_bufflen); | 
 | 2060 | 	SBP2_DEBUG("SCSI s/g elements = %x", (unsigned int)SCpnt->use_sg); | 
 | 2061 |  | 
 | 2062 | 	/* | 
 | 2063 | 	 * Allocate a command orb and s/g structure | 
 | 2064 | 	 */ | 
 | 2065 | 	command = sbp2util_allocate_command_orb(scsi_id, SCpnt, done); | 
 | 2066 | 	if (!command) { | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2067 | 		return -EIO; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2068 | 	} | 
 | 2069 |  | 
 | 2070 | 	/* | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2071 | 	 * Now actually fill in the comamnd orb and sbp2 s/g list | 
 | 2072 | 	 */ | 
 | 2073 | 	sbp2_create_command_orb(scsi_id, command, cmd, SCpnt->use_sg, | 
 | 2074 | 				request_bufflen, SCpnt->request_buffer, | 
 | 2075 | 				SCpnt->sc_data_direction); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2076 |  | 
 | 2077 | 	sbp2util_packet_dump(&command->command_orb, sizeof(struct sbp2_command_orb), | 
 | 2078 | 			     "sbp2 command orb", command->command_orb_dma); | 
 | 2079 |  | 
 | 2080 | 	/* | 
 | 2081 | 	 * Initialize status fifo | 
 | 2082 | 	 */ | 
 | 2083 | 	memset(&scsi_id->status_block, 0, sizeof(struct sbp2_status_block)); | 
 | 2084 |  | 
 | 2085 | 	/* | 
 | 2086 | 	 * Link up the orb, and ring the doorbell if needed | 
 | 2087 | 	 */ | 
 | 2088 | 	sbp2_link_orb_command(scsi_id, command); | 
 | 2089 |  | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2090 | 	return 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2091 | } | 
 | 2092 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2093 | /* | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2094 |  * Translates SBP-2 status into SCSI sense data for check conditions | 
 | 2095 |  */ | 
 | 2096 | static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data) | 
 | 2097 | { | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 2098 | 	SBP2_DEBUG_ENTER(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2099 |  | 
 | 2100 | 	/* | 
 | 2101 | 	 * Ok, it's pretty ugly...   ;-) | 
 | 2102 | 	 */ | 
 | 2103 | 	sense_data[0] = 0x70; | 
 | 2104 | 	sense_data[1] = 0x0; | 
 | 2105 | 	sense_data[2] = sbp2_status[9]; | 
 | 2106 | 	sense_data[3] = sbp2_status[12]; | 
 | 2107 | 	sense_data[4] = sbp2_status[13]; | 
 | 2108 | 	sense_data[5] = sbp2_status[14]; | 
 | 2109 | 	sense_data[6] = sbp2_status[15]; | 
 | 2110 | 	sense_data[7] = 10; | 
 | 2111 | 	sense_data[8] = sbp2_status[16]; | 
 | 2112 | 	sense_data[9] = sbp2_status[17]; | 
 | 2113 | 	sense_data[10] = sbp2_status[18]; | 
 | 2114 | 	sense_data[11] = sbp2_status[19]; | 
 | 2115 | 	sense_data[12] = sbp2_status[10]; | 
 | 2116 | 	sense_data[13] = sbp2_status[11]; | 
 | 2117 | 	sense_data[14] = sbp2_status[20]; | 
 | 2118 | 	sense_data[15] = sbp2_status[21]; | 
 | 2119 |  | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2120 | 	return sbp2_status[8] & 0x3f;	/* return scsi status */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2121 | } | 
 | 2122 |  | 
 | 2123 | /* | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2124 |  * This function deals with status writes from the SBP-2 device | 
 | 2125 |  */ | 
 | 2126 | static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid, int destid, | 
 | 2127 | 				    quadlet_t *data, u64 addr, size_t length, u16 fl) | 
 | 2128 | { | 
 | 2129 | 	struct sbp2scsi_host_info *hi; | 
 | 2130 | 	struct scsi_id_instance_data *scsi_id = NULL, *scsi_id_tmp; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2131 | 	struct scsi_cmnd *SCpnt = NULL; | 
 | 2132 | 	u32 scsi_status = SBP2_SCSI_STATUS_GOOD; | 
 | 2133 | 	struct sbp2_command_info *command; | 
| Jody McIntyre | 7945619 | 2005-11-07 06:29:39 -0500 | [diff] [blame] | 2134 | 	unsigned long flags; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2135 |  | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 2136 | 	SBP2_DEBUG_ENTER(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2137 |  | 
 | 2138 | 	sbp2util_packet_dump(data, length, "sbp2 status write by device", (u32)addr); | 
 | 2139 |  | 
 | 2140 | 	if (!host) { | 
 | 2141 | 		SBP2_ERR("host is NULL - this is bad!"); | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2142 | 		return RCODE_ADDRESS_ERROR; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2143 | 	} | 
 | 2144 |  | 
 | 2145 | 	hi = hpsb_get_hostinfo(&sbp2_highlevel, host); | 
 | 2146 |  | 
 | 2147 | 	if (!hi) { | 
 | 2148 | 		SBP2_ERR("host info is NULL - this is bad!"); | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2149 | 		return RCODE_ADDRESS_ERROR; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2150 | 	} | 
 | 2151 |  | 
 | 2152 | 	/* | 
| Stefan Richter | 35bdddb | 2006-01-31 00:13:33 -0500 | [diff] [blame] | 2153 | 	 * Find our scsi_id structure by looking at the status fifo address | 
 | 2154 | 	 * written to by the sbp2 device. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2155 | 	 */ | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2156 | 	list_for_each_entry(scsi_id_tmp, &hi->scsi_ids, scsi_list) { | 
| Stefan Richter | 35bdddb | 2006-01-31 00:13:33 -0500 | [diff] [blame] | 2157 | 		if (scsi_id_tmp->ne->nodeid == nodeid && | 
 | 2158 | 		    scsi_id_tmp->status_fifo_addr == addr) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2159 | 			scsi_id = scsi_id_tmp; | 
 | 2160 | 			break; | 
 | 2161 | 		} | 
 | 2162 | 	} | 
 | 2163 |  | 
 | 2164 | 	if (!scsi_id) { | 
 | 2165 | 		SBP2_ERR("scsi_id is NULL - device is gone?"); | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2166 | 		return RCODE_ADDRESS_ERROR; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2167 | 	} | 
 | 2168 |  | 
 | 2169 | 	/* | 
 | 2170 | 	 * Put response into scsi_id status fifo... | 
 | 2171 | 	 */ | 
 | 2172 | 	memcpy(&scsi_id->status_block, data, length); | 
 | 2173 |  | 
 | 2174 | 	/* | 
 | 2175 | 	 * Byte swap first two quadlets (8 bytes) of status for processing | 
 | 2176 | 	 */ | 
 | 2177 | 	sbp2util_be32_to_cpu_buffer(&scsi_id->status_block, 8); | 
 | 2178 |  | 
 | 2179 | 	/* | 
 | 2180 | 	 * Handle command ORB status here if necessary. First, need to match status with command. | 
 | 2181 | 	 */ | 
 | 2182 | 	command = sbp2util_find_command_for_orb(scsi_id, scsi_id->status_block.ORB_offset_lo); | 
 | 2183 | 	if (command) { | 
 | 2184 |  | 
 | 2185 | 		SBP2_DEBUG("Found status for command ORB"); | 
 | 2186 | 		pci_dma_sync_single_for_cpu(hi->host->pdev, command->command_orb_dma, | 
 | 2187 | 					    sizeof(struct sbp2_command_orb), | 
 | 2188 | 					    PCI_DMA_BIDIRECTIONAL); | 
 | 2189 | 		pci_dma_sync_single_for_cpu(hi->host->pdev, command->sge_dma, | 
 | 2190 | 					    sizeof(command->scatter_gather_element), | 
 | 2191 | 					    PCI_DMA_BIDIRECTIONAL); | 
 | 2192 |  | 
 | 2193 | 		SBP2_ORB_DEBUG("matched command orb %p", &command->command_orb); | 
 | 2194 | 		outstanding_orb_decr; | 
 | 2195 |  | 
 | 2196 | 		/* | 
 | 2197 | 		 * Matched status with command, now grab scsi command pointers and check status | 
 | 2198 | 		 */ | 
 | 2199 | 		SCpnt = command->Current_SCpnt; | 
| Stefan Richter | 24c7cd0 | 2006-04-01 21:11:41 +0200 | [diff] [blame] | 2200 | 		spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2201 | 		sbp2util_mark_command_completed(scsi_id, command); | 
| Stefan Richter | 24c7cd0 | 2006-04-01 21:11:41 +0200 | [diff] [blame] | 2202 | 		spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2203 |  | 
 | 2204 | 		if (SCpnt) { | 
 | 2205 |  | 
 | 2206 | 			/* | 
 | 2207 | 			 * See if the target stored any scsi status information | 
 | 2208 | 			 */ | 
 | 2209 | 			if (STATUS_GET_LENGTH(scsi_id->status_block.ORB_offset_hi_misc) > 1) { | 
 | 2210 | 				/* | 
 | 2211 | 				 * Translate SBP-2 status to SCSI sense data | 
 | 2212 | 				 */ | 
 | 2213 | 				SBP2_DEBUG("CHECK CONDITION"); | 
 | 2214 | 				scsi_status = sbp2_status_to_sense_data((unchar *)&scsi_id->status_block, SCpnt->sense_buffer); | 
 | 2215 | 			} | 
 | 2216 |  | 
 | 2217 | 			/* | 
 | 2218 | 			 * Check to see if the dead bit is set. If so, we'll have to initiate | 
 | 2219 | 			 * a fetch agent reset. | 
 | 2220 | 			 */ | 
 | 2221 | 			if (STATUS_GET_DEAD_BIT(scsi_id->status_block.ORB_offset_hi_misc)) { | 
 | 2222 |  | 
 | 2223 | 				/* | 
 | 2224 | 				 * Initiate a fetch agent reset. | 
 | 2225 | 				 */ | 
 | 2226 | 				SBP2_DEBUG("Dead bit set - initiating fetch agent reset"); | 
 | 2227 |                                 sbp2_agent_reset(scsi_id, 0); | 
 | 2228 | 			} | 
 | 2229 |  | 
 | 2230 | 			SBP2_ORB_DEBUG("completing command orb %p", &command->command_orb); | 
 | 2231 | 		} | 
 | 2232 |  | 
 | 2233 | 		/* | 
 | 2234 | 		 * Check here to see if there are no commands in-use. If there are none, we can | 
 | 2235 | 		 * null out last orb so that next time around we write directly to the orb pointer... | 
 | 2236 | 		 * Quick start saves one 1394 bus transaction. | 
 | 2237 | 		 */ | 
| Jody McIntyre | 7945619 | 2005-11-07 06:29:39 -0500 | [diff] [blame] | 2238 | 		spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2239 | 		if (list_empty(&scsi_id->sbp2_command_orb_inuse)) { | 
 | 2240 | 			scsi_id->last_orb = NULL; | 
 | 2241 | 		} | 
| Jody McIntyre | 7945619 | 2005-11-07 06:29:39 -0500 | [diff] [blame] | 2242 | 		spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2243 |  | 
 | 2244 | 	} else { | 
 | 2245 |  | 
 | 2246 | 		/* | 
 | 2247 | 		 * It's probably a login/logout/reconnect status. | 
 | 2248 | 		 */ | 
 | 2249 | 		if ((scsi_id->login_orb_dma == scsi_id->status_block.ORB_offset_lo) || | 
 | 2250 | 		    (scsi_id->query_logins_orb_dma == scsi_id->status_block.ORB_offset_lo) || | 
 | 2251 | 		    (scsi_id->reconnect_orb_dma == scsi_id->status_block.ORB_offset_lo) || | 
 | 2252 | 		    (scsi_id->logout_orb_dma == scsi_id->status_block.ORB_offset_lo)) { | 
 | 2253 | 			atomic_set(&scsi_id->sbp2_login_complete, 1); | 
 | 2254 | 		} | 
 | 2255 | 	} | 
 | 2256 |  | 
 | 2257 | 	if (SCpnt) { | 
 | 2258 |  | 
 | 2259 | 		/* Complete the SCSI command. */ | 
 | 2260 | 		SBP2_DEBUG("Completing SCSI command"); | 
 | 2261 | 		sbp2scsi_complete_command(scsi_id, scsi_status, SCpnt, | 
 | 2262 | 					  command->Current_done); | 
 | 2263 | 		SBP2_ORB_DEBUG("command orb completed"); | 
 | 2264 | 	} | 
 | 2265 |  | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2266 | 	return RCODE_COMPLETE; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2267 | } | 
 | 2268 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2269 | /************************************** | 
 | 2270 |  * SCSI interface related section | 
 | 2271 |  **************************************/ | 
 | 2272 |  | 
 | 2273 | /* | 
 | 2274 |  * This routine is the main request entry routine for doing I/O. It is | 
 | 2275 |  * called from the scsi stack directly. | 
 | 2276 |  */ | 
 | 2277 | static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt, | 
 | 2278 | 				 void (*done)(struct scsi_cmnd *)) | 
 | 2279 | { | 
 | 2280 | 	struct scsi_id_instance_data *scsi_id = | 
 | 2281 | 		(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0]; | 
 | 2282 | 	struct sbp2scsi_host_info *hi; | 
| Jody McIntyre | abd559b | 2005-09-30 11:59:06 -0700 | [diff] [blame] | 2283 | 	int result = DID_NO_CONNECT << 16; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2284 |  | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 2285 | 	SBP2_DEBUG_ENTER(); | 
 | 2286 | #if (CONFIG_IEEE1394_SBP2_DEBUG >= 2) || defined(CONFIG_IEEE1394_SBP2_PACKET_DUMP) | 
 | 2287 | 	scsi_print_command(SCpnt); | 
 | 2288 | #endif | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2289 |  | 
| Jody McIntyre | abd559b | 2005-09-30 11:59:06 -0700 | [diff] [blame] | 2290 | 	if (!sbp2util_node_is_available(scsi_id)) | 
 | 2291 | 		goto done; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2292 |  | 
 | 2293 | 	hi = scsi_id->hi; | 
 | 2294 |  | 
 | 2295 | 	if (!hi) { | 
 | 2296 | 		SBP2_ERR("sbp2scsi_host_info is NULL - this is bad!"); | 
| Jody McIntyre | abd559b | 2005-09-30 11:59:06 -0700 | [diff] [blame] | 2297 | 		goto done; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2298 | 	} | 
 | 2299 |  | 
 | 2300 | 	/* | 
 | 2301 | 	 * Until we handle multiple luns, just return selection time-out | 
 | 2302 | 	 * to any IO directed at non-zero LUNs | 
 | 2303 | 	 */ | 
| Jody McIntyre | abd559b | 2005-09-30 11:59:06 -0700 | [diff] [blame] | 2304 | 	if (SCpnt->device->lun) | 
 | 2305 | 		goto done; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2306 |  | 
 | 2307 | 	/* | 
 | 2308 | 	 * Check for request sense command, and handle it here | 
 | 2309 | 	 * (autorequest sense) | 
 | 2310 | 	 */ | 
 | 2311 | 	if (SCpnt->cmnd[0] == REQUEST_SENSE) { | 
 | 2312 | 		SBP2_DEBUG("REQUEST_SENSE"); | 
 | 2313 | 		memcpy(SCpnt->request_buffer, SCpnt->sense_buffer, SCpnt->request_bufflen); | 
 | 2314 | 		memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer)); | 
 | 2315 | 		sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_GOOD, SCpnt, done); | 
| Jody McIntyre | abd559b | 2005-09-30 11:59:06 -0700 | [diff] [blame] | 2316 | 		return 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2317 | 	} | 
 | 2318 |  | 
 | 2319 | 	/* | 
 | 2320 | 	 * Check to see if we are in the middle of a bus reset. | 
 | 2321 | 	 */ | 
 | 2322 | 	if (!hpsb_node_entry_valid(scsi_id->ne)) { | 
 | 2323 | 		SBP2_ERR("Bus reset in progress - rejecting command"); | 
| Jody McIntyre | abd559b | 2005-09-30 11:59:06 -0700 | [diff] [blame] | 2324 | 		result = DID_BUS_BUSY << 16; | 
 | 2325 | 		goto done; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2326 | 	} | 
 | 2327 |  | 
 | 2328 | 	/* | 
| Stefan Richter | 43863eb | 2005-12-12 23:03:24 -0500 | [diff] [blame] | 2329 | 	 * Bidirectional commands are not yet implemented, | 
 | 2330 | 	 * and unknown transfer direction not handled. | 
 | 2331 | 	 */ | 
 | 2332 | 	if (SCpnt->sc_data_direction == DMA_BIDIRECTIONAL) { | 
 | 2333 | 		SBP2_ERR("Cannot handle DMA_BIDIRECTIONAL - rejecting command"); | 
 | 2334 | 		result = DID_ERROR << 16; | 
 | 2335 | 		goto done; | 
 | 2336 | 	} | 
 | 2337 |  | 
 | 2338 | 	/* | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2339 | 	 * Try and send our SCSI command | 
 | 2340 | 	 */ | 
 | 2341 | 	if (sbp2_send_command(scsi_id, SCpnt, done)) { | 
 | 2342 | 		SBP2_ERR("Error sending SCSI command"); | 
 | 2343 | 		sbp2scsi_complete_command(scsi_id, SBP2_SCSI_STATUS_SELECTION_TIMEOUT, | 
 | 2344 | 					  SCpnt, done); | 
 | 2345 | 	} | 
| Jody McIntyre | abd559b | 2005-09-30 11:59:06 -0700 | [diff] [blame] | 2346 | 	return 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2347 |  | 
| Jody McIntyre | abd559b | 2005-09-30 11:59:06 -0700 | [diff] [blame] | 2348 | done: | 
 | 2349 | 	SCpnt->result = result; | 
 | 2350 | 	done(SCpnt); | 
 | 2351 | 	return 0; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2352 | } | 
 | 2353 |  | 
 | 2354 | /* | 
 | 2355 |  * This function is called in order to complete all outstanding SBP-2 | 
 | 2356 |  * commands (in case of resets, etc.). | 
 | 2357 |  */ | 
 | 2358 | static void sbp2scsi_complete_all_commands(struct scsi_id_instance_data *scsi_id, | 
 | 2359 | 					   u32 status) | 
 | 2360 | { | 
 | 2361 | 	struct sbp2scsi_host_info *hi = scsi_id->hi; | 
 | 2362 | 	struct list_head *lh; | 
 | 2363 | 	struct sbp2_command_info *command; | 
| Jody McIntyre | 7945619 | 2005-11-07 06:29:39 -0500 | [diff] [blame] | 2364 | 	unsigned long flags; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2365 |  | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 2366 | 	SBP2_DEBUG_ENTER(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2367 |  | 
| Jody McIntyre | 7945619 | 2005-11-07 06:29:39 -0500 | [diff] [blame] | 2368 | 	spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2369 | 	while (!list_empty(&scsi_id->sbp2_command_orb_inuse)) { | 
 | 2370 | 		SBP2_DEBUG("Found pending command to complete"); | 
 | 2371 | 		lh = scsi_id->sbp2_command_orb_inuse.next; | 
 | 2372 | 		command = list_entry(lh, struct sbp2_command_info, list); | 
 | 2373 | 		pci_dma_sync_single_for_cpu(hi->host->pdev, command->command_orb_dma, | 
 | 2374 | 					    sizeof(struct sbp2_command_orb), | 
 | 2375 | 					    PCI_DMA_BIDIRECTIONAL); | 
 | 2376 | 		pci_dma_sync_single_for_cpu(hi->host->pdev, command->sge_dma, | 
 | 2377 | 					    sizeof(command->scatter_gather_element), | 
 | 2378 | 					    PCI_DMA_BIDIRECTIONAL); | 
 | 2379 | 		sbp2util_mark_command_completed(scsi_id, command); | 
 | 2380 | 		if (command->Current_SCpnt) { | 
 | 2381 | 			command->Current_SCpnt->result = status << 16; | 
 | 2382 | 			command->Current_done(command->Current_SCpnt); | 
 | 2383 | 		} | 
 | 2384 | 	} | 
| Jody McIntyre | 7945619 | 2005-11-07 06:29:39 -0500 | [diff] [blame] | 2385 | 	spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2386 |  | 
 | 2387 | 	return; | 
 | 2388 | } | 
 | 2389 |  | 
 | 2390 | /* | 
 | 2391 |  * This function is called in order to complete a regular SBP-2 command. | 
 | 2392 |  * | 
 | 2393 |  * This can be called in interrupt context. | 
 | 2394 |  */ | 
 | 2395 | static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id, | 
 | 2396 | 				      u32 scsi_status, struct scsi_cmnd *SCpnt, | 
 | 2397 | 				      void (*done)(struct scsi_cmnd *)) | 
 | 2398 | { | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 2399 | 	SBP2_DEBUG_ENTER(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2400 |  | 
 | 2401 | 	/* | 
 | 2402 | 	 * Sanity | 
 | 2403 | 	 */ | 
 | 2404 | 	if (!SCpnt) { | 
 | 2405 | 		SBP2_ERR("SCpnt is NULL"); | 
 | 2406 | 		return; | 
 | 2407 | 	} | 
 | 2408 |  | 
 | 2409 | 	/* | 
 | 2410 | 	 * If a bus reset is in progress and there was an error, don't | 
 | 2411 | 	 * complete the command, just let it get retried at the end of the | 
 | 2412 | 	 * bus reset. | 
 | 2413 | 	 */ | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2414 | 	if (!hpsb_node_entry_valid(scsi_id->ne) | 
 | 2415 | 	    && (scsi_status != SBP2_SCSI_STATUS_GOOD)) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2416 | 		SBP2_ERR("Bus reset in progress - retry command later"); | 
 | 2417 | 		return; | 
 | 2418 | 	} | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2419 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2420 | 	/* | 
 | 2421 | 	 * Switch on scsi status | 
 | 2422 | 	 */ | 
 | 2423 | 	switch (scsi_status) { | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2424 | 	case SBP2_SCSI_STATUS_GOOD: | 
| Stefan Richter | 8f0525f | 2006-03-28 20:03:45 -0500 | [diff] [blame] | 2425 | 		SCpnt->result = DID_OK << 16; | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2426 | 		break; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2427 |  | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2428 | 	case SBP2_SCSI_STATUS_BUSY: | 
 | 2429 | 		SBP2_ERR("SBP2_SCSI_STATUS_BUSY"); | 
 | 2430 | 		SCpnt->result = DID_BUS_BUSY << 16; | 
 | 2431 | 		break; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2432 |  | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2433 | 	case SBP2_SCSI_STATUS_CHECK_CONDITION: | 
 | 2434 | 		SBP2_DEBUG("SBP2_SCSI_STATUS_CHECK_CONDITION"); | 
| Stefan Richter | 8f0525f | 2006-03-28 20:03:45 -0500 | [diff] [blame] | 2435 | 		SCpnt->result = CHECK_CONDITION << 1 | DID_OK << 16; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2436 | #if CONFIG_IEEE1394_SBP2_DEBUG >= 1 | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2437 | 		scsi_print_command(SCpnt); | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 2438 | 		scsi_print_sense(SBP2_DEVICE_NAME, SCpnt); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2439 | #endif | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2440 | 		break; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2441 |  | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2442 | 	case SBP2_SCSI_STATUS_SELECTION_TIMEOUT: | 
 | 2443 | 		SBP2_ERR("SBP2_SCSI_STATUS_SELECTION_TIMEOUT"); | 
 | 2444 | 		SCpnt->result = DID_NO_CONNECT << 16; | 
 | 2445 | 		scsi_print_command(SCpnt); | 
 | 2446 | 		break; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2447 |  | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2448 | 	case SBP2_SCSI_STATUS_CONDITION_MET: | 
 | 2449 | 	case SBP2_SCSI_STATUS_RESERVATION_CONFLICT: | 
 | 2450 | 	case SBP2_SCSI_STATUS_COMMAND_TERMINATED: | 
 | 2451 | 		SBP2_ERR("Bad SCSI status = %x", scsi_status); | 
 | 2452 | 		SCpnt->result = DID_ERROR << 16; | 
 | 2453 | 		scsi_print_command(SCpnt); | 
 | 2454 | 		break; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2455 |  | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2456 | 	default: | 
 | 2457 | 		SBP2_ERR("Unsupported SCSI status = %x", scsi_status); | 
 | 2458 | 		SCpnt->result = DID_ERROR << 16; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2459 | 	} | 
 | 2460 |  | 
 | 2461 | 	/* | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2462 | 	 * If a bus reset is in progress and there was an error, complete | 
 | 2463 | 	 * the command as busy so that it will get retried. | 
 | 2464 | 	 */ | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2465 | 	if (!hpsb_node_entry_valid(scsi_id->ne) | 
 | 2466 | 	    && (scsi_status != SBP2_SCSI_STATUS_GOOD)) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2467 | 		SBP2_ERR("Completing command with busy (bus reset)"); | 
 | 2468 | 		SCpnt->result = DID_BUS_BUSY << 16; | 
 | 2469 | 	} | 
 | 2470 |  | 
 | 2471 | 	/* | 
 | 2472 | 	 * If a unit attention occurs, return busy status so it gets | 
 | 2473 | 	 * retried... it could have happened because of a 1394 bus reset | 
 | 2474 | 	 * or hot-plug... | 
| Stefan Richter | 8f0525f | 2006-03-28 20:03:45 -0500 | [diff] [blame] | 2475 | 	 * XXX  DID_BUS_BUSY is actually a bad idea because it will defy | 
 | 2476 | 	 * the scsi layer's retry logic. | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2477 | 	 */ | 
 | 2478 | #if 0 | 
 | 2479 | 	if ((scsi_status == SBP2_SCSI_STATUS_CHECK_CONDITION) && | 
 | 2480 | 	    (SCpnt->sense_buffer[2] == UNIT_ATTENTION)) { | 
 | 2481 | 		SBP2_DEBUG("UNIT ATTENTION - return busy"); | 
 | 2482 | 		SCpnt->result = DID_BUS_BUSY << 16; | 
 | 2483 | 	} | 
 | 2484 | #endif | 
 | 2485 |  | 
 | 2486 | 	/* | 
 | 2487 | 	 * Tell scsi stack that we're done with this command | 
 | 2488 | 	 */ | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2489 | 	done(SCpnt); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2490 | } | 
 | 2491 |  | 
| Jody McIntyre | abd559b | 2005-09-30 11:59:06 -0700 | [diff] [blame] | 2492 | static int sbp2scsi_slave_alloc(struct scsi_device *sdev) | 
 | 2493 | { | 
| Stefan Richter | a80614d | 2006-02-14 22:04:19 -0500 | [diff] [blame] | 2494 | 	struct scsi_id_instance_data *scsi_id = | 
 | 2495 | 		(struct scsi_id_instance_data *)sdev->host->hostdata[0]; | 
 | 2496 |  | 
 | 2497 | 	scsi_id->sdev = sdev; | 
 | 2498 |  | 
| Stefan Richter | 24d3bf8 | 2006-05-15 22:04:59 +0200 | [diff] [blame] | 2499 | 	if (scsi_id->workarounds & SBP2_WORKAROUND_INQUIRY_36) | 
| Stefan Richter | a80614d | 2006-02-14 22:04:19 -0500 | [diff] [blame] | 2500 | 		sdev->inquiry_len = 36; | 
| Jody McIntyre | abd559b | 2005-09-30 11:59:06 -0700 | [diff] [blame] | 2501 | 	return 0; | 
 | 2502 | } | 
 | 2503 |  | 
| Jody McIntyre | abd559b | 2005-09-30 11:59:06 -0700 | [diff] [blame] | 2504 | static int sbp2scsi_slave_configure(struct scsi_device *sdev) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2505 | { | 
| Stefan Richter | 24d3bf8 | 2006-05-15 22:04:59 +0200 | [diff] [blame] | 2506 | 	struct scsi_id_instance_data *scsi_id = | 
 | 2507 | 		(struct scsi_id_instance_data *)sdev->host->hostdata[0]; | 
 | 2508 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2509 | 	blk_queue_dma_alignment(sdev->request_queue, (512 - 1)); | 
| Ben Collins | 365c786 | 2005-11-07 06:31:24 -0500 | [diff] [blame] | 2510 | 	sdev->use_10_for_rw = 1; | 
 | 2511 | 	sdev->use_10_for_ms = 1; | 
| Stefan Richter | 24d3bf8 | 2006-05-15 22:04:59 +0200 | [diff] [blame] | 2512 |  | 
 | 2513 | 	if (sdev->type == TYPE_DISK && | 
 | 2514 | 	    scsi_id->workarounds & SBP2_WORKAROUND_MODE_SENSE_8) | 
 | 2515 | 		sdev->skip_ms_page_8 = 1; | 
| Stefan Richter | e9a1c52 | 2006-05-15 22:06:37 +0200 | [diff] [blame] | 2516 | 	if (scsi_id->workarounds & SBP2_WORKAROUND_FIX_CAPACITY) | 
 | 2517 | 		sdev->fix_capacity = 1; | 
| Stefan Richter | e31f59c | 2006-08-05 12:14:53 -0700 | [diff] [blame] | 2518 | 	if (scsi_id->ne->guid_vendor_id == 0x0010b9 && /* Maxtor's OUI */ | 
 | 2519 | 	    (sdev->type == TYPE_DISK || sdev->type == TYPE_RBC)) | 
 | 2520 | 		sdev->allow_restart = 1; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2521 | 	return 0; | 
 | 2522 | } | 
 | 2523 |  | 
| Jody McIntyre | abd559b | 2005-09-30 11:59:06 -0700 | [diff] [blame] | 2524 | static void sbp2scsi_slave_destroy(struct scsi_device *sdev) | 
 | 2525 | { | 
 | 2526 | 	((struct scsi_id_instance_data *)sdev->host->hostdata[0])->sdev = NULL; | 
 | 2527 | 	return; | 
 | 2528 | } | 
 | 2529 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2530 | /* | 
 | 2531 |  * Called by scsi stack when something has really gone wrong.  Usually | 
 | 2532 |  * called when a command has timed-out for some reason. | 
 | 2533 |  */ | 
 | 2534 | static int sbp2scsi_abort(struct scsi_cmnd *SCpnt) | 
 | 2535 | { | 
 | 2536 | 	struct scsi_id_instance_data *scsi_id = | 
 | 2537 | 		(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0]; | 
 | 2538 | 	struct sbp2scsi_host_info *hi = scsi_id->hi; | 
 | 2539 | 	struct sbp2_command_info *command; | 
| Stefan Richter | 24c7cd0 | 2006-04-01 21:11:41 +0200 | [diff] [blame] | 2540 | 	unsigned long flags; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2541 |  | 
 | 2542 | 	SBP2_ERR("aborting sbp2 command"); | 
 | 2543 | 	scsi_print_command(SCpnt); | 
 | 2544 |  | 
| Jody McIntyre | abd559b | 2005-09-30 11:59:06 -0700 | [diff] [blame] | 2545 | 	if (sbp2util_node_is_available(scsi_id)) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2546 |  | 
 | 2547 | 		/* | 
 | 2548 | 		 * Right now, just return any matching command structures | 
 | 2549 | 		 * to the free pool. | 
 | 2550 | 		 */ | 
| Stefan Richter | 24c7cd0 | 2006-04-01 21:11:41 +0200 | [diff] [blame] | 2551 | 		spin_lock_irqsave(&scsi_id->sbp2_command_orb_lock, flags); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2552 | 		command = sbp2util_find_command_for_SCpnt(scsi_id, SCpnt); | 
 | 2553 | 		if (command) { | 
 | 2554 | 			SBP2_DEBUG("Found command to abort"); | 
 | 2555 | 			pci_dma_sync_single_for_cpu(hi->host->pdev, | 
 | 2556 | 						    command->command_orb_dma, | 
 | 2557 | 						    sizeof(struct sbp2_command_orb), | 
 | 2558 | 						    PCI_DMA_BIDIRECTIONAL); | 
 | 2559 | 			pci_dma_sync_single_for_cpu(hi->host->pdev, | 
 | 2560 | 						    command->sge_dma, | 
 | 2561 | 						    sizeof(command->scatter_gather_element), | 
 | 2562 | 						    PCI_DMA_BIDIRECTIONAL); | 
 | 2563 | 			sbp2util_mark_command_completed(scsi_id, command); | 
 | 2564 | 			if (command->Current_SCpnt) { | 
 | 2565 | 				command->Current_SCpnt->result = DID_ABORT << 16; | 
 | 2566 | 				command->Current_done(command->Current_SCpnt); | 
 | 2567 | 			} | 
 | 2568 | 		} | 
| Stefan Richter | 24c7cd0 | 2006-04-01 21:11:41 +0200 | [diff] [blame] | 2569 | 		spin_unlock_irqrestore(&scsi_id->sbp2_command_orb_lock, flags); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2570 |  | 
 | 2571 | 		/* | 
 | 2572 | 		 * Initiate a fetch agent reset. | 
 | 2573 | 		 */ | 
 | 2574 | 		sbp2_agent_reset(scsi_id, 0); | 
 | 2575 | 		sbp2scsi_complete_all_commands(scsi_id, DID_BUS_BUSY); | 
 | 2576 | 	} | 
 | 2577 |  | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2578 | 	return SUCCESS; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2579 | } | 
 | 2580 |  | 
 | 2581 | /* | 
 | 2582 |  * Called by scsi stack when something has really gone wrong. | 
 | 2583 |  */ | 
| Jody McIntyre | abd559b | 2005-09-30 11:59:06 -0700 | [diff] [blame] | 2584 | static int sbp2scsi_reset(struct scsi_cmnd *SCpnt) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2585 | { | 
 | 2586 | 	struct scsi_id_instance_data *scsi_id = | 
 | 2587 | 		(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0]; | 
 | 2588 |  | 
 | 2589 | 	SBP2_ERR("reset requested"); | 
 | 2590 |  | 
| Jody McIntyre | abd559b | 2005-09-30 11:59:06 -0700 | [diff] [blame] | 2591 | 	if (sbp2util_node_is_available(scsi_id)) { | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2592 | 		SBP2_ERR("Generating sbp2 fetch agent reset"); | 
 | 2593 | 		sbp2_agent_reset(scsi_id, 0); | 
 | 2594 | 	} | 
 | 2595 |  | 
| Jody McIntyre | abd559b | 2005-09-30 11:59:06 -0700 | [diff] [blame] | 2596 | 	return SUCCESS; | 
| Jeff Garzik  | 94d0e7b8 | 2005-05-28 07:55:48 -0400 | [diff] [blame] | 2597 | } | 
 | 2598 |  | 
| Stefan Richter | a237f35 | 2005-11-07 06:31:39 -0500 | [diff] [blame] | 2599 | static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev, | 
 | 2600 | 					   struct device_attribute *attr, | 
 | 2601 | 					   char *buf) | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2602 | { | 
 | 2603 | 	struct scsi_device *sdev; | 
 | 2604 | 	struct scsi_id_instance_data *scsi_id; | 
 | 2605 | 	int lun; | 
 | 2606 |  | 
 | 2607 | 	if (!(sdev = to_scsi_device(dev))) | 
 | 2608 | 		return 0; | 
 | 2609 |  | 
 | 2610 | 	if (!(scsi_id = (struct scsi_id_instance_data *)sdev->host->hostdata[0])) | 
 | 2611 | 		return 0; | 
 | 2612 |  | 
| Ben Collins | e309fc6 | 2005-11-07 06:31:34 -0500 | [diff] [blame] | 2613 | 	lun = ORB_SET_LUN(scsi_id->sbp2_lun); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2614 |  | 
 | 2615 | 	return sprintf(buf, "%016Lx:%d:%d\n", (unsigned long long)scsi_id->ne->guid, | 
 | 2616 | 		       scsi_id->ud->id, lun); | 
 | 2617 | } | 
 | 2618 | static DEVICE_ATTR(ieee1394_id, S_IRUGO, sbp2_sysfs_ieee1394_id_show, NULL); | 
 | 2619 |  | 
 | 2620 | static struct device_attribute *sbp2_sysfs_sdev_attrs[] = { | 
 | 2621 | 	&dev_attr_ieee1394_id, | 
 | 2622 | 	NULL | 
 | 2623 | }; | 
 | 2624 |  | 
 | 2625 | MODULE_AUTHOR("Ben Collins <bcollins@debian.org>"); | 
 | 2626 | MODULE_DESCRIPTION("IEEE-1394 SBP-2 protocol driver"); | 
 | 2627 | MODULE_SUPPORTED_DEVICE(SBP2_DEVICE_NAME); | 
 | 2628 | MODULE_LICENSE("GPL"); | 
 | 2629 |  | 
 | 2630 | /* SCSI host template */ | 
 | 2631 | static struct scsi_host_template scsi_driver_template = { | 
 | 2632 | 	.module =			THIS_MODULE, | 
 | 2633 | 	.name =				"SBP-2 IEEE-1394", | 
 | 2634 | 	.proc_name =			SBP2_DEVICE_NAME, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2635 | 	.queuecommand =			sbp2scsi_queuecommand, | 
 | 2636 | 	.eh_abort_handler =		sbp2scsi_abort, | 
 | 2637 | 	.eh_device_reset_handler =	sbp2scsi_reset, | 
| Jody McIntyre | abd559b | 2005-09-30 11:59:06 -0700 | [diff] [blame] | 2638 | 	.slave_alloc =			sbp2scsi_slave_alloc, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2639 | 	.slave_configure =		sbp2scsi_slave_configure, | 
| Jody McIntyre | abd559b | 2005-09-30 11:59:06 -0700 | [diff] [blame] | 2640 | 	.slave_destroy =		sbp2scsi_slave_destroy, | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2641 | 	.this_id =			-1, | 
 | 2642 | 	.sg_tablesize =			SG_ALL, | 
 | 2643 | 	.use_clustering =		ENABLE_CLUSTERING, | 
 | 2644 | 	.cmd_per_lun =			SBP2_MAX_CMDS, | 
 | 2645 | 	.can_queue = 			SBP2_MAX_CMDS, | 
 | 2646 | 	.emulated =			1, | 
 | 2647 | 	.sdev_attrs =			sbp2_sysfs_sdev_attrs, | 
 | 2648 | }; | 
 | 2649 |  | 
 | 2650 | static int sbp2_module_init(void) | 
 | 2651 | { | 
 | 2652 | 	int ret; | 
 | 2653 |  | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 2654 | 	SBP2_DEBUG_ENTER(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2655 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2656 | 	/* Module load debug option to force one command at a time (serializing I/O) */ | 
 | 2657 | 	if (serialize_io) { | 
| Jody McIntyre | 2bab359 | 2005-09-30 11:59:07 -0700 | [diff] [blame] | 2658 | 		SBP2_INFO("Driver forced to serialize I/O (serialize_io=1)"); | 
 | 2659 | 		SBP2_INFO("Try serialize_io=0 for better performance"); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2660 | 		scsi_driver_template.can_queue = 1; | 
 | 2661 | 		scsi_driver_template.cmd_per_lun = 1; | 
 | 2662 | 	} | 
 | 2663 |  | 
| Stefan Richter | 24d3bf8 | 2006-05-15 22:04:59 +0200 | [diff] [blame] | 2664 | 	if (sbp2_default_workarounds & SBP2_WORKAROUND_128K_MAX_TRANS && | 
 | 2665 | 	    (max_sectors * 512) > (128 * 1024)) | 
 | 2666 | 		max_sectors = 128 * 1024 / 512; | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2667 | 	scsi_driver_template.max_sectors = max_sectors; | 
 | 2668 |  | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2669 | 	/* Register our high level driver with 1394 stack */ | 
 | 2670 | 	hpsb_register_highlevel(&sbp2_highlevel); | 
 | 2671 |  | 
 | 2672 | 	ret = hpsb_register_protocol(&sbp2_driver); | 
 | 2673 | 	if (ret) { | 
 | 2674 | 		SBP2_ERR("Failed to register protocol"); | 
 | 2675 | 		hpsb_unregister_highlevel(&sbp2_highlevel); | 
 | 2676 | 		return ret; | 
 | 2677 | 	} | 
 | 2678 |  | 
 | 2679 | 	return 0; | 
 | 2680 | } | 
 | 2681 |  | 
 | 2682 | static void __exit sbp2_module_exit(void) | 
 | 2683 | { | 
| Stefan Richter | d024ebc | 2006-03-28 20:03:55 -0500 | [diff] [blame] | 2684 | 	SBP2_DEBUG_ENTER(); | 
| Linus Torvalds | 1da177e | 2005-04-16 15:20:36 -0700 | [diff] [blame] | 2685 |  | 
 | 2686 | 	hpsb_unregister_protocol(&sbp2_driver); | 
 | 2687 |  | 
 | 2688 | 	hpsb_unregister_highlevel(&sbp2_highlevel); | 
 | 2689 | } | 
 | 2690 |  | 
 | 2691 | module_init(sbp2_module_init); | 
 | 2692 | module_exit(sbp2_module_exit); |