Blame view

drivers/scsi/aacraid/aachba.c 85.4 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
  /*
   *	Adaptec AAC series RAID controller driver
fa195afe4   Alan Cox   [SCSI] Clean up m...
3
   *	(c) Copyright 2001 Red Hat Inc.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
5
6
7
   *
   * based on the old aacraid driver that is..
   * Adaptec aacraid device driver for Linux.
   *
e8b12f0fb   Mahesh Rajashekhara   [SCSI] aacraid: A...
8
9
   * Copyright (c) 2000-2010 Adaptec, Inc.
   *               2010 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2, or (at your option)
   * any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; see the file COPYING.  If not, write to
   * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
   *
   */
  
  #include <linux/kernel.h>
  #include <linux/init.h>
  #include <linux/types.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
32
33
34
  #include <linux/pci.h>
  #include <linux/spinlock.h>
  #include <linux/slab.h>
  #include <linux/completion.h>
  #include <linux/blkdev.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
  #include <asm/uaccess.h>
3a0086a80   Salyzyn, Mark   [SCSI] aacraid: a...
36
  #include <linux/highmem.h> /* For flush_kernel_dcache_page */
acf3368ff   Paul Gortmaker   scsi: Fix up file...
37
  #include <linux/module.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
  
  #include <scsi/scsi.h>
  #include <scsi/scsi_cmnd.h>
  #include <scsi/scsi_device.h>
  #include <scsi/scsi_host.h>
  
  #include "aacraid.h"
  
  /* values for inqd_pdt: Peripheral device type in plain English */
  #define	INQD_PDT_DA	0x00	/* Direct-access (DISK) device */
  #define	INQD_PDT_PROC	0x03	/* Processor device */
  #define	INQD_PDT_CHNGR	0x08	/* Changer (jukebox, scsi2) */
  #define	INQD_PDT_COMM	0x09	/* Communication device (scsi2) */
  #define	INQD_PDT_NOLUN2 0x1f	/* Unknown Device (scsi2) */
  #define	INQD_PDT_NOLUN	0x7f	/* Logical Unit Not Present */
  
  #define	INQD_PDT_DMASK	0x1F	/* Peripheral Device Type Mask */
  #define	INQD_PDT_QMASK	0xE0	/* Peripheral Device Qualifer Mask */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
57
58
  /*
   *	Sense codes
   */
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
  
  #define SENCODE_NO_SENSE			0x00
  #define SENCODE_END_OF_DATA			0x00
  #define SENCODE_BECOMING_READY			0x04
  #define SENCODE_INIT_CMD_REQUIRED		0x04
  #define SENCODE_PARAM_LIST_LENGTH_ERROR		0x1A
  #define SENCODE_INVALID_COMMAND			0x20
  #define SENCODE_LBA_OUT_OF_RANGE		0x21
  #define SENCODE_INVALID_CDB_FIELD		0x24
  #define SENCODE_LUN_NOT_SUPPORTED		0x25
  #define SENCODE_INVALID_PARAM_FIELD		0x26
  #define SENCODE_PARAM_NOT_SUPPORTED		0x26
  #define SENCODE_PARAM_VALUE_INVALID		0x26
  #define SENCODE_RESET_OCCURRED			0x29
  #define SENCODE_LUN_NOT_SELF_CONFIGURED_YET	0x3E
  #define SENCODE_INQUIRY_DATA_CHANGED		0x3F
  #define SENCODE_SAVING_PARAMS_NOT_SUPPORTED	0x39
  #define SENCODE_DIAGNOSTIC_FAILURE		0x40
  #define SENCODE_INTERNAL_TARGET_FAILURE		0x44
  #define SENCODE_INVALID_MESSAGE_ERROR		0x49
  #define SENCODE_LUN_FAILED_SELF_CONFIG		0x4c
  #define SENCODE_OVERLAPPED_COMMAND		0x4E
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
82
83
84
  
  /*
   *	Additional sense codes
   */
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
  
  #define ASENCODE_NO_SENSE			0x00
  #define ASENCODE_END_OF_DATA			0x05
  #define ASENCODE_BECOMING_READY			0x01
  #define ASENCODE_INIT_CMD_REQUIRED		0x02
  #define ASENCODE_PARAM_LIST_LENGTH_ERROR	0x00
  #define ASENCODE_INVALID_COMMAND		0x00
  #define ASENCODE_LBA_OUT_OF_RANGE		0x00
  #define ASENCODE_INVALID_CDB_FIELD		0x00
  #define ASENCODE_LUN_NOT_SUPPORTED		0x00
  #define ASENCODE_INVALID_PARAM_FIELD		0x00
  #define ASENCODE_PARAM_NOT_SUPPORTED		0x01
  #define ASENCODE_PARAM_VALUE_INVALID		0x02
  #define ASENCODE_RESET_OCCURRED			0x00
  #define ASENCODE_LUN_NOT_SELF_CONFIGURED_YET	0x00
  #define ASENCODE_INQUIRY_DATA_CHANGED		0x03
  #define ASENCODE_SAVING_PARAMS_NOT_SUPPORTED	0x00
  #define ASENCODE_DIAGNOSTIC_FAILURE		0x80
  #define ASENCODE_INTERNAL_TARGET_FAILURE	0x00
  #define ASENCODE_INVALID_MESSAGE_ERROR		0x00
  #define ASENCODE_LUN_FAILED_SELF_CONFIG		0x00
  #define ASENCODE_OVERLAPPED_COMMAND		0x00
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
108
109
110
111
112
113
114
115
116
117
  
  #define BYTE0(x) (unsigned char)(x)
  #define BYTE1(x) (unsigned char)((x) >> 8)
  #define BYTE2(x) (unsigned char)((x) >> 16)
  #define BYTE3(x) (unsigned char)((x) >> 24)
  
  /*------------------------------------------------------------------------------
   *              S T R U C T S / T Y P E D E F S
   *----------------------------------------------------------------------------*/
  /* SCSI inquiry data */
  struct inquiry_data {
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
118
119
  	u8 inqd_pdt;	/* Peripheral qualifier | Peripheral Device Type */
  	u8 inqd_dtq;	/* RMB | Device Type Qualifier */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
121
122
123
124
125
126
127
128
129
130
131
132
  	u8 inqd_ver;	/* ISO version | ECMA version | ANSI-approved version */
  	u8 inqd_rdf;	/* AENC | TrmIOP | Response data format */
  	u8 inqd_len;	/* Additional length (n-4) */
  	u8 inqd_pad1[2];/* Reserved - must be zero */
  	u8 inqd_pad2;	/* RelAdr | WBus32 | WBus16 |  Sync  | Linked |Reserved| CmdQue | SftRe */
  	u8 inqd_vid[8];	/* Vendor ID */
  	u8 inqd_pid[16];/* Product ID */
  	u8 inqd_prl[4];	/* Product Revision Level */
  };
  
  /*
   *              M O D U L E   G L O B A L S
   */
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
133

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
135
  static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* sgmap);
  static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* psg);
0e68c0037   Mark Haverkamp   [SCSI] aacraid: s...
136
  static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
138
139
140
141
142
143
  static int aac_send_srb_fib(struct scsi_cmnd* scsicmd);
  #ifdef AAC_DETAILED_STATUS_INFO
  static char *aac_get_status_string(u32 status);
  #endif
  
  /*
   *	Non dasd selection is handled entirely in aachba now
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
144
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
  static int nondasd = -1;
d8e965076   Leubner, Achim   [SCSI] aacraid dr...
146
  static int aac_cache = 2;	/* WCE=0 to avoid performance problems */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
  static int dacmode = -1;
8ef222470   Salyzyn, Mark   [SCSI] aacraid: a...
148
  int aac_msi;
1208bab5d   Salyzyn, Mark   [SCSI] aacraid: a...
149
  int aac_commit = -1;
404d9a900   Mark Haverkamp   [SCSI] aacraid: a...
150
151
  int startup_timeout = 180;
  int aif_timeout = 120;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
152

9a72f976d   Mark Haverkamp   [SCSI] aacraid: D...
153
  module_param(nondasd, int, S_IRUGO|S_IWUSR);
8ef222470   Salyzyn, Mark   [SCSI] aacraid: a...
154
155
  MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices."
  	" 0=off, 1=on");
95e852e1e   Salyzyn, Mark   [SCSI] aacraid: a...
156
  module_param_named(cache, aac_cache, int, S_IRUGO|S_IWUSR);
8ef222470   Salyzyn, Mark   [SCSI] aacraid: a...
157
158
159
160
161
162
  MODULE_PARM_DESC(cache, "Disable Queue Flush commands:
  "
  	"\tbit 0 - Disable FUA in WRITE SCSI commands
  "
  	"\tbit 1 - Disable SYNCHRONIZE_CACHE SCSI command
  "
d8e965076   Leubner, Achim   [SCSI] aacraid dr...
163
  	"\tbit 2 - Disable only if Battery is protecting Cache");
9a72f976d   Mark Haverkamp   [SCSI] aacraid: D...
164
  module_param(dacmode, int, S_IRUGO|S_IWUSR);
8ef222470   Salyzyn, Mark   [SCSI] aacraid: a...
165
166
  MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC."
  	" 0=off, 1=on");
1208bab5d   Salyzyn, Mark   [SCSI] aacraid: a...
167
  module_param_named(commit, aac_commit, int, S_IRUGO|S_IWUSR);
8ef222470   Salyzyn, Mark   [SCSI] aacraid: a...
168
169
170
171
172
173
174
175
  MODULE_PARM_DESC(commit, "Control whether a COMMIT_CONFIG is issued to the"
  	" adapter for foreign arrays.
  "
  	"This is typically needed in systems that do not have a BIOS."
  	" 0=off, 1=on");
  module_param_named(msi, aac_msi, int, S_IRUGO|S_IWUSR);
  MODULE_PARM_DESC(msi, "IRQ handling."
  	" 0=PIC(default), 1=MSI, 2=MSI-X(unsupported, uses MSI)");
404d9a900   Mark Haverkamp   [SCSI] aacraid: a...
176
  module_param(startup_timeout, int, S_IRUGO|S_IWUSR);
8ef222470   Salyzyn, Mark   [SCSI] aacraid: a...
177
178
179
180
181
  MODULE_PARM_DESC(startup_timeout, "The duration of time in seconds to wait for"
  	" adapter to have it's kernel up and
  "
  	"running. This is typically adjusted for large systems that do not"
  	" have a BIOS.");
404d9a900   Mark Haverkamp   [SCSI] aacraid: a...
182
  module_param(aif_timeout, int, S_IRUGO|S_IWUSR);
8ef222470   Salyzyn, Mark   [SCSI] aacraid: a...
183
184
185
186
187
  MODULE_PARM_DESC(aif_timeout, "The duration of time in seconds to wait for"
  	" applications to pick up AIFs before
  "
  	"deregistering them. This is typically adjusted for heavily burdened"
  	" systems.");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
188

7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
189
190
  int numacb = -1;
  module_param(numacb, int, S_IRUGO|S_IWUSR);
8ef222470   Salyzyn, Mark   [SCSI] aacraid: a...
191
192
193
  MODULE_PARM_DESC(numacb, "Request a limit to the number of adapter control"
  	" blocks (FIB) allocated. Valid values are 512 and down. Default is"
  	" to use suggestion from Firmware.");
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
194
195
196
  
  int acbsize = -1;
  module_param(acbsize, int, S_IRUGO|S_IWUSR);
8ef222470   Salyzyn, Mark   [SCSI] aacraid: a...
197
198
199
  MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB)"
  	" size. Valid values are 512, 2048, 4096 and 8192. Default is to use"
  	" suggestion from Firmware.");
653ba58d5   Mark Haverkamp   [SCSI] aacraid: e...
200

29c976844   Salyzyn, Mark   [SCSI] aacraid: a...
201
202
  int update_interval = 30 * 60;
  module_param(update_interval, int, S_IRUGO|S_IWUSR);
8ef222470   Salyzyn, Mark   [SCSI] aacraid: a...
203
204
  MODULE_PARM_DESC(update_interval, "Interval in seconds between time sync"
  	" updates issued to adapter.");
29c976844   Salyzyn, Mark   [SCSI] aacraid: a...
205
206
207
  
  int check_interval = 24 * 60 * 60;
  module_param(check_interval, int, S_IRUGO|S_IWUSR);
8ef222470   Salyzyn, Mark   [SCSI] aacraid: a...
208
209
  MODULE_PARM_DESC(check_interval, "Interval in seconds between adapter health"
  	" checks.");
29c976844   Salyzyn, Mark   [SCSI] aacraid: a...
210

87f3bda35   Andrew Morton   [SCSI] aacraid: r...
211
212
  int aac_check_reset = 1;
  module_param_named(check_reset, aac_check_reset, int, S_IRUGO|S_IWUSR);
95e7a8efd   Paul Bolle   [SCSI] aacraid: D...
213
  MODULE_PARM_DESC(check_reset, "If adapter fails health check, reset the"
8ef222470   Salyzyn, Mark   [SCSI] aacraid: a...
214
215
  	" adapter. a value of -1 forces the reset to adapters programmed to"
  	" ignore it.");
29c976844   Salyzyn, Mark   [SCSI] aacraid: a...
216

e37ee4bec   Mark Haverkamp   [SCSI] aacraid: e...
217
  int expose_physicals = -1;
653ba58d5   Mark Haverkamp   [SCSI] aacraid: e...
218
  module_param(expose_physicals, int, S_IRUGO|S_IWUSR);
8ef222470   Salyzyn, Mark   [SCSI] aacraid: a...
219
220
  MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays."
  	" -1=protect 0=off, 1=on");
03d443372   Mark Haverkamp   [SCSI] aacraid: I...
221

8ef222470   Salyzyn, Mark   [SCSI] aacraid: a...
222
  int aac_reset_devices;
1208bab5d   Salyzyn, Mark   [SCSI] aacraid: a...
223
224
  module_param_named(reset_devices, aac_reset_devices, int, S_IRUGO|S_IWUSR);
  MODULE_PARM_DESC(reset_devices, "Force an adapter reset at initialization.");
03d443372   Mark Haverkamp   [SCSI] aacraid: I...
225

d8e965076   Leubner, Achim   [SCSI] aacraid dr...
226
227
228
229
230
231
232
233
234
  int aac_wwn = 1;
  module_param_named(wwn, aac_wwn, int, S_IRUGO|S_IWUSR);
  MODULE_PARM_DESC(wwn, "Select a WWN type for the arrays:
  "
  	"\t0 - Disable
  "
  	"\t1 - Array Meta Data Signature (default)
  "
  	"\t2 - Adapter Serial Number");
03d443372   Mark Haverkamp   [SCSI] aacraid: I...
235
236
237
  static inline int aac_valid_context(struct scsi_cmnd *scsicmd,
  		struct fib *fibptr) {
  	struct scsi_device *device;
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
238
  	if (unlikely(!scsicmd || !scsicmd->scsi_done)) {
c835e3727   Salyzyn, Mark   [SCSI] aacraid: d...
239
240
  		dprintk((KERN_WARNING "aac_valid_context: scsi command corrupt
  "));
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
241
242
243
244
  		aac_fib_complete(fibptr);
  		aac_fib_free(fibptr);
  		return 0;
  	}
03d443372   Mark Haverkamp   [SCSI] aacraid: I...
245
246
247
248
249
250
251
252
253
254
255
  	scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;
  	device = scsicmd->device;
  	if (unlikely(!device || !scsi_device_online(device))) {
  		dprintk((KERN_WARNING "aac_valid_context: scsi device corrupt
  "));
  		aac_fib_complete(fibptr);
  		aac_fib_free(fibptr);
  		return 0;
  	}
  	return 1;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
256
257
258
259
260
261
  /**
   *	aac_get_config_status	-	check the adapter configuration
   *	@common: adapter to query
   *
   *	Query config status, and commit the configuration if needed.
   */
8c867b257   Mark Haverkamp   [SCSI] aacraid: R...
262
  int aac_get_config_status(struct aac_dev *dev, int commit_flag)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
263
264
265
  {
  	int status = 0;
  	struct fib * fibptr;
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
266
  	if (!(fibptr = aac_fib_alloc(dev)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
  		return -ENOMEM;
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
268
  	aac_fib_init(fibptr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
269
270
271
272
273
274
275
276
  	{
  		struct aac_get_config_status *dinfo;
  		dinfo = (struct aac_get_config_status *) fib_data(fibptr);
  
  		dinfo->command = cpu_to_le32(VM_ContainerConfig);
  		dinfo->type = cpu_to_le32(CT_GET_CONFIG_STATUS);
  		dinfo->count = cpu_to_le32(sizeof(((struct aac_get_config_status_resp *)NULL)->data));
  	}
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
277
  	status = aac_fib_send(ContainerCommand,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
278
279
280
281
282
  			    fibptr,
  			    sizeof (struct aac_get_config_status),
  			    FsaNormal,
  			    1, 1,
  			    NULL, NULL);
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
283
  	if (status < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
  		printk(KERN_WARNING "aac_get_config_status: SendFIB failed.
  ");
  	} else {
  		struct aac_get_config_status_resp *reply
  		  = (struct aac_get_config_status_resp *) fib_data(fibptr);
  		dprintk((KERN_WARNING
  		  "aac_get_config_status: response=%d status=%d action=%d
  ",
  		  le32_to_cpu(reply->response),
  		  le32_to_cpu(reply->status),
  		  le32_to_cpu(reply->data.action)));
  		if ((le32_to_cpu(reply->response) != ST_OK) ||
  		     (le32_to_cpu(reply->status) != CT_OK) ||
  		     (le32_to_cpu(reply->data.action) > CFACT_PAUSE)) {
  			printk(KERN_WARNING "aac_get_config_status: Will not issue the Commit Configuration
  ");
  			status = -EINVAL;
  		}
  	}
cacb6dc3d   Penchala Narasimha Reddy Chilakala, ERS-HCLTech   [SCSI] aacraid: f...
303
304
305
  	/* Do not set XferState to zero unless receives a response from F/W */
  	if (status >= 0)
  		aac_fib_complete(fibptr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
306
307
  	/* Send a CT_COMMIT_CONFIG to enable discovery of devices */
  	if (status >= 0) {
1208bab5d   Salyzyn, Mark   [SCSI] aacraid: a...
308
  		if ((aac_commit == 1) || commit_flag) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
  			struct aac_commit_config * dinfo;
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
310
  			aac_fib_init(fibptr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
311
  			dinfo = (struct aac_commit_config *) fib_data(fibptr);
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
312

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
313
314
  			dinfo->command = cpu_to_le32(VM_ContainerConfig);
  			dinfo->type = cpu_to_le32(CT_COMMIT_CONFIG);
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
315

bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
316
  			status = aac_fib_send(ContainerCommand,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
317
318
319
320
321
  				    fibptr,
  				    sizeof (struct aac_commit_config),
  				    FsaNormal,
  				    1, 1,
  				    NULL, NULL);
cacb6dc3d   Penchala Narasimha Reddy Chilakala, ERS-HCLTech   [SCSI] aacraid: f...
322
323
324
325
  			/* Do not set XferState to zero unless
  			 * receives a response from F/W */
  			if (status >= 0)
  				aac_fib_complete(fibptr);
1208bab5d   Salyzyn, Mark   [SCSI] aacraid: a...
326
  		} else if (aac_commit == 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
327
328
329
330
331
  			printk(KERN_WARNING
  			  "aac_get_config_status: Foreign device configurations are being ignored
  ");
  		}
  	}
cacb6dc3d   Penchala Narasimha Reddy Chilakala, ERS-HCLTech   [SCSI] aacraid: f...
332
333
334
  	/* FIB should be freed only after getting the response from the F/W */
  	if (status != -ERESTARTSYS)
  		aac_fib_free(fibptr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
335
336
  	return status;
  }
e3cc268fe   Rajashekhara, Mahesh   [SCSI] aacraid: e...
337
338
339
340
341
342
343
344
345
  static void aac_expose_phy_device(struct scsi_cmnd *scsicmd)
  {
  	char inq_data;
  	scsi_sg_copy_to_buffer(scsicmd,  &inq_data, sizeof(inq_data));
  	if ((inq_data & 0x20) && (inq_data & 0x1f) == TYPE_DISK) {
  		inq_data &= 0xdf;
  		scsi_sg_copy_from_buffer(scsicmd, &inq_data, sizeof(inq_data));
  	}
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
346
347
348
349
350
351
352
353
354
  /**
   *	aac_get_containers	-	list containers
   *	@common: adapter to probe
   *
   *	Make a list of all containers on this controller
   */
  int aac_get_containers(struct aac_dev *dev)
  {
  	struct fsa_dev_info *fsa_dev_ptr;
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
355
  	u32 index;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
356
357
  	int status = 0;
  	struct fib * fibptr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
358
359
360
  	struct aac_get_container_count *dinfo;
  	struct aac_get_container_count_resp *dresp;
  	int maximum_num_containers = MAXIMUM_NUM_CONTAINERS;
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
361
  	if (!(fibptr = aac_fib_alloc(dev)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
  		return -ENOMEM;
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
363
  	aac_fib_init(fibptr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
364
365
366
  	dinfo = (struct aac_get_container_count *) fib_data(fibptr);
  	dinfo->command = cpu_to_le32(VM_ContainerConfig);
  	dinfo->type = cpu_to_le32(CT_GET_CONTAINER_COUNT);
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
367
  	status = aac_fib_send(ContainerCommand,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
368
369
370
371
372
373
374
375
  		    fibptr,
  		    sizeof (struct aac_get_container_count),
  		    FsaNormal,
  		    1, 1,
  		    NULL, NULL);
  	if (status >= 0) {
  		dresp = (struct aac_get_container_count_resp *)fib_data(fibptr);
  		maximum_num_containers = le32_to_cpu(dresp->ContainerSwitchEntries);
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
376
  		aac_fib_complete(fibptr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
377
  	}
cacb6dc3d   Penchala Narasimha Reddy Chilakala, ERS-HCLTech   [SCSI] aacraid: f...
378
379
380
  	/* FIB should be freed only after getting the response from the F/W */
  	if (status != -ERESTARTSYS)
  		aac_fib_free(fibptr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
381
382
383
  
  	if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS)
  		maximum_num_containers = MAXIMUM_NUM_CONTAINERS;
1a655040c   Salyzyn, Mark   [SCSI] aacraid: p...
384
  	fsa_dev_ptr = kzalloc(sizeof(*fsa_dev_ptr) * maximum_num_containers,
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
385
386
  			GFP_KERNEL);
  	if (!fsa_dev_ptr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
387
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
388
389
390
  
  	dev->fsa_dev = fsa_dev_ptr;
  	dev->maximum_num_containers = maximum_num_containers;
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
391
  	for (index = 0; index < dev->maximum_num_containers; ) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
392
  		fsa_dev_ptr[index].devname[0] = '\0';
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
393
  		status = aac_probe_container(dev, index);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
394

fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
395
  		if (status < 0) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
396
397
398
399
  			printk(KERN_WARNING "aac_get_containers: SendFIB failed.
  ");
  			break;
  		}
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
400

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
401
402
403
  		/*
  		 *	If there are no more containers, then stop asking.
  		 */
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
404
  		if (++index >= status)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
405
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
407
408
  	return status;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
409
410
411
412
413
414
  static void get_container_name_callback(void *context, struct fib * fibptr)
  {
  	struct aac_get_name_resp * get_name_reply;
  	struct scsi_cmnd * scsicmd;
  
  	scsicmd = (struct scsi_cmnd *) context;
03d443372   Mark Haverkamp   [SCSI] aacraid: I...
415
416
  	if (!aac_valid_context(scsicmd, fibptr))
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
418
  	dprintk((KERN_DEBUG "get_container_name_callback[cpu %d]: t = %ld.
  ", smp_processor_id(), jiffies));
125e18745   Eric Sesterhenn   [PATCH] More BUG_...
419
  	BUG_ON(fibptr == NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
420
421
422
423
424
  
  	get_name_reply = (struct aac_get_name_resp *) fib_data(fibptr);
  	/* Failure is irrelevant, using default value instead */
  	if ((le32_to_cpu(get_name_reply->status) == CT_OK)
  	 && (get_name_reply->data[0] != '\0')) {
3b2946cc9   Mark Haverkamp   [SCSI] aacraid: F...
425
  		char *sp = get_name_reply->data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
426
427
428
  		sp[sizeof(((struct aac_get_name_resp *)NULL)->data)-1] = '\0';
  		while (*sp == ' ')
  			++sp;
3b2946cc9   Mark Haverkamp   [SCSI] aacraid: F...
429
  		if (*sp) {
d4345028d   FUJITA Tomonori   [SCSI] aacraid: u...
430
  			struct inquiry_data inq;
3b2946cc9   Mark Haverkamp   [SCSI] aacraid: F...
431
432
433
434
435
436
  			char d[sizeof(((struct inquiry_data *)NULL)->inqd_pid)];
  			int count = sizeof(d);
  			char *dp = d;
  			do {
  				*dp++ = (*sp) ? *sp++ : ' ';
  			} while (--count > 0);
d4345028d   FUJITA Tomonori   [SCSI] aacraid: u...
437
438
439
440
  
  			scsi_sg_copy_to_buffer(scsicmd, &inq, sizeof(inq));
  			memcpy(inq.inqd_pid, d, sizeof(d));
  			scsi_sg_copy_from_buffer(scsicmd, &inq, sizeof(inq));
3b2946cc9   Mark Haverkamp   [SCSI] aacraid: F...
441
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
442
  	}
3b2946cc9   Mark Haverkamp   [SCSI] aacraid: F...
443

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
  	scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
445
446
  	aac_fib_complete(fibptr);
  	aac_fib_free(fibptr);
8e0c5ebde   Mark Haverkamp   [SCSI] aacraid: N...
447
  	scsicmd->scsi_done(scsicmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
448
449
450
451
452
  }
  
  /**
   *	aac_get_container_name	-	get container name, none blocking.
   */
9e7c349c9   Mark Haverkamp   [SCSI] aacraid: r...
453
  static int aac_get_container_name(struct scsi_cmnd * scsicmd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
454
455
456
457
458
459
460
  {
  	int status;
  	struct aac_get_name *dinfo;
  	struct fib * cmd_fibcontext;
  	struct aac_dev * dev;
  
  	dev = (struct aac_dev *)scsicmd->device->host->hostdata;
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
461
  	if (!(cmd_fibcontext = aac_fib_alloc(dev)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
462
  		return -ENOMEM;
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
463
  	aac_fib_init(cmd_fibcontext);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
464
465
466
467
  	dinfo = (struct aac_get_name *) fib_data(cmd_fibcontext);
  
  	dinfo->command = cpu_to_le32(VM_ContainerConfig);
  	dinfo->type = cpu_to_le32(CT_READ_NAME);
9e7c349c9   Mark Haverkamp   [SCSI] aacraid: r...
468
  	dinfo->cid = cpu_to_le32(scmd_id(scsicmd));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
469
  	dinfo->count = cpu_to_le32(sizeof(((struct aac_get_name_resp *)NULL)->data));
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
470
  	status = aac_fib_send(ContainerCommand,
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
471
  		  cmd_fibcontext,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
472
  		  sizeof (struct aac_get_name),
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
473
474
475
  		  FsaNormal,
  		  0, 1,
  		  (fib_callback)get_container_name_callback,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
476
  		  (void *) scsicmd);
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
477

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
478
479
480
  	/*
  	 *	Check that the command queued to the controller
  	 */
77d644d4d   Mark Haverkamp   [SCSI] aacraid: T...
481
482
  	if (status == -EINPROGRESS) {
  		scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
483
  		return 0;
77d644d4d   Mark Haverkamp   [SCSI] aacraid: T...
484
  	}
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
485

bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
486
487
488
489
  	printk(KERN_WARNING "aac_get_container_name: aac_fib_send failed with status: %d.
  ", status);
  	aac_fib_complete(cmd_fibcontext);
  	aac_fib_free(cmd_fibcontext);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
490
491
  	return -1;
  }
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
492
  static int aac_probe_container_callback2(struct scsi_cmnd * scsicmd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
493
  {
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
494
  	struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
495

1a655040c   Salyzyn, Mark   [SCSI] aacraid: p...
496
  	if ((fsa_dev_ptr[scmd_id(scsicmd)].valid & 1))
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
497
  		return aac_scsi_cmd(scsicmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
498

fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
499
500
501
502
  	scsicmd->result = DID_NO_CONNECT << 16;
  	scsicmd->scsi_done(scsicmd);
  	return 0;
  }
1a655040c   Salyzyn, Mark   [SCSI] aacraid: p...
503
  static void _aac_probe_container2(void * context, struct fib * fibptr)
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
504
  {
03d443372   Mark Haverkamp   [SCSI] aacraid: I...
505
  	struct fsa_dev_info *fsa_dev_ptr;
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
506
  	int (*callback)(struct scsi_cmnd *);
03d443372   Mark Haverkamp   [SCSI] aacraid: I...
507
  	struct scsi_cmnd * scsicmd = (struct scsi_cmnd *)context;
03d443372   Mark Haverkamp   [SCSI] aacraid: I...
508

1a655040c   Salyzyn, Mark   [SCSI] aacraid: p...
509
510
  	if (!aac_valid_context(scsicmd, fibptr))
  		return;
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
511
512
  
  	scsicmd->SCp.Status = 0;
1a655040c   Salyzyn, Mark   [SCSI] aacraid: p...
513
  	fsa_dev_ptr = fibptr->dev->fsa_dev;
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
514
515
516
517
518
519
520
521
  	if (fsa_dev_ptr) {
  		struct aac_mount * dresp = (struct aac_mount *) fib_data(fibptr);
  		fsa_dev_ptr += scmd_id(scsicmd);
  
  		if ((le32_to_cpu(dresp->status) == ST_OK) &&
  		    (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) &&
  		    (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) {
  			fsa_dev_ptr->valid = 1;
655d722cf   Mark Salyzyn   [SCSI] aacraid: A...
522
523
524
525
526
  			/* sense_key holds the current state of the spin-up */
  			if (dresp->mnt[0].state & cpu_to_le32(FSCS_NOT_READY))
  				fsa_dev_ptr->sense_data.sense_key = NOT_READY;
  			else if (fsa_dev_ptr->sense_data.sense_key == NOT_READY)
  				fsa_dev_ptr->sense_data.sense_key = NO_SENSE;
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
527
528
529
530
531
532
533
534
535
536
537
538
539
540
  			fsa_dev_ptr->type = le32_to_cpu(dresp->mnt[0].vol);
  			fsa_dev_ptr->size
  			  = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) +
  			    (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32);
  			fsa_dev_ptr->ro = ((le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) != 0);
  		}
  		if ((fsa_dev_ptr->valid & 1) == 0)
  			fsa_dev_ptr->valid = 0;
  		scsicmd->SCp.Status = le32_to_cpu(dresp->count);
  	}
  	aac_fib_complete(fibptr);
  	aac_fib_free(fibptr);
  	callback = (int (*)(struct scsi_cmnd *))(scsicmd->SCp.ptr);
  	scsicmd->SCp.ptr = NULL;
1a655040c   Salyzyn, Mark   [SCSI] aacraid: p...
541
542
  	(*callback)(scsicmd);
  	return;
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
543
  }
1a655040c   Salyzyn, Mark   [SCSI] aacraid: p...
544
  static void _aac_probe_container1(void * context, struct fib * fibptr)
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
545
546
547
548
549
550
551
552
553
  {
  	struct scsi_cmnd * scsicmd;
  	struct aac_mount * dresp;
  	struct aac_query_mount *dinfo;
  	int status;
  
  	dresp = (struct aac_mount *) fib_data(fibptr);
  	dresp->mnt[0].capacityhigh = 0;
  	if ((le32_to_cpu(dresp->status) != ST_OK) ||
1a655040c   Salyzyn, Mark   [SCSI] aacraid: p...
554
555
556
557
  	    (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) {
  		_aac_probe_container2(context, fibptr);
  		return;
  	}
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
558
  	scsicmd = (struct scsi_cmnd *) context;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
559

03d443372   Mark Haverkamp   [SCSI] aacraid: I...
560
  	if (!aac_valid_context(scsicmd, fibptr))
1a655040c   Salyzyn, Mark   [SCSI] aacraid: p...
561
  		return;
03d443372   Mark Haverkamp   [SCSI] aacraid: I...
562

bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
563
  	aac_fib_init(fibptr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
564
565
  
  	dinfo = (struct aac_query_mount *)fib_data(fibptr);
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
566
567
  	dinfo->command = cpu_to_le32(VM_NameServe64);
  	dinfo->count = cpu_to_le32(scmd_id(scsicmd));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
568
  	dinfo->type = cpu_to_le32(FT_FILESYS);
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
569
  	status = aac_fib_send(ContainerCommand,
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
570
571
572
573
  			  fibptr,
  			  sizeof(struct aac_query_mount),
  			  FsaNormal,
  			  0, 1,
1a655040c   Salyzyn, Mark   [SCSI] aacraid: p...
574
  			  _aac_probe_container2,
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
575
576
577
578
  			  (void *) scsicmd);
  	/*
  	 *	Check that the command queued to the controller
  	 */
1a655040c   Salyzyn, Mark   [SCSI] aacraid: p...
579
  	if (status == -EINPROGRESS)
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
580
  		scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
1a655040c   Salyzyn, Mark   [SCSI] aacraid: p...
581
  	else if (status < 0) {
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
582
583
  		/* Inherit results from VM_NameServe, if any */
  		dresp->status = cpu_to_le32(ST_OK);
1a655040c   Salyzyn, Mark   [SCSI] aacraid: p...
584
  		_aac_probe_container2(context, fibptr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
585
  	}
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
586
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
587

fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
588
589
590
591
592
593
594
595
596
597
598
  static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(struct scsi_cmnd *))
  {
  	struct fib * fibptr;
  	int status = -ENOMEM;
  
  	if ((fibptr = aac_fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata))) {
  		struct aac_query_mount *dinfo;
  
  		aac_fib_init(fibptr);
  
  		dinfo = (struct aac_query_mount *)fib_data(fibptr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
599

fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
600
601
  		dinfo->command = cpu_to_le32(VM_NameServe);
  		dinfo->count = cpu_to_le32(scmd_id(scsicmd));
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
602
  		dinfo->type = cpu_to_le32(FT_FILESYS);
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
603
  		scsicmd->SCp.ptr = (char *)callback;
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
604

fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
605
606
607
608
609
  		status = aac_fib_send(ContainerCommand,
  			  fibptr,
  			  sizeof(struct aac_query_mount),
  			  FsaNormal,
  			  0, 1,
1a655040c   Salyzyn, Mark   [SCSI] aacraid: p...
610
  			  _aac_probe_container1,
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
  			  (void *) scsicmd);
  		/*
  		 *	Check that the command queued to the controller
  		 */
  		if (status == -EINPROGRESS) {
  			scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
  			return 0;
  		}
  		if (status < 0) {
  			scsicmd->SCp.ptr = NULL;
  			aac_fib_complete(fibptr);
  			aac_fib_free(fibptr);
  		}
  	}
  	if (status < 0) {
  		struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev;
  		if (fsa_dev_ptr) {
  			fsa_dev_ptr += scmd_id(scsicmd);
  			if ((fsa_dev_ptr->valid & 1) == 0) {
  				fsa_dev_ptr->valid = 0;
  				return (*callback)(scsicmd);
  			}
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
634
  	}
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
635
636
  	return status;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
637

fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
638
639
640
641
642
643
644
645
646
647
648
649
650
  /**
   *	aac_probe_container		-	query a logical volume
   *	@dev: device to query
   *	@cid: container identifier
   *
   *	Queries the controller about the given volume. The volume information
   *	is updated in the struct fsa_dev_info structure rather than returned.
   */
  static int aac_probe_container_callback1(struct scsi_cmnd * scsicmd)
  {
  	scsicmd->device = NULL;
  	return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
651

fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
652
653
654
655
656
657
658
659
660
661
662
663
  int aac_probe_container(struct aac_dev *dev, int cid)
  {
  	struct scsi_cmnd *scsicmd = kmalloc(sizeof(*scsicmd), GFP_KERNEL);
  	struct scsi_device *scsidev = kmalloc(sizeof(*scsidev), GFP_KERNEL);
  	int status;
  
  	if (!scsicmd || !scsidev) {
  		kfree(scsicmd);
  		kfree(scsidev);
  		return -ENOMEM;
  	}
  	scsicmd->list.next = NULL;
1a655040c   Salyzyn, Mark   [SCSI] aacraid: p...
664
  	scsicmd->scsi_done = (void (*)(struct scsi_cmnd*))aac_probe_container_callback1;
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
665
666
667
668
669
670
671
672
673
  
  	scsicmd->device = scsidev;
  	scsidev->sdev_state = 0;
  	scsidev->id = cid;
  	scsidev->host = dev->scsi_host_ptr;
  
  	if (_aac_probe_container(scsicmd, aac_probe_container_callback1) == 0)
  		while (scsicmd->device == scsidev)
  			schedule();
802ae2f05   Salyzyn, Mark   [SCSI] aacraid: c...
674
  	kfree(scsidev);
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
675
676
  	status = scsicmd->SCp.Status;
  	kfree(scsicmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
  	return status;
  }
  
  /* Local Structure to set SCSI inquiry data strings */
  struct scsi_inq {
  	char vid[8];         /* Vendor ID */
  	char pid[16];        /* Product ID */
  	char prl[4];         /* Product Revision Level */
  };
  
  /**
   *	InqStrCopy	-	string merge
   *	@a:	string to copy from
   *	@b:	string to copy to
   *
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
692
   *	Copy a String from one location to another
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
693
694
695
696
697
   *	without copying \0
   */
  
  static void inqstrcpy(char *a, char *b)
  {
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
698
  	while (*a != (char)0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
699
700
701
702
  		*b++ = *a++;
  }
  
  static char *container_types[] = {
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
703
704
705
706
707
708
709
710
711
712
713
714
715
716
  	"None",
  	"Volume",
  	"Mirror",
  	"Stripe",
  	"RAID5",
  	"SSRW",
  	"SSRO",
  	"Morph",
  	"Legacy",
  	"RAID4",
  	"RAID10",
  	"RAID00",
  	"V-MIRRORS",
  	"PSEUDO R4",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
717
  	"RAID50",
849717383   Mark Haverkamp   [SCSI] aacraid: N...
718
719
720
721
722
  	"RAID5D",
  	"RAID5D0",
  	"RAID1E",
  	"RAID6",
  	"RAID60",
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
723
  	"Unknown"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
724
  };
17eaaceef   Salyzyn, Mark   [SCSI] aacraid: a...
725
726
727
728
729
730
  char * get_container_type(unsigned tindex)
  {
  	if (tindex >= ARRAY_SIZE(container_types))
  		tindex = ARRAY_SIZE(container_types) - 1;
  	return container_types[tindex];
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
731
732
733
734
735
736
  
  /* Function: setinqstr
   *
   * Arguments: [1] pointer to void [1] int
   *
   * Purpose: Sets SCSI inquiry data strings for vendor, product
25985edce   Lucas De Marchi   Fix common misspe...
737
738
   * and revision level. Allows strings to be set in platform dependent
   * files instead of in OS dependent driver source.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
739
   */
794d0601e   Mark Haverkamp   [SCSI] aacraid: f...
740
  static void setinqstr(struct aac_dev *dev, void *data, int tindex)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
741
742
  {
  	struct scsi_inq *str;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
743

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
744
  	str = (struct scsi_inq *)(data); /* cast data to scsi inq block */
794d0601e   Mark Haverkamp   [SCSI] aacraid: f...
745
746
747
748
  	memset(str, ' ', sizeof(*str));
  
  	if (dev->supplement_adapter_info.AdapterTypeText[0]) {
  		char * cp = dev->supplement_adapter_info.AdapterTypeText;
3bc8070fb   Salyzyn, Mark   [SCSI] aacraid: S...
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
  		int c;
  		if ((cp[0] == 'A') && (cp[1] == 'O') && (cp[2] == 'C'))
  			inqstrcpy("SMC", str->vid);
  		else {
  			c = sizeof(str->vid);
  			while (*cp && *cp != ' ' && --c)
  				++cp;
  			c = *cp;
  			*cp = '\0';
  			inqstrcpy (dev->supplement_adapter_info.AdapterTypeText,
  				   str->vid);
  			*cp = c;
  			while (*cp && *cp != ' ')
  				++cp;
  		}
794d0601e   Mark Haverkamp   [SCSI] aacraid: f...
764
765
766
767
768
769
770
771
772
773
774
775
776
  		while (*cp == ' ')
  			++cp;
  		/* last six chars reserved for vol type */
  		c = 0;
  		if (strlen(cp) > sizeof(str->pid)) {
  			c = cp[sizeof(str->pid)];
  			cp[sizeof(str->pid)] = '\0';
  		}
  		inqstrcpy (cp, str->pid);
  		if (c)
  			cp[sizeof(str->pid)] = c;
  	} else {
  		struct aac_driver_ident *mp = aac_get_driver_ident(dev->cardtype);
6391a1137   Tobias Klauser   [SCSI] drivers/sc...
777
778
  
  		inqstrcpy (mp->vname, str->vid);
794d0601e   Mark Haverkamp   [SCSI] aacraid: f...
779
780
781
  		/* last six chars reserved for vol type */
  		inqstrcpy (mp->model, str->pid);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
782

6391a1137   Tobias Klauser   [SCSI] drivers/sc...
783
  	if (tindex < ARRAY_SIZE(container_types)){
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
784
785
786
787
788
789
  		char *findit = str->pid;
  
  		for ( ; *findit != ' '; findit++); /* walk till we find a space */
  		/* RAID is superfluous in the context of a RAID device */
  		if (memcmp(findit-4, "RAID", 4) == 0)
  			*(findit -= 4) = ' ';
794d0601e   Mark Haverkamp   [SCSI] aacraid: f...
790
791
792
  		if (((findit - str->pid) + strlen(container_types[tindex]))
  		 < (sizeof(str->pid) + sizeof(str->prl)))
  			inqstrcpy (container_types[tindex], findit + 1);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
793
794
795
  	}
  	inqstrcpy ("V1.0", str->prl);
  }
88e2f98e1   Salyzyn, Mark   [SCSI] aacraid: a...
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
  static void get_container_serial_callback(void *context, struct fib * fibptr)
  {
  	struct aac_get_serial_resp * get_serial_reply;
  	struct scsi_cmnd * scsicmd;
  
  	BUG_ON(fibptr == NULL);
  
  	scsicmd = (struct scsi_cmnd *) context;
  	if (!aac_valid_context(scsicmd, fibptr))
  		return;
  
  	get_serial_reply = (struct aac_get_serial_resp *) fib_data(fibptr);
  	/* Failure is irrelevant, using default value instead */
  	if (le32_to_cpu(get_serial_reply->status) == CT_OK) {
  		char sp[13];
  		/* EVPD bit set */
  		sp[0] = INQD_PDT_DA;
  		sp[1] = scsicmd->cmnd[2];
  		sp[2] = 0;
  		sp[3] = snprintf(sp+4, sizeof(sp)-4, "%08X",
  		  le32_to_cpu(get_serial_reply->uid));
d4345028d   FUJITA Tomonori   [SCSI] aacraid: u...
817
  		scsi_sg_copy_from_buffer(scsicmd, sp, sizeof(sp));
88e2f98e1   Salyzyn, Mark   [SCSI] aacraid: a...
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
  	}
  
  	scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
  
  	aac_fib_complete(fibptr);
  	aac_fib_free(fibptr);
  	scsicmd->scsi_done(scsicmd);
  }
  
  /**
   *	aac_get_container_serial - get container serial, none blocking.
   */
  static int aac_get_container_serial(struct scsi_cmnd * scsicmd)
  {
  	int status;
  	struct aac_get_serial *dinfo;
  	struct fib * cmd_fibcontext;
  	struct aac_dev * dev;
  
  	dev = (struct aac_dev *)scsicmd->device->host->hostdata;
  
  	if (!(cmd_fibcontext = aac_fib_alloc(dev)))
  		return -ENOMEM;
  
  	aac_fib_init(cmd_fibcontext);
  	dinfo = (struct aac_get_serial *) fib_data(cmd_fibcontext);
  
  	dinfo->command = cpu_to_le32(VM_ContainerConfig);
  	dinfo->type = cpu_to_le32(CT_CID_TO_32BITS_UID);
  	dinfo->cid = cpu_to_le32(scmd_id(scsicmd));
  
  	status = aac_fib_send(ContainerCommand,
  		  cmd_fibcontext,
  		  sizeof (struct aac_get_serial),
  		  FsaNormal,
  		  0, 1,
  		  (fib_callback) get_container_serial_callback,
  		  (void *) scsicmd);
  
  	/*
  	 *	Check that the command queued to the controller
  	 */
  	if (status == -EINPROGRESS) {
  		scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
  		return 0;
  	}
  
  	printk(KERN_WARNING "aac_get_container_serial: aac_fib_send failed with status: %d.
  ", status);
  	aac_fib_complete(cmd_fibcontext);
  	aac_fib_free(cmd_fibcontext);
  	return -1;
  }
  
  /* Function: setinqserial
   *
   * Arguments: [1] pointer to void [1] int
   *
   * Purpose: Sets SCSI Unit Serial number.
   *          This is a fake. We should read a proper
   *          serial number from the container. <SuSE>But
   *          without docs it's quite hard to do it :-)
   *          So this will have to do in the meantime.</SuSE>
   */
  
  static int setinqserial(struct aac_dev *dev, void *data, int cid)
  {
  	/*
  	 *	This breaks array migration.
  	 */
  	return snprintf((char *)(data), sizeof(struct scsi_inq) - 4, "%08X%02X",
  			le32_to_cpu(dev->adapter_info.serial[0]), cid);
  }
8e31e607e   Salyzyn, Mark   [SCSI] aacraid: d...
891
892
  static inline void set_sense(struct sense_data *sense_data, u8 sense_key,
  	u8 sense_code, u8 a_sense_code, u8 bit_pointer, u16 field_pointer)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
893
  {
8e31e607e   Salyzyn, Mark   [SCSI] aacraid: d...
894
895
896
  	u8 *sense_buf = (u8 *)sense_data;
  	/* Sense data valid, err code 70h */
  	sense_buf[0] = 0x70; /* No info field */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
897
  	sense_buf[1] = 0;	/* Segment number, always zero */
8e31e607e   Salyzyn, Mark   [SCSI] aacraid: d...
898
  	sense_buf[2] = sense_key;	/* Sense key */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
899
900
901
  
  	sense_buf[12] = sense_code;	/* Additional sense code */
  	sense_buf[13] = a_sense_code;	/* Additional sense code qualifier */
8e31e607e   Salyzyn, Mark   [SCSI] aacraid: d...
902

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
903
  	if (sense_key == ILLEGAL_REQUEST) {
8e31e607e   Salyzyn, Mark   [SCSI] aacraid: d...
904
  		sense_buf[7] = 10;	/* Additional sense length */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
905

8e31e607e   Salyzyn, Mark   [SCSI] aacraid: d...
906
  		sense_buf[15] = bit_pointer;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
907
  		/* Illegal parameter is in the parameter block */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
908
  		if (sense_code == SENCODE_INVALID_CDB_FIELD)
8e31e607e   Salyzyn, Mark   [SCSI] aacraid: d...
909
  			sense_buf[15] |= 0xc0;/* Std sense key specific field */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
910
  		/* Illegal parameter is in the CDB block */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
911
912
  		sense_buf[16] = field_pointer >> 8;	/* MSB */
  		sense_buf[17] = field_pointer;		/* LSB */
8e31e607e   Salyzyn, Mark   [SCSI] aacraid: d...
913
914
  	} else
  		sense_buf[7] = 6;	/* Additional sense length */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
915
  }
e8f32de52   Mark Haverkamp   [SCSI] aacraid: r...
916
917
918
919
920
921
922
923
  static int aac_bounds_32(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba)
  {
  	if (lba & 0xffffffff00000000LL) {
  		int cid = scmd_id(cmd);
  		dprintk((KERN_DEBUG "aacraid: Illegal lba
  "));
  		cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
  			SAM_STAT_CHECK_CONDITION;
8e31e607e   Salyzyn, Mark   [SCSI] aacraid: d...
924
925
926
  		set_sense(&dev->fsa_dev[cid].sense_data,
  		  HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
  		  ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
e8f32de52   Mark Haverkamp   [SCSI] aacraid: r...
927
  		memcpy(cmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
3ace426f9   Salyzyn, Mark   [SCSI] aacraid: r...
928
929
  		       min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
  			     SCSI_SENSE_BUFFERSIZE));
e8f32de52   Mark Haverkamp   [SCSI] aacraid: r...
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
  		cmd->scsi_done(cmd);
  		return 1;
  	}
  	return 0;
  }
  
  static int aac_bounds_64(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba)
  {
  	return 0;
  }
  
  static void io_callback(void *context, struct fib * fibptr);
  
  static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
  {
  	u16 fibsize;
  	struct aac_raw_io *readcmd;
  	aac_fib_init(fib);
  	readcmd = (struct aac_raw_io *) fib_data(fib);
  	readcmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff));
  	readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
  	readcmd->count = cpu_to_le32(count<<9);
  	readcmd->cid = cpu_to_le16(scmd_id(cmd));
9d399cc7f   Salyzyn, Mark   [SCSI] aacraid: a...
953
  	readcmd->flags = cpu_to_le16(IO_TYPE_READ);
e8f32de52   Mark Haverkamp   [SCSI] aacraid: r...
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
  	readcmd->bpTotal = 0;
  	readcmd->bpComplete = 0;
  
  	aac_build_sgraw(cmd, &readcmd->sg);
  	fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(readcmd->sg.count) - 1) * sizeof (struct sgentryraw));
  	BUG_ON(fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr)));
  	/*
  	 *	Now send the Fib to the adapter
  	 */
  	return aac_fib_send(ContainerRawIo,
  			  fib,
  			  fibsize,
  			  FsaNormal,
  			  0, 1,
  			  (fib_callback) io_callback,
  			  (void *) cmd);
  }
  
  static int aac_read_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
  {
  	u16 fibsize;
  	struct aac_read64 *readcmd;
  	aac_fib_init(fib);
  	readcmd = (struct aac_read64 *) fib_data(fib);
  	readcmd->command = cpu_to_le32(VM_CtHostRead64);
  	readcmd->cid = cpu_to_le16(scmd_id(cmd));
  	readcmd->sector_count = cpu_to_le16(count);
  	readcmd->block = cpu_to_le32((u32)(lba&0xffffffff));
  	readcmd->pad   = 0;
  	readcmd->flags = 0;
  
  	aac_build_sg64(cmd, &readcmd->sg);
  	fibsize = sizeof(struct aac_read64) +
  		((le32_to_cpu(readcmd->sg.count) - 1) *
  		 sizeof (struct sgentry64));
  	BUG_ON (fibsize > (fib->dev->max_fib_size -
  				sizeof(struct aac_fibhdr)));
  	/*
  	 *	Now send the Fib to the adapter
  	 */
  	return aac_fib_send(ContainerCommand64,
  			  fib,
  			  fibsize,
  			  FsaNormal,
  			  0, 1,
  			  (fib_callback) io_callback,
  			  (void *) cmd);
  }
  
  static int aac_read_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count)
  {
  	u16 fibsize;
  	struct aac_read *readcmd;
  	aac_fib_init(fib);
  	readcmd = (struct aac_read *) fib_data(fib);
  	readcmd->command = cpu_to_le32(VM_CtBlockRead);
f3307f727   Christoph Hellwig   [SCSI] aacraid: d...
1010
  	readcmd->cid = cpu_to_le32(scmd_id(cmd));
e8f32de52   Mark Haverkamp   [SCSI] aacraid: r...
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
  	readcmd->block = cpu_to_le32((u32)(lba&0xffffffff));
  	readcmd->count = cpu_to_le32(count * 512);
  
  	aac_build_sg(cmd, &readcmd->sg);
  	fibsize = sizeof(struct aac_read) +
  			((le32_to_cpu(readcmd->sg.count) - 1) *
  			 sizeof (struct sgentry));
  	BUG_ON (fibsize > (fib->dev->max_fib_size -
  				sizeof(struct aac_fibhdr)));
  	/*
  	 *	Now send the Fib to the adapter
  	 */
  	return aac_fib_send(ContainerCommand,
  			  fib,
  			  fibsize,
  			  FsaNormal,
  			  0, 1,
  			  (fib_callback) io_callback,
  			  (void *) cmd);
  }
9d399cc7f   Salyzyn, Mark   [SCSI] aacraid: a...
1031
  static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua)
e8f32de52   Mark Haverkamp   [SCSI] aacraid: r...
1032
1033
1034
1035
1036
1037
1038
1039
1040
  {
  	u16 fibsize;
  	struct aac_raw_io *writecmd;
  	aac_fib_init(fib);
  	writecmd = (struct aac_raw_io *) fib_data(fib);
  	writecmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff));
  	writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32));
  	writecmd->count = cpu_to_le32(count<<9);
  	writecmd->cid = cpu_to_le16(scmd_id(cmd));
95e852e1e   Salyzyn, Mark   [SCSI] aacraid: a...
1041
1042
  	writecmd->flags = (fua && ((aac_cache & 5) != 1) &&
  	  (((aac_cache & 5) != 5) || !fib->dev->cache_protected)) ?
9d399cc7f   Salyzyn, Mark   [SCSI] aacraid: a...
1043
1044
  		cpu_to_le16(IO_TYPE_WRITE|IO_SUREWRITE) :
  		cpu_to_le16(IO_TYPE_WRITE);
e8f32de52   Mark Haverkamp   [SCSI] aacraid: r...
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
  	writecmd->bpTotal = 0;
  	writecmd->bpComplete = 0;
  
  	aac_build_sgraw(cmd, &writecmd->sg);
  	fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(writecmd->sg.count) - 1) * sizeof (struct sgentryraw));
  	BUG_ON(fibsize > (fib->dev->max_fib_size - sizeof(struct aac_fibhdr)));
  	/*
  	 *	Now send the Fib to the adapter
  	 */
  	return aac_fib_send(ContainerRawIo,
  			  fib,
  			  fibsize,
  			  FsaNormal,
  			  0, 1,
  			  (fib_callback) io_callback,
  			  (void *) cmd);
  }
9d399cc7f   Salyzyn, Mark   [SCSI] aacraid: a...
1062
  static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua)
e8f32de52   Mark Haverkamp   [SCSI] aacraid: r...
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
  {
  	u16 fibsize;
  	struct aac_write64 *writecmd;
  	aac_fib_init(fib);
  	writecmd = (struct aac_write64 *) fib_data(fib);
  	writecmd->command = cpu_to_le32(VM_CtHostWrite64);
  	writecmd->cid = cpu_to_le16(scmd_id(cmd));
  	writecmd->sector_count = cpu_to_le16(count);
  	writecmd->block = cpu_to_le32((u32)(lba&0xffffffff));
  	writecmd->pad	= 0;
  	writecmd->flags	= 0;
  
  	aac_build_sg64(cmd, &writecmd->sg);
  	fibsize = sizeof(struct aac_write64) +
  		((le32_to_cpu(writecmd->sg.count) - 1) *
  		 sizeof (struct sgentry64));
  	BUG_ON (fibsize > (fib->dev->max_fib_size -
  				sizeof(struct aac_fibhdr)));
  	/*
  	 *	Now send the Fib to the adapter
  	 */
  	return aac_fib_send(ContainerCommand64,
  			  fib,
  			  fibsize,
  			  FsaNormal,
  			  0, 1,
  			  (fib_callback) io_callback,
  			  (void *) cmd);
  }
9d399cc7f   Salyzyn, Mark   [SCSI] aacraid: a...
1092
  static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua)
e8f32de52   Mark Haverkamp   [SCSI] aacraid: r...
1093
1094
1095
1096
1097
1098
  {
  	u16 fibsize;
  	struct aac_write *writecmd;
  	aac_fib_init(fib);
  	writecmd = (struct aac_write *) fib_data(fib);
  	writecmd->command = cpu_to_le32(VM_CtBlockWrite);
f3307f727   Christoph Hellwig   [SCSI] aacraid: d...
1099
  	writecmd->cid = cpu_to_le32(scmd_id(cmd));
e8f32de52   Mark Haverkamp   [SCSI] aacraid: r...
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
  	writecmd->block = cpu_to_le32((u32)(lba&0xffffffff));
  	writecmd->count = cpu_to_le32(count * 512);
  	writecmd->sg.count = cpu_to_le32(1);
  	/* ->stable is not used - it did mean which type of write */
  
  	aac_build_sg(cmd, &writecmd->sg);
  	fibsize = sizeof(struct aac_write) +
  		((le32_to_cpu(writecmd->sg.count) - 1) *
  		 sizeof (struct sgentry));
  	BUG_ON (fibsize > (fib->dev->max_fib_size -
  				sizeof(struct aac_fibhdr)));
  	/*
  	 *	Now send the Fib to the adapter
  	 */
  	return aac_fib_send(ContainerCommand,
  			  fib,
  			  fibsize,
  			  FsaNormal,
  			  0, 1,
  			  (fib_callback) io_callback,
  			  (void *) cmd);
  }
  
  static struct aac_srb * aac_scsi_common(struct fib * fib, struct scsi_cmnd * cmd)
  {
  	struct aac_srb * srbcmd;
  	u32 flag;
  	u32 timeout;
  
  	aac_fib_init(fib);
  	switch(cmd->sc_data_direction){
  	case DMA_TO_DEVICE:
  		flag = SRB_DataOut;
  		break;
  	case DMA_BIDIRECTIONAL:
  		flag = SRB_DataIn | SRB_DataOut;
  		break;
  	case DMA_FROM_DEVICE:
  		flag = SRB_DataIn;
  		break;
  	case DMA_NONE:
  	default:	/* shuts up some versions of gcc */
  		flag = SRB_NoDataXfer;
  		break;
  	}
  
  	srbcmd = (struct aac_srb*) fib_data(fib);
  	srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);
  	srbcmd->channel  = cpu_to_le32(aac_logical_to_phys(scmd_channel(cmd)));
  	srbcmd->id       = cpu_to_le32(scmd_id(cmd));
  	srbcmd->lun      = cpu_to_le32(cmd->device->lun);
  	srbcmd->flags    = cpu_to_le32(flag);
242f9dcb8   Jens Axboe   block: unify requ...
1152
  	timeout = cmd->request->timeout/HZ;
e8f32de52   Mark Haverkamp   [SCSI] aacraid: r...
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
  	if (timeout == 0)
  		timeout = 1;
  	srbcmd->timeout  = cpu_to_le32(timeout);  // timeout in seconds
  	srbcmd->retry_limit = 0; /* Obsolete parameter */
  	srbcmd->cdb_size = cpu_to_le32(cmd->cmd_len);
  	return srbcmd;
  }
  
  static void aac_srb_callback(void *context, struct fib * fibptr);
  
  static int aac_scsi_64(struct fib * fib, struct scsi_cmnd * cmd)
  {
  	u16 fibsize;
  	struct aac_srb * srbcmd = aac_scsi_common(fib, cmd);
  
  	aac_build_sg64(cmd, (struct sgmap64*) &srbcmd->sg);
727eead62   FUJITA Tomonori   [SCSI] aacraid: c...
1169
  	srbcmd->count = cpu_to_le32(scsi_bufflen(cmd));
e8f32de52   Mark Haverkamp   [SCSI] aacraid: r...
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
  
  	memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
  	memcpy(srbcmd->cdb, cmd->cmnd, cmd->cmd_len);
  	/*
  	 *	Build Scatter/Gather list
  	 */
  	fibsize = sizeof (struct aac_srb) - sizeof (struct sgentry) +
  		((le32_to_cpu(srbcmd->sg.count) & 0xff) *
  		 sizeof (struct sgentry64));
  	BUG_ON (fibsize > (fib->dev->max_fib_size -
  				sizeof(struct aac_fibhdr)));
  
  	/*
  	 *	Now send the Fib to the adapter
  	 */
  	return aac_fib_send(ScsiPortCommand64, fib,
  				fibsize, FsaNormal, 0, 1,
  				  (fib_callback) aac_srb_callback,
  				  (void *) cmd);
  }
  
  static int aac_scsi_32(struct fib * fib, struct scsi_cmnd * cmd)
  {
  	u16 fibsize;
  	struct aac_srb * srbcmd = aac_scsi_common(fib, cmd);
  
  	aac_build_sg(cmd, (struct sgmap*)&srbcmd->sg);
727eead62   FUJITA Tomonori   [SCSI] aacraid: c...
1197
  	srbcmd->count = cpu_to_le32(scsi_bufflen(cmd));
e8f32de52   Mark Haverkamp   [SCSI] aacraid: r...
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
  
  	memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
  	memcpy(srbcmd->cdb, cmd->cmnd, cmd->cmd_len);
  	/*
  	 *	Build Scatter/Gather list
  	 */
  	fibsize = sizeof (struct aac_srb) +
  		(((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) *
  		 sizeof (struct sgentry));
  	BUG_ON (fibsize > (fib->dev->max_fib_size -
  				sizeof(struct aac_fibhdr)));
  
  	/*
  	 *	Now send the Fib to the adapter
  	 */
  	return aac_fib_send(ScsiPortCommand, fib, fibsize, FsaNormal, 0, 1,
  				  (fib_callback) aac_srb_callback, (void *) cmd);
  }
94cf6ba11   Salyzyn, Mark   [SCSI] aacraid: f...
1216
1217
  static int aac_scsi_32_64(struct fib * fib, struct scsi_cmnd * cmd)
  {
d8e965076   Leubner, Achim   [SCSI] aacraid dr...
1218
1219
  	if ((sizeof(dma_addr_t) > 4) && fib->dev->needs_dac &&
  	    (fib->dev->adapter_info.options & AAC_OPT_SGMAP_HOST64))
94cf6ba11   Salyzyn, Mark   [SCSI] aacraid: f...
1220
1221
1222
  		return FAILED;
  	return aac_scsi_32(fib, cmd);
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1223
1224
1225
  int aac_get_adapter_info(struct aac_dev* dev)
  {
  	struct fib* fibptr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1226
1227
  	int rcode;
  	u32 tmp;
849717383   Mark Haverkamp   [SCSI] aacraid: N...
1228
1229
1230
  	struct aac_adapter_info *info;
  	struct aac_bus_info *command;
  	struct aac_bus_info_response *bus_info;
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
1231

bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
1232
  	if (!(fibptr = aac_fib_alloc(dev)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1233
  		return -ENOMEM;
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
1234
  	aac_fib_init(fibptr);
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
1235
1236
  	info = (struct aac_adapter_info *) fib_data(fibptr);
  	memset(info,0,sizeof(*info));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1237

bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
1238
  	rcode = aac_fib_send(RequestAdapterInfo,
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
1239
  			 fibptr,
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
1240
  			 sizeof(*info),
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
1241
  			 FsaNormal,
9203344cb   Mark Haverkamp   [SCSI] aacraid: i...
1242
  			 -1, 1, /* First `interrupt' command uses special wait */
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
1243
  			 NULL,
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
1244
1245
1246
  			 NULL);
  
  	if (rcode < 0) {
cacb6dc3d   Penchala Narasimha Reddy Chilakala, ERS-HCLTech   [SCSI] aacraid: f...
1247
1248
1249
1250
1251
1252
  		/* FIB should be freed only after
  		 * getting the response from the F/W */
  		if (rcode != -ERESTARTSYS) {
  			aac_fib_complete(fibptr);
  			aac_fib_free(fibptr);
  		}
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
1253
1254
1255
  		return rcode;
  	}
  	memcpy(&dev->adapter_info, info, sizeof(*info));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1256

7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
1257
  	if (dev->adapter_info.options & AAC_OPT_SUPPLEMENT_ADAPTER_INFO) {
06a43d172   Salyzyn, Mark   [SCSI] aacraid: v...
1258
  		struct aac_supplement_adapter_info * sinfo;
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
1259

bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
1260
  		aac_fib_init(fibptr);
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
1261

06a43d172   Salyzyn, Mark   [SCSI] aacraid: v...
1262
  		sinfo = (struct aac_supplement_adapter_info *) fib_data(fibptr);
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
1263

06a43d172   Salyzyn, Mark   [SCSI] aacraid: v...
1264
  		memset(sinfo,0,sizeof(*sinfo));
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
1265

bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
1266
  		rcode = aac_fib_send(RequestSupplementAdapterInfo,
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
1267
  				 fibptr,
06a43d172   Salyzyn, Mark   [SCSI] aacraid: v...
1268
  				 sizeof(*sinfo),
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
1269
1270
1271
1272
1273
1274
  				 FsaNormal,
  				 1, 1,
  				 NULL,
  				 NULL);
  
  		if (rcode >= 0)
06a43d172   Salyzyn, Mark   [SCSI] aacraid: v...
1275
  			memcpy(&dev->supplement_adapter_info, sinfo, sizeof(*sinfo));
cacb6dc3d   Penchala Narasimha Reddy Chilakala, ERS-HCLTech   [SCSI] aacraid: f...
1276
1277
1278
1279
1280
  		if (rcode == -ERESTARTSYS) {
  			fibptr = aac_fib_alloc(dev);
  			if (!fibptr)
  				return -ENOMEM;
  		}
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
1281
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1282

849717383   Mark Haverkamp   [SCSI] aacraid: N...
1283

8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
1284
1285
  	/*
  	 * GetBusInfo
849717383   Mark Haverkamp   [SCSI] aacraid: N...
1286
  	 */
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
1287
  	aac_fib_init(fibptr);
849717383   Mark Haverkamp   [SCSI] aacraid: N...
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
  
  	bus_info = (struct aac_bus_info_response *) fib_data(fibptr);
  
  	memset(bus_info, 0, sizeof(*bus_info));
  
  	command = (struct aac_bus_info *)bus_info;
  
  	command->Command = cpu_to_le32(VM_Ioctl);
  	command->ObjType = cpu_to_le32(FT_DRIVE);
  	command->MethodId = cpu_to_le32(1);
  	command->CtlCmd = cpu_to_le32(GetBusInfo);
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
1299
  	rcode = aac_fib_send(ContainerCommand,
849717383   Mark Haverkamp   [SCSI] aacraid: N...
1300
1301
1302
1303
1304
  			 fibptr,
  			 sizeof (*bus_info),
  			 FsaNormal,
  			 1, 1,
  			 NULL, NULL);
94cf6ba11   Salyzyn, Mark   [SCSI] aacraid: f...
1305
1306
  	/* reasoned default */
  	dev->maximum_num_physicals = 16;
849717383   Mark Haverkamp   [SCSI] aacraid: N...
1307
1308
1309
1310
  	if (rcode >= 0 && le32_to_cpu(bus_info->Status) == ST_OK) {
  		dev->maximum_num_physicals = le32_to_cpu(bus_info->TargetsPerBus);
  		dev->maximum_num_channels = le32_to_cpu(bus_info->BusCount);
  	}
8c867b257   Mark Haverkamp   [SCSI] aacraid: R...
1311
  	if (!dev->in_reset) {
24f02e1d8   Salyzyn, Mark   [SCSI] aacraid: a...
1312
  		char buffer[16];
8c867b257   Mark Haverkamp   [SCSI] aacraid: R...
1313
1314
1315
  		tmp = le32_to_cpu(dev->adapter_info.kernelrev);
  		printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d] %.*s
  ",
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
1316
  			dev->name,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1317
1318
1319
1320
  			dev->id,
  			tmp>>24,
  			(tmp>>16)&0xff,
  			tmp&0xff,
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
1321
1322
1323
  			le32_to_cpu(dev->adapter_info.kernelbuild),
  			(int)sizeof(dev->supplement_adapter_info.BuildDate),
  			dev->supplement_adapter_info.BuildDate);
8c867b257   Mark Haverkamp   [SCSI] aacraid: R...
1324
1325
1326
  		tmp = le32_to_cpu(dev->adapter_info.monitorrev);
  		printk(KERN_INFO "%s%d: monitor %d.%d-%d[%d]
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1327
1328
1329
  			dev->name, dev->id,
  			tmp>>24,(tmp>>16)&0xff,tmp&0xff,
  			le32_to_cpu(dev->adapter_info.monitorbuild));
8c867b257   Mark Haverkamp   [SCSI] aacraid: R...
1330
1331
1332
  		tmp = le32_to_cpu(dev->adapter_info.biosrev);
  		printk(KERN_INFO "%s%d: bios %d.%d-%d[%d]
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1333
1334
1335
  			dev->name, dev->id,
  			tmp>>24,(tmp>>16)&0xff,tmp&0xff,
  			le32_to_cpu(dev->adapter_info.biosbuild));
24f02e1d8   Salyzyn, Mark   [SCSI] aacraid: a...
1336
  		buffer[0] = '\0';
ee959b00c   Tony Jones   SCSI: convert str...
1337
  		if (aac_get_serial_number(
24f02e1d8   Salyzyn, Mark   [SCSI] aacraid: a...
1338
1339
1340
  		  shost_to_class(dev->scsi_host_ptr), buffer))
  			printk(KERN_INFO "%s%d: serial %s",
  			  dev->name, dev->id, buffer);
a45c863f0   Salyzyn, Mark   [SCSI] aacraid: f...
1341
1342
1343
1344
1345
1346
1347
  		if (dev->supplement_adapter_info.VpdInfo.Tsid[0]) {
  			printk(KERN_INFO "%s%d: TSID %.*s
  ",
  			  dev->name, dev->id,
  			  (int)sizeof(dev->supplement_adapter_info.VpdInfo.Tsid),
  			  dev->supplement_adapter_info.VpdInfo.Tsid);
  		}
2f7ecc55b   Salyzyn, Mark   [SCSI] aacraid: i...
1348
  		if (!aac_check_reset || ((aac_check_reset == 1) &&
a3940da5e   Salyzyn, Mark   [SCSI] aacraid: f...
1349
1350
  		  (dev->supplement_adapter_info.SupportedOptions2 &
  		  AAC_OPTION_IGNORE_RESET))) {
29c976844   Salyzyn, Mark   [SCSI] aacraid: a...
1351
1352
1353
1354
  			printk(KERN_INFO "%s%d: Reset Adapter Ignored
  ",
  			  dev->name, dev->id);
  		}
8c867b257   Mark Haverkamp   [SCSI] aacraid: R...
1355
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1356

95e852e1e   Salyzyn, Mark   [SCSI] aacraid: a...
1357
  	dev->cache_protected = 0;
cb1042f28   Salyzyn, Mark   [SCSI] aacraid: a...
1358
1359
  	dev->jbod = ((dev->supplement_adapter_info.FeatureBits &
  		AAC_FEATURE_JBOD) != 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1360
1361
  	dev->nondasd_support = 0;
  	dev->raid_scsi_mode = 0;
95e852e1e   Salyzyn, Mark   [SCSI] aacraid: a...
1362
  	if(dev->adapter_info.options & AAC_OPT_NONDASD)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1363
  		dev->nondasd_support = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
  
  	/*
  	 * If the firmware supports ROMB RAID/SCSI mode and we are currently
  	 * in RAID/SCSI mode, set the flag. For now if in this mode we will
  	 * force nondasd support on. If we decide to allow the non-dasd flag
  	 * additional changes changes will have to be made to support
  	 * RAID/SCSI.  the function aac_scsi_cmd in this module will have to be
  	 * changed to support the new dev->raid_scsi_mode flag instead of
  	 * leaching off of the dev->nondasd_support flag. Also in linit.c the
  	 * function aac_detect will have to be modified where it sets up the
  	 * max number of channels based on the aac->nondasd_support flag only.
  	 */
  	if ((dev->adapter_info.options & AAC_OPT_SCSI_MANAGED) &&
  	    (dev->adapter_info.options & AAC_OPT_RAID_SCSI_MODE)) {
  		dev->nondasd_support = 1;
  		dev->raid_scsi_mode = 1;
  	}
  	if (dev->raid_scsi_mode != 0)
  		printk(KERN_INFO "%s%d: ROMB RAID/SCSI mode enabled
  ",
  				dev->name, dev->id);
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
1385

95e852e1e   Salyzyn, Mark   [SCSI] aacraid: a...
1386
  	if (nondasd != -1)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1387
  		dev->nondasd_support = (nondasd!=0);
2f7ecc55b   Salyzyn, Mark   [SCSI] aacraid: i...
1388
  	if (dev->nondasd_support && !dev->in_reset)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1389
1390
  		printk(KERN_INFO "%s%d: Non-DASD support enabled.
  ",dev->name, dev->id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1391

e930438c4   Yang Hongyang   Replace all DMA_n...
1392
  	if (dma_get_required_mask(&dev->pdev->dev) > DMA_BIT_MASK(32))
d8e965076   Leubner, Achim   [SCSI] aacraid dr...
1393
  		dev->needs_dac = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1394
  	dev->dac_support = 0;
d8e965076   Leubner, Achim   [SCSI] aacraid dr...
1395
1396
  	if ((sizeof(dma_addr_t) > 4) && dev->needs_dac &&
  	    (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)) {
2f7ecc55b   Salyzyn, Mark   [SCSI] aacraid: i...
1397
1398
1399
1400
  		if (!dev->in_reset)
  			printk(KERN_INFO "%s%d: 64bit support enabled.
  ",
  				dev->name, dev->id);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1401
1402
1403
1404
1405
1406
  		dev->dac_support = 1;
  	}
  
  	if(dacmode != -1) {
  		dev->dac_support = (dacmode!=0);
  	}
d8e965076   Leubner, Achim   [SCSI] aacraid dr...
1407
1408
1409
1410
1411
1412
1413
1414
  
  	/* avoid problems with AAC_QUIRK_SCSI_32 controllers */
  	if (dev->dac_support &&	(aac_get_driver_ident(dev->cardtype)->quirks
  		& AAC_QUIRK_SCSI_32)) {
  		dev->nondasd_support = 0;
  		dev->jbod = 0;
  		expose_physicals = 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1415
  	if(dev->dac_support != 0) {
6a35528a8   Yang Hongyang   dma-mapping: repl...
1416
1417
  		if (!pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(64)) &&
  			!pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(64))) {
2f7ecc55b   Salyzyn, Mark   [SCSI] aacraid: i...
1418
1419
1420
1421
  			if (!dev->in_reset)
  				printk(KERN_INFO"%s%d: 64 Bit DAC enabled
  ",
  					dev->name, dev->id);
284901a90   Yang Hongyang   dma-mapping: repl...
1422
1423
  		} else if (!pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(32)) &&
  			!pci_set_consistent_dma_mask(dev->pdev, DMA_BIT_MASK(32))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
  			printk(KERN_INFO"%s%d: DMA mask set failed, 64 Bit DAC disabled
  ",
  				dev->name, dev->id);
  			dev->dac_support = 0;
  		} else {
  			printk(KERN_WARNING"%s%d: No suitable DMA available.
  ",
  				dev->name, dev->id);
  			rcode = -ENOMEM;
  		}
  	}
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
1435
  	/*
e8f32de52   Mark Haverkamp   [SCSI] aacraid: r...
1436
1437
  	 * Deal with configuring for the individualized limits of each packet
  	 * interface.
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
1438
  	 */
e8f32de52   Mark Haverkamp   [SCSI] aacraid: r...
1439
  	dev->a_ops.adapter_scsi = (dev->dac_support)
94cf6ba11   Salyzyn, Mark   [SCSI] aacraid: f...
1440
1441
1442
  	  ? ((aac_get_driver_ident(dev->cardtype)->quirks & AAC_QUIRK_SCSI_32)
  				? aac_scsi_32_64
  				: aac_scsi_64)
e8f32de52   Mark Haverkamp   [SCSI] aacraid: r...
1443
1444
1445
1446
1447
1448
1449
1450
1451
  				: aac_scsi_32;
  	if (dev->raw_io_interface) {
  		dev->a_ops.adapter_bounds = (dev->raw_io_64)
  					? aac_bounds_64
  					: aac_bounds_32;
  		dev->a_ops.adapter_read = aac_read_raw_io;
  		dev->a_ops.adapter_write = aac_write_raw_io;
  	} else {
  		dev->a_ops.adapter_bounds = aac_bounds_32;
0e68c0037   Mark Haverkamp   [SCSI] aacraid: s...
1452
  		dev->scsi_host_ptr->sg_tablesize = (dev->max_fib_size -
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
1453
  			sizeof(struct aac_fibhdr) -
63a70eeaa   Mark Haverkamp   [SCSI] aacraid: f...
1454
1455
  			sizeof(struct aac_write) + sizeof(struct sgentry)) /
  				sizeof(struct sgentry);
0e68c0037   Mark Haverkamp   [SCSI] aacraid: s...
1456
  		if (dev->dac_support) {
e8f32de52   Mark Haverkamp   [SCSI] aacraid: r...
1457
1458
  			dev->a_ops.adapter_read = aac_read_block64;
  			dev->a_ops.adapter_write = aac_write_block64;
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
1459
1460
  			/*
  			 * 38 scatter gather elements
0e68c0037   Mark Haverkamp   [SCSI] aacraid: s...
1461
1462
1463
1464
1465
  			 */
  			dev->scsi_host_ptr->sg_tablesize =
  				(dev->max_fib_size -
  				sizeof(struct aac_fibhdr) -
  				sizeof(struct aac_write64) +
63a70eeaa   Mark Haverkamp   [SCSI] aacraid: f...
1466
1467
  				sizeof(struct sgentry64)) /
  					sizeof(struct sgentry64);
e8f32de52   Mark Haverkamp   [SCSI] aacraid: r...
1468
1469
1470
  		} else {
  			dev->a_ops.adapter_read = aac_read_block;
  			dev->a_ops.adapter_write = aac_write_block;
0e68c0037   Mark Haverkamp   [SCSI] aacraid: s...
1471
1472
  		}
  		dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT;
e8b12f0fb   Mahesh Rajashekhara   [SCSI] aacraid: A...
1473
1474
1475
  		if (dev->adapter_info.options & AAC_OPT_NEW_COMM_TYPE1)
  			dev->adapter_info.options |= AAC_OPT_NEW_COMM;
  		if (!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) {
0e68c0037   Mark Haverkamp   [SCSI] aacraid: s...
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
  			/*
  			 * Worst case size that could cause sg overflow when
  			 * we break up SG elements that are larger than 64KB.
  			 * Would be nice if we could tell the SCSI layer what
  			 * the maximum SG element size can be. Worst case is
  			 * (sg_tablesize-1) 4KB elements with one 64KB
  			 * element.
  			 *	32bit -> 468 or 238KB	64bit -> 424 or 212KB
  			 */
  			dev->scsi_host_ptr->max_sectors =
  			  (dev->scsi_host_ptr->sg_tablesize * 8) + 112;
  		}
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
1488
  	}
cacb6dc3d   Penchala Narasimha Reddy Chilakala, ERS-HCLTech   [SCSI] aacraid: f...
1489
1490
1491
1492
1493
  	/* FIB should be freed only after getting the response from the F/W */
  	if (rcode != -ERESTARTSYS) {
  		aac_fib_complete(fibptr);
  		aac_fib_free(fibptr);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1494
1495
1496
  
  	return rcode;
  }
e53cb35aa   Mark Haverkamp   [SCSI] aacraid: r...
1497
  static void io_callback(void *context, struct fib * fibptr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1498
1499
1500
1501
  {
  	struct aac_dev *dev;
  	struct aac_read_reply *readreply;
  	struct scsi_cmnd *scsicmd;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1502
1503
1504
  	u32 cid;
  
  	scsicmd = (struct scsi_cmnd *) context;
03d443372   Mark Haverkamp   [SCSI] aacraid: I...
1505
1506
  	if (!aac_valid_context(scsicmd, fibptr))
  		return;
1a655040c   Salyzyn, Mark   [SCSI] aacraid: p...
1507
  	dev = fibptr->dev;
e5718774f   Mark Haverkamp   [SCSI] aacraid: U...
1508
  	cid = scmd_id(scsicmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1509

7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
  	if (nblank(dprintk(x))) {
  		u64 lba;
  		switch (scsicmd->cmnd[0]) {
  		case WRITE_6:
  		case READ_6:
  			lba = ((scsicmd->cmnd[1] & 0x1F) << 16) |
  			    (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
  			break;
  		case WRITE_16:
  		case READ_16:
  			lba = ((u64)scsicmd->cmnd[2] << 56) |
  			      ((u64)scsicmd->cmnd[3] << 48) |
  			      ((u64)scsicmd->cmnd[4] << 40) |
  			      ((u64)scsicmd->cmnd[5] << 32) |
  			      ((u64)scsicmd->cmnd[6] << 24) |
  			      (scsicmd->cmnd[7] << 16) |
  			      (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
  			break;
  		case WRITE_12:
  		case READ_12:
  			lba = ((u64)scsicmd->cmnd[2] << 24) |
  			      (scsicmd->cmnd[3] << 16) |
  			      (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
  			break;
  		default:
  			lba = ((u64)scsicmd->cmnd[2] << 24) |
  			       (scsicmd->cmnd[3] << 16) |
  			       (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
  			break;
  		}
  		printk(KERN_DEBUG
  		  "io_callback[cpu %d]: lba = %llu, t = %ld.
  ",
  		  smp_processor_id(), (unsigned long long)lba, jiffies);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1545

125e18745   Eric Sesterhenn   [PATCH] More BUG_...
1546
  	BUG_ON(fibptr == NULL);
727eead62   FUJITA Tomonori   [SCSI] aacraid: c...
1547
1548
  
  	scsi_dma_unmap(scsicmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1549
  	readreply = (struct aac_read_reply *)fib_data(fibptr);
655d722cf   Mark Salyzyn   [SCSI] aacraid: A...
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
  	switch (le32_to_cpu(readreply->status)) {
  	case ST_OK:
  		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
  			SAM_STAT_GOOD;
  		dev->fsa_dev[cid].sense_data.sense_key = NO_SENSE;
  		break;
  	case ST_NOT_READY:
  		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
  			SAM_STAT_CHECK_CONDITION;
  		set_sense(&dev->fsa_dev[cid].sense_data, NOT_READY,
  		  SENCODE_BECOMING_READY, ASENCODE_BECOMING_READY, 0, 0);
  		memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
  		       min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
  			     SCSI_SENSE_BUFFERSIZE));
  		break;
  	default:
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
1566
  #ifdef AAC_DETAILED_STATUS_INFO
e53cb35aa   Mark Haverkamp   [SCSI] aacraid: r...
1567
1568
  		printk(KERN_WARNING "io_callback: io failed, status = %d
  ",
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
1569
1570
  		  le32_to_cpu(readreply->status));
  #endif
655d722cf   Mark Salyzyn   [SCSI] aacraid: A...
1571
1572
  		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
  			SAM_STAT_CHECK_CONDITION;
8e31e607e   Salyzyn, Mark   [SCSI] aacraid: d...
1573
1574
1575
  		set_sense(&dev->fsa_dev[cid].sense_data,
  		  HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
  		  ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1576
  		memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
3ace426f9   Salyzyn, Mark   [SCSI] aacraid: r...
1577
1578
  		       min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
  			     SCSI_SENSE_BUFFERSIZE));
655d722cf   Mark Salyzyn   [SCSI] aacraid: A...
1579
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1580
  	}
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
1581
1582
  	aac_fib_complete(fibptr);
  	aac_fib_free(fibptr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1583

8e0c5ebde   Mark Haverkamp   [SCSI] aacraid: N...
1584
  	scsicmd->scsi_done(scsicmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1585
  }
9e7c349c9   Mark Haverkamp   [SCSI] aacraid: r...
1586
  static int aac_read(struct scsi_cmnd * scsicmd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1587
  {
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1588
  	u64 lba;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1589
1590
  	u32 count;
  	int status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1591
1592
  	struct aac_dev *dev;
  	struct fib * cmd_fibcontext;
da3cc679b   Rajashekhara, Mahesh   [SCSI] aacraid: p...
1593
  	int cid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1594
1595
1596
1597
1598
  
  	dev = (struct aac_dev *)scsicmd->device->host->hostdata;
  	/*
  	 *	Get block address and transfer length
  	 */
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1599
1600
  	switch (scsicmd->cmnd[0]) {
  	case READ_6:
9e7c349c9   Mark Haverkamp   [SCSI] aacraid: r...
1601
1602
  		dprintk((KERN_DEBUG "aachba: received a read(6) command on id %d.
  ", scmd_id(scsicmd)));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1603

8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
1604
  		lba = ((scsicmd->cmnd[1] & 0x1F) << 16) |
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1605
  			(scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1606
1607
1608
1609
  		count = scsicmd->cmnd[4];
  
  		if (count == 0)
  			count = 256;
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1610
1611
  		break;
  	case READ_16:
9e7c349c9   Mark Haverkamp   [SCSI] aacraid: r...
1612
1613
  		dprintk((KERN_DEBUG "aachba: received a read(16) command on id %d.
  ", scmd_id(scsicmd)));
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1614

8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
1615
1616
  		lba =	((u64)scsicmd->cmnd[2] << 56) |
  			((u64)scsicmd->cmnd[3] << 48) |
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1617
1618
  			((u64)scsicmd->cmnd[4] << 40) |
  			((u64)scsicmd->cmnd[5] << 32) |
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
1619
  			((u64)scsicmd->cmnd[6] << 24) |
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1620
1621
  			(scsicmd->cmnd[7] << 16) |
  			(scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
1622
  		count = (scsicmd->cmnd[10] << 24) |
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1623
1624
1625
1626
  			(scsicmd->cmnd[11] << 16) |
  			(scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13];
  		break;
  	case READ_12:
9e7c349c9   Mark Haverkamp   [SCSI] aacraid: r...
1627
1628
  		dprintk((KERN_DEBUG "aachba: received a read(12) command on id %d.
  ", scmd_id(scsicmd)));
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1629

8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
1630
  		lba = ((u64)scsicmd->cmnd[2] << 24) |
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1631
  			(scsicmd->cmnd[3] << 16) |
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
1632
1633
  			(scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
  		count = (scsicmd->cmnd[6] << 24) |
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1634
  			(scsicmd->cmnd[7] << 16) |
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
1635
  			(scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1636
1637
  		break;
  	default:
9e7c349c9   Mark Haverkamp   [SCSI] aacraid: r...
1638
1639
  		dprintk((KERN_DEBUG "aachba: received a read(10) command on id %d.
  ", scmd_id(scsicmd)));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1640

8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
1641
1642
  		lba = ((u64)scsicmd->cmnd[2] << 24) |
  			(scsicmd->cmnd[3] << 16) |
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1643
  			(scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1644
  		count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1645
  		break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1646
  	}
da3cc679b   Rajashekhara, Mahesh   [SCSI] aacraid: p...
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
  
  	if ((lba + count) > (dev->fsa_dev[scmd_id(scsicmd)].size)) {
  		cid = scmd_id(scsicmd);
  		dprintk((KERN_DEBUG "aacraid: Illegal lba
  "));
  		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
  			SAM_STAT_CHECK_CONDITION;
  		set_sense(&dev->fsa_dev[cid].sense_data,
  			  HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
  			  ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
  		memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
  		       min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
  			     SCSI_SENSE_BUFFERSIZE));
  		scsicmd->scsi_done(scsicmd);
  		return 1;
  	}
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1663
1664
  	dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %llu, t = %ld.
  ",
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
1665
  	  smp_processor_id(), (unsigned long long)lba, jiffies));
e8f32de52   Mark Haverkamp   [SCSI] aacraid: r...
1666
  	if (aac_adapter_bounds(dev,scsicmd,lba))
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1667
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1668
1669
1670
  	/*
  	 *	Alocate and initialize a Fib
  	 */
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
1671
  	if (!(cmd_fibcontext = aac_fib_alloc(dev))) {
cacb6dc3d   Penchala Narasimha Reddy Chilakala, ERS-HCLTech   [SCSI] aacraid: f...
1672
1673
  		printk(KERN_WARNING "aac_read: fib allocation failed
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1674
1675
  		return -1;
  	}
e8f32de52   Mark Haverkamp   [SCSI] aacraid: r...
1676
  	status = aac_adapter_read(cmd_fibcontext, scsicmd, lba, count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1677
1678
1679
1680
  
  	/*
  	 *	Check that the command queued to the controller
  	 */
77d644d4d   Mark Haverkamp   [SCSI] aacraid: T...
1681
1682
  	if (status == -EINPROGRESS) {
  		scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1683
  		return 0;
77d644d4d   Mark Haverkamp   [SCSI] aacraid: T...
1684
  	}
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
1685

bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
1686
1687
  	printk(KERN_WARNING "aac_read: aac_fib_send failed with status: %d.
  ", status);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1688
1689
1690
1691
  	/*
  	 *	For some reason, the Fib didn't queue, return QUEUE_FULL
  	 */
  	scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL;
8e0c5ebde   Mark Haverkamp   [SCSI] aacraid: N...
1692
  	scsicmd->scsi_done(scsicmd);
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
1693
1694
  	aac_fib_complete(cmd_fibcontext);
  	aac_fib_free(cmd_fibcontext);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1695
1696
  	return 0;
  }
9e7c349c9   Mark Haverkamp   [SCSI] aacraid: r...
1697
  static int aac_write(struct scsi_cmnd * scsicmd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1698
  {
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1699
  	u64 lba;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1700
  	u32 count;
9d399cc7f   Salyzyn, Mark   [SCSI] aacraid: a...
1701
  	int fua;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1702
  	int status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1703
1704
  	struct aac_dev *dev;
  	struct fib * cmd_fibcontext;
da3cc679b   Rajashekhara, Mahesh   [SCSI] aacraid: p...
1705
  	int cid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
  
  	dev = (struct aac_dev *)scsicmd->device->host->hostdata;
  	/*
  	 *	Get block address and transfer length
  	 */
  	if (scsicmd->cmnd[0] == WRITE_6)	/* 6 byte command */
  	{
  		lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
  		count = scsicmd->cmnd[4];
  		if (count == 0)
  			count = 256;
9d399cc7f   Salyzyn, Mark   [SCSI] aacraid: a...
1717
  		fua = 0;
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1718
  	} else if (scsicmd->cmnd[0] == WRITE_16) { /* 16 byte command */
9e7c349c9   Mark Haverkamp   [SCSI] aacraid: r...
1719
1720
  		dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.
  ", scmd_id(scsicmd)));
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1721

8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
1722
  		lba =	((u64)scsicmd->cmnd[2] << 56) |
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1723
1724
1725
  			((u64)scsicmd->cmnd[3] << 48) |
  			((u64)scsicmd->cmnd[4] << 40) |
  			((u64)scsicmd->cmnd[5] << 32) |
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
1726
  			((u64)scsicmd->cmnd[6] << 24) |
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1727
1728
1729
1730
  			(scsicmd->cmnd[7] << 16) |
  			(scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
  		count = (scsicmd->cmnd[10] << 24) | (scsicmd->cmnd[11] << 16) |
  			(scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13];
9d399cc7f   Salyzyn, Mark   [SCSI] aacraid: a...
1731
  		fua = scsicmd->cmnd[1] & 0x8;
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1732
  	} else if (scsicmd->cmnd[0] == WRITE_12) { /* 12 byte command */
9e7c349c9   Mark Haverkamp   [SCSI] aacraid: r...
1733
1734
  		dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.
  ", scmd_id(scsicmd)));
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1735
1736
1737
1738
1739
  
  		lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16)
  		    | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
  		count = (scsicmd->cmnd[6] << 24) | (scsicmd->cmnd[7] << 16)
  		      | (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9];
9d399cc7f   Salyzyn, Mark   [SCSI] aacraid: a...
1740
  		fua = scsicmd->cmnd[1] & 0x8;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1741
  	} else {
9e7c349c9   Mark Haverkamp   [SCSI] aacraid: r...
1742
1743
  		dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.
  ", scmd_id(scsicmd)));
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1744
  		lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1745
  		count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
9d399cc7f   Salyzyn, Mark   [SCSI] aacraid: a...
1746
  		fua = scsicmd->cmnd[1] & 0x8;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1747
  	}
da3cc679b   Rajashekhara, Mahesh   [SCSI] aacraid: p...
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
  
  	if ((lba + count) > (dev->fsa_dev[scmd_id(scsicmd)].size)) {
  		cid = scmd_id(scsicmd);
  		dprintk((KERN_DEBUG "aacraid: Illegal lba
  "));
  		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
  			SAM_STAT_CHECK_CONDITION;
  		set_sense(&dev->fsa_dev[cid].sense_data,
  			  HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
  			  ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
  		memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
  		       min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
  			     SCSI_SENSE_BUFFERSIZE));
  		scsicmd->scsi_done(scsicmd);
  		return 1;
  	}
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1764
1765
  	dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %llu, t = %ld.
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1766
  	  smp_processor_id(), (unsigned long long)lba, jiffies));
e8f32de52   Mark Haverkamp   [SCSI] aacraid: r...
1767
  	if (aac_adapter_bounds(dev,scsicmd,lba))
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
1768
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1769
1770
1771
  	/*
  	 *	Allocate and initialize a Fib then setup a BlockWrite command
  	 */
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
1772
  	if (!(cmd_fibcontext = aac_fib_alloc(dev))) {
cacb6dc3d   Penchala Narasimha Reddy Chilakala, ERS-HCLTech   [SCSI] aacraid: f...
1773
1774
1775
1776
1777
1778
1779
1780
1781
  		/* FIB temporarily unavailable,not catastrophic failure */
  
  		/* scsicmd->result = DID_ERROR << 16;
  		 * scsicmd->scsi_done(scsicmd);
  		 * return 0;
  		 */
  		printk(KERN_WARNING "aac_write: fib allocation failed
  ");
  		return -1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1782
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1783

9d399cc7f   Salyzyn, Mark   [SCSI] aacraid: a...
1784
  	status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count, fua);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1785
1786
1787
1788
  
  	/*
  	 *	Check that the command queued to the controller
  	 */
77d644d4d   Mark Haverkamp   [SCSI] aacraid: T...
1789
1790
  	if (status == -EINPROGRESS) {
  		scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1791
1792
  		return 0;
  	}
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
1793
1794
  	printk(KERN_WARNING "aac_write: aac_fib_send failed with status: %d
  ", status);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1795
1796
1797
1798
  	/*
  	 *	For some reason, the Fib didn't queue, return QUEUE_FULL
  	 */
  	scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL;
8e0c5ebde   Mark Haverkamp   [SCSI] aacraid: N...
1799
  	scsicmd->scsi_done(scsicmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1800

bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
1801
1802
  	aac_fib_complete(cmd_fibcontext);
  	aac_fib_free(cmd_fibcontext);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1803
1804
1805
1806
1807
1808
1809
1810
1811
  	return 0;
  }
  
  static void synchronize_callback(void *context, struct fib *fibptr)
  {
  	struct aac_synchronize_reply *synchronizereply;
  	struct scsi_cmnd *cmd;
  
  	cmd = context;
03d443372   Mark Haverkamp   [SCSI] aacraid: I...
1812
1813
  	if (!aac_valid_context(cmd, fibptr))
  		return;
b90f90d23   Salyzyn, Mark   [SCSI] aacraid: a...
1814
1815
  	dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1816
1817
1818
1819
1820
1821
  				smp_processor_id(), jiffies));
  	BUG_ON(fibptr == NULL);
  
  
  	synchronizereply = fib_data(fibptr);
  	if (le32_to_cpu(synchronizereply->status) == CT_OK)
b90f90d23   Salyzyn, Mark   [SCSI] aacraid: a...
1822
  		cmd->result = DID_OK << 16 |
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1823
1824
1825
  			COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
  	else {
  		struct scsi_device *sdev = cmd->device;
1a655040c   Salyzyn, Mark   [SCSI] aacraid: p...
1826
  		struct aac_dev *dev = fibptr->dev;
e5718774f   Mark Haverkamp   [SCSI] aacraid: U...
1827
  		u32 cid = sdev_id(sdev);
b90f90d23   Salyzyn, Mark   [SCSI] aacraid: a...
1828
  		printk(KERN_WARNING
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1829
1830
1831
  		     "synchronize_callback: synchronize failed, status = %d
  ",
  		     le32_to_cpu(synchronizereply->status));
b90f90d23   Salyzyn, Mark   [SCSI] aacraid: a...
1832
  		cmd->result = DID_OK << 16 |
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1833
  			COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
8e31e607e   Salyzyn, Mark   [SCSI] aacraid: d...
1834
1835
1836
  		set_sense(&dev->fsa_dev[cid].sense_data,
  		  HARDWARE_ERROR, SENCODE_INTERNAL_TARGET_FAILURE,
  		  ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1837
  		memcpy(cmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
b80ca4f7e   FUJITA Tomonori   [SCSI] replace si...
1838
1839
  		       min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
  			     SCSI_SENSE_BUFFERSIZE));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1840
  	}
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
1841
1842
  	aac_fib_complete(fibptr);
  	aac_fib_free(fibptr);
8e0c5ebde   Mark Haverkamp   [SCSI] aacraid: N...
1843
  	cmd->scsi_done(cmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1844
  }
9e7c349c9   Mark Haverkamp   [SCSI] aacraid: r...
1845
  static int aac_synchronize(struct scsi_cmnd *scsicmd)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1846
1847
1848
1849
1850
1851
1852
  {
  	int status;
  	struct fib *cmd_fibcontext;
  	struct aac_synchronize *synchronizecmd;
  	struct scsi_cmnd *cmd;
  	struct scsi_device *sdev = scsicmd->device;
  	int active = 0;
90ee34665   Mark Haverkamp   [SCSI] aacraid: C...
1853
  	struct aac_dev *aac;
b90f90d23   Salyzyn, Mark   [SCSI] aacraid: a...
1854
1855
1856
  	u64 lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) |
  		(scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
  	u32 count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1857
1858
1859
  	unsigned long flags;
  
  	/*
77d644d4d   Mark Haverkamp   [SCSI] aacraid: T...
1860
1861
  	 * Wait for all outstanding queued commands to complete to this
  	 * specific target (block).
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1862
1863
1864
  	 */
  	spin_lock_irqsave(&sdev->list_lock, flags);
  	list_for_each_entry(cmd, &sdev->cmd_list, list)
b90f90d23   Salyzyn, Mark   [SCSI] aacraid: a...
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
  		if (cmd->SCp.phase == AAC_OWNER_FIRMWARE) {
  			u64 cmnd_lba;
  			u32 cmnd_count;
  
  			if (cmd->cmnd[0] == WRITE_6) {
  				cmnd_lba = ((cmd->cmnd[1] & 0x1F) << 16) |
  					(cmd->cmnd[2] << 8) |
  					cmd->cmnd[3];
  				cmnd_count = cmd->cmnd[4];
  				if (cmnd_count == 0)
  					cmnd_count = 256;
  			} else if (cmd->cmnd[0] == WRITE_16) {
  				cmnd_lba = ((u64)cmd->cmnd[2] << 56) |
  					((u64)cmd->cmnd[3] << 48) |
  					((u64)cmd->cmnd[4] << 40) |
  					((u64)cmd->cmnd[5] << 32) |
  					((u64)cmd->cmnd[6] << 24) |
  					(cmd->cmnd[7] << 16) |
  					(cmd->cmnd[8] << 8) |
  					cmd->cmnd[9];
  				cmnd_count = (cmd->cmnd[10] << 24) |
  					(cmd->cmnd[11] << 16) |
  					(cmd->cmnd[12] << 8) |
  					cmd->cmnd[13];
  			} else if (cmd->cmnd[0] == WRITE_12) {
  				cmnd_lba = ((u64)cmd->cmnd[2] << 24) |
  					(cmd->cmnd[3] << 16) |
  					(cmd->cmnd[4] << 8) |
  					cmd->cmnd[5];
  				cmnd_count = (cmd->cmnd[6] << 24) |
  					(cmd->cmnd[7] << 16) |
  					(cmd->cmnd[8] << 8) |
  					cmd->cmnd[9];
  			} else if (cmd->cmnd[0] == WRITE_10) {
  				cmnd_lba = ((u64)cmd->cmnd[2] << 24) |
  					(cmd->cmnd[3] << 16) |
  					(cmd->cmnd[4] << 8) |
  					cmd->cmnd[5];
  				cmnd_count = (cmd->cmnd[7] << 8) |
  					cmd->cmnd[8];
  			} else
  				continue;
  			if (((cmnd_lba + cmnd_count) < lba) ||
  			  (count && ((lba + count) < cmnd_lba)))
  				continue;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
  			++active;
  			break;
  		}
  
  	spin_unlock_irqrestore(&sdev->list_lock, flags);
  
  	/*
  	 *	Yield the processor (requeue for later)
  	 */
  	if (active)
  		return SCSI_MLQUEUE_DEVICE_BUSY;
f858317d8   Salyzyn, Mark   [SCSI] aacraid: f...
1921
  	aac = (struct aac_dev *)sdev->host->hostdata;
8c867b257   Mark Haverkamp   [SCSI] aacraid: R...
1922
1923
  	if (aac->in_reset)
  		return SCSI_MLQUEUE_HOST_BUSY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1924
  	/*
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
1925
  	 *	Allocate and initialize a Fib
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1926
  	 */
90ee34665   Mark Haverkamp   [SCSI] aacraid: C...
1927
  	if (!(cmd_fibcontext = aac_fib_alloc(aac)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1928
  		return SCSI_MLQUEUE_HOST_BUSY;
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
1929
  	aac_fib_init(cmd_fibcontext);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1930
1931
1932
1933
  
  	synchronizecmd = fib_data(cmd_fibcontext);
  	synchronizecmd->command = cpu_to_le32(VM_ContainerConfig);
  	synchronizecmd->type = cpu_to_le32(CT_FLUSH_CACHE);
9e7c349c9   Mark Haverkamp   [SCSI] aacraid: r...
1934
  	synchronizecmd->cid = cpu_to_le32(scmd_id(scsicmd));
b90f90d23   Salyzyn, Mark   [SCSI] aacraid: a...
1935
  	synchronizecmd->count =
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1936
1937
1938
1939
1940
  	     cpu_to_le32(sizeof(((struct aac_synchronize_reply *)NULL)->data));
  
  	/*
  	 *	Now send the Fib to the adapter
  	 */
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
1941
  	status = aac_fib_send(ContainerCommand,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
  		  cmd_fibcontext,
  		  sizeof(struct aac_synchronize),
  		  FsaNormal,
  		  0, 1,
  		  (fib_callback)synchronize_callback,
  		  (void *)scsicmd);
  
  	/*
  	 *	Check that the command queued to the controller
  	 */
77d644d4d   Mark Haverkamp   [SCSI] aacraid: T...
1952
1953
  	if (status == -EINPROGRESS) {
  		scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1954
  		return 0;
77d644d4d   Mark Haverkamp   [SCSI] aacraid: T...
1955
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1956

b90f90d23   Salyzyn, Mark   [SCSI] aacraid: a...
1957
  	printk(KERN_WARNING
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
1958
1959
1960
1961
  		"aac_synchronize: aac_fib_send failed with status: %d.
  ", status);
  	aac_fib_complete(cmd_fibcontext);
  	aac_fib_free(cmd_fibcontext);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1962
1963
  	return SCSI_MLQUEUE_HOST_BUSY;
  }
655d722cf   Mark Salyzyn   [SCSI] aacraid: A...
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
  static void aac_start_stop_callback(void *context, struct fib *fibptr)
  {
  	struct scsi_cmnd *scsicmd = context;
  
  	if (!aac_valid_context(scsicmd, fibptr))
  		return;
  
  	BUG_ON(fibptr == NULL);
  
  	scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
  
  	aac_fib_complete(fibptr);
  	aac_fib_free(fibptr);
  	scsicmd->scsi_done(scsicmd);
  }
  
  static int aac_start_stop(struct scsi_cmnd *scsicmd)
  {
  	int status;
  	struct fib *cmd_fibcontext;
  	struct aac_power_management *pmcmd;
  	struct scsi_device *sdev = scsicmd->device;
  	struct aac_dev *aac = (struct aac_dev *)sdev->host->hostdata;
  
  	if (!(aac->supplement_adapter_info.SupportedOptions2 &
  	      AAC_OPTION_POWER_MANAGEMENT)) {
  		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
  				  SAM_STAT_GOOD;
  		scsicmd->scsi_done(scsicmd);
  		return 0;
  	}
  
  	if (aac->in_reset)
  		return SCSI_MLQUEUE_HOST_BUSY;
  
  	/*
  	 *	Allocate and initialize a Fib
  	 */
  	cmd_fibcontext = aac_fib_alloc(aac);
  	if (!cmd_fibcontext)
  		return SCSI_MLQUEUE_HOST_BUSY;
  
  	aac_fib_init(cmd_fibcontext);
  
  	pmcmd = fib_data(cmd_fibcontext);
  	pmcmd->command = cpu_to_le32(VM_ContainerConfig);
  	pmcmd->type = cpu_to_le32(CT_POWER_MANAGEMENT);
  	/* Eject bit ignored, not relevant */
  	pmcmd->sub = (scsicmd->cmnd[4] & 1) ?
  		cpu_to_le32(CT_PM_START_UNIT) : cpu_to_le32(CT_PM_STOP_UNIT);
  	pmcmd->cid = cpu_to_le32(sdev_id(sdev));
  	pmcmd->parm = (scsicmd->cmnd[1] & 1) ?
  		cpu_to_le32(CT_PM_UNIT_IMMEDIATE) : 0;
  
  	/*
  	 *	Now send the Fib to the adapter
  	 */
  	status = aac_fib_send(ContainerCommand,
  		  cmd_fibcontext,
  		  sizeof(struct aac_power_management),
  		  FsaNormal,
  		  0, 1,
  		  (fib_callback)aac_start_stop_callback,
  		  (void *)scsicmd);
  
  	/*
  	 *	Check that the command queued to the controller
  	 */
  	if (status == -EINPROGRESS) {
  		scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
  		return 0;
  	}
  
  	aac_fib_complete(cmd_fibcontext);
  	aac_fib_free(cmd_fibcontext);
  	return SCSI_MLQUEUE_HOST_BUSY;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2041
2042
2043
2044
2045
2046
2047
  /**
   *	aac_scsi_cmd()		-	Process SCSI command
   *	@scsicmd:		SCSI command block
   *
   *	Emulate a SCSI command and queue the required request for the
   *	aacraid firmware.
   */
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
2048

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2049
2050
  int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
  {
1a655040c   Salyzyn, Mark   [SCSI] aacraid: p...
2051
  	u32 cid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2052
2053
2054
  	struct Scsi_Host *host = scsicmd->device->host;
  	struct aac_dev *dev = (struct aac_dev *)host->hostdata;
  	struct fsa_dev_info *fsa_dev_ptr = dev->fsa_dev;
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
2055

90ee34665   Mark Haverkamp   [SCSI] aacraid: C...
2056
2057
  	if (fsa_dev_ptr == NULL)
  		return -1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2058
2059
2060
2061
2062
  	/*
  	 *	If the bus, id or lun is out of range, return fail
  	 *	Test does not apply to ID 16, the pseudo id for the controller
  	 *	itself.
  	 */
1a655040c   Salyzyn, Mark   [SCSI] aacraid: p...
2063
2064
2065
2066
  	cid = scmd_id(scsicmd);
  	if (cid != host->this_id) {
  		if (scmd_channel(scsicmd) == CONTAINER_CHANNEL) {
  			if((cid >= dev->maximum_num_containers) ||
e5718774f   Mark Haverkamp   [SCSI] aacraid: U...
2067
  					(scsicmd->device->lun != 0)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2068
2069
2070
2071
  				scsicmd->result = DID_NO_CONNECT << 16;
  				scsicmd->scsi_done(scsicmd);
  				return 0;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2072
2073
2074
2075
2076
  
  			/*
  			 *	If the target container doesn't exist, it may have
  			 *	been newly created
  			 */
655d722cf   Mark Salyzyn   [SCSI] aacraid: A...
2077
2078
2079
  			if (((fsa_dev_ptr[cid].valid & 1) == 0) ||
  			  (fsa_dev_ptr[cid].sense_data.sense_key ==
  			   NOT_READY)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2080
  				switch (scsicmd->cmnd[0]) {
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
2081
2082
2083
2084
2085
  				case SERVICE_ACTION_IN:
  					if (!(dev->raw_io_interface) ||
  					    !(dev->raw_io_64) ||
  					    ((scsicmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16))
  						break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2086
2087
2088
  				case INQUIRY:
  				case READ_CAPACITY:
  				case TEST_UNIT_READY:
8c867b257   Mark Haverkamp   [SCSI] aacraid: R...
2089
2090
  					if (dev->in_reset)
  						return -1;
fe76df423   Mark Haverkamp   [SCSI] aacraid: F...
2091
2092
  					return _aac_probe_container(scsicmd,
  							aac_probe_container_callback2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2093
2094
2095
2096
  				default:
  					break;
  				}
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2097
  		} else {  /* check for physical non-dasd devices */
cb1042f28   Salyzyn, Mark   [SCSI] aacraid: a...
2098
2099
  			if (dev->nondasd_support || expose_physicals ||
  					dev->jbod) {
8c867b257   Mark Haverkamp   [SCSI] aacraid: R...
2100
2101
  				if (dev->in_reset)
  					return -1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
  				return aac_send_srb_fib(scsicmd);
  			} else {
  				scsicmd->result = DID_NO_CONNECT << 16;
  				scsicmd->scsi_done(scsicmd);
  				return 0;
  			}
  		}
  	}
  	/*
  	 * else Command for the controller itself
  	 */
  	else if ((scsicmd->cmnd[0] != INQUIRY) &&	/* only INQUIRY & TUR cmnd supported for controller */
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
2114
  		(scsicmd->cmnd[0] != TEST_UNIT_READY))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2115
2116
2117
2118
  	{
  		dprintk((KERN_WARNING "Only INQUIRY & TUR command supported for controller, rcvd = 0x%x.
  ", scsicmd->cmnd[0]));
  		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
8e31e607e   Salyzyn, Mark   [SCSI] aacraid: d...
2119
2120
2121
  		set_sense(&dev->fsa_dev[cid].sense_data,
  		  ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND,
  		  ASENCODE_INVALID_COMMAND, 0, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2122
  		memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
3ace426f9   Salyzyn, Mark   [SCSI] aacraid: r...
2123
2124
  		       min_t(size_t, sizeof(dev->fsa_dev[cid].sense_data),
  			     SCSI_SENSE_BUFFERSIZE));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2125
2126
2127
2128
2129
2130
2131
2132
2133
  		scsicmd->scsi_done(scsicmd);
  		return 0;
  	}
  
  
  	/* Handle commands here that don't really require going out to the adapter */
  	switch (scsicmd->cmnd[0]) {
  	case INQUIRY:
  	{
3b2946cc9   Mark Haverkamp   [SCSI] aacraid: F...
2134
  		struct inquiry_data inq_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2135

1a655040c   Salyzyn, Mark   [SCSI] aacraid: p...
2136
2137
  		dprintk((KERN_DEBUG "INQUIRY command, ID: %d.
  ", cid));
3b2946cc9   Mark Haverkamp   [SCSI] aacraid: F...
2138
  		memset(&inq_data, 0, sizeof (struct inquiry_data));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2139

d8e965076   Leubner, Achim   [SCSI] aacraid dr...
2140
  		if ((scsicmd->cmnd[1] & 0x1) && aac_wwn) {
88e2f98e1   Salyzyn, Mark   [SCSI] aacraid: a...
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
  			char *arr = (char *)&inq_data;
  
  			/* EVPD bit set */
  			arr[0] = (scmd_id(scsicmd) == host->this_id) ?
  			  INQD_PDT_PROC : INQD_PDT_DA;
  			if (scsicmd->cmnd[2] == 0) {
  				/* supported vital product data pages */
  				arr[3] = 2;
  				arr[4] = 0x0;
  				arr[5] = 0x80;
  				arr[1] = scsicmd->cmnd[2];
d4345028d   FUJITA Tomonori   [SCSI] aacraid: u...
2152
2153
  				scsi_sg_copy_from_buffer(scsicmd, &inq_data,
  							 sizeof(inq_data));
88e2f98e1   Salyzyn, Mark   [SCSI] aacraid: a...
2154
2155
2156
2157
2158
2159
2160
  				scsicmd->result = DID_OK << 16 |
  				  COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
  			} else if (scsicmd->cmnd[2] == 0x80) {
  				/* unit serial number page */
  				arr[3] = setinqserial(dev, &arr[4],
  				  scmd_id(scsicmd));
  				arr[1] = scsicmd->cmnd[2];
d4345028d   FUJITA Tomonori   [SCSI] aacraid: u...
2161
2162
  				scsi_sg_copy_from_buffer(scsicmd, &inq_data,
  							 sizeof(inq_data));
d8e965076   Leubner, Achim   [SCSI] aacraid dr...
2163
2164
2165
2166
2167
2168
  				if (aac_wwn != 2)
  					return aac_get_container_serial(
  						scsicmd);
  				/* SLES 10 SP1 special */
  				scsicmd->result = DID_OK << 16 |
  				  COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
88e2f98e1   Salyzyn, Mark   [SCSI] aacraid: a...
2169
2170
2171
2172
2173
  			} else {
  				/* vpd page not implemented */
  				scsicmd->result = DID_OK << 16 |
  				  COMMAND_COMPLETE << 8 |
  				  SAM_STAT_CHECK_CONDITION;
8e31e607e   Salyzyn, Mark   [SCSI] aacraid: d...
2174
2175
2176
  				set_sense(&dev->fsa_dev[cid].sense_data,
  				  ILLEGAL_REQUEST, SENCODE_INVALID_CDB_FIELD,
  				  ASENCODE_NO_SENSE, 7, 2);
88e2f98e1   Salyzyn, Mark   [SCSI] aacraid: a...
2177
2178
  				memcpy(scsicmd->sense_buffer,
  				  &dev->fsa_dev[cid].sense_data,
3ace426f9   Salyzyn, Mark   [SCSI] aacraid: r...
2179
2180
2181
  				  min_t(size_t,
  					sizeof(dev->fsa_dev[cid].sense_data),
  					SCSI_SENSE_BUFFERSIZE));
88e2f98e1   Salyzyn, Mark   [SCSI] aacraid: a...
2182
2183
2184
2185
  			}
  			scsicmd->scsi_done(scsicmd);
  			return 0;
  		}
3b2946cc9   Mark Haverkamp   [SCSI] aacraid: F...
2186
  		inq_data.inqd_ver = 2;	/* claim compliance to SCSI-2 */
3b2946cc9   Mark Haverkamp   [SCSI] aacraid: F...
2187
2188
  		inq_data.inqd_rdf = 2;	/* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */
  		inq_data.inqd_len = 31;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2189
  		/*Format for "pad2" is  RelAdr | WBus32 | WBus16 |  Sync  | Linked |Reserved| CmdQue | SftRe */
3b2946cc9   Mark Haverkamp   [SCSI] aacraid: F...
2190
  		inq_data.inqd_pad2= 0x32 ;	 /*WBus16|Sync|CmdQue */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2191
2192
2193
2194
  		/*
  		 *	Set the Vendor, Product, and Revision Level
  		 *	see: <vendor>.c i.e. aac.c
  		 */
1a655040c   Salyzyn, Mark   [SCSI] aacraid: p...
2195
  		if (cid == host->this_id) {
6391a1137   Tobias Klauser   [SCSI] drivers/sc...
2196
  			setinqstr(dev, (void *) (inq_data.inqd_vid), ARRAY_SIZE(container_types));
3b2946cc9   Mark Haverkamp   [SCSI] aacraid: F...
2197
  			inq_data.inqd_pdt = INQD_PDT_PROC;	/* Processor device */
d4345028d   FUJITA Tomonori   [SCSI] aacraid: u...
2198
2199
  			scsi_sg_copy_from_buffer(scsicmd, &inq_data,
  						 sizeof(inq_data));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2200
2201
2202
2203
  			scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
  			scsicmd->scsi_done(scsicmd);
  			return 0;
  		}
8c867b257   Mark Haverkamp   [SCSI] aacraid: R...
2204
2205
  		if (dev->in_reset)
  			return -1;
794d0601e   Mark Haverkamp   [SCSI] aacraid: f...
2206
  		setinqstr(dev, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type);
3b2946cc9   Mark Haverkamp   [SCSI] aacraid: F...
2207
  		inq_data.inqd_pdt = INQD_PDT_DA;	/* Direct/random access device */
d4345028d   FUJITA Tomonori   [SCSI] aacraid: u...
2208
  		scsi_sg_copy_from_buffer(scsicmd, &inq_data, sizeof(inq_data));
9e7c349c9   Mark Haverkamp   [SCSI] aacraid: r...
2209
  		return aac_get_container_name(scsicmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2210
  	}
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
2211
2212
2213
2214
2215
2216
2217
  	case SERVICE_ACTION_IN:
  		if (!(dev->raw_io_interface) ||
  		    !(dev->raw_io_64) ||
  		    ((scsicmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16))
  			break;
  	{
  		u64 capacity;
07ce5eba8   Mark Haverkamp   [SCSI] aacraid: F...
2218
  		char cp[13];
b271f1c88   FUJITA Tomonori   [SCSI] aacraid: R...
2219
  		unsigned int alloc_len;
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
2220
2221
2222
2223
  
  		dprintk((KERN_DEBUG "READ CAPACITY_16 command.
  "));
  		capacity = fsa_dev_ptr[cid].size - 1;
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
  		cp[0] = (capacity >> 56) & 0xff;
  		cp[1] = (capacity >> 48) & 0xff;
  		cp[2] = (capacity >> 40) & 0xff;
  		cp[3] = (capacity >> 32) & 0xff;
  		cp[4] = (capacity >> 24) & 0xff;
  		cp[5] = (capacity >> 16) & 0xff;
  		cp[6] = (capacity >> 8) & 0xff;
  		cp[7] = (capacity >> 0) & 0xff;
  		cp[8] = 0;
  		cp[9] = 0;
  		cp[10] = 2;
  		cp[11] = 0;
07ce5eba8   Mark Haverkamp   [SCSI] aacraid: F...
2236
  		cp[12] = 0;
07ce5eba8   Mark Haverkamp   [SCSI] aacraid: F...
2237

b271f1c88   FUJITA Tomonori   [SCSI] aacraid: R...
2238
2239
2240
2241
2242
  		alloc_len = ((scsicmd->cmnd[10] << 24)
  			     + (scsicmd->cmnd[11] << 16)
  			     + (scsicmd->cmnd[12] << 8) + scsicmd->cmnd[13]);
  
  		alloc_len = min_t(size_t, alloc_len, sizeof(cp));
d4345028d   FUJITA Tomonori   [SCSI] aacraid: u...
2243
  		scsi_sg_copy_from_buffer(scsicmd, cp, alloc_len);
b271f1c88   FUJITA Tomonori   [SCSI] aacraid: R...
2244
2245
2246
  		if (alloc_len < scsi_bufflen(scsicmd))
  			scsi_set_resid(scsicmd,
  				       scsi_bufflen(scsicmd) - alloc_len);
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
2247
2248
2249
2250
2251
2252
2253
2254
2255
  
  		/* Do not cache partition table for arrays */
  		scsicmd->device->removable = 1;
  
  		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
  		scsicmd->scsi_done(scsicmd);
  
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2256
2257
2258
  	case READ_CAPACITY:
  	{
  		u32 capacity;
3b2946cc9   Mark Haverkamp   [SCSI] aacraid: F...
2259
  		char cp[8];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2260
2261
2262
  
  		dprintk((KERN_DEBUG "READ CAPACITY command.
  "));
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
2263
  		if (fsa_dev_ptr[cid].size <= 0x100000000ULL)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2264
2265
2266
  			capacity = fsa_dev_ptr[cid].size - 1;
  		else
  			capacity = (u32)-1;
3b2946cc9   Mark Haverkamp   [SCSI] aacraid: F...
2267

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2268
2269
2270
2271
2272
2273
2274
2275
  		cp[0] = (capacity >> 24) & 0xff;
  		cp[1] = (capacity >> 16) & 0xff;
  		cp[2] = (capacity >> 8) & 0xff;
  		cp[3] = (capacity >> 0) & 0xff;
  		cp[4] = 0;
  		cp[5] = 0;
  		cp[6] = 2;
  		cp[7] = 0;
d4345028d   FUJITA Tomonori   [SCSI] aacraid: u...
2276
  		scsi_sg_copy_from_buffer(scsicmd, cp, sizeof(cp));
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
2277
2278
  		/* Do not cache partition table for arrays */
  		scsicmd->device->removable = 1;
655d722cf   Mark Salyzyn   [SCSI] aacraid: A...
2279
2280
  		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
  		  SAM_STAT_GOOD;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2281
2282
2283
2284
2285
2286
2287
  		scsicmd->scsi_done(scsicmd);
  
  		return 0;
  	}
  
  	case MODE_SENSE:
  	{
9d399cc7f   Salyzyn, Mark   [SCSI] aacraid: a...
2288
2289
  		char mode_buf[7];
  		int mode_buf_length = 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2290
2291
2292
  
  		dprintk((KERN_DEBUG "MODE SENSE command.
  "));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2293
2294
  		mode_buf[0] = 3;	/* Mode data length */
  		mode_buf[1] = 0;	/* Medium type - default */
9d399cc7f   Salyzyn, Mark   [SCSI] aacraid: a...
2295
2296
2297
  		mode_buf[2] = 0;	/* Device-specific param,
  					   bit 8: 0/1 = write enabled/protected
  					   bit 4: 0/1 = FUA enabled */
95e852e1e   Salyzyn, Mark   [SCSI] aacraid: a...
2298
  		if (dev->raw_io_interface && ((aac_cache & 5) != 1))
9d399cc7f   Salyzyn, Mark   [SCSI] aacraid: a...
2299
  			mode_buf[2] = 0x10;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2300
  		mode_buf[3] = 0;	/* Block descriptor length */
9d399cc7f   Salyzyn, Mark   [SCSI] aacraid: a...
2301
2302
2303
2304
2305
  		if (((scsicmd->cmnd[2] & 0x3f) == 8) ||
  		  ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) {
  			mode_buf[0] = 6;
  			mode_buf[4] = 8;
  			mode_buf[5] = 1;
95e852e1e   Salyzyn, Mark   [SCSI] aacraid: a...
2306
2307
  			mode_buf[6] = ((aac_cache & 6) == 2)
  				? 0 : 0x04; /* WCE */
9d399cc7f   Salyzyn, Mark   [SCSI] aacraid: a...
2308
2309
2310
2311
  			mode_buf_length = 7;
  			if (mode_buf_length > scsicmd->cmnd[4])
  				mode_buf_length = scsicmd->cmnd[4];
  		}
d4345028d   FUJITA Tomonori   [SCSI] aacraid: u...
2312
  		scsi_sg_copy_from_buffer(scsicmd, mode_buf, mode_buf_length);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2313
2314
2315
2316
2317
2318
2319
  		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
  		scsicmd->scsi_done(scsicmd);
  
  		return 0;
  	}
  	case MODE_SENSE_10:
  	{
9d399cc7f   Salyzyn, Mark   [SCSI] aacraid: a...
2320
2321
  		char mode_buf[11];
  		int mode_buf_length = 8;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2322
2323
2324
  
  		dprintk((KERN_DEBUG "MODE SENSE 10 byte command.
  "));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2325
2326
2327
  		mode_buf[0] = 0;	/* Mode data length (MSB) */
  		mode_buf[1] = 6;	/* Mode data length (LSB) */
  		mode_buf[2] = 0;	/* Medium type - default */
9d399cc7f   Salyzyn, Mark   [SCSI] aacraid: a...
2328
2329
2330
  		mode_buf[3] = 0;	/* Device-specific param,
  					   bit 8: 0/1 = write enabled/protected
  					   bit 4: 0/1 = FUA enabled */
95e852e1e   Salyzyn, Mark   [SCSI] aacraid: a...
2331
  		if (dev->raw_io_interface && ((aac_cache & 5) != 1))
9d399cc7f   Salyzyn, Mark   [SCSI] aacraid: a...
2332
  			mode_buf[3] = 0x10;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2333
2334
2335
2336
  		mode_buf[4] = 0;	/* reserved */
  		mode_buf[5] = 0;	/* reserved */
  		mode_buf[6] = 0;	/* Block descriptor length (MSB) */
  		mode_buf[7] = 0;	/* Block descriptor length (LSB) */
9d399cc7f   Salyzyn, Mark   [SCSI] aacraid: a...
2337
2338
2339
2340
2341
  		if (((scsicmd->cmnd[2] & 0x3f) == 8) ||
  		  ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) {
  			mode_buf[1] = 9;
  			mode_buf[8] = 8;
  			mode_buf[9] = 1;
95e852e1e   Salyzyn, Mark   [SCSI] aacraid: a...
2342
2343
  			mode_buf[10] = ((aac_cache & 6) == 2)
  				? 0 : 0x04; /* WCE */
9d399cc7f   Salyzyn, Mark   [SCSI] aacraid: a...
2344
2345
2346
2347
  			mode_buf_length = 11;
  			if (mode_buf_length > scsicmd->cmnd[8])
  				mode_buf_length = scsicmd->cmnd[8];
  		}
d4345028d   FUJITA Tomonori   [SCSI] aacraid: u...
2348
  		scsi_sg_copy_from_buffer(scsicmd, mode_buf, mode_buf_length);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
  
  		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
  		scsicmd->scsi_done(scsicmd);
  
  		return 0;
  	}
  	case REQUEST_SENSE:
  		dprintk((KERN_DEBUG "REQUEST SENSE command.
  "));
  		memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data, sizeof (struct sense_data));
  		memset(&dev->fsa_dev[cid].sense_data, 0, sizeof (struct sense_data));
  		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
  		scsicmd->scsi_done(scsicmd);
  		return 0;
  
  	case ALLOW_MEDIUM_REMOVAL:
  		dprintk((KERN_DEBUG "LOCK command.
  "));
  		if (scsicmd->cmnd[4])
  			fsa_dev_ptr[cid].locked = 1;
  		else
  			fsa_dev_ptr[cid].locked = 0;
  
  		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
  		scsicmd->scsi_done(scsicmd);
  		return 0;
  	/*
  	 *	These commands are all No-Ops
  	 */
  	case TEST_UNIT_READY:
655d722cf   Mark Salyzyn   [SCSI] aacraid: A...
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
  		if (fsa_dev_ptr[cid].sense_data.sense_key == NOT_READY) {
  			scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 |
  				SAM_STAT_CHECK_CONDITION;
  			set_sense(&dev->fsa_dev[cid].sense_data,
  				  NOT_READY, SENCODE_BECOMING_READY,
  				  ASENCODE_BECOMING_READY, 0, 0);
  			memcpy(scsicmd->sense_buffer,
  			       &dev->fsa_dev[cid].sense_data,
  			       min_t(size_t,
  				     sizeof(dev->fsa_dev[cid].sense_data),
  				     SCSI_SENSE_BUFFERSIZE));
  			scsicmd->scsi_done(scsicmd);
  			return 0;
  		}
  		/* FALLTHRU */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2394
2395
2396
2397
2398
  	case RESERVE:
  	case RELEASE:
  	case REZERO_UNIT:
  	case REASSIGN_BLOCKS:
  	case SEEK_10:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2399
2400
2401
  		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
  		scsicmd->scsi_done(scsicmd);
  		return 0;
655d722cf   Mark Salyzyn   [SCSI] aacraid: A...
2402
2403
2404
  
  	case START_STOP:
  		return aac_start_stop(scsicmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2405
  	}
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
2406
  	switch (scsicmd->cmnd[0])
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2407
2408
2409
  	{
  		case READ_6:
  		case READ_10:
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
2410
2411
  		case READ_12:
  		case READ_16:
8c867b257   Mark Haverkamp   [SCSI] aacraid: R...
2412
2413
  			if (dev->in_reset)
  				return -1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2414
2415
2416
2417
2418
  			/*
  			 *	Hack to keep track of ordinal number of the device that
  			 *	corresponds to a container. Needed to convert
  			 *	containers to /dev/sd device names
  			 */
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
2419

7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
2420
2421
2422
  			if (scsicmd->request->rq_disk)
  				strlcpy(fsa_dev_ptr[cid].devname,
  				scsicmd->request->rq_disk->disk_name,
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
2423
  				min(sizeof(fsa_dev_ptr[cid].devname),
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
2424
  				sizeof(scsicmd->request->rq_disk->disk_name) + 1));
77d644d4d   Mark Haverkamp   [SCSI] aacraid: T...
2425

9e7c349c9   Mark Haverkamp   [SCSI] aacraid: r...
2426
  			return aac_read(scsicmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2427
2428
2429
  
  		case WRITE_6:
  		case WRITE_10:
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
2430
2431
  		case WRITE_12:
  		case WRITE_16:
8c867b257   Mark Haverkamp   [SCSI] aacraid: R...
2432
2433
  			if (dev->in_reset)
  				return -1;
9e7c349c9   Mark Haverkamp   [SCSI] aacraid: r...
2434
  			return aac_write(scsicmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2435
2436
  
  		case SYNCHRONIZE_CACHE:
95e852e1e   Salyzyn, Mark   [SCSI] aacraid: a...
2437
2438
2439
2440
2441
2442
  			if (((aac_cache & 6) == 6) && dev->cache_protected) {
  				scsicmd->result = DID_OK << 16 |
  					COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
  				scsicmd->scsi_done(scsicmd);
  				return 0;
  			}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2443
  			/* Issue FIB to tell Firmware to flush it's cache */
95e852e1e   Salyzyn, Mark   [SCSI] aacraid: a...
2444
2445
2446
  			if ((aac_cache & 6) != 2)
  				return aac_synchronize(scsicmd);
  			/* FALLTHRU */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2447
2448
2449
2450
  		default:
  			/*
  			 *	Unhandled commands
  			 */
7c00ffa31   Mark Haverkamp   [SCSI] 2.6 aacrai...
2451
2452
  			dprintk((KERN_WARNING "Unhandled SCSI Command: 0x%x.
  ", scsicmd->cmnd[0]));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2453
  			scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
8e31e607e   Salyzyn, Mark   [SCSI] aacraid: d...
2454
2455
2456
  			set_sense(&dev->fsa_dev[cid].sense_data,
  			  ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND,
  			  ASENCODE_INVALID_COMMAND, 0, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2457
  			memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,
3ace426f9   Salyzyn, Mark   [SCSI] aacraid: r...
2458
2459
2460
  				min_t(size_t,
  				      sizeof(dev->fsa_dev[cid].sense_data),
  				      SCSI_SENSE_BUFFERSIZE));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
  			scsicmd->scsi_done(scsicmd);
  			return 0;
  	}
  }
  
  static int query_disk(struct aac_dev *dev, void __user *arg)
  {
  	struct aac_query_disk qd;
  	struct fsa_dev_info *fsa_dev_ptr;
  
  	fsa_dev_ptr = dev->fsa_dev;
90ee34665   Mark Haverkamp   [SCSI] aacraid: C...
2472
  	if (!fsa_dev_ptr)
651013554   Mark Haverkamp   [SCSI] aacraid: m...
2473
  		return -EBUSY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2474
2475
2476
  	if (copy_from_user(&qd, arg, sizeof (struct aac_query_disk)))
  		return -EFAULT;
  	if (qd.cnum == -1)
e5718774f   Mark Haverkamp   [SCSI] aacraid: U...
2477
  		qd.cnum = qd.id;
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
2478
  	else if ((qd.bus == -1) && (qd.id == -1) && (qd.lun == -1))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2479
2480
2481
2482
2483
2484
2485
2486
2487
  	{
  		if (qd.cnum < 0 || qd.cnum >= dev->maximum_num_containers)
  			return -EINVAL;
  		qd.instance = dev->scsi_host_ptr->host_no;
  		qd.bus = 0;
  		qd.id = CONTAINER_TO_ID(qd.cnum);
  		qd.lun = CONTAINER_TO_LUN(qd.cnum);
  	}
  	else return -EINVAL;
fd622b1b4   Salyzyn, Mark   [SCSI] aacraid: c...
2488
  	qd.valid = fsa_dev_ptr[qd.cnum].valid != 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
  	qd.locked = fsa_dev_ptr[qd.cnum].locked;
  	qd.deleted = fsa_dev_ptr[qd.cnum].deleted;
  
  	if (fsa_dev_ptr[qd.cnum].devname[0] == '\0')
  		qd.unmapped = 1;
  	else
  		qd.unmapped = 0;
  
  	strlcpy(qd.name, fsa_dev_ptr[qd.cnum].devname,
  	  min(sizeof(qd.name), sizeof(fsa_dev_ptr[qd.cnum].devname) + 1));
  
  	if (copy_to_user(arg, &qd, sizeof (struct aac_query_disk)))
  		return -EFAULT;
  	return 0;
  }
  
  static int force_delete_disk(struct aac_dev *dev, void __user *arg)
  {
  	struct aac_delete_disk dd;
  	struct fsa_dev_info *fsa_dev_ptr;
  
  	fsa_dev_ptr = dev->fsa_dev;
651013554   Mark Haverkamp   [SCSI] aacraid: m...
2511
2512
  	if (!fsa_dev_ptr)
  		return -EBUSY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
  
  	if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk)))
  		return -EFAULT;
  
  	if (dd.cnum >= dev->maximum_num_containers)
  		return -EINVAL;
  	/*
  	 *	Mark this container as being deleted.
  	 */
  	fsa_dev_ptr[dd.cnum].deleted = 1;
  	/*
  	 *	Mark the container as no longer valid
  	 */
  	fsa_dev_ptr[dd.cnum].valid = 0;
  	return 0;
  }
  
  static int delete_disk(struct aac_dev *dev, void __user *arg)
  {
  	struct aac_delete_disk dd;
  	struct fsa_dev_info *fsa_dev_ptr;
  
  	fsa_dev_ptr = dev->fsa_dev;
90ee34665   Mark Haverkamp   [SCSI] aacraid: C...
2536
  	if (!fsa_dev_ptr)
651013554   Mark Haverkamp   [SCSI] aacraid: m...
2537
  		return -EBUSY;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
  
  	if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk)))
  		return -EFAULT;
  
  	if (dd.cnum >= dev->maximum_num_containers)
  		return -EINVAL;
  	/*
  	 *	If the container is locked, it can not be deleted by the API.
  	 */
  	if (fsa_dev_ptr[dd.cnum].locked)
  		return -EBUSY;
  	else {
  		/*
  		 *	Mark the container as no longer being valid.
  		 */
  		fsa_dev_ptr[dd.cnum].valid = 0;
  		fsa_dev_ptr[dd.cnum].devname[0] = '\0';
  		return 0;
  	}
  }
  
  int aac_dev_ioctl(struct aac_dev *dev, int cmd, void __user *arg)
  {
  	switch (cmd) {
  	case FSACTL_QUERY_DISK:
  		return query_disk(dev, arg);
  	case FSACTL_DELETE_DISK:
  		return delete_disk(dev, arg);
  	case FSACTL_FORCE_DELETE_DISK:
  		return force_delete_disk(dev, arg);
  	case FSACTL_GET_CONTAINERS:
  		return aac_get_containers(dev);
  	default:
  		return -ENOTTY;
  	}
  }
  
  /**
   *
   * aac_srb_callback
   * @context: the context set in the fib - here it is scsi cmd
   * @fibptr: pointer to the fib
   *
   * Handles the completion of a scsi command to a non dasd device
   *
   */
  
  static void aac_srb_callback(void *context, struct fib * fibptr)
  {
  	struct aac_dev *dev;
  	struct aac_srb_reply *srbreply;
  	struct scsi_cmnd *scsicmd;
  
  	scsicmd = (struct scsi_cmnd *) context;
03d443372   Mark Haverkamp   [SCSI] aacraid: I...
2592
2593
2594
  
  	if (!aac_valid_context(scsicmd, fibptr))
  		return;
125e18745   Eric Sesterhenn   [PATCH] More BUG_...
2595
  	BUG_ON(fibptr == NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2596

1a655040c   Salyzyn, Mark   [SCSI] aacraid: p...
2597
  	dev = fibptr->dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2598
2599
2600
2601
  	srbreply = (struct aac_srb_reply *) fib_data(fibptr);
  
  	scsicmd->sense_buffer[0] = '\0';  /* Initialize sense valid flag to false */
  	/*
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
2602
  	 *	Calculate resid for sg
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2603
  	 */
727eead62   FUJITA Tomonori   [SCSI] aacraid: c...
2604
2605
2606
2607
2608
  
  	scsi_set_resid(scsicmd, scsi_bufflen(scsicmd)
  		       - le32_to_cpu(srbreply->data_xfer_length));
  
  	scsi_dma_unmap(scsicmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2609

e3cc268fe   Rajashekhara, Mahesh   [SCSI] aacraid: e...
2610
2611
2612
2613
  	/* expose physical device if expose_physicald flag is on */
  	if (scsicmd->cmnd[0] == INQUIRY && !(scsicmd->cmnd[1] & 0x01)
  	  && expose_physicals > 0)
  		aac_expose_phy_device(scsicmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2614
2615
2616
2617
2618
2619
2620
2621
  	/*
  	 * First check the fib status
  	 */
  
  	if (le32_to_cpu(srbreply->status) != ST_OK){
  		int len;
  		printk(KERN_WARNING "aac_srb_callback: srb failed, status = %d
  ", le32_to_cpu(srbreply->status));
3ace426f9   Salyzyn, Mark   [SCSI] aacraid: r...
2622
2623
  		len = min_t(u32, le32_to_cpu(srbreply->sense_data_size),
  			    SCSI_SENSE_BUFFERSIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
  		scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
  		memcpy(scsicmd->sense_buffer, srbreply->sense_data, len);
  	}
  
  	/*
  	 * Next check the srb status
  	 */
  	switch( (le32_to_cpu(srbreply->srb_status))&0x3f){
  	case SRB_STATUS_ERROR_RECOVERY:
  	case SRB_STATUS_PENDING:
  	case SRB_STATUS_SUCCESS:
bb08f92eb   Mark Haverkamp   [SCSI] aacraid: u...
2635
  		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2636
2637
2638
2639
2640
2641
2642
2643
2644
  		break;
  	case SRB_STATUS_DATA_OVERRUN:
  		switch(scsicmd->cmnd[0]){
  		case  READ_6:
  		case  WRITE_6:
  		case  READ_10:
  		case  WRITE_10:
  		case  READ_12:
  		case  WRITE_12:
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
2645
2646
  		case  READ_16:
  		case  WRITE_16:
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
2647
  			if (le32_to_cpu(srbreply->data_xfer_length) < scsicmd->underflow) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2648
2649
2650
2651
2652
2653
2654
2655
2656
  				printk(KERN_WARNING"aacraid: SCSI CMD underflow
  ");
  			} else {
  				printk(KERN_WARNING"aacraid: SCSI CMD Data Overrun
  ");
  			}
  			scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8;
  			break;
  		case INQUIRY: {
bb08f92eb   Mark Haverkamp   [SCSI] aacraid: u...
2657
  			scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
  			break;
  		}
  		default:
  			scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
  			break;
  		}
  		break;
  	case SRB_STATUS_ABORTED:
  		scsicmd->result = DID_ABORT << 16 | ABORT << 8;
  		break;
  	case SRB_STATUS_ABORT_FAILED:
  		// Not sure about this one - but assuming the hba was trying to abort for some reason
  		scsicmd->result = DID_ERROR << 16 | ABORT << 8;
  		break;
  	case SRB_STATUS_PARITY_ERROR:
  		scsicmd->result = DID_PARITY << 16 | MSG_PARITY_ERROR << 8;
  		break;
  	case SRB_STATUS_NO_DEVICE:
  	case SRB_STATUS_INVALID_PATH_ID:
  	case SRB_STATUS_INVALID_TARGET_ID:
  	case SRB_STATUS_INVALID_LUN:
  	case SRB_STATUS_SELECTION_TIMEOUT:
  		scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8;
  		break;
  
  	case SRB_STATUS_COMMAND_TIMEOUT:
  	case SRB_STATUS_TIMEOUT:
  		scsicmd->result = DID_TIME_OUT << 16 | COMMAND_COMPLETE << 8;
  		break;
  
  	case SRB_STATUS_BUSY:
760af100d   Salyzyn, Mark   [SCSI] aacraid: c...
2689
  		scsicmd->result = DID_BUS_BUSY << 16 | COMMAND_COMPLETE << 8;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
  		break;
  
  	case SRB_STATUS_BUS_RESET:
  		scsicmd->result = DID_RESET << 16 | COMMAND_COMPLETE << 8;
  		break;
  
  	case SRB_STATUS_MESSAGE_REJECTED:
  		scsicmd->result = DID_ERROR << 16 | MESSAGE_REJECT << 8;
  		break;
  	case SRB_STATUS_REQUEST_FLUSHED:
  	case SRB_STATUS_ERROR:
  	case SRB_STATUS_INVALID_REQUEST:
  	case SRB_STATUS_REQUEST_SENSE_FAILED:
  	case SRB_STATUS_NO_HBA:
  	case SRB_STATUS_UNEXPECTED_BUS_FREE:
  	case SRB_STATUS_PHASE_SEQUENCE_FAILURE:
  	case SRB_STATUS_BAD_SRB_BLOCK_LENGTH:
  	case SRB_STATUS_DELAYED_RETRY:
  	case SRB_STATUS_BAD_FUNCTION:
  	case SRB_STATUS_NOT_STARTED:
  	case SRB_STATUS_NOT_IN_USE:
  	case SRB_STATUS_FORCE_ABORT:
  	case SRB_STATUS_DOMAIN_VALIDATION_FAIL:
  	default:
  #ifdef AAC_DETAILED_STATUS_INFO
  		printk("aacraid: SRB ERROR(%u) %s scsi cmd 0x%x - scsi status 0x%x
  ",
  			le32_to_cpu(srbreply->srb_status) & 0x3F,
  			aac_get_status_string(
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
2719
2720
  				le32_to_cpu(srbreply->srb_status) & 0x3F),
  			scsicmd->cmnd[0],
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2721
2722
  			le32_to_cpu(srbreply->scsi_status));
  #endif
1fc8010a5   Rajashekhara, Mahesh   [SCSI] aacraid: a...
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
  		if ((scsicmd->cmnd[0] == ATA_12)
  		  || (scsicmd->cmnd[0] == ATA_16)) {
  			if (scsicmd->cmnd[2] & (0x01 << 5)) {
  				scsicmd->result = DID_OK << 16
  						| COMMAND_COMPLETE << 8;
  				break;
  			} else {
  				scsicmd->result = DID_ERROR << 16
  						| COMMAND_COMPLETE << 8;
  				break;
  			}
  		} else {
  			scsicmd->result = DID_ERROR << 16
  					| COMMAND_COMPLETE << 8;
  			break;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2739
  	}
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
2740
  	if (le32_to_cpu(srbreply->scsi_status) == SAM_STAT_CHECK_CONDITION) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2741
2742
  		int len;
  		scsicmd->result |= SAM_STAT_CHECK_CONDITION;
3ace426f9   Salyzyn, Mark   [SCSI] aacraid: r...
2743
2744
  		len = min_t(u32, le32_to_cpu(srbreply->sense_data_size),
  			    SCSI_SENSE_BUFFERSIZE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2745
  #ifdef AAC_DETAILED_STATUS_INFO
7a8cf29d6   Mark Haverkamp   [SCSI] aacraid: G...
2746
2747
2748
  		printk(KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d
  ",
  					le32_to_cpu(srbreply->status), len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2749
2750
  #endif
  		memcpy(scsicmd->sense_buffer, srbreply->sense_data, len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2751
2752
2753
2754
2755
  	}
  	/*
  	 * OR in the scsi status (already shifted up a bit)
  	 */
  	scsicmd->result |= le32_to_cpu(srbreply->scsi_status);
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
2756
2757
  	aac_fib_complete(fibptr);
  	aac_fib_free(fibptr);
8e0c5ebde   Mark Haverkamp   [SCSI] aacraid: N...
2758
  	scsicmd->scsi_done(scsicmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2759
2760
2761
2762
2763
2764
2765
  }
  
  /**
   *
   * aac_send_scb_fib
   * @scsicmd: the scsi command block
   *
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
2766
   * This routine will form a FIB and fill in the aac_srb from the
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2767
2768
2769
2770
2771
2772
2773
2774
   * scsicmd passed in.
   */
  
  static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
  {
  	struct fib* cmd_fibcontext;
  	struct aac_dev* dev;
  	int status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2775

849717383   Mark Haverkamp   [SCSI] aacraid: N...
2776
  	dev = (struct aac_dev *)scsicmd->device->host->hostdata;
e5718774f   Mark Haverkamp   [SCSI] aacraid: U...
2777
  	if (scmd_id(scsicmd) >= dev->maximum_num_physicals ||
849717383   Mark Haverkamp   [SCSI] aacraid: N...
2778
  			scsicmd->device->lun > 7) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2779
2780
2781
2782
  		scsicmd->result = DID_NO_CONNECT << 16;
  		scsicmd->scsi_done(scsicmd);
  		return 0;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2783
2784
2785
  	/*
  	 *	Allocate and initialize a Fib then setup a BlockWrite command
  	 */
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
2786
  	if (!(cmd_fibcontext = aac_fib_alloc(dev))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2787
2788
  		return -1;
  	}
e8f32de52   Mark Haverkamp   [SCSI] aacraid: r...
2789
  	status = aac_adapter_scsi(cmd_fibcontext, scsicmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2790

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2791
2792
2793
  	/*
  	 *	Check that the command queued to the controller
  	 */
77d644d4d   Mark Haverkamp   [SCSI] aacraid: T...
2794
2795
  	if (status == -EINPROGRESS) {
  		scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2796
2797
  		return 0;
  	}
bfb35aa85   Mark Haverkamp   [SCSI] aacraid: U...
2798
2799
2800
2801
  	printk(KERN_WARNING "aac_srb: aac_fib_send failed with status: %d
  ", status);
  	aac_fib_complete(cmd_fibcontext);
  	aac_fib_free(cmd_fibcontext);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2802
2803
2804
2805
2806
2807
2808
2809
  
  	return -1;
  }
  
  static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg)
  {
  	struct aac_dev *dev;
  	unsigned long byte_count = 0;
727eead62   FUJITA Tomonori   [SCSI] aacraid: c...
2810
  	int nseg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2811
2812
2813
2814
2815
  
  	dev = (struct aac_dev *)scsicmd->device->host->hostdata;
  	// Get rid of old data
  	psg->count = 0;
  	psg->sg[0].addr = 0;
727eead62   FUJITA Tomonori   [SCSI] aacraid: c...
2816
2817
2818
2819
2820
  	psg->sg[0].count = 0;
  
  	nseg = scsi_dma_map(scsicmd);
  	BUG_ON(nseg < 0);
  	if (nseg) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2821
2822
  		struct scatterlist *sg;
  		int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2823

727eead62   FUJITA Tomonori   [SCSI] aacraid: c...
2824
  		psg->count = cpu_to_le32(nseg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2825

727eead62   FUJITA Tomonori   [SCSI] aacraid: c...
2826
  		scsi_for_each_sg(scsicmd, sg, nseg, i) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2827
2828
2829
  			psg->sg[i].addr = cpu_to_le32(sg_dma_address(sg));
  			psg->sg[i].count = cpu_to_le32(sg_dma_len(sg));
  			byte_count += sg_dma_len(sg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2830
2831
  		}
  		/* hba wants the size to be exact */
727eead62   FUJITA Tomonori   [SCSI] aacraid: c...
2832
2833
2834
  		if (byte_count > scsi_bufflen(scsicmd)) {
  			u32 temp = le32_to_cpu(psg->sg[i-1].count) -
  				(byte_count - scsi_bufflen(scsicmd));
56b587122   Mark Haverkamp   [SCSI] aacraid: r...
2835
  			psg->sg[i-1].count = cpu_to_le32(temp);
727eead62   FUJITA Tomonori   [SCSI] aacraid: c...
2836
  			byte_count = scsi_bufflen(scsicmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2837
2838
2839
2840
2841
2842
2843
2844
  		}
  		/* Check for command underflow */
  		if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
  			printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X
  ",
  					byte_count, scsicmd->underflow);
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2845
2846
2847
2848
2849
2850
2851
2852
  	return byte_count;
  }
  
  
  static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* psg)
  {
  	struct aac_dev *dev;
  	unsigned long byte_count = 0;
56b587122   Mark Haverkamp   [SCSI] aacraid: r...
2853
  	u64 addr;
727eead62   FUJITA Tomonori   [SCSI] aacraid: c...
2854
  	int nseg;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2855
2856
2857
2858
2859
2860
2861
  
  	dev = (struct aac_dev *)scsicmd->device->host->hostdata;
  	// Get rid of old data
  	psg->count = 0;
  	psg->sg[0].addr[0] = 0;
  	psg->sg[0].addr[1] = 0;
  	psg->sg[0].count = 0;
727eead62   FUJITA Tomonori   [SCSI] aacraid: c...
2862
2863
2864
2865
  
  	nseg = scsi_dma_map(scsicmd);
  	BUG_ON(nseg < 0);
  	if (nseg) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2866
2867
  		struct scatterlist *sg;
  		int i;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2868

727eead62   FUJITA Tomonori   [SCSI] aacraid: c...
2869
  		scsi_for_each_sg(scsicmd, sg, nseg, i) {
1241f3593   Mark Haverkamp   [SCSI] aacraid: G...
2870
  			int count = sg_dma_len(sg);
56b587122   Mark Haverkamp   [SCSI] aacraid: r...
2871
2872
2873
  			addr = sg_dma_address(sg);
  			psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
  			psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
1241f3593   Mark Haverkamp   [SCSI] aacraid: G...
2874
2875
  			psg->sg[i].count = cpu_to_le32(count);
  			byte_count += count;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2876
  		}
727eead62   FUJITA Tomonori   [SCSI] aacraid: c...
2877
  		psg->count = cpu_to_le32(nseg);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2878
  		/* hba wants the size to be exact */
727eead62   FUJITA Tomonori   [SCSI] aacraid: c...
2879
2880
2881
  		if (byte_count > scsi_bufflen(scsicmd)) {
  			u32 temp = le32_to_cpu(psg->sg[i-1].count) -
  				(byte_count - scsi_bufflen(scsicmd));
56b587122   Mark Haverkamp   [SCSI] aacraid: r...
2882
  			psg->sg[i-1].count = cpu_to_le32(temp);
727eead62   FUJITA Tomonori   [SCSI] aacraid: c...
2883
  			byte_count = scsi_bufflen(scsicmd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2884
2885
2886
2887
2888
2889
2890
2891
  		}
  		/* Check for command underflow */
  		if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
  			printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X
  ",
  					byte_count, scsicmd->underflow);
  		}
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2892
2893
  	return byte_count;
  }
0e68c0037   Mark Haverkamp   [SCSI] aacraid: s...
2894
2895
  static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg)
  {
0e68c0037   Mark Haverkamp   [SCSI] aacraid: s...
2896
  	unsigned long byte_count = 0;
727eead62   FUJITA Tomonori   [SCSI] aacraid: c...
2897
  	int nseg;
0e68c0037   Mark Haverkamp   [SCSI] aacraid: s...
2898
2899
2900
2901
2902
2903
2904
2905
2906
  
  	// Get rid of old data
  	psg->count = 0;
  	psg->sg[0].next = 0;
  	psg->sg[0].prev = 0;
  	psg->sg[0].addr[0] = 0;
  	psg->sg[0].addr[1] = 0;
  	psg->sg[0].count = 0;
  	psg->sg[0].flags = 0;
727eead62   FUJITA Tomonori   [SCSI] aacraid: c...
2907
2908
2909
2910
  
  	nseg = scsi_dma_map(scsicmd);
  	BUG_ON(nseg < 0);
  	if (nseg) {
0e68c0037   Mark Haverkamp   [SCSI] aacraid: s...
2911
2912
  		struct scatterlist *sg;
  		int i;
0e68c0037   Mark Haverkamp   [SCSI] aacraid: s...
2913

727eead62   FUJITA Tomonori   [SCSI] aacraid: c...
2914
  		scsi_for_each_sg(scsicmd, sg, nseg, i) {
0e68c0037   Mark Haverkamp   [SCSI] aacraid: s...
2915
2916
2917
2918
2919
2920
2921
2922
2923
  			int count = sg_dma_len(sg);
  			u64 addr = sg_dma_address(sg);
  			psg->sg[i].next = 0;
  			psg->sg[i].prev = 0;
  			psg->sg[i].addr[1] = cpu_to_le32((u32)(addr>>32));
  			psg->sg[i].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff));
  			psg->sg[i].count = cpu_to_le32(count);
  			psg->sg[i].flags = 0;
  			byte_count += count;
0e68c0037   Mark Haverkamp   [SCSI] aacraid: s...
2924
  		}
727eead62   FUJITA Tomonori   [SCSI] aacraid: c...
2925
  		psg->count = cpu_to_le32(nseg);
0e68c0037   Mark Haverkamp   [SCSI] aacraid: s...
2926
  		/* hba wants the size to be exact */
727eead62   FUJITA Tomonori   [SCSI] aacraid: c...
2927
2928
2929
  		if (byte_count > scsi_bufflen(scsicmd)) {
  			u32 temp = le32_to_cpu(psg->sg[i-1].count) -
  				(byte_count - scsi_bufflen(scsicmd));
0e68c0037   Mark Haverkamp   [SCSI] aacraid: s...
2930
  			psg->sg[i-1].count = cpu_to_le32(temp);
727eead62   FUJITA Tomonori   [SCSI] aacraid: c...
2931
  			byte_count = scsi_bufflen(scsicmd);
0e68c0037   Mark Haverkamp   [SCSI] aacraid: s...
2932
2933
2934
2935
2936
2937
2938
2939
  		}
  		/* Check for command underflow */
  		if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
  			printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X
  ",
  					byte_count, scsicmd->underflow);
  		}
  	}
0e68c0037   Mark Haverkamp   [SCSI] aacraid: s...
2940
2941
  	return byte_count;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
  #ifdef AAC_DETAILED_STATUS_INFO
  
  struct aac_srb_status_info {
  	u32	status;
  	char	*str;
  };
  
  
  static struct aac_srb_status_info srb_status_info[] = {
  	{ SRB_STATUS_PENDING,		"Pending Status"},
  	{ SRB_STATUS_SUCCESS,		"Success"},
  	{ SRB_STATUS_ABORTED,		"Aborted Command"},
  	{ SRB_STATUS_ABORT_FAILED,	"Abort Failed"},
6391a1137   Tobias Klauser   [SCSI] drivers/sc...
2955
  	{ SRB_STATUS_ERROR,		"Error Event"},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
  	{ SRB_STATUS_BUSY,		"Device Busy"},
  	{ SRB_STATUS_INVALID_REQUEST,	"Invalid Request"},
  	{ SRB_STATUS_INVALID_PATH_ID,	"Invalid Path ID"},
  	{ SRB_STATUS_NO_DEVICE,		"No Device"},
  	{ SRB_STATUS_TIMEOUT,		"Timeout"},
  	{ SRB_STATUS_SELECTION_TIMEOUT,	"Selection Timeout"},
  	{ SRB_STATUS_COMMAND_TIMEOUT,	"Command Timeout"},
  	{ SRB_STATUS_MESSAGE_REJECTED,	"Message Rejected"},
  	{ SRB_STATUS_BUS_RESET,		"Bus Reset"},
  	{ SRB_STATUS_PARITY_ERROR,	"Parity Error"},
  	{ SRB_STATUS_REQUEST_SENSE_FAILED,"Request Sense Failed"},
  	{ SRB_STATUS_NO_HBA,		"No HBA"},
  	{ SRB_STATUS_DATA_OVERRUN,	"Data Overrun/Data Underrun"},
  	{ SRB_STATUS_UNEXPECTED_BUS_FREE,"Unexpected Bus Free"},
  	{ SRB_STATUS_PHASE_SEQUENCE_FAILURE,"Phase Error"},
  	{ SRB_STATUS_BAD_SRB_BLOCK_LENGTH,"Bad Srb Block Length"},
  	{ SRB_STATUS_REQUEST_FLUSHED,	"Request Flushed"},
  	{ SRB_STATUS_DELAYED_RETRY,	"Delayed Retry"},
6391a1137   Tobias Klauser   [SCSI] drivers/sc...
2974
  	{ SRB_STATUS_INVALID_LUN,	"Invalid LUN"},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2975
2976
2977
2978
2979
  	{ SRB_STATUS_INVALID_TARGET_ID,	"Invalid TARGET ID"},
  	{ SRB_STATUS_BAD_FUNCTION,	"Bad Function"},
  	{ SRB_STATUS_ERROR_RECOVERY,	"Error Recovery"},
  	{ SRB_STATUS_NOT_STARTED,	"Not Started"},
  	{ SRB_STATUS_NOT_IN_USE,	"Not In Use"},
8ce3eca4d   Salyzyn, Mark   [SCSI] aacraid: r...
2980
  	{ SRB_STATUS_FORCE_ABORT,	"Force Abort"},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2981
2982
2983
2984
2985
2986
2987
  	{ SRB_STATUS_DOMAIN_VALIDATION_FAIL,"Domain Validation Failure"},
  	{ 0xff,				"Unknown Error"}
  };
  
  char *aac_get_status_string(u32 status)
  {
  	int i;
6391a1137   Tobias Klauser   [SCSI] drivers/sc...
2988
2989
  	for (i = 0; i < ARRAY_SIZE(srb_status_info); i++)
  		if (srb_status_info[i].status == status)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2990
  			return srb_status_info[i].str;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2991
2992
2993
2994
2995
  
  	return "Bad Status Code";
  }
  
  #endif