blob: 9133ad4c7b1b79d776e81c448a1944dd3c78cc6f [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Mike Millerbd4f36d2007-10-24 10:30:34 +02002 * Disk Array driver for HP Smart Array controllers, SCSI Tape module.
3 * (C) Copyright 2001, 2007 Hewlett-Packard Development Company, L.P.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
Mike Millerbd4f36d2007-10-24 10:30:34 +02007 * the Free Software Foundation; version 2 of the License.
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Mike Millerbd4f36d2007-10-24 10:30:34 +020011 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
Linus Torvalds1da177e2005-04-16 15:20:36 -070013 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
Mike Millerbd4f36d2007-10-24 10:30:34 +020016 * Foundation, Inc., 59 Temple Place, Suite 300, Boston, MA
17 * 02111-1307, USA.
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 *
19 * Questions/Comments/Bugfixes to iss_storagedev@hp.com
20 *
21 * Author: Stephen M. Cameron
22 */
23#ifdef CONFIG_CISS_SCSI_TAPE
24
25/* Here we have code to present the driver as a scsi driver
26 as it is simultaneously presented as a block driver. The
27 reason for doing this is to allow access to SCSI tape drives
28 through the array controller. Note in particular, neither
29 physical nor logical disks are presented through the scsi layer. */
30
Tim Schmielau4e57b682005-10-30 15:03:48 -080031#include <linux/timer.h>
32#include <linux/completion.h>
33#include <linux/slab.h>
34#include <linux/string.h>
35
36#include <asm/atomic.h>
37
Linus Torvalds1da177e2005-04-16 15:20:36 -070038#include <scsi/scsi_cmnd.h>
39#include <scsi/scsi_device.h>
40#include <scsi/scsi_host.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
42#include "cciss_scsi.h"
43
mike.miller@hp.com3da8b712005-11-04 12:30:37 -060044#define CCISS_ABORT_MSG 0x00
45#define CCISS_RESET_MSG 0x01
46
Stephen M. Cameronf70dba82010-07-19 13:46:38 -050047static int fill_cmd(ctlr_info_t *h, CommandList_struct *c, __u8 cmd, void *buff,
Stephen M. Cameron88f627a2009-06-02 14:48:11 +020048 size_t size,
scameron@beardog.cca.cpqcorp.netb57695f2009-06-08 16:02:17 -050049 __u8 page_code, unsigned char *scsi3addr,
Stephen M. Cameron88f627a2009-06-02 14:48:11 +020050 int cmd_type);
51
Stephen M. Cameron88f627a2009-06-02 14:48:11 +020052static CommandList_struct *cmd_alloc(ctlr_info_t *h, int get_from_pool);
53static void cmd_free(ctlr_info_t *h, CommandList_struct *c, int got_from_pool);
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
55static int cciss_scsi_proc_info(
56 struct Scsi_Host *sh,
57 char *buffer, /* data buffer */
58 char **start, /* where data in buffer starts */
59 off_t offset, /* offset from start of imaginary file */
60 int length, /* length of data in buffer */
61 int func); /* 0 == read, 1 == write */
62
63static int cciss_scsi_queue_command (struct scsi_cmnd *cmd,
64 void (* done)(struct scsi_cmnd *));
mike.miller@hp.com3da8b712005-11-04 12:30:37 -060065static int cciss_eh_device_reset_handler(struct scsi_cmnd *);
66static int cciss_eh_abort_handler(struct scsi_cmnd *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070067
68static struct cciss_scsi_hba_t ccissscsi[MAX_CTLR] = {
69 { .name = "cciss0", .ndevices = 0 },
70 { .name = "cciss1", .ndevices = 0 },
71 { .name = "cciss2", .ndevices = 0 },
72 { .name = "cciss3", .ndevices = 0 },
73 { .name = "cciss4", .ndevices = 0 },
74 { .name = "cciss5", .ndevices = 0 },
75 { .name = "cciss6", .ndevices = 0 },
76 { .name = "cciss7", .ndevices = 0 },
77};
78
79static struct scsi_host_template cciss_driver_template = {
80 .module = THIS_MODULE,
81 .name = "cciss",
82 .proc_name = "cciss",
83 .proc_info = cciss_scsi_proc_info,
84 .queuecommand = cciss_scsi_queue_command,
85 .can_queue = SCSI_CCISS_CAN_QUEUE,
86 .this_id = 7,
Linus Torvalds1da177e2005-04-16 15:20:36 -070087 .cmd_per_lun = 1,
88 .use_clustering = DISABLE_CLUSTERING,
mike.miller@hp.com3da8b712005-11-04 12:30:37 -060089 /* Can't have eh_bus_reset_handler or eh_host_reset_handler for cciss */
90 .eh_device_reset_handler= cciss_eh_device_reset_handler,
91 .eh_abort_handler = cciss_eh_abort_handler,
Linus Torvalds1da177e2005-04-16 15:20:36 -070092};
93
94#pragma pack(1)
Stephen M. Cameron1b7d0d22010-02-26 16:01:17 -060095
Mike Miller5e216152010-06-02 12:58:06 -070096#define SCSI_PAD_32 8
97#define SCSI_PAD_64 8
Stephen M. Cameron1b7d0d22010-02-26 16:01:17 -060098
Linus Torvalds1da177e2005-04-16 15:20:36 -070099struct cciss_scsi_cmd_stack_elem_t {
100 CommandList_struct cmd;
101 ErrorInfo_struct Err;
102 __u32 busaddr;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600103 int cmdindex;
Stephen M. Cameron1b7d0d22010-02-26 16:01:17 -0600104 u8 pad[IS_32_BIT * SCSI_PAD_32 + IS_64_BIT * SCSI_PAD_64];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105};
106
107#pragma pack()
108
109#define CMD_STACK_SIZE (SCSI_CCISS_CAN_QUEUE * \
110 CCISS_MAX_SCSI_DEVS_PER_HBA + 2)
111 // plus two for init time usage
112
113#pragma pack(1)
114struct cciss_scsi_cmd_stack_t {
115 struct cciss_scsi_cmd_stack_elem_t *pool;
116 struct cciss_scsi_cmd_stack_elem_t *elem[CMD_STACK_SIZE];
117 dma_addr_t cmd_pool_handle;
118 int top;
119};
120#pragma pack()
121
122struct cciss_scsi_adapter_data_t {
123 struct Scsi_Host *scsi_host;
124 struct cciss_scsi_cmd_stack_t cmd_stack;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600125 SGDescriptor_struct **cmd_sg_list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 int registered;
127 spinlock_t lock; // to protect ccissscsi[ctlr];
128};
129
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500130#define CPQ_TAPE_LOCK(h, flags) spin_lock_irqsave( \
131 &h->scsi_ctlr->lock, flags);
132#define CPQ_TAPE_UNLOCK(h, flags) spin_unlock_irqrestore( \
133 &h->scsi_ctlr->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134
135static CommandList_struct *
136scsi_cmd_alloc(ctlr_info_t *h)
137{
138 /* assume only one process in here at a time, locking done by caller. */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500139 /* use h->lock */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140 /* might be better to rewrite how we allocate scsi commands in a way that */
141 /* needs no locking at all. */
142
143 /* take the top memory chunk off the stack and return it, if any. */
144 struct cciss_scsi_cmd_stack_elem_t *c;
145 struct cciss_scsi_adapter_data_t *sa;
146 struct cciss_scsi_cmd_stack_t *stk;
147 u64bit temp64;
148
Stephen M. Cameronaad9fb62010-02-26 16:01:42 -0600149 sa = h->scsi_ctlr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150 stk = &sa->cmd_stack;
151
152 if (stk->top < 0)
153 return NULL;
154 c = stk->elem[stk->top];
155 /* memset(c, 0, sizeof(*c)); */
156 memset(&c->cmd, 0, sizeof(c->cmd));
157 memset(&c->Err, 0, sizeof(c->Err));
158 /* set physical addr of cmd and addr of scsi parameters */
159 c->cmd.busaddr = c->busaddr;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600160 c->cmd.cmdindex = c->cmdindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161 /* (__u32) (stk->cmd_pool_handle +
162 (sizeof(struct cciss_scsi_cmd_stack_elem_t)*stk->top)); */
163
164 temp64.val = (__u64) (c->busaddr + sizeof(CommandList_struct));
165 /* (__u64) (stk->cmd_pool_handle +
166 (sizeof(struct cciss_scsi_cmd_stack_elem_t)*stk->top) +
167 sizeof(CommandList_struct)); */
168 stk->top--;
169 c->cmd.ErrDesc.Addr.lower = temp64.val32.lower;
170 c->cmd.ErrDesc.Addr.upper = temp64.val32.upper;
171 c->cmd.ErrDesc.Len = sizeof(ErrorInfo_struct);
172
173 c->cmd.ctlr = h->ctlr;
174 c->cmd.err_info = &c->Err;
175
176 return (CommandList_struct *) c;
177}
178
179static void
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500180scsi_cmd_free(ctlr_info_t *h, CommandList_struct *c)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181{
182 /* assume only one process in here at a time, locking done by caller. */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500183 /* use h->lock */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 /* drop the free memory chunk on top of the stack. */
185
186 struct cciss_scsi_adapter_data_t *sa;
187 struct cciss_scsi_cmd_stack_t *stk;
188
Stephen M. Cameronaad9fb62010-02-26 16:01:42 -0600189 sa = h->scsi_ctlr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 stk = &sa->cmd_stack;
Dan Carpenter713b6862010-06-01 12:17:48 +0200191 stk->top++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 if (stk->top >= CMD_STACK_SIZE) {
193 printk("cciss: scsi_cmd_free called too many times.\n");
194 BUG();
195 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500196 stk->elem[stk->top] = (struct cciss_scsi_cmd_stack_elem_t *) c;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197}
198
199static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500200scsi_cmd_stack_setup(ctlr_info_t *h, struct cciss_scsi_adapter_data_t *sa)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201{
202 int i;
203 struct cciss_scsi_cmd_stack_t *stk;
204 size_t size;
205
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500206 sa->cmd_sg_list = cciss_allocate_sg_chain_blocks(h,
207 h->chainsize, CMD_STACK_SIZE);
208 if (!sa->cmd_sg_list && h->chainsize > 0)
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600209 return -ENOMEM;
210
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 stk = &sa->cmd_stack;
212 size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE;
213
Stephen M. Cameron1b7d0d22010-02-26 16:01:17 -0600214 /* Check alignment, see cciss_cmd.h near CommandList_struct def. */
215 BUILD_BUG_ON((sizeof(*stk->pool) % COMMANDLIST_ALIGNMENT) != 0);
216 /* pci_alloc_consistent guarantees 32-bit DMA address will be used */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217 stk->pool = (struct cciss_scsi_cmd_stack_elem_t *)
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500218 pci_alloc_consistent(h->pdev, size, &stk->cmd_pool_handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219
220 if (stk->pool == NULL) {
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600221 cciss_free_sg_chain_blocks(sa->cmd_sg_list, CMD_STACK_SIZE);
222 sa->cmd_sg_list = NULL;
223 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 }
225
226 for (i=0; i<CMD_STACK_SIZE; i++) {
227 stk->elem[i] = &stk->pool[i];
228 stk->elem[i]->busaddr = (__u32) (stk->cmd_pool_handle +
229 (sizeof(struct cciss_scsi_cmd_stack_elem_t) * i));
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600230 stk->elem[i]->cmdindex = i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700231 }
232 stk->top = CMD_STACK_SIZE-1;
233 return 0;
234}
235
236static void
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500237scsi_cmd_stack_free(ctlr_info_t *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238{
239 struct cciss_scsi_adapter_data_t *sa;
240 struct cciss_scsi_cmd_stack_t *stk;
241 size_t size;
242
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500243 sa = h->scsi_ctlr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 stk = &sa->cmd_stack;
245 if (stk->top != CMD_STACK_SIZE-1) {
246 printk( "cciss: %d scsi commands are still outstanding.\n",
247 CMD_STACK_SIZE - stk->top);
248 // BUG();
249 printk("WE HAVE A BUG HERE!!! stk=0x%p\n", stk);
250 }
251 size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE;
252
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500253 pci_free_consistent(h->pdev, size, stk->pool, stk->cmd_pool_handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 stk->pool = NULL;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600255 cciss_free_sg_chain_blocks(sa->cmd_sg_list, CMD_STACK_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256}
257
Grant Coady400bb232005-11-15 00:09:20 -0800258#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259static int xmargin=8;
260static int amargin=60;
261
262static void
263print_bytes (unsigned char *c, int len, int hex, int ascii)
264{
265
266 int i;
267 unsigned char *x;
268
269 if (hex)
270 {
271 x = c;
272 for (i=0;i<len;i++)
273 {
274 if ((i % xmargin) == 0 && i>0) printk("\n");
275 if ((i % xmargin) == 0) printk("0x%04x:", i);
276 printk(" %02x", *x);
277 x++;
278 }
279 printk("\n");
280 }
281 if (ascii)
282 {
283 x = c;
284 for (i=0;i<len;i++)
285 {
286 if ((i % amargin) == 0 && i>0) printk("\n");
287 if ((i % amargin) == 0) printk("0x%04x:", i);
288 if (*x > 26 && *x < 128) printk("%c", *x);
289 else printk(".");
290 x++;
291 }
292 printk("\n");
293 }
294}
295
296static void
297print_cmd(CommandList_struct *cp)
298{
299 printk("queue:%d\n", cp->Header.ReplyQueue);
300 printk("sglist:%d\n", cp->Header.SGList);
301 printk("sgtot:%d\n", cp->Header.SGTotal);
302 printk("Tag:0x%08x/0x%08x\n", cp->Header.Tag.upper,
303 cp->Header.Tag.lower);
304 printk("LUN:0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
305 cp->Header.LUN.LunAddrBytes[0],
306 cp->Header.LUN.LunAddrBytes[1],
307 cp->Header.LUN.LunAddrBytes[2],
308 cp->Header.LUN.LunAddrBytes[3],
309 cp->Header.LUN.LunAddrBytes[4],
310 cp->Header.LUN.LunAddrBytes[5],
311 cp->Header.LUN.LunAddrBytes[6],
312 cp->Header.LUN.LunAddrBytes[7]);
313 printk("CDBLen:%d\n", cp->Request.CDBLen);
314 printk("Type:%d\n",cp->Request.Type.Type);
315 printk("Attr:%d\n",cp->Request.Type.Attribute);
316 printk(" Dir:%d\n",cp->Request.Type.Direction);
317 printk("Timeout:%d\n",cp->Request.Timeout);
318 printk( "CDB: %02x %02x %02x %02x %02x %02x %02x %02x"
319 " %02x %02x %02x %02x %02x %02x %02x %02x\n",
320 cp->Request.CDB[0], cp->Request.CDB[1],
321 cp->Request.CDB[2], cp->Request.CDB[3],
322 cp->Request.CDB[4], cp->Request.CDB[5],
323 cp->Request.CDB[6], cp->Request.CDB[7],
324 cp->Request.CDB[8], cp->Request.CDB[9],
325 cp->Request.CDB[10], cp->Request.CDB[11],
326 cp->Request.CDB[12], cp->Request.CDB[13],
327 cp->Request.CDB[14], cp->Request.CDB[15]),
328 printk("edesc.Addr: 0x%08x/0%08x, Len = %d\n",
329 cp->ErrDesc.Addr.upper, cp->ErrDesc.Addr.lower,
330 cp->ErrDesc.Len);
331 printk("sgs..........Errorinfo:\n");
332 printk("scsistatus:%d\n", cp->err_info->ScsiStatus);
333 printk("senselen:%d\n", cp->err_info->SenseLen);
334 printk("cmd status:%d\n", cp->err_info->CommandStatus);
335 printk("resid cnt:%d\n", cp->err_info->ResidualCnt);
336 printk("offense size:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_size);
337 printk("offense byte:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_num);
338 printk("offense value:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_value);
339
340}
341
342#endif
343
344static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500345find_bus_target_lun(ctlr_info_t *h, int *bus, int *target, int *lun)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346{
347 /* finds an unused bus, target, lun for a new device */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500348 /* assumes h->scsi_ctlr->lock is held */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 int i, found=0;
350 unsigned char target_taken[CCISS_MAX_SCSI_DEVS_PER_HBA];
351
352 memset(&target_taken[0], 0, CCISS_MAX_SCSI_DEVS_PER_HBA);
353
354 target_taken[SELF_SCSI_ID] = 1;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500355 for (i = 0; i < ccissscsi[h->ctlr].ndevices; i++)
356 target_taken[ccissscsi[h->ctlr].dev[i].target] = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500358 for (i = 0; i < CCISS_MAX_SCSI_DEVS_PER_HBA; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 if (!target_taken[i]) {
360 *bus = 0; *target=i; *lun = 0; found=1;
361 break;
362 }
363 }
364 return (!found);
365}
Mike Millerf4a93bc2008-08-04 11:54:53 +0200366struct scsi2map {
367 char scsi3addr[8];
368 int bus, target, lun;
369};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370
371static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500372cciss_scsi_add_entry(ctlr_info_t *h, int hostno,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700373 struct cciss_scsi_dev_t *device,
Mike Millerf4a93bc2008-08-04 11:54:53 +0200374 struct scsi2map *added, int *nadded)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375{
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500376 /* assumes h->scsi_ctlr->lock is held */
377 int n = ccissscsi[h->ctlr].ndevices;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 struct cciss_scsi_dev_t *sd;
Mike Miller935dc8d2008-08-04 11:54:54 +0200379 int i, bus, target, lun;
380 unsigned char addr1[8], addr2[8];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381
382 if (n >= CCISS_MAX_SCSI_DEVS_PER_HBA) {
383 printk("cciss%d: Too many devices, "
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500384 "some will be inaccessible.\n", h->ctlr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 return -1;
386 }
Mike Millerf4a93bc2008-08-04 11:54:53 +0200387
Mike Miller935dc8d2008-08-04 11:54:54 +0200388 bus = target = -1;
389 lun = 0;
390 /* Is this device a non-zero lun of a multi-lun device */
391 /* byte 4 of the 8-byte LUN addr will contain the logical unit no. */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700392 if (device->scsi3addr[4] != 0) {
Mike Miller935dc8d2008-08-04 11:54:54 +0200393 /* Search through our list and find the device which */
394 /* has the same 8 byte LUN address, excepting byte 4. */
395 /* Assign the same bus and target for this new LUN. */
396 /* Use the logical unit number from the firmware. */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700397 memcpy(addr1, device->scsi3addr, 8);
Mike Miller935dc8d2008-08-04 11:54:54 +0200398 addr1[4] = 0;
399 for (i = 0; i < n; i++) {
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500400 sd = &ccissscsi[h->ctlr].dev[i];
Mike Miller935dc8d2008-08-04 11:54:54 +0200401 memcpy(addr2, sd->scsi3addr, 8);
402 addr2[4] = 0;
403 /* differ only in byte 4? */
404 if (memcmp(addr1, addr2, 8) == 0) {
405 bus = sd->bus;
406 target = sd->target;
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700407 lun = device->scsi3addr[4];
Mike Miller935dc8d2008-08-04 11:54:54 +0200408 break;
409 }
410 }
411 }
412
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500413 sd = &ccissscsi[h->ctlr].dev[n];
Mike Miller935dc8d2008-08-04 11:54:54 +0200414 if (lun == 0) {
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500415 if (find_bus_target_lun(h,
Mike Miller935dc8d2008-08-04 11:54:54 +0200416 &sd->bus, &sd->target, &sd->lun) != 0)
417 return -1;
418 } else {
419 sd->bus = bus;
420 sd->target = target;
421 sd->lun = lun;
422 }
Mike Millerf4a93bc2008-08-04 11:54:53 +0200423 added[*nadded].bus = sd->bus;
424 added[*nadded].target = sd->target;
425 added[*nadded].lun = sd->lun;
426 (*nadded)++;
427
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700428 memcpy(sd->scsi3addr, device->scsi3addr, 8);
429 memcpy(sd->vendor, device->vendor, sizeof(sd->vendor));
430 memcpy(sd->revision, device->revision, sizeof(sd->revision));
431 memcpy(sd->device_id, device->device_id, sizeof(sd->device_id));
432 sd->devtype = device->devtype;
433
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500434 ccissscsi[h->ctlr].ndevices++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435
436 /* initially, (before registering with scsi layer) we don't
437 know our hostno and we don't want to print anything first
438 time anyway (the scsi layer's inquiries will show that info) */
439 if (hostno != -1)
440 printk("cciss%d: %s device c%db%dt%dl%d added.\n",
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500441 h->ctlr, scsi_device_type(sd->devtype), hostno,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 sd->bus, sd->target, sd->lun);
443 return 0;
444}
445
446static void
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500447cciss_scsi_remove_entry(ctlr_info_t *h, int hostno, int entry,
Mike Millerf4a93bc2008-08-04 11:54:53 +0200448 struct scsi2map *removed, int *nremoved)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449{
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500450 /* assumes h->ctlr]->scsi_ctlr->lock is held */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 int i;
452 struct cciss_scsi_dev_t sd;
453
454 if (entry < 0 || entry >= CCISS_MAX_SCSI_DEVS_PER_HBA) return;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500455 sd = ccissscsi[h->ctlr].dev[entry];
Mike Millerf4a93bc2008-08-04 11:54:53 +0200456 removed[*nremoved].bus = sd.bus;
457 removed[*nremoved].target = sd.target;
458 removed[*nremoved].lun = sd.lun;
459 (*nremoved)++;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500460 for (i = entry; i < ccissscsi[h->ctlr].ndevices-1; i++)
461 ccissscsi[h->ctlr].dev[i] = ccissscsi[h->ctlr].dev[i+1];
462 ccissscsi[h->ctlr].ndevices--;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 printk("cciss%d: %s device c%db%dt%dl%d removed.\n",
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500464 h->ctlr, scsi_device_type(sd.devtype), hostno,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 sd.bus, sd.target, sd.lun);
466}
467
468
469#define SCSI3ADDR_EQ(a,b) ( \
470 (a)[7] == (b)[7] && \
471 (a)[6] == (b)[6] && \
472 (a)[5] == (b)[5] && \
473 (a)[4] == (b)[4] && \
474 (a)[3] == (b)[3] && \
475 (a)[2] == (b)[2] && \
476 (a)[1] == (b)[1] && \
477 (a)[0] == (b)[0])
478
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500479static void fixup_botched_add(ctlr_info_t *h, char *scsi3addr)
Mike Millerf4a93bc2008-08-04 11:54:53 +0200480{
481 /* called when scsi_add_device fails in order to re-adjust */
482 /* ccissscsi[] to match the mid layer's view. */
483 unsigned long flags;
484 int i, j;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500485 CPQ_TAPE_LOCK(h, flags);
486 for (i = 0; i < ccissscsi[h->ctlr].ndevices; i++) {
Mike Millerf4a93bc2008-08-04 11:54:53 +0200487 if (memcmp(scsi3addr,
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500488 ccissscsi[h->ctlr].dev[i].scsi3addr, 8) == 0) {
489 for (j = i; j < ccissscsi[h->ctlr].ndevices-1; j++)
490 ccissscsi[h->ctlr].dev[j] =
491 ccissscsi[h->ctlr].dev[j+1];
492 ccissscsi[h->ctlr].ndevices--;
Mike Millerf4a93bc2008-08-04 11:54:53 +0200493 break;
494 }
495 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500496 CPQ_TAPE_UNLOCK(h, flags);
Mike Millerf4a93bc2008-08-04 11:54:53 +0200497}
498
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700499static int device_is_the_same(struct cciss_scsi_dev_t *dev1,
500 struct cciss_scsi_dev_t *dev2)
501{
502 return dev1->devtype == dev2->devtype &&
503 memcmp(dev1->scsi3addr, dev2->scsi3addr,
504 sizeof(dev1->scsi3addr)) == 0 &&
505 memcmp(dev1->device_id, dev2->device_id,
506 sizeof(dev1->device_id)) == 0 &&
507 memcmp(dev1->vendor, dev2->vendor,
508 sizeof(dev1->vendor)) == 0 &&
509 memcmp(dev1->model, dev2->model,
510 sizeof(dev1->model)) == 0 &&
511 memcmp(dev1->revision, dev2->revision,
512 sizeof(dev1->revision)) == 0;
513}
514
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500516adjust_cciss_scsi_table(ctlr_info_t *h, int hostno,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 struct cciss_scsi_dev_t sd[], int nsds)
518{
519 /* sd contains scsi3 addresses and devtypes, but
520 bus target and lun are not filled in. This funciton
521 takes what's in sd to be the current and adjusts
522 ccissscsi[] to be in line with what's in sd. */
523
524 int i,j, found, changes=0;
525 struct cciss_scsi_dev_t *csd;
526 unsigned long flags;
Mike Millerf4a93bc2008-08-04 11:54:53 +0200527 struct scsi2map *added, *removed;
528 int nadded, nremoved;
529 struct Scsi_Host *sh = NULL;
530
531 added = kzalloc(sizeof(*added) * CCISS_MAX_SCSI_DEVS_PER_HBA,
532 GFP_KERNEL);
533 removed = kzalloc(sizeof(*removed) * CCISS_MAX_SCSI_DEVS_PER_HBA,
534 GFP_KERNEL);
535
536 if (!added || !removed) {
537 printk(KERN_WARNING "cciss%d: Out of memory in "
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500538 "adjust_cciss_scsi_table\n", h->ctlr);
Mike Millerf4a93bc2008-08-04 11:54:53 +0200539 goto free_and_out;
540 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500542 CPQ_TAPE_LOCK(h, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543
Mike Millerf4a93bc2008-08-04 11:54:53 +0200544 if (hostno != -1) /* if it's not the first time... */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500545 sh = h->scsi_ctlr->scsi_host;
Mike Millerf4a93bc2008-08-04 11:54:53 +0200546
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 /* find any devices in ccissscsi[] that are not in
548 sd[] and remove them from ccissscsi[] */
549
550 i = 0;
Mike Millerf4a93bc2008-08-04 11:54:53 +0200551 nremoved = 0;
552 nadded = 0;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500553 while (i < ccissscsi[h->ctlr].ndevices) {
554 csd = &ccissscsi[h->ctlr].dev[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 found=0;
556 for (j=0;j<nsds;j++) {
557 if (SCSI3ADDR_EQ(sd[j].scsi3addr,
558 csd->scsi3addr)) {
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700559 if (device_is_the_same(&sd[j], csd))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 found=2;
561 else
562 found=1;
563 break;
564 }
565 }
566
567 if (found == 0) { /* device no longer present. */
568 changes++;
569 /* printk("cciss%d: %s device c%db%dt%dl%d removed.\n",
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500570 h->ctlr, scsi_device_type(csd->devtype), hostno,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 csd->bus, csd->target, csd->lun); */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500572 cciss_scsi_remove_entry(h, hostno, i,
Mike Millerf4a93bc2008-08-04 11:54:53 +0200573 removed, &nremoved);
574 /* remove ^^^, hence i not incremented */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700575 } else if (found == 1) { /* device is different in some way */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 changes++;
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700577 printk("cciss%d: device c%db%dt%dl%d has changed.\n",
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500578 h->ctlr, hostno,
579 csd->bus, csd->target, csd->lun);
580 cciss_scsi_remove_entry(h, hostno, i,
Mike Millerf4a93bc2008-08-04 11:54:53 +0200581 removed, &nremoved);
582 /* remove ^^^, hence i not incremented */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500583 if (cciss_scsi_add_entry(h, hostno, &sd[j],
Mike Millerf4a93bc2008-08-04 11:54:53 +0200584 added, &nadded) != 0)
585 /* we just removed one, so add can't fail. */
586 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 csd->devtype = sd[j].devtype;
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700588 memcpy(csd->device_id, sd[j].device_id,
589 sizeof(csd->device_id));
590 memcpy(csd->vendor, sd[j].vendor,
591 sizeof(csd->vendor));
592 memcpy(csd->model, sd[j].model,
593 sizeof(csd->model));
594 memcpy(csd->revision, sd[j].revision,
595 sizeof(csd->revision));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 } else /* device is same as it ever was, */
597 i++; /* so just move along. */
598 }
599
600 /* Now, make sure every device listed in sd[] is also
601 listed in ccissscsi[], adding them if they aren't found */
602
603 for (i=0;i<nsds;i++) {
604 found=0;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500605 for (j = 0; j < ccissscsi[h->ctlr].ndevices; j++) {
606 csd = &ccissscsi[h->ctlr].dev[j];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 if (SCSI3ADDR_EQ(sd[i].scsi3addr,
608 csd->scsi3addr)) {
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700609 if (device_is_the_same(&sd[i], csd))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 found=2; /* found device */
611 else
612 found=1; /* found a bug. */
613 break;
614 }
615 }
616 if (!found) {
617 changes++;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500618 if (cciss_scsi_add_entry(h, hostno, &sd[i],
Mike Millerf4a93bc2008-08-04 11:54:53 +0200619 added, &nadded) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 break;
621 } else if (found == 1) {
622 /* should never happen... */
623 changes++;
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700624 printk(KERN_WARNING "cciss%d: device "
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500625 "unexpectedly changed\n", h->ctlr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 /* but if it does happen, we just ignore that device */
627 }
628 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500629 CPQ_TAPE_UNLOCK(h, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630
Mike Millerf4a93bc2008-08-04 11:54:53 +0200631 /* Don't notify scsi mid layer of any changes the first time through */
632 /* (or if there are no changes) scsi_scan_host will do it later the */
633 /* first time through. */
634 if (hostno == -1 || !changes)
635 goto free_and_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636
Mike Millerf4a93bc2008-08-04 11:54:53 +0200637 /* Notify scsi mid layer of any removed devices */
638 for (i = 0; i < nremoved; i++) {
639 struct scsi_device *sdev =
640 scsi_device_lookup(sh, removed[i].bus,
641 removed[i].target, removed[i].lun);
642 if (sdev != NULL) {
643 scsi_remove_device(sdev);
644 scsi_device_put(sdev);
645 } else {
646 /* We don't expect to get here. */
647 /* future cmds to this device will get selection */
648 /* timeout as if the device was gone. */
649 printk(KERN_WARNING "cciss%d: didn't find "
650 "c%db%dt%dl%d\n for removal.",
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500651 h->ctlr, hostno, removed[i].bus,
Mike Millerf4a93bc2008-08-04 11:54:53 +0200652 removed[i].target, removed[i].lun);
653 }
654 }
655
656 /* Notify scsi mid layer of any added devices */
657 for (i = 0; i < nadded; i++) {
658 int rc;
659 rc = scsi_add_device(sh, added[i].bus,
660 added[i].target, added[i].lun);
661 if (rc == 0)
662 continue;
663 printk(KERN_WARNING "cciss%d: scsi_add_device "
664 "c%db%dt%dl%d failed, device not added.\n",
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500665 h->ctlr, hostno,
Mike Millerf4a93bc2008-08-04 11:54:53 +0200666 added[i].bus, added[i].target, added[i].lun);
667 /* now we have to remove it from ccissscsi, */
668 /* since it didn't get added to scsi mid layer */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500669 fixup_botched_add(h, added[i].scsi3addr);
Mike Millerf4a93bc2008-08-04 11:54:53 +0200670 }
671
672free_and_out:
673 kfree(added);
674 kfree(removed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675 return 0;
676}
677
678static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500679lookup_scsi3addr(ctlr_info_t *h, int bus, int target, int lun, char *scsi3addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680{
681 int i;
682 struct cciss_scsi_dev_t *sd;
683 unsigned long flags;
684
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500685 CPQ_TAPE_LOCK(h, flags);
686 for (i = 0; i < ccissscsi[h->ctlr].ndevices; i++) {
687 sd = &ccissscsi[h->ctlr].dev[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 if (sd->bus == bus &&
689 sd->target == target &&
690 sd->lun == lun) {
691 memcpy(scsi3addr, &sd->scsi3addr[0], 8);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500692 CPQ_TAPE_UNLOCK(h, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 return 0;
694 }
695 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500696 CPQ_TAPE_UNLOCK(h, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 return -1;
698}
699
700static void
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500701cciss_scsi_setup(ctlr_info_t *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702{
703 struct cciss_scsi_adapter_data_t * shba;
704
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500705 ccissscsi[h->ctlr].ndevices = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 shba = (struct cciss_scsi_adapter_data_t *)
707 kmalloc(sizeof(*shba), GFP_KERNEL);
708 if (shba == NULL)
709 return;
710 shba->scsi_host = NULL;
711 spin_lock_init(&shba->lock);
712 shba->registered = 0;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500713 if (scsi_cmd_stack_setup(h, shba) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 kfree(shba);
715 shba = NULL;
716 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500717 h->scsi_ctlr = shba;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 return;
719}
720
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500721static void complete_scsi_command(CommandList_struct *c, int timeout,
722 __u32 tag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723{
724 struct scsi_cmnd *cmd;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500725 ctlr_info_t *h;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 ErrorInfo_struct *ei;
727
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500728 ei = c->err_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729
730 /* First, see if it was a message rather than a command */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500731 if (c->Request.Type.Type == TYPE_MSG) {
732 c->cmd_type = CMD_MSG_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 return;
734 }
735
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500736 cmd = (struct scsi_cmnd *) c->scsi_cmd;
737 h = hba[c->ctlr];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738
FUJITA Tomonori41ce6392007-05-26 02:45:17 +0900739 scsi_dma_unmap(cmd);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500740 if (c->Header.SGTotal > h->max_cmd_sgentries)
741 cciss_unmap_sg_chain_block(h, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742
743 cmd->result = (DID_OK << 16); /* host byte */
744 cmd->result |= (COMMAND_COMPLETE << 8); /* msg byte */
745 /* cmd->result |= (GOOD < 1); */ /* status byte */
746
747 cmd->result |= (ei->ScsiStatus);
748 /* printk("Scsistatus is 0x%02x\n", ei->ScsiStatus); */
749
750 /* copy the sense data whether we need to or not. */
751
752 memcpy(cmd->sense_buffer, ei->SenseInfo,
753 ei->SenseLen > SCSI_SENSE_BUFFERSIZE ?
754 SCSI_SENSE_BUFFERSIZE :
755 ei->SenseLen);
FUJITA Tomonori41ce6392007-05-26 02:45:17 +0900756 scsi_set_resid(cmd, ei->ResidualCnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757
758 if(ei->CommandStatus != 0)
759 { /* an error has occurred */
760 switch(ei->CommandStatus)
761 {
762 case CMD_TARGET_STATUS:
763 /* Pass it up to the upper layers... */
764 if( ei->ScsiStatus)
765 {
766#if 0
767 printk(KERN_WARNING "cciss: cmd %p "
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500768 "has SCSI Status = %x\n",
769 c, ei->ScsiStatus);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770#endif
Stephen M. Cameronb0e15f62009-11-12 12:49:45 -0600771 cmd->result |= (ei->ScsiStatus << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 }
773 else { /* scsi status is zero??? How??? */
774
775 /* Ordinarily, this case should never happen, but there is a bug
776 in some released firmware revisions that allows it to happen
777 if, for example, a 4100 backplane loses power and the tape
778 drive is in it. We assume that it's a fatal error of some
779 kind because we can't show that it wasn't. We will make it
780 look like selection timeout since that is the most common
781 reason for this to occur, and it's severe enough. */
782
783 cmd->result = DID_NO_CONNECT << 16;
784 }
785 break;
786 case CMD_DATA_UNDERRUN: /* let mid layer handle it. */
787 break;
788 case CMD_DATA_OVERRUN:
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500789 printk(KERN_WARNING "cciss: %p has"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 " completed with data overrun "
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500791 "reported\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 break;
793 case CMD_INVALID: {
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500794 /* print_bytes(c, sizeof(*c), 1, 0);
795 print_cmd(c); */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 /* We get CMD_INVALID if you address a non-existent tape drive instead
797 of a selection timeout (no response). You will see this if you yank
798 out a tape drive, then try to access it. This is kind of a shame
799 because it means that any other CMD_INVALID (e.g. driver bug) will
800 get interpreted as a missing target. */
801 cmd->result = DID_NO_CONNECT << 16;
802 }
803 break;
804 case CMD_PROTOCOL_ERR:
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500805 printk(KERN_WARNING "cciss: %p has "
806 "protocol error\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 break;
808 case CMD_HARDWARE_ERR:
809 cmd->result = DID_ERROR << 16;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500810 printk(KERN_WARNING "cciss: %p had "
811 " hardware error\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 break;
813 case CMD_CONNECTION_LOST:
814 cmd->result = DID_ERROR << 16;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500815 printk(KERN_WARNING "cciss: %p had "
816 "connection lost\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 break;
818 case CMD_ABORTED:
819 cmd->result = DID_ABORT << 16;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500820 printk(KERN_WARNING "cciss: %p was "
821 "aborted\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 break;
823 case CMD_ABORT_FAILED:
824 cmd->result = DID_ERROR << 16;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500825 printk(KERN_WARNING "cciss: %p reports "
826 "abort failed\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 break;
828 case CMD_UNSOLICITED_ABORT:
829 cmd->result = DID_ABORT << 16;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500830 printk(KERN_WARNING "cciss: %p aborted "
831 "do to an unsolicited abort\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 break;
833 case CMD_TIMEOUT:
834 cmd->result = DID_TIME_OUT << 16;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500835 printk(KERN_WARNING "cciss: %p timedout\n",
836 c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 break;
838 default:
839 cmd->result = DID_ERROR << 16;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500840 printk(KERN_WARNING "cciss: %p returned "
841 "unknown status %x\n", c,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 ei->CommandStatus);
843 }
844 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 cmd->scsi_done(cmd);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500846 scsi_cmd_free(h, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847}
848
849static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500850cciss_scsi_detect(ctlr_info_t *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851{
852 struct Scsi_Host *sh;
853 int error;
854
855 sh = scsi_host_alloc(&cciss_driver_template, sizeof(struct ctlr_info *));
856 if (sh == NULL)
857 goto fail;
858 sh->io_port = 0; // good enough? FIXME,
859 sh->n_io_port = 0; // I don't think we use these two...
860 sh->this_id = SELF_SCSI_ID;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500861 sh->sg_tablesize = h->maxsgentries;
Stephen M. Cameron79600aa2010-06-15 08:12:34 +0200862 sh->max_cmd_len = MAX_COMMAND_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863
864 ((struct cciss_scsi_adapter_data_t *)
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500865 h->scsi_ctlr)->scsi_host = sh;
866 sh->hostdata[0] = (unsigned long) h;
867 sh->irq = h->intr[SIMPLE_MODE_INT];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868 sh->unique_id = sh->irq;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500869 error = scsi_add_host(sh, &h->pdev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870 if (error)
871 goto fail_host_put;
872 scsi_scan_host(sh);
873 return 1;
874
875 fail_host_put:
876 scsi_host_put(sh);
877 fail:
878 return 0;
879}
880
881static void
882cciss_unmap_one(struct pci_dev *pdev,
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500883 CommandList_struct *c,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 size_t buflen,
885 int data_direction)
886{
887 u64bit addr64;
888
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500889 addr64.val32.lower = c->SG[0].Addr.lower;
890 addr64.val32.upper = c->SG[0].Addr.upper;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 pci_unmap_single(pdev, (dma_addr_t) addr64.val, buflen, data_direction);
892}
893
894static void
895cciss_map_one(struct pci_dev *pdev,
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500896 CommandList_struct *c,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 unsigned char *buf,
898 size_t buflen,
899 int data_direction)
900{
901 __u64 addr64;
902
903 addr64 = (__u64) pci_map_single(pdev, buf, buflen, data_direction);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500904 c->SG[0].Addr.lower =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500906 c->SG[0].Addr.upper =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500908 c->SG[0].Len = buflen;
909 c->Header.SGList = (__u8) 1; /* no. SGs contig in this cmd */
910 c->Header.SGTotal = (__u16) 1; /* total sgs in this cmd list */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911}
912
913static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500914cciss_scsi_do_simple_cmd(ctlr_info_t *h,
915 CommandList_struct *c,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 unsigned char *scsi3addr,
917 unsigned char *cdb,
918 unsigned char cdblen,
919 unsigned char *buf, int bufsize,
920 int direction)
921{
Peter Zijlstra6e9a4732006-09-30 23:28:10 -0700922 DECLARE_COMPLETION_ONSTACK(wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500924 c->cmd_type = CMD_IOCTL_PEND; /* treat this like an ioctl */
925 c->scsi_cmd = NULL;
926 c->Header.ReplyQueue = 0; /* unused in simple mode */
927 memcpy(&c->Header.LUN, scsi3addr, sizeof(c->Header.LUN));
928 c->Header.Tag.lower = c->busaddr; /* Use k. address of cmd as tag */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 // Fill in the request block...
930
931 /* printk("Using scsi3addr 0x%02x%0x2%0x2%0x2%0x2%0x2%0x2%0x2\n",
932 scsi3addr[0], scsi3addr[1], scsi3addr[2], scsi3addr[3],
933 scsi3addr[4], scsi3addr[5], scsi3addr[6], scsi3addr[7]); */
934
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500935 memset(c->Request.CDB, 0, sizeof(c->Request.CDB));
936 memcpy(c->Request.CDB, cdb, cdblen);
937 c->Request.Timeout = 0;
938 c->Request.CDBLen = cdblen;
939 c->Request.Type.Type = TYPE_CMD;
940 c->Request.Type.Attribute = ATTR_SIMPLE;
941 c->Request.Type.Direction = direction;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942
943 /* Fill in the SG list and do dma mapping */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500944 cciss_map_one(h->pdev, c, (unsigned char *) buf,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 bufsize, DMA_FROM_DEVICE);
946
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500947 c->waiting = &wait;
948 enqueue_cmd_and_start_io(h, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 wait_for_completion(&wait);
950
951 /* undo the dma mapping */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500952 cciss_unmap_one(h->pdev, c, bufsize, DMA_FROM_DEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 return(0);
954}
955
956static void
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500957cciss_scsi_interpret_error(CommandList_struct *c)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958{
959 ErrorInfo_struct *ei;
960
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500961 ei = c->err_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 switch(ei->CommandStatus)
963 {
964 case CMD_TARGET_STATUS:
965 printk(KERN_WARNING "cciss: cmd %p has "
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500966 "completed with errors\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 printk(KERN_WARNING "cciss: cmd %p "
968 "has SCSI Status = %x\n",
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500969 c, ei->ScsiStatus);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 if (ei->ScsiStatus == 0)
971 printk(KERN_WARNING
972 "cciss:SCSI status is abnormally zero. "
973 "(probably indicates selection timeout "
974 "reported incorrectly due to a known "
975 "firmware bug, circa July, 2001.)\n");
976 break;
977 case CMD_DATA_UNDERRUN: /* let mid layer handle it. */
978 printk("UNDERRUN\n");
979 break;
980 case CMD_DATA_OVERRUN:
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500981 printk(KERN_WARNING "cciss: %p has"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 " completed with data overrun "
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500983 "reported\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 break;
985 case CMD_INVALID: {
986 /* controller unfortunately reports SCSI passthru's */
987 /* to non-existent targets as invalid commands. */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500988 printk(KERN_WARNING "cciss: %p is "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 "reported invalid (probably means "
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500990 "target device no longer present)\n", c);
991 /* print_bytes((unsigned char *) c, sizeof(*c), 1, 0);
992 print_cmd(c); */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 }
994 break;
995 case CMD_PROTOCOL_ERR:
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500996 printk(KERN_WARNING "cciss: %p has "
997 "protocol error\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 break;
999 case CMD_HARDWARE_ERR:
1000 /* cmd->result = DID_ERROR << 16; */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001001 printk(KERN_WARNING "cciss: %p had "
1002 " hardware error\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 break;
1004 case CMD_CONNECTION_LOST:
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001005 printk(KERN_WARNING "cciss: %p had "
1006 "connection lost\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 break;
1008 case CMD_ABORTED:
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001009 printk(KERN_WARNING "cciss: %p was "
1010 "aborted\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 break;
1012 case CMD_ABORT_FAILED:
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001013 printk(KERN_WARNING "cciss: %p reports "
1014 "abort failed\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 break;
1016 case CMD_UNSOLICITED_ABORT:
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001017 printk(KERN_WARNING "cciss: %p aborted "
1018 "do to an unsolicited abort\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 break;
1020 case CMD_TIMEOUT:
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001021 printk(KERN_WARNING "cciss: %p timedout\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 break;
1023 default:
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001024 printk(KERN_WARNING "cciss: %p returned "
1025 "unknown status %x\n", c, ei->CommandStatus);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 }
1027}
1028
1029static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001030cciss_scsi_do_inquiry(ctlr_info_t *h, unsigned char *scsi3addr,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001031 unsigned char page, unsigned char *buf,
1032 unsigned char bufsize)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033{
1034 int rc;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001035 CommandList_struct *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 char cdb[6];
1037 ErrorInfo_struct *ei;
1038 unsigned long flags;
1039
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001040 spin_lock_irqsave(&h->lock, flags);
1041 c = scsi_cmd_alloc(h);
1042 spin_unlock_irqrestore(&h->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001044 if (c == NULL) { /* trouble... */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 printk("cmd_alloc returned NULL!\n");
1046 return -1;
1047 }
1048
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001049 ei = c->err_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050
1051 cdb[0] = CISS_INQUIRY;
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001052 cdb[1] = (page != 0);
1053 cdb[2] = page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 cdb[3] = 0;
Mike Miller47922d02005-09-13 01:25:25 -07001055 cdb[4] = bufsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 cdb[5] = 0;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001057 rc = cciss_scsi_do_simple_cmd(h, c, scsi3addr, cdb,
Mike Miller47922d02005-09-13 01:25:25 -07001058 6, buf, bufsize, XFER_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059
1060 if (rc != 0) return rc; /* something went wrong */
1061
1062 if (ei->CommandStatus != 0 &&
1063 ei->CommandStatus != CMD_DATA_UNDERRUN) {
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001064 cciss_scsi_interpret_error(c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 rc = -1;
1066 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001067 spin_lock_irqsave(&h->lock, flags);
1068 scsi_cmd_free(h, c);
1069 spin_unlock_irqrestore(&h->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 return rc;
1071}
1072
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001073/* Get the device id from inquiry page 0x83 */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001074static int cciss_scsi_get_device_id(ctlr_info_t *h, unsigned char *scsi3addr,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001075 unsigned char *device_id, int buflen)
1076{
1077 int rc;
1078 unsigned char *buf;
1079
1080 if (buflen > 16)
1081 buflen = 16;
1082 buf = kzalloc(64, GFP_KERNEL);
1083 if (!buf)
1084 return -1;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001085 rc = cciss_scsi_do_inquiry(h, scsi3addr, 0x83, buf, 64);
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001086 if (rc == 0)
1087 memcpy(device_id, &buf[8], buflen);
1088 kfree(buf);
1089 return rc != 0;
1090}
1091
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001093cciss_scsi_do_report_phys_luns(ctlr_info_t *h,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 ReportLunData_struct *buf, int bufsize)
1095{
1096 int rc;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001097 CommandList_struct *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098 unsigned char cdb[12];
1099 unsigned char scsi3addr[8];
1100 ErrorInfo_struct *ei;
1101 unsigned long flags;
1102
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001103 spin_lock_irqsave(&h->lock, flags);
1104 c = scsi_cmd_alloc(h);
1105 spin_unlock_irqrestore(&h->lock, flags);
1106 if (c == NULL) { /* trouble... */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 printk("cmd_alloc returned NULL!\n");
1108 return -1;
1109 }
1110
1111 memset(&scsi3addr[0], 0, 8); /* address the controller */
1112 cdb[0] = CISS_REPORT_PHYS;
1113 cdb[1] = 0;
1114 cdb[2] = 0;
1115 cdb[3] = 0;
1116 cdb[4] = 0;
1117 cdb[5] = 0;
1118 cdb[6] = (bufsize >> 24) & 0xFF; //MSB
1119 cdb[7] = (bufsize >> 16) & 0xFF;
1120 cdb[8] = (bufsize >> 8) & 0xFF;
1121 cdb[9] = bufsize & 0xFF;
1122 cdb[10] = 0;
1123 cdb[11] = 0;
1124
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001125 rc = cciss_scsi_do_simple_cmd(h, c, scsi3addr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 cdb, 12,
1127 (unsigned char *) buf,
1128 bufsize, XFER_READ);
1129
1130 if (rc != 0) return rc; /* something went wrong */
1131
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001132 ei = c->err_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 if (ei->CommandStatus != 0 &&
1134 ei->CommandStatus != CMD_DATA_UNDERRUN) {
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001135 cciss_scsi_interpret_error(c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 rc = -1;
1137 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001138 spin_lock_irqsave(&h->lock, flags);
1139 scsi_cmd_free(h, c);
1140 spin_unlock_irqrestore(&h->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 return rc;
1142}
1143
1144static void
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001145cciss_update_non_disk_devices(ctlr_info_t *h, int hostno)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146{
1147 /* the idea here is we could get notified from /proc
1148 that some devices have changed, so we do a report
1149 physical luns cmd, and adjust our list of devices
1150 accordingly. (We can't rely on the scsi-mid layer just
1151 doing inquiries, because the "busses" that the scsi
1152 mid-layer probes are totally fabricated by this driver,
1153 so new devices wouldn't show up.
1154
1155 the scsi3addr's of devices won't change so long as the
1156 adapter is not reset. That means we can rescan and
1157 tell which devices we already know about, vs. new
1158 devices, vs. disappearing devices.
1159
1160 Also, if you yank out a tape drive, then put in a disk
1161 in it's place, (say, a configured volume from another
1162 array controller for instance) _don't_ poke this driver
1163 (so it thinks it's still a tape, but _do_ poke the scsi
1164 mid layer, so it does an inquiry... the scsi mid layer
1165 will see the physical disk. This would be bad. Need to
1166 think about how to prevent that. One idea would be to
1167 snoop all scsi responses and if an inquiry repsonse comes
1168 back that reports a disk, chuck it an return selection
1169 timeout instead and adjust our table... Not sure i like
1170 that though.
1171
1172 */
Mike Miller47922d02005-09-13 01:25:25 -07001173#define OBDR_TAPE_INQ_SIZE 49
1174#define OBDR_TAPE_SIG "$DR-10"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 ReportLunData_struct *ld_buff;
Mike Miller47922d02005-09-13 01:25:25 -07001176 unsigned char *inq_buff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 unsigned char scsi3addr[8];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 __u32 num_luns=0;
1179 unsigned char *ch;
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001180 struct cciss_scsi_dev_t *currentsd, *this_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 int ncurrent=0;
1182 int reportlunsize = sizeof(*ld_buff) + CISS_MAX_PHYS_LUN * 8;
1183 int i;
1184
Eric Sesterhenn06ff37f2006-03-08 11:21:52 +01001185 ld_buff = kzalloc(reportlunsize, GFP_KERNEL);
Mike Miller47922d02005-09-13 01:25:25 -07001186 inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001187 currentsd = kzalloc(sizeof(*currentsd) *
1188 (CCISS_MAX_SCSI_DEVS_PER_HBA+1), GFP_KERNEL);
1189 if (ld_buff == NULL || inq_buff == NULL || currentsd == NULL) {
1190 printk(KERN_ERR "cciss: out of memory\n");
1191 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 }
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001193 this_device = &currentsd[CCISS_MAX_SCSI_DEVS_PER_HBA];
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001194 if (cciss_scsi_do_report_phys_luns(h, ld_buff, reportlunsize) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 ch = &ld_buff->LUNListLength[0];
1196 num_luns = ((ch[0]<<24) | (ch[1]<<16) | (ch[2]<<8) | ch[3]) / 8;
1197 if (num_luns > CISS_MAX_PHYS_LUN) {
1198 printk(KERN_WARNING
1199 "cciss: Maximum physical LUNs (%d) exceeded. "
1200 "%d LUNs ignored.\n", CISS_MAX_PHYS_LUN,
1201 num_luns - CISS_MAX_PHYS_LUN);
1202 num_luns = CISS_MAX_PHYS_LUN;
1203 }
1204 }
1205 else {
1206 printk(KERN_ERR "cciss: Report physical LUNs failed.\n");
1207 goto out;
1208 }
1209
1210
1211 /* adjust our table of devices */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001212 for (i = 0; i < num_luns; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 /* for each physical lun, do an inquiry */
1214 if (ld_buff->LUN[i][3] & 0xC0) continue;
Mike Miller47922d02005-09-13 01:25:25 -07001215 memset(inq_buff, 0, OBDR_TAPE_INQ_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8);
1217
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001218 if (cciss_scsi_do_inquiry(h, scsi3addr, 0, inq_buff,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001219 (unsigned char) OBDR_TAPE_INQ_SIZE) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 /* Inquiry failed (msg printed already) */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001221 continue; /* so we will skip this device. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001223 this_device->devtype = (inq_buff[0] & 0x1f);
1224 this_device->bus = -1;
1225 this_device->target = -1;
1226 this_device->lun = -1;
1227 memcpy(this_device->scsi3addr, scsi3addr, 8);
1228 memcpy(this_device->vendor, &inq_buff[8],
1229 sizeof(this_device->vendor));
1230 memcpy(this_device->model, &inq_buff[16],
1231 sizeof(this_device->model));
1232 memcpy(this_device->revision, &inq_buff[32],
1233 sizeof(this_device->revision));
1234 memset(this_device->device_id, 0,
1235 sizeof(this_device->device_id));
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001236 cciss_scsi_get_device_id(h, scsi3addr,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001237 this_device->device_id, sizeof(this_device->device_id));
1238
1239 switch (this_device->devtype)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 {
Mike Miller47922d02005-09-13 01:25:25 -07001241 case 0x05: /* CD-ROM */ {
1242
1243 /* We don't *really* support actual CD-ROM devices,
1244 * just this "One Button Disaster Recovery" tape drive
1245 * which temporarily pretends to be a CD-ROM drive.
1246 * So we check that the device is really an OBDR tape
1247 * device by checking for "$DR-10" in bytes 43-48 of
1248 * the inquiry data.
1249 */
1250 char obdr_sig[7];
1251
1252 strncpy(obdr_sig, &inq_buff[43], 6);
1253 obdr_sig[6] = '\0';
1254 if (strncmp(obdr_sig, OBDR_TAPE_SIG, 6) != 0)
1255 /* Not OBDR device, ignore it. */
1256 break;
1257 }
1258 /* fall through . . . */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259 case 0x01: /* sequential access, (tape) */
1260 case 0x08: /* medium changer */
1261 if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) {
1262 printk(KERN_INFO "cciss%d: %s ignored, "
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001263 "too many devices.\n", h->ctlr,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001264 scsi_device_type(this_device->devtype));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 break;
1266 }
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001267 currentsd[ncurrent] = *this_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 ncurrent++;
1269 break;
1270 default:
1271 break;
1272 }
1273 }
1274
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001275 adjust_cciss_scsi_table(h, hostno, currentsd, ncurrent);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276out:
1277 kfree(inq_buff);
1278 kfree(ld_buff);
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001279 kfree(currentsd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 return;
1281}
1282
1283static int
1284is_keyword(char *ptr, int len, char *verb) // Thanks to ncr53c8xx.c
1285{
1286 int verb_len = strlen(verb);
1287 if (len >= verb_len && !memcmp(verb,ptr,verb_len))
1288 return verb_len;
1289 else
1290 return 0;
1291}
1292
1293static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001294cciss_scsi_user_command(ctlr_info_t *h, int hostno, char *buffer, int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295{
1296 int arg_len;
1297
1298 if ((arg_len = is_keyword(buffer, length, "rescan")) != 0)
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001299 cciss_update_non_disk_devices(h, hostno);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 else
1301 return -EINVAL;
1302 return length;
1303}
1304
1305
1306static int
1307cciss_scsi_proc_info(struct Scsi_Host *sh,
1308 char *buffer, /* data buffer */
1309 char **start, /* where data in buffer starts */
1310 off_t offset, /* offset from start of imaginary file */
1311 int length, /* length of data in buffer */
1312 int func) /* 0 == read, 1 == write */
1313{
1314
1315 int buflen, datalen;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001316 ctlr_info_t *h;
Mike Millerb9f0bd02005-09-13 01:25:26 -07001317 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001319 h = (ctlr_info_t *) sh->hostdata[0];
1320 if (h == NULL) /* This really shouldn't ever happen. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 return -EINVAL;
1322
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 if (func == 0) { /* User is reading from /proc/scsi/ciss*?/?* */
Mike Millerb9f0bd02005-09-13 01:25:26 -07001324 buflen = sprintf(buffer, "cciss%d: SCSI host: %d\n",
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001325 h->ctlr, sh->host_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326
Mike Millerb9f0bd02005-09-13 01:25:26 -07001327 /* this information is needed by apps to know which cciss
1328 device corresponds to which scsi host number without
1329 having to open a scsi target device node. The device
1330 information is not a duplicate of /proc/scsi/scsi because
1331 the two may be out of sync due to scsi hotplug, rather
1332 this info is for an app to be able to use to know how to
1333 get them back in sync. */
1334
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001335 for (i = 0; i < ccissscsi[h->ctlr].ndevices; i++) {
1336 struct cciss_scsi_dev_t *sd =
1337 &ccissscsi[h->ctlr].dev[i];
Mike Millerb9f0bd02005-09-13 01:25:26 -07001338 buflen += sprintf(&buffer[buflen], "c%db%dt%dl%d %02d "
1339 "0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
1340 sh->host_no, sd->bus, sd->target, sd->lun,
1341 sd->devtype,
1342 sd->scsi3addr[0], sd->scsi3addr[1],
1343 sd->scsi3addr[2], sd->scsi3addr[3],
1344 sd->scsi3addr[4], sd->scsi3addr[5],
1345 sd->scsi3addr[6], sd->scsi3addr[7]);
1346 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 datalen = buflen - offset;
1348 if (datalen < 0) { /* they're reading past EOF. */
1349 datalen = 0;
1350 *start = buffer+buflen;
1351 } else
1352 *start = buffer + offset;
1353 return(datalen);
1354 } else /* User is writing to /proc/scsi/cciss*?/?* ... */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001355 return cciss_scsi_user_command(h, sh->host_no,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356 buffer, length);
1357}
1358
1359/* cciss_scatter_gather takes a struct scsi_cmnd, (cmd), and does the pci
1360 dma mapping and fills in the scatter gather entries of the
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001361 cciss command, c. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001363static void cciss_scatter_gather(ctlr_info_t *h, CommandList_struct *c,
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001364 struct scsi_cmnd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365{
FUJITA Tomonori41ce6392007-05-26 02:45:17 +09001366 unsigned int len;
1367 struct scatterlist *sg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368 __u64 addr64;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001369 int request_nsgs, i, chained, sg_index;
1370 struct cciss_scsi_adapter_data_t *sa = h->scsi_ctlr;
1371 SGDescriptor_struct *curr_sg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001373 BUG_ON(scsi_sg_count(cmd) > h->maxsgentries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001375 chained = 0;
1376 sg_index = 0;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001377 curr_sg = c->SG;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001378 request_nsgs = scsi_dma_map(cmd);
1379 if (request_nsgs) {
1380 scsi_for_each_sg(cmd, sg, request_nsgs, i) {
1381 if (sg_index + 1 == h->max_cmd_sgentries &&
1382 !chained && request_nsgs - i > 1) {
1383 chained = 1;
1384 sg_index = 0;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001385 curr_sg = sa->cmd_sg_list[c->cmdindex];
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001386 }
FUJITA Tomonori41ce6392007-05-26 02:45:17 +09001387 addr64 = (__u64) sg_dma_address(sg);
1388 len = sg_dma_len(sg);
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001389 curr_sg[sg_index].Addr.lower =
1390 (__u32) (addr64 & 0x0FFFFFFFFULL);
1391 curr_sg[sg_index].Addr.upper =
1392 (__u32) ((addr64 >> 32) & 0x0FFFFFFFFULL);
1393 curr_sg[sg_index].Len = len;
1394 curr_sg[sg_index].Ext = 0;
1395 ++sg_index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 }
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001397 if (chained)
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001398 cciss_map_sg_chain_block(h, c,
1399 sa->cmd_sg_list[c->cmdindex],
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001400 (request_nsgs - (h->max_cmd_sgentries - 1)) *
1401 sizeof(SGDescriptor_struct));
FUJITA Tomonori41ce6392007-05-26 02:45:17 +09001402 }
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001403 /* track how many SG entries we are using */
1404 if (request_nsgs > h->maxSG)
1405 h->maxSG = request_nsgs;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001406 c->Header.SGTotal = (__u8) request_nsgs + chained;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001407 if (request_nsgs > h->max_cmd_sgentries)
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001408 c->Header.SGList = h->max_cmd_sgentries;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001409 else
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001410 c->Header.SGList = c->Header.SGTotal;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 return;
1412}
1413
1414
1415static int
1416cciss_scsi_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
1417{
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001418 ctlr_info_t *h;
1419 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 unsigned char scsi3addr[8];
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001421 CommandList_struct *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 unsigned long flags;
1423
1424 // Get the ptr to our adapter structure (hba[i]) out of cmd->host.
1425 // We violate cmd->host privacy here. (Is there another way?)
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001426 h = (ctlr_info_t *) cmd->device->host->hostdata[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001428 rc = lookup_scsi3addr(h, cmd->device->channel, cmd->device->id,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 cmd->device->lun, scsi3addr);
1430 if (rc != 0) {
1431 /* the scsi nexus does not match any that we presented... */
1432 /* pretend to mid layer that we got selection timeout */
1433 cmd->result = DID_NO_CONNECT << 16;
1434 done(cmd);
1435 /* we might want to think about registering controller itself
1436 as a processor device on the bus so sg binds to it. */
1437 return 0;
1438 }
1439
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 /* Ok, we have a reasonable scsi nexus, so send the cmd down, and
1441 see what the device thinks of it. */
1442
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001443 spin_lock_irqsave(&h->lock, flags);
1444 c = scsi_cmd_alloc(h);
1445 spin_unlock_irqrestore(&h->lock, flags);
1446 if (c == NULL) { /* trouble... */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 printk("scsi_cmd_alloc returned NULL!\n");
1448 /* FIXME: next 3 lines are -> BAD! <- */
1449 cmd->result = DID_NO_CONNECT << 16;
1450 done(cmd);
1451 return 0;
1452 }
1453
1454 // Fill in the command list header
1455
1456 cmd->scsi_done = done; // save this for use by completion code
1457
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001458 /* save c in case we have to abort it */
1459 cmd->host_scribble = (unsigned char *) c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001461 c->cmd_type = CMD_SCSI;
1462 c->scsi_cmd = cmd;
1463 c->Header.ReplyQueue = 0; /* unused in simple mode */
1464 memcpy(&c->Header.LUN.LunAddrBytes[0], &scsi3addr[0], 8);
1465 c->Header.Tag.lower = c->busaddr; /* Use k. address of cmd as tag */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466
1467 // Fill in the request block...
1468
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001469 c->Request.Timeout = 0;
1470 memset(c->Request.CDB, 0, sizeof(c->Request.CDB));
1471 BUG_ON(cmd->cmd_len > sizeof(c->Request.CDB));
1472 c->Request.CDBLen = cmd->cmd_len;
1473 memcpy(c->Request.CDB, cmd->cmnd, cmd->cmd_len);
1474 c->Request.Type.Type = TYPE_CMD;
1475 c->Request.Type.Attribute = ATTR_SIMPLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476 switch(cmd->sc_data_direction)
1477 {
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001478 case DMA_TO_DEVICE:
1479 c->Request.Type.Direction = XFER_WRITE;
1480 break;
1481 case DMA_FROM_DEVICE:
1482 c->Request.Type.Direction = XFER_READ;
1483 break;
1484 case DMA_NONE:
1485 c->Request.Type.Direction = XFER_NONE;
1486 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 case DMA_BIDIRECTIONAL:
1488 // This can happen if a buggy application does a scsi passthru
1489 // and sets both inlen and outlen to non-zero. ( see
1490 // ../scsi/scsi_ioctl.c:scsi_ioctl_send_command() )
1491
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001492 c->Request.Type.Direction = XFER_RSVD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 // This is technically wrong, and cciss controllers should
1494 // reject it with CMD_INVALID, which is the most correct
1495 // response, but non-fibre backends appear to let it
1496 // slide by, and give the same results as if this field
1497 // were set correctly. Either way is acceptable for
1498 // our purposes here.
1499
1500 break;
1501
1502 default:
1503 printk("cciss: unknown data direction: %d\n",
1504 cmd->sc_data_direction);
1505 BUG();
1506 break;
1507 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001508 cciss_scatter_gather(h, c, cmd);
1509 enqueue_cmd_and_start_io(h, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 /* the cmd'll come back via intr handler in complete_scsi_command() */
1511 return 0;
1512}
1513
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001514static void cciss_unregister_scsi(ctlr_info_t *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515{
1516 struct cciss_scsi_adapter_data_t *sa;
1517 struct cciss_scsi_cmd_stack_t *stk;
1518 unsigned long flags;
1519
1520 /* we are being forcibly unloaded, and may not refuse. */
1521
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001522 spin_lock_irqsave(&h->lock, flags);
1523 sa = h->scsi_ctlr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 stk = &sa->cmd_stack;
1525
1526 /* if we weren't ever actually registered, don't unregister */
1527 if (sa->registered) {
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001528 spin_unlock_irqrestore(&h->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529 scsi_remove_host(sa->scsi_host);
1530 scsi_host_put(sa->scsi_host);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001531 spin_lock_irqsave(&h->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532 }
1533
1534 /* set scsi_host to NULL so our detect routine will
1535 find us on register */
1536 sa->scsi_host = NULL;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001537 spin_unlock_irqrestore(&h->lock, flags);
1538 scsi_cmd_stack_free(h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 kfree(sa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540}
1541
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001542static int cciss_engage_scsi(ctlr_info_t *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543{
1544 struct cciss_scsi_adapter_data_t *sa;
1545 struct cciss_scsi_cmd_stack_t *stk;
1546 unsigned long flags;
1547
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001548 spin_lock_irqsave(&h->lock, flags);
1549 sa = h->scsi_ctlr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 stk = &sa->cmd_stack;
1551
Mike Millerf4a93bc2008-08-04 11:54:53 +02001552 if (sa->registered) {
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001553 printk(KERN_INFO "cciss%d: SCSI subsystem already engaged.\n",
1554 h->ctlr);
1555 spin_unlock_irqrestore(&h->lock, flags);
Stephen M. Cameron8721c812009-11-12 12:50:06 -06001556 return -ENXIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 }
Mike Millerf4a93bc2008-08-04 11:54:53 +02001558 sa->registered = 1;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001559 spin_unlock_irqrestore(&h->lock, flags);
1560 cciss_update_non_disk_devices(h, -1);
1561 cciss_scsi_detect(h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562 return 0;
1563}
1564
1565static void
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001566cciss_seq_tape_report(struct seq_file *seq, ctlr_info_t *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567{
1568 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001570 CPQ_TAPE_LOCK(h, flags);
Mike Miller89b6e742008-02-21 08:54:03 +01001571 seq_printf(seq,
Mike Millerb9f0bd02005-09-13 01:25:26 -07001572 "Sequential access devices: %d\n\n",
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001573 ccissscsi[h->ctlr].ndevices);
1574 CPQ_TAPE_UNLOCK(h, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575}
1576
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001577static int wait_for_device_to_become_ready(ctlr_info_t *h,
1578 unsigned char lunaddr[])
1579{
1580 int rc;
1581 int count = 0;
1582 int waittime = HZ;
1583 CommandList_struct *c;
1584
1585 c = cmd_alloc(h, 1);
1586 if (!c) {
1587 printk(KERN_WARNING "cciss%d: out of memory in "
1588 "wait_for_device_to_become_ready.\n", h->ctlr);
1589 return IO_ERROR;
1590 }
1591
1592 /* Send test unit ready until device ready, or give up. */
1593 while (count < 20) {
1594
1595 /* Wait for a bit. do this first, because if we send
1596 * the TUR right away, the reset will just abort it.
1597 */
scameron@beardog.cca.cpqcorp.net40df6ae2009-06-08 15:59:38 -05001598 schedule_timeout_uninterruptible(waittime);
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001599 count++;
1600
1601 /* Increase wait time with each try, up to a point. */
1602 if (waittime < (HZ * 30))
1603 waittime = waittime * 2;
1604
1605 /* Send the Test Unit Ready */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001606 rc = fill_cmd(h, c, TEST_UNIT_READY, NULL, 0, 0,
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001607 lunaddr, TYPE_CMD);
scameron@beardog.cca.cpqcorp.net85cc61a2009-06-08 16:07:45 -05001608 if (rc == 0)
1609 rc = sendcmd_withirq_core(h, c, 0);
1610
1611 (void) process_sendcmd_error(h, c);
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001612
scameron@beardog.cca.cpqcorp.net39692512009-06-08 16:10:57 -05001613 if (rc != 0)
1614 goto retry_tur;
1615
1616 if (c->err_info->CommandStatus == CMD_SUCCESS)
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001617 break;
1618
scameron@beardog.cca.cpqcorp.net39692512009-06-08 16:10:57 -05001619 if (c->err_info->CommandStatus == CMD_TARGET_STATUS &&
1620 c->err_info->ScsiStatus == SAM_STAT_CHECK_CONDITION) {
1621 if (c->err_info->SenseInfo[2] == NO_SENSE)
1622 break;
1623 if (c->err_info->SenseInfo[2] == UNIT_ATTENTION) {
1624 unsigned char asc;
1625 asc = c->err_info->SenseInfo[12];
1626 check_for_unit_attention(h, c);
1627 if (asc == POWER_OR_RESET)
1628 break;
1629 }
1630 }
1631retry_tur:
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001632 printk(KERN_WARNING "cciss%d: Waiting %d secs "
1633 "for device to become ready.\n",
1634 h->ctlr, waittime / HZ);
1635 rc = 1; /* device not ready. */
1636 }
1637
1638 if (rc)
1639 printk("cciss%d: giving up on device.\n", h->ctlr);
1640 else
1641 printk(KERN_WARNING "cciss%d: device is ready.\n", h->ctlr);
1642
1643 cmd_free(h, c, 1);
1644 return rc;
1645}
Mike Miller89b6e742008-02-21 08:54:03 +01001646
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001647/* Need at least one of these error handlers to keep ../scsi/hosts.c from
1648 * complaining. Doing a host- or bus-reset can't do anything good here.
1649 * Despite what it might say in scsi_error.c, there may well be commands
1650 * on the controller, as the cciss driver registers twice, once as a block
1651 * device for the logical drives, and once as a scsi device, for any tape
1652 * drives. So we know there are no commands out on the tape drives, but we
1653 * don't know there are no commands on the controller, and it is likely
1654 * that there probably are, as the cciss block device is most commonly used
1655 * as a boot device (embedded controller on HP/Compaq systems.)
1656*/
1657
1658static int cciss_eh_device_reset_handler(struct scsi_cmnd *scsicmd)
1659{
1660 int rc;
1661 CommandList_struct *cmd_in_trouble;
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001662 unsigned char lunaddr[8];
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001663 ctlr_info_t *h;
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001664
1665 /* find the controller to which the command to be aborted was sent */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001666 h = (ctlr_info_t *) scsicmd->device->host->hostdata[0];
1667 if (h == NULL) /* paranoia */
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001668 return FAILED;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001669 printk(KERN_WARNING
1670 "cciss%d: resetting tape drive or medium changer.\n", h->ctlr);
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001671 /* find the command that's giving us trouble */
1672 cmd_in_trouble = (CommandList_struct *) scsicmd->host_scribble;
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001673 if (cmd_in_trouble == NULL) /* paranoia */
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001674 return FAILED;
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001675 memcpy(lunaddr, &cmd_in_trouble->Header.LUN.LunAddrBytes[0], 8);
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001676 /* send a reset to the SCSI LUN which the command was sent to */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001677 rc = sendcmd_withirq(h, CCISS_RESET_MSG, NULL, 0, 0, lunaddr,
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001678 TYPE_MSG);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001679 if (rc == 0 && wait_for_device_to_become_ready(h, lunaddr) == 0)
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001680 return SUCCESS;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001681 printk(KERN_WARNING "cciss%d: resetting device failed.\n", h->ctlr);
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001682 return FAILED;
1683}
1684
1685static int cciss_eh_abort_handler(struct scsi_cmnd *scsicmd)
1686{
1687 int rc;
1688 CommandList_struct *cmd_to_abort;
scameron@beardog.cca.cpqcorp.net85cc61a2009-06-08 16:07:45 -05001689 unsigned char lunaddr[8];
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001690 ctlr_info_t *h;
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001691
1692 /* find the controller to which the command to be aborted was sent */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001693 h = (ctlr_info_t *) scsicmd->device->host->hostdata[0];
1694 if (h == NULL) /* paranoia */
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001695 return FAILED;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001696 printk(KERN_WARNING "cciss%d: aborting tardy SCSI cmd\n", h->ctlr);
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001697
1698 /* find the command to be aborted */
1699 cmd_to_abort = (CommandList_struct *) scsicmd->host_scribble;
1700 if (cmd_to_abort == NULL) /* paranoia */
1701 return FAILED;
scameron@beardog.cca.cpqcorp.net85cc61a2009-06-08 16:07:45 -05001702 memcpy(lunaddr, &cmd_to_abort->Header.LUN.LunAddrBytes[0], 8);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001703 rc = sendcmd_withirq(h, CCISS_ABORT_MSG, &cmd_to_abort->Header.Tag,
scameron@beardog.cca.cpqcorp.net85cc61a2009-06-08 16:07:45 -05001704 0, 0, lunaddr, TYPE_MSG);
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001705 if (rc == 0)
1706 return SUCCESS;
1707 return FAILED;
1708
1709}
1710
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711#else /* no CONFIG_CISS_SCSI_TAPE */
1712
1713/* If no tape support, then these become defined out of existence */
1714
1715#define cciss_scsi_setup(cntl_num)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716
1717#endif /* CONFIG_CISS_SCSI_TAPE */