blob: 007ab8aea85bf120a5f75d4f0ac60d74d7d32ae0 [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. Cameron88f627a2009-06-02 14:48:11 +020047static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff,
48 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
52static int sendcmd_core(ctlr_info_t *h, CommandList_struct *c);
53
54static CommandList_struct *cmd_alloc(ctlr_info_t *h, int get_from_pool);
55static void cmd_free(ctlr_info_t *h, CommandList_struct *c, int got_from_pool);
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
57static int cciss_scsi_proc_info(
58 struct Scsi_Host *sh,
59 char *buffer, /* data buffer */
60 char **start, /* where data in buffer starts */
61 off_t offset, /* offset from start of imaginary file */
62 int length, /* length of data in buffer */
63 int func); /* 0 == read, 1 == write */
64
65static int cciss_scsi_queue_command (struct scsi_cmnd *cmd,
66 void (* done)(struct scsi_cmnd *));
mike.miller@hp.com3da8b712005-11-04 12:30:37 -060067static int cciss_eh_device_reset_handler(struct scsi_cmnd *);
68static int cciss_eh_abort_handler(struct scsi_cmnd *);
Linus Torvalds1da177e2005-04-16 15:20:36 -070069
70static struct cciss_scsi_hba_t ccissscsi[MAX_CTLR] = {
71 { .name = "cciss0", .ndevices = 0 },
72 { .name = "cciss1", .ndevices = 0 },
73 { .name = "cciss2", .ndevices = 0 },
74 { .name = "cciss3", .ndevices = 0 },
75 { .name = "cciss4", .ndevices = 0 },
76 { .name = "cciss5", .ndevices = 0 },
77 { .name = "cciss6", .ndevices = 0 },
78 { .name = "cciss7", .ndevices = 0 },
79};
80
81static struct scsi_host_template cciss_driver_template = {
82 .module = THIS_MODULE,
83 .name = "cciss",
84 .proc_name = "cciss",
85 .proc_info = cciss_scsi_proc_info,
86 .queuecommand = cciss_scsi_queue_command,
87 .can_queue = SCSI_CCISS_CAN_QUEUE,
88 .this_id = 7,
89 .sg_tablesize = MAXSGENTRIES,
90 .cmd_per_lun = 1,
91 .use_clustering = DISABLE_CLUSTERING,
mike.miller@hp.com3da8b712005-11-04 12:30:37 -060092 /* Can't have eh_bus_reset_handler or eh_host_reset_handler for cciss */
93 .eh_device_reset_handler= cciss_eh_device_reset_handler,
94 .eh_abort_handler = cciss_eh_abort_handler,
Linus Torvalds1da177e2005-04-16 15:20:36 -070095};
96
97#pragma pack(1)
98struct cciss_scsi_cmd_stack_elem_t {
99 CommandList_struct cmd;
100 ErrorInfo_struct Err;
101 __u32 busaddr;
Mike Miller33079b22005-09-13 01:25:22 -0700102 __u32 pad;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700103};
104
105#pragma pack()
106
107#define CMD_STACK_SIZE (SCSI_CCISS_CAN_QUEUE * \
108 CCISS_MAX_SCSI_DEVS_PER_HBA + 2)
109 // plus two for init time usage
110
111#pragma pack(1)
112struct cciss_scsi_cmd_stack_t {
113 struct cciss_scsi_cmd_stack_elem_t *pool;
114 struct cciss_scsi_cmd_stack_elem_t *elem[CMD_STACK_SIZE];
115 dma_addr_t cmd_pool_handle;
116 int top;
117};
118#pragma pack()
119
120struct cciss_scsi_adapter_data_t {
121 struct Scsi_Host *scsi_host;
122 struct cciss_scsi_cmd_stack_t cmd_stack;
123 int registered;
124 spinlock_t lock; // to protect ccissscsi[ctlr];
125};
126
127#define CPQ_TAPE_LOCK(ctlr, flags) spin_lock_irqsave( \
128 &(((struct cciss_scsi_adapter_data_t *) \
129 hba[ctlr]->scsi_ctlr)->lock), flags);
130#define CPQ_TAPE_UNLOCK(ctlr, flags) spin_unlock_irqrestore( \
131 &(((struct cciss_scsi_adapter_data_t *) \
132 hba[ctlr]->scsi_ctlr)->lock), flags);
133
134static CommandList_struct *
135scsi_cmd_alloc(ctlr_info_t *h)
136{
137 /* assume only one process in here at a time, locking done by caller. */
138 /* use CCISS_LOCK(ctlr) */
139 /* might be better to rewrite how we allocate scsi commands in a way that */
140 /* needs no locking at all. */
141
142 /* take the top memory chunk off the stack and return it, if any. */
143 struct cciss_scsi_cmd_stack_elem_t *c;
144 struct cciss_scsi_adapter_data_t *sa;
145 struct cciss_scsi_cmd_stack_t *stk;
146 u64bit temp64;
147
148 sa = (struct cciss_scsi_adapter_data_t *) h->scsi_ctlr;
149 stk = &sa->cmd_stack;
150
151 if (stk->top < 0)
152 return NULL;
153 c = stk->elem[stk->top];
154 /* memset(c, 0, sizeof(*c)); */
155 memset(&c->cmd, 0, sizeof(c->cmd));
156 memset(&c->Err, 0, sizeof(c->Err));
157 /* set physical addr of cmd and addr of scsi parameters */
158 c->cmd.busaddr = c->busaddr;
159 /* (__u32) (stk->cmd_pool_handle +
160 (sizeof(struct cciss_scsi_cmd_stack_elem_t)*stk->top)); */
161
162 temp64.val = (__u64) (c->busaddr + sizeof(CommandList_struct));
163 /* (__u64) (stk->cmd_pool_handle +
164 (sizeof(struct cciss_scsi_cmd_stack_elem_t)*stk->top) +
165 sizeof(CommandList_struct)); */
166 stk->top--;
167 c->cmd.ErrDesc.Addr.lower = temp64.val32.lower;
168 c->cmd.ErrDesc.Addr.upper = temp64.val32.upper;
169 c->cmd.ErrDesc.Len = sizeof(ErrorInfo_struct);
170
171 c->cmd.ctlr = h->ctlr;
172 c->cmd.err_info = &c->Err;
173
174 return (CommandList_struct *) c;
175}
176
177static void
178scsi_cmd_free(ctlr_info_t *h, CommandList_struct *cmd)
179{
180 /* assume only one process in here at a time, locking done by caller. */
181 /* use CCISS_LOCK(ctlr) */
182 /* drop the free memory chunk on top of the stack. */
183
184 struct cciss_scsi_adapter_data_t *sa;
185 struct cciss_scsi_cmd_stack_t *stk;
186
187 sa = (struct cciss_scsi_adapter_data_t *) h->scsi_ctlr;
188 stk = &sa->cmd_stack;
189 if (stk->top >= CMD_STACK_SIZE) {
190 printk("cciss: scsi_cmd_free called too many times.\n");
191 BUG();
192 }
193 stk->top++;
194 stk->elem[stk->top] = (struct cciss_scsi_cmd_stack_elem_t *) cmd;
195}
196
197static int
198scsi_cmd_stack_setup(int ctlr, struct cciss_scsi_adapter_data_t *sa)
199{
200 int i;
201 struct cciss_scsi_cmd_stack_t *stk;
202 size_t size;
203
204 stk = &sa->cmd_stack;
205 size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE;
206
207 // pci_alloc_consistent guarantees 32-bit DMA address will
208 // be used
209
210 stk->pool = (struct cciss_scsi_cmd_stack_elem_t *)
211 pci_alloc_consistent(hba[ctlr]->pdev, size, &stk->cmd_pool_handle);
212
213 if (stk->pool == NULL) {
214 printk("stk->pool is null\n");
215 return -1;
216 }
217
218 for (i=0; i<CMD_STACK_SIZE; i++) {
219 stk->elem[i] = &stk->pool[i];
220 stk->elem[i]->busaddr = (__u32) (stk->cmd_pool_handle +
221 (sizeof(struct cciss_scsi_cmd_stack_elem_t) * i));
222 }
223 stk->top = CMD_STACK_SIZE-1;
224 return 0;
225}
226
227static void
228scsi_cmd_stack_free(int ctlr)
229{
230 struct cciss_scsi_adapter_data_t *sa;
231 struct cciss_scsi_cmd_stack_t *stk;
232 size_t size;
233
234 sa = (struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr;
235 stk = &sa->cmd_stack;
236 if (stk->top != CMD_STACK_SIZE-1) {
237 printk( "cciss: %d scsi commands are still outstanding.\n",
238 CMD_STACK_SIZE - stk->top);
239 // BUG();
240 printk("WE HAVE A BUG HERE!!! stk=0x%p\n", stk);
241 }
242 size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE;
243
244 pci_free_consistent(hba[ctlr]->pdev, size, stk->pool, stk->cmd_pool_handle);
245 stk->pool = NULL;
246}
247
Grant Coady400bb232005-11-15 00:09:20 -0800248#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249static int xmargin=8;
250static int amargin=60;
251
252static void
253print_bytes (unsigned char *c, int len, int hex, int ascii)
254{
255
256 int i;
257 unsigned char *x;
258
259 if (hex)
260 {
261 x = c;
262 for (i=0;i<len;i++)
263 {
264 if ((i % xmargin) == 0 && i>0) printk("\n");
265 if ((i % xmargin) == 0) printk("0x%04x:", i);
266 printk(" %02x", *x);
267 x++;
268 }
269 printk("\n");
270 }
271 if (ascii)
272 {
273 x = c;
274 for (i=0;i<len;i++)
275 {
276 if ((i % amargin) == 0 && i>0) printk("\n");
277 if ((i % amargin) == 0) printk("0x%04x:", i);
278 if (*x > 26 && *x < 128) printk("%c", *x);
279 else printk(".");
280 x++;
281 }
282 printk("\n");
283 }
284}
285
286static void
287print_cmd(CommandList_struct *cp)
288{
289 printk("queue:%d\n", cp->Header.ReplyQueue);
290 printk("sglist:%d\n", cp->Header.SGList);
291 printk("sgtot:%d\n", cp->Header.SGTotal);
292 printk("Tag:0x%08x/0x%08x\n", cp->Header.Tag.upper,
293 cp->Header.Tag.lower);
294 printk("LUN:0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
295 cp->Header.LUN.LunAddrBytes[0],
296 cp->Header.LUN.LunAddrBytes[1],
297 cp->Header.LUN.LunAddrBytes[2],
298 cp->Header.LUN.LunAddrBytes[3],
299 cp->Header.LUN.LunAddrBytes[4],
300 cp->Header.LUN.LunAddrBytes[5],
301 cp->Header.LUN.LunAddrBytes[6],
302 cp->Header.LUN.LunAddrBytes[7]);
303 printk("CDBLen:%d\n", cp->Request.CDBLen);
304 printk("Type:%d\n",cp->Request.Type.Type);
305 printk("Attr:%d\n",cp->Request.Type.Attribute);
306 printk(" Dir:%d\n",cp->Request.Type.Direction);
307 printk("Timeout:%d\n",cp->Request.Timeout);
308 printk( "CDB: %02x %02x %02x %02x %02x %02x %02x %02x"
309 " %02x %02x %02x %02x %02x %02x %02x %02x\n",
310 cp->Request.CDB[0], cp->Request.CDB[1],
311 cp->Request.CDB[2], cp->Request.CDB[3],
312 cp->Request.CDB[4], cp->Request.CDB[5],
313 cp->Request.CDB[6], cp->Request.CDB[7],
314 cp->Request.CDB[8], cp->Request.CDB[9],
315 cp->Request.CDB[10], cp->Request.CDB[11],
316 cp->Request.CDB[12], cp->Request.CDB[13],
317 cp->Request.CDB[14], cp->Request.CDB[15]),
318 printk("edesc.Addr: 0x%08x/0%08x, Len = %d\n",
319 cp->ErrDesc.Addr.upper, cp->ErrDesc.Addr.lower,
320 cp->ErrDesc.Len);
321 printk("sgs..........Errorinfo:\n");
322 printk("scsistatus:%d\n", cp->err_info->ScsiStatus);
323 printk("senselen:%d\n", cp->err_info->SenseLen);
324 printk("cmd status:%d\n", cp->err_info->CommandStatus);
325 printk("resid cnt:%d\n", cp->err_info->ResidualCnt);
326 printk("offense size:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_size);
327 printk("offense byte:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_num);
328 printk("offense value:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_value);
329
330}
331
332#endif
333
334static int
335find_bus_target_lun(int ctlr, int *bus, int *target, int *lun)
336{
337 /* finds an unused bus, target, lun for a new device */
338 /* assumes hba[ctlr]->scsi_ctlr->lock is held */
339 int i, found=0;
340 unsigned char target_taken[CCISS_MAX_SCSI_DEVS_PER_HBA];
341
342 memset(&target_taken[0], 0, CCISS_MAX_SCSI_DEVS_PER_HBA);
343
344 target_taken[SELF_SCSI_ID] = 1;
345 for (i=0;i<ccissscsi[ctlr].ndevices;i++)
346 target_taken[ccissscsi[ctlr].dev[i].target] = 1;
347
348 for (i=0;i<CCISS_MAX_SCSI_DEVS_PER_HBA;i++) {
349 if (!target_taken[i]) {
350 *bus = 0; *target=i; *lun = 0; found=1;
351 break;
352 }
353 }
354 return (!found);
355}
Mike Millerf4a93bc2008-08-04 11:54:53 +0200356struct scsi2map {
357 char scsi3addr[8];
358 int bus, target, lun;
359};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360
361static int
362cciss_scsi_add_entry(int ctlr, int hostno,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700363 struct cciss_scsi_dev_t *device,
Mike Millerf4a93bc2008-08-04 11:54:53 +0200364 struct scsi2map *added, int *nadded)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365{
366 /* assumes hba[ctlr]->scsi_ctlr->lock is held */
367 int n = ccissscsi[ctlr].ndevices;
368 struct cciss_scsi_dev_t *sd;
Mike Miller935dc8d2008-08-04 11:54:54 +0200369 int i, bus, target, lun;
370 unsigned char addr1[8], addr2[8];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371
372 if (n >= CCISS_MAX_SCSI_DEVS_PER_HBA) {
373 printk("cciss%d: Too many devices, "
374 "some will be inaccessible.\n", ctlr);
375 return -1;
376 }
Mike Millerf4a93bc2008-08-04 11:54:53 +0200377
Mike Miller935dc8d2008-08-04 11:54:54 +0200378 bus = target = -1;
379 lun = 0;
380 /* Is this device a non-zero lun of a multi-lun device */
381 /* byte 4 of the 8-byte LUN addr will contain the logical unit no. */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700382 if (device->scsi3addr[4] != 0) {
Mike Miller935dc8d2008-08-04 11:54:54 +0200383 /* Search through our list and find the device which */
384 /* has the same 8 byte LUN address, excepting byte 4. */
385 /* Assign the same bus and target for this new LUN. */
386 /* Use the logical unit number from the firmware. */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700387 memcpy(addr1, device->scsi3addr, 8);
Mike Miller935dc8d2008-08-04 11:54:54 +0200388 addr1[4] = 0;
389 for (i = 0; i < n; i++) {
390 sd = &ccissscsi[ctlr].dev[i];
391 memcpy(addr2, sd->scsi3addr, 8);
392 addr2[4] = 0;
393 /* differ only in byte 4? */
394 if (memcmp(addr1, addr2, 8) == 0) {
395 bus = sd->bus;
396 target = sd->target;
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700397 lun = device->scsi3addr[4];
Mike Miller935dc8d2008-08-04 11:54:54 +0200398 break;
399 }
400 }
401 }
402
403 sd = &ccissscsi[ctlr].dev[n];
404 if (lun == 0) {
405 if (find_bus_target_lun(ctlr,
406 &sd->bus, &sd->target, &sd->lun) != 0)
407 return -1;
408 } else {
409 sd->bus = bus;
410 sd->target = target;
411 sd->lun = lun;
412 }
Mike Millerf4a93bc2008-08-04 11:54:53 +0200413 added[*nadded].bus = sd->bus;
414 added[*nadded].target = sd->target;
415 added[*nadded].lun = sd->lun;
416 (*nadded)++;
417
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700418 memcpy(sd->scsi3addr, device->scsi3addr, 8);
419 memcpy(sd->vendor, device->vendor, sizeof(sd->vendor));
420 memcpy(sd->revision, device->revision, sizeof(sd->revision));
421 memcpy(sd->device_id, device->device_id, sizeof(sd->device_id));
422 sd->devtype = device->devtype;
423
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 ccissscsi[ctlr].ndevices++;
425
426 /* initially, (before registering with scsi layer) we don't
427 know our hostno and we don't want to print anything first
428 time anyway (the scsi layer's inquiries will show that info) */
429 if (hostno != -1)
430 printk("cciss%d: %s device c%db%dt%dl%d added.\n",
Matthew Wilcox4ff36712006-07-04 12:15:20 -0600431 ctlr, scsi_device_type(sd->devtype), hostno,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 sd->bus, sd->target, sd->lun);
433 return 0;
434}
435
436static void
Mike Millerf4a93bc2008-08-04 11:54:53 +0200437cciss_scsi_remove_entry(int ctlr, int hostno, int entry,
438 struct scsi2map *removed, int *nremoved)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439{
440 /* assumes hba[ctlr]->scsi_ctlr->lock is held */
441 int i;
442 struct cciss_scsi_dev_t sd;
443
444 if (entry < 0 || entry >= CCISS_MAX_SCSI_DEVS_PER_HBA) return;
445 sd = ccissscsi[ctlr].dev[entry];
Mike Millerf4a93bc2008-08-04 11:54:53 +0200446 removed[*nremoved].bus = sd.bus;
447 removed[*nremoved].target = sd.target;
448 removed[*nremoved].lun = sd.lun;
449 (*nremoved)++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 for (i=entry;i<ccissscsi[ctlr].ndevices-1;i++)
451 ccissscsi[ctlr].dev[i] = ccissscsi[ctlr].dev[i+1];
452 ccissscsi[ctlr].ndevices--;
453 printk("cciss%d: %s device c%db%dt%dl%d removed.\n",
Matthew Wilcox4ff36712006-07-04 12:15:20 -0600454 ctlr, scsi_device_type(sd.devtype), hostno,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 sd.bus, sd.target, sd.lun);
456}
457
458
459#define SCSI3ADDR_EQ(a,b) ( \
460 (a)[7] == (b)[7] && \
461 (a)[6] == (b)[6] && \
462 (a)[5] == (b)[5] && \
463 (a)[4] == (b)[4] && \
464 (a)[3] == (b)[3] && \
465 (a)[2] == (b)[2] && \
466 (a)[1] == (b)[1] && \
467 (a)[0] == (b)[0])
468
Mike Millerf4a93bc2008-08-04 11:54:53 +0200469static void fixup_botched_add(int ctlr, char *scsi3addr)
470{
471 /* called when scsi_add_device fails in order to re-adjust */
472 /* ccissscsi[] to match the mid layer's view. */
473 unsigned long flags;
474 int i, j;
475 CPQ_TAPE_LOCK(ctlr, flags);
476 for (i = 0; i < ccissscsi[ctlr].ndevices; i++) {
477 if (memcmp(scsi3addr,
478 ccissscsi[ctlr].dev[i].scsi3addr, 8) == 0) {
479 for (j = i; j < ccissscsi[ctlr].ndevices-1; j++)
480 ccissscsi[ctlr].dev[j] =
481 ccissscsi[ctlr].dev[j+1];
482 ccissscsi[ctlr].ndevices--;
483 break;
484 }
485 }
486 CPQ_TAPE_UNLOCK(ctlr, flags);
487}
488
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700489static int device_is_the_same(struct cciss_scsi_dev_t *dev1,
490 struct cciss_scsi_dev_t *dev2)
491{
492 return dev1->devtype == dev2->devtype &&
493 memcmp(dev1->scsi3addr, dev2->scsi3addr,
494 sizeof(dev1->scsi3addr)) == 0 &&
495 memcmp(dev1->device_id, dev2->device_id,
496 sizeof(dev1->device_id)) == 0 &&
497 memcmp(dev1->vendor, dev2->vendor,
498 sizeof(dev1->vendor)) == 0 &&
499 memcmp(dev1->model, dev2->model,
500 sizeof(dev1->model)) == 0 &&
501 memcmp(dev1->revision, dev2->revision,
502 sizeof(dev1->revision)) == 0;
503}
504
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505static int
506adjust_cciss_scsi_table(int ctlr, int hostno,
507 struct cciss_scsi_dev_t sd[], int nsds)
508{
509 /* sd contains scsi3 addresses and devtypes, but
510 bus target and lun are not filled in. This funciton
511 takes what's in sd to be the current and adjusts
512 ccissscsi[] to be in line with what's in sd. */
513
514 int i,j, found, changes=0;
515 struct cciss_scsi_dev_t *csd;
516 unsigned long flags;
Mike Millerf4a93bc2008-08-04 11:54:53 +0200517 struct scsi2map *added, *removed;
518 int nadded, nremoved;
519 struct Scsi_Host *sh = NULL;
520
521 added = kzalloc(sizeof(*added) * CCISS_MAX_SCSI_DEVS_PER_HBA,
522 GFP_KERNEL);
523 removed = kzalloc(sizeof(*removed) * CCISS_MAX_SCSI_DEVS_PER_HBA,
524 GFP_KERNEL);
525
526 if (!added || !removed) {
527 printk(KERN_WARNING "cciss%d: Out of memory in "
528 "adjust_cciss_scsi_table\n", ctlr);
529 goto free_and_out;
530 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531
532 CPQ_TAPE_LOCK(ctlr, flags);
533
Mike Millerf4a93bc2008-08-04 11:54:53 +0200534 if (hostno != -1) /* if it's not the first time... */
535 sh = ((struct cciss_scsi_adapter_data_t *)
536 hba[ctlr]->scsi_ctlr)->scsi_host;
537
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 /* find any devices in ccissscsi[] that are not in
539 sd[] and remove them from ccissscsi[] */
540
541 i = 0;
Mike Millerf4a93bc2008-08-04 11:54:53 +0200542 nremoved = 0;
543 nadded = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 while(i<ccissscsi[ctlr].ndevices) {
545 csd = &ccissscsi[ctlr].dev[i];
546 found=0;
547 for (j=0;j<nsds;j++) {
548 if (SCSI3ADDR_EQ(sd[j].scsi3addr,
549 csd->scsi3addr)) {
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700550 if (device_is_the_same(&sd[j], csd))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 found=2;
552 else
553 found=1;
554 break;
555 }
556 }
557
558 if (found == 0) { /* device no longer present. */
559 changes++;
560 /* printk("cciss%d: %s device c%db%dt%dl%d removed.\n",
Matthew Wilcox4ff36712006-07-04 12:15:20 -0600561 ctlr, scsi_device_type(csd->devtype), hostno,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 csd->bus, csd->target, csd->lun); */
Mike Millerf4a93bc2008-08-04 11:54:53 +0200563 cciss_scsi_remove_entry(ctlr, hostno, i,
564 removed, &nremoved);
565 /* remove ^^^, hence i not incremented */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700566 } else if (found == 1) { /* device is different in some way */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700567 changes++;
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700568 printk("cciss%d: device c%db%dt%dl%d has changed.\n",
569 ctlr, hostno, csd->bus, csd->target, csd->lun);
Mike Millerf4a93bc2008-08-04 11:54:53 +0200570 cciss_scsi_remove_entry(ctlr, hostno, i,
571 removed, &nremoved);
572 /* remove ^^^, hence i not incremented */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700573 if (cciss_scsi_add_entry(ctlr, hostno, &sd[j],
Mike Millerf4a93bc2008-08-04 11:54:53 +0200574 added, &nadded) != 0)
575 /* we just removed one, so add can't fail. */
576 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 csd->devtype = sd[j].devtype;
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700578 memcpy(csd->device_id, sd[j].device_id,
579 sizeof(csd->device_id));
580 memcpy(csd->vendor, sd[j].vendor,
581 sizeof(csd->vendor));
582 memcpy(csd->model, sd[j].model,
583 sizeof(csd->model));
584 memcpy(csd->revision, sd[j].revision,
585 sizeof(csd->revision));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 } else /* device is same as it ever was, */
587 i++; /* so just move along. */
588 }
589
590 /* Now, make sure every device listed in sd[] is also
591 listed in ccissscsi[], adding them if they aren't found */
592
593 for (i=0;i<nsds;i++) {
594 found=0;
595 for (j=0;j<ccissscsi[ctlr].ndevices;j++) {
596 csd = &ccissscsi[ctlr].dev[j];
597 if (SCSI3ADDR_EQ(sd[i].scsi3addr,
598 csd->scsi3addr)) {
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700599 if (device_is_the_same(&sd[i], csd))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 found=2; /* found device */
601 else
602 found=1; /* found a bug. */
603 break;
604 }
605 }
606 if (!found) {
607 changes++;
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700608 if (cciss_scsi_add_entry(ctlr, hostno, &sd[i],
Mike Millerf4a93bc2008-08-04 11:54:53 +0200609 added, &nadded) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 break;
611 } else if (found == 1) {
612 /* should never happen... */
613 changes++;
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700614 printk(KERN_WARNING "cciss%d: device "
615 "unexpectedly changed\n", ctlr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 /* but if it does happen, we just ignore that device */
617 }
618 }
619 CPQ_TAPE_UNLOCK(ctlr, flags);
620
Mike Millerf4a93bc2008-08-04 11:54:53 +0200621 /* Don't notify scsi mid layer of any changes the first time through */
622 /* (or if there are no changes) scsi_scan_host will do it later the */
623 /* first time through. */
624 if (hostno == -1 || !changes)
625 goto free_and_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626
Mike Millerf4a93bc2008-08-04 11:54:53 +0200627 /* Notify scsi mid layer of any removed devices */
628 for (i = 0; i < nremoved; i++) {
629 struct scsi_device *sdev =
630 scsi_device_lookup(sh, removed[i].bus,
631 removed[i].target, removed[i].lun);
632 if (sdev != NULL) {
633 scsi_remove_device(sdev);
634 scsi_device_put(sdev);
635 } else {
636 /* We don't expect to get here. */
637 /* future cmds to this device will get selection */
638 /* timeout as if the device was gone. */
639 printk(KERN_WARNING "cciss%d: didn't find "
640 "c%db%dt%dl%d\n for removal.",
641 ctlr, hostno, removed[i].bus,
642 removed[i].target, removed[i].lun);
643 }
644 }
645
646 /* Notify scsi mid layer of any added devices */
647 for (i = 0; i < nadded; i++) {
648 int rc;
649 rc = scsi_add_device(sh, added[i].bus,
650 added[i].target, added[i].lun);
651 if (rc == 0)
652 continue;
653 printk(KERN_WARNING "cciss%d: scsi_add_device "
654 "c%db%dt%dl%d failed, device not added.\n",
655 ctlr, hostno,
656 added[i].bus, added[i].target, added[i].lun);
657 /* now we have to remove it from ccissscsi, */
658 /* since it didn't get added to scsi mid layer */
659 fixup_botched_add(ctlr, added[i].scsi3addr);
660 }
661
662free_and_out:
663 kfree(added);
664 kfree(removed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 return 0;
666}
667
668static int
669lookup_scsi3addr(int ctlr, int bus, int target, int lun, char *scsi3addr)
670{
671 int i;
672 struct cciss_scsi_dev_t *sd;
673 unsigned long flags;
674
675 CPQ_TAPE_LOCK(ctlr, flags);
676 for (i=0;i<ccissscsi[ctlr].ndevices;i++) {
677 sd = &ccissscsi[ctlr].dev[i];
678 if (sd->bus == bus &&
679 sd->target == target &&
680 sd->lun == lun) {
681 memcpy(scsi3addr, &sd->scsi3addr[0], 8);
682 CPQ_TAPE_UNLOCK(ctlr, flags);
683 return 0;
684 }
685 }
686 CPQ_TAPE_UNLOCK(ctlr, flags);
687 return -1;
688}
689
690static void
691cciss_scsi_setup(int cntl_num)
692{
693 struct cciss_scsi_adapter_data_t * shba;
694
695 ccissscsi[cntl_num].ndevices = 0;
696 shba = (struct cciss_scsi_adapter_data_t *)
697 kmalloc(sizeof(*shba), GFP_KERNEL);
698 if (shba == NULL)
699 return;
700 shba->scsi_host = NULL;
701 spin_lock_init(&shba->lock);
702 shba->registered = 0;
703 if (scsi_cmd_stack_setup(cntl_num, shba) != 0) {
704 kfree(shba);
705 shba = NULL;
706 }
707 hba[cntl_num]->scsi_ctlr = (void *) shba;
708 return;
709}
710
711static void
712complete_scsi_command( CommandList_struct *cp, int timeout, __u32 tag)
713{
714 struct scsi_cmnd *cmd;
715 ctlr_info_t *ctlr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 ErrorInfo_struct *ei;
717
718 ei = cp->err_info;
719
720 /* First, see if it was a message rather than a command */
721 if (cp->Request.Type.Type == TYPE_MSG) {
722 cp->cmd_type = CMD_MSG_DONE;
723 return;
724 }
725
726 cmd = (struct scsi_cmnd *) cp->scsi_cmd;
727 ctlr = hba[cp->ctlr];
728
FUJITA Tomonori41ce6392007-05-26 02:45:17 +0900729 scsi_dma_unmap(cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730
731 cmd->result = (DID_OK << 16); /* host byte */
732 cmd->result |= (COMMAND_COMPLETE << 8); /* msg byte */
733 /* cmd->result |= (GOOD < 1); */ /* status byte */
734
735 cmd->result |= (ei->ScsiStatus);
736 /* printk("Scsistatus is 0x%02x\n", ei->ScsiStatus); */
737
738 /* copy the sense data whether we need to or not. */
739
740 memcpy(cmd->sense_buffer, ei->SenseInfo,
741 ei->SenseLen > SCSI_SENSE_BUFFERSIZE ?
742 SCSI_SENSE_BUFFERSIZE :
743 ei->SenseLen);
FUJITA Tomonori41ce6392007-05-26 02:45:17 +0900744 scsi_set_resid(cmd, ei->ResidualCnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745
746 if(ei->CommandStatus != 0)
747 { /* an error has occurred */
748 switch(ei->CommandStatus)
749 {
750 case CMD_TARGET_STATUS:
751 /* Pass it up to the upper layers... */
752 if( ei->ScsiStatus)
753 {
754#if 0
755 printk(KERN_WARNING "cciss: cmd %p "
756 "has SCSI Status = %x\n",
757 cp,
758 ei->ScsiStatus);
759#endif
760 cmd->result |= (ei->ScsiStatus < 1);
761 }
762 else { /* scsi status is zero??? How??? */
763
764 /* Ordinarily, this case should never happen, but there is a bug
765 in some released firmware revisions that allows it to happen
766 if, for example, a 4100 backplane loses power and the tape
767 drive is in it. We assume that it's a fatal error of some
768 kind because we can't show that it wasn't. We will make it
769 look like selection timeout since that is the most common
770 reason for this to occur, and it's severe enough. */
771
772 cmd->result = DID_NO_CONNECT << 16;
773 }
774 break;
775 case CMD_DATA_UNDERRUN: /* let mid layer handle it. */
776 break;
777 case CMD_DATA_OVERRUN:
778 printk(KERN_WARNING "cciss: cp %p has"
779 " completed with data overrun "
780 "reported\n", cp);
781 break;
782 case CMD_INVALID: {
783 /* print_bytes(cp, sizeof(*cp), 1, 0);
784 print_cmd(cp); */
785 /* We get CMD_INVALID if you address a non-existent tape drive instead
786 of a selection timeout (no response). You will see this if you yank
787 out a tape drive, then try to access it. This is kind of a shame
788 because it means that any other CMD_INVALID (e.g. driver bug) will
789 get interpreted as a missing target. */
790 cmd->result = DID_NO_CONNECT << 16;
791 }
792 break;
793 case CMD_PROTOCOL_ERR:
794 printk(KERN_WARNING "cciss: cp %p has "
795 "protocol error \n", cp);
796 break;
797 case CMD_HARDWARE_ERR:
798 cmd->result = DID_ERROR << 16;
799 printk(KERN_WARNING "cciss: cp %p had "
800 " hardware error\n", cp);
801 break;
802 case CMD_CONNECTION_LOST:
803 cmd->result = DID_ERROR << 16;
804 printk(KERN_WARNING "cciss: cp %p had "
805 "connection lost\n", cp);
806 break;
807 case CMD_ABORTED:
808 cmd->result = DID_ABORT << 16;
809 printk(KERN_WARNING "cciss: cp %p was "
810 "aborted\n", cp);
811 break;
812 case CMD_ABORT_FAILED:
813 cmd->result = DID_ERROR << 16;
814 printk(KERN_WARNING "cciss: cp %p reports "
815 "abort failed\n", cp);
816 break;
817 case CMD_UNSOLICITED_ABORT:
818 cmd->result = DID_ABORT << 16;
819 printk(KERN_WARNING "cciss: cp %p aborted "
820 "do to an unsolicited abort\n", cp);
821 break;
822 case CMD_TIMEOUT:
823 cmd->result = DID_TIME_OUT << 16;
824 printk(KERN_WARNING "cciss: cp %p timedout\n",
825 cp);
826 break;
827 default:
828 cmd->result = DID_ERROR << 16;
829 printk(KERN_WARNING "cciss: cp %p returned "
830 "unknown status %x\n", cp,
831 ei->CommandStatus);
832 }
833 }
834 // printk("c:%p:c%db%dt%dl%d ", cmd, ctlr->ctlr, cmd->channel,
835 // cmd->target, cmd->lun);
836 cmd->scsi_done(cmd);
837 scsi_cmd_free(ctlr, cp);
838}
839
840static int
841cciss_scsi_detect(int ctlr)
842{
843 struct Scsi_Host *sh;
844 int error;
845
846 sh = scsi_host_alloc(&cciss_driver_template, sizeof(struct ctlr_info *));
847 if (sh == NULL)
848 goto fail;
849 sh->io_port = 0; // good enough? FIXME,
850 sh->n_io_port = 0; // I don't think we use these two...
851 sh->this_id = SELF_SCSI_ID;
852
853 ((struct cciss_scsi_adapter_data_t *)
854 hba[ctlr]->scsi_ctlr)->scsi_host = (void *) sh;
855 sh->hostdata[0] = (unsigned long) hba[ctlr];
Mike Millerfb86a352006-01-08 01:03:50 -0800856 sh->irq = hba[ctlr]->intr[SIMPLE_MODE_INT];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 sh->unique_id = sh->irq;
858 error = scsi_add_host(sh, &hba[ctlr]->pdev->dev);
859 if (error)
860 goto fail_host_put;
861 scsi_scan_host(sh);
862 return 1;
863
864 fail_host_put:
865 scsi_host_put(sh);
866 fail:
867 return 0;
868}
869
870static void
871cciss_unmap_one(struct pci_dev *pdev,
872 CommandList_struct *cp,
873 size_t buflen,
874 int data_direction)
875{
876 u64bit addr64;
877
878 addr64.val32.lower = cp->SG[0].Addr.lower;
879 addr64.val32.upper = cp->SG[0].Addr.upper;
880 pci_unmap_single(pdev, (dma_addr_t) addr64.val, buflen, data_direction);
881}
882
883static void
884cciss_map_one(struct pci_dev *pdev,
885 CommandList_struct *cp,
886 unsigned char *buf,
887 size_t buflen,
888 int data_direction)
889{
890 __u64 addr64;
891
892 addr64 = (__u64) pci_map_single(pdev, buf, buflen, data_direction);
893 cp->SG[0].Addr.lower =
894 (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF);
895 cp->SG[0].Addr.upper =
896 (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF);
897 cp->SG[0].Len = buflen;
898 cp->Header.SGList = (__u8) 1; /* no. SGs contig in this cmd */
899 cp->Header.SGTotal = (__u16) 1; /* total sgs in this cmd list */
900}
901
902static int
903cciss_scsi_do_simple_cmd(ctlr_info_t *c,
904 CommandList_struct *cp,
905 unsigned char *scsi3addr,
906 unsigned char *cdb,
907 unsigned char cdblen,
908 unsigned char *buf, int bufsize,
909 int direction)
910{
911 unsigned long flags;
Peter Zijlstra6e9a4732006-09-30 23:28:10 -0700912 DECLARE_COMPLETION_ONSTACK(wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913
914 cp->cmd_type = CMD_IOCTL_PEND; // treat this like an ioctl
915 cp->scsi_cmd = NULL;
916 cp->Header.ReplyQueue = 0; // unused in simple mode
917 memcpy(&cp->Header.LUN, scsi3addr, sizeof(cp->Header.LUN));
918 cp->Header.Tag.lower = cp->busaddr; // Use k. address of cmd as tag
919 // Fill in the request block...
920
921 /* printk("Using scsi3addr 0x%02x%0x2%0x2%0x2%0x2%0x2%0x2%0x2\n",
922 scsi3addr[0], scsi3addr[1], scsi3addr[2], scsi3addr[3],
923 scsi3addr[4], scsi3addr[5], scsi3addr[6], scsi3addr[7]); */
924
925 memset(cp->Request.CDB, 0, sizeof(cp->Request.CDB));
926 memcpy(cp->Request.CDB, cdb, cdblen);
927 cp->Request.Timeout = 0;
928 cp->Request.CDBLen = cdblen;
929 cp->Request.Type.Type = TYPE_CMD;
930 cp->Request.Type.Attribute = ATTR_SIMPLE;
931 cp->Request.Type.Direction = direction;
932
933 /* Fill in the SG list and do dma mapping */
934 cciss_map_one(c->pdev, cp, (unsigned char *) buf,
935 bufsize, DMA_FROM_DEVICE);
936
937 cp->waiting = &wait;
938
939 /* Put the request on the tail of the request queue */
940 spin_lock_irqsave(CCISS_LOCK(c->ctlr), flags);
941 addQ(&c->reqQ, cp);
942 c->Qdepth++;
943 start_io(c);
944 spin_unlock_irqrestore(CCISS_LOCK(c->ctlr), flags);
945
946 wait_for_completion(&wait);
947
948 /* undo the dma mapping */
949 cciss_unmap_one(c->pdev, cp, bufsize, DMA_FROM_DEVICE);
950 return(0);
951}
952
953static void
954cciss_scsi_interpret_error(CommandList_struct *cp)
955{
956 ErrorInfo_struct *ei;
957
958 ei = cp->err_info;
959 switch(ei->CommandStatus)
960 {
961 case CMD_TARGET_STATUS:
962 printk(KERN_WARNING "cciss: cmd %p has "
963 "completed with errors\n", cp);
964 printk(KERN_WARNING "cciss: cmd %p "
965 "has SCSI Status = %x\n",
966 cp,
967 ei->ScsiStatus);
968 if (ei->ScsiStatus == 0)
969 printk(KERN_WARNING
970 "cciss:SCSI status is abnormally zero. "
971 "(probably indicates selection timeout "
972 "reported incorrectly due to a known "
973 "firmware bug, circa July, 2001.)\n");
974 break;
975 case CMD_DATA_UNDERRUN: /* let mid layer handle it. */
976 printk("UNDERRUN\n");
977 break;
978 case CMD_DATA_OVERRUN:
979 printk(KERN_WARNING "cciss: cp %p has"
980 " completed with data overrun "
981 "reported\n", cp);
982 break;
983 case CMD_INVALID: {
984 /* controller unfortunately reports SCSI passthru's */
985 /* to non-existent targets as invalid commands. */
986 printk(KERN_WARNING "cciss: cp %p is "
987 "reported invalid (probably means "
988 "target device no longer present)\n",
989 cp);
990 /* print_bytes((unsigned char *) cp, sizeof(*cp), 1, 0);
991 print_cmd(cp); */
992 }
993 break;
994 case CMD_PROTOCOL_ERR:
995 printk(KERN_WARNING "cciss: cp %p has "
996 "protocol error \n", cp);
997 break;
998 case CMD_HARDWARE_ERR:
999 /* cmd->result = DID_ERROR << 16; */
1000 printk(KERN_WARNING "cciss: cp %p had "
1001 " hardware error\n", cp);
1002 break;
1003 case CMD_CONNECTION_LOST:
1004 printk(KERN_WARNING "cciss: cp %p had "
1005 "connection lost\n", cp);
1006 break;
1007 case CMD_ABORTED:
1008 printk(KERN_WARNING "cciss: cp %p was "
1009 "aborted\n", cp);
1010 break;
1011 case CMD_ABORT_FAILED:
1012 printk(KERN_WARNING "cciss: cp %p reports "
1013 "abort failed\n", cp);
1014 break;
1015 case CMD_UNSOLICITED_ABORT:
1016 printk(KERN_WARNING "cciss: cp %p aborted "
1017 "do to an unsolicited abort\n", cp);
1018 break;
1019 case CMD_TIMEOUT:
1020 printk(KERN_WARNING "cciss: cp %p timedout\n",
1021 cp);
1022 break;
1023 default:
1024 printk(KERN_WARNING "cciss: cp %p returned "
1025 "unknown status %x\n", cp,
1026 ei->CommandStatus);
1027 }
1028}
1029
1030static int
1031cciss_scsi_do_inquiry(ctlr_info_t *c, unsigned char *scsi3addr,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001032 unsigned char page, unsigned char *buf,
1033 unsigned char bufsize)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034{
1035 int rc;
1036 CommandList_struct *cp;
1037 char cdb[6];
1038 ErrorInfo_struct *ei;
1039 unsigned long flags;
1040
1041 spin_lock_irqsave(CCISS_LOCK(c->ctlr), flags);
1042 cp = scsi_cmd_alloc(c);
1043 spin_unlock_irqrestore(CCISS_LOCK(c->ctlr), flags);
1044
1045 if (cp == NULL) { /* trouble... */
1046 printk("cmd_alloc returned NULL!\n");
1047 return -1;
1048 }
1049
1050 ei = cp->err_info;
1051
1052 cdb[0] = CISS_INQUIRY;
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001053 cdb[1] = (page != 0);
1054 cdb[2] = page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 cdb[3] = 0;
Mike Miller47922d02005-09-13 01:25:25 -07001056 cdb[4] = bufsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 cdb[5] = 0;
1058 rc = cciss_scsi_do_simple_cmd(c, cp, scsi3addr, cdb,
Mike Miller47922d02005-09-13 01:25:25 -07001059 6, buf, bufsize, XFER_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060
1061 if (rc != 0) return rc; /* something went wrong */
1062
1063 if (ei->CommandStatus != 0 &&
1064 ei->CommandStatus != CMD_DATA_UNDERRUN) {
1065 cciss_scsi_interpret_error(cp);
1066 rc = -1;
1067 }
1068 spin_lock_irqsave(CCISS_LOCK(c->ctlr), flags);
1069 scsi_cmd_free(c, cp);
1070 spin_unlock_irqrestore(CCISS_LOCK(c->ctlr), flags);
1071 return rc;
1072}
1073
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001074/* Get the device id from inquiry page 0x83 */
1075static int cciss_scsi_get_device_id(ctlr_info_t *c, unsigned char *scsi3addr,
1076 unsigned char *device_id, int buflen)
1077{
1078 int rc;
1079 unsigned char *buf;
1080
1081 if (buflen > 16)
1082 buflen = 16;
1083 buf = kzalloc(64, GFP_KERNEL);
1084 if (!buf)
1085 return -1;
1086 rc = cciss_scsi_do_inquiry(c, scsi3addr, 0x83, buf, 64);
1087 if (rc == 0)
1088 memcpy(device_id, &buf[8], buflen);
1089 kfree(buf);
1090 return rc != 0;
1091}
1092
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093static int
1094cciss_scsi_do_report_phys_luns(ctlr_info_t *c,
1095 ReportLunData_struct *buf, int bufsize)
1096{
1097 int rc;
1098 CommandList_struct *cp;
1099 unsigned char cdb[12];
1100 unsigned char scsi3addr[8];
1101 ErrorInfo_struct *ei;
1102 unsigned long flags;
1103
1104 spin_lock_irqsave(CCISS_LOCK(c->ctlr), flags);
1105 cp = scsi_cmd_alloc(c);
1106 spin_unlock_irqrestore(CCISS_LOCK(c->ctlr), flags);
1107 if (cp == NULL) { /* trouble... */
1108 printk("cmd_alloc returned NULL!\n");
1109 return -1;
1110 }
1111
1112 memset(&scsi3addr[0], 0, 8); /* address the controller */
1113 cdb[0] = CISS_REPORT_PHYS;
1114 cdb[1] = 0;
1115 cdb[2] = 0;
1116 cdb[3] = 0;
1117 cdb[4] = 0;
1118 cdb[5] = 0;
1119 cdb[6] = (bufsize >> 24) & 0xFF; //MSB
1120 cdb[7] = (bufsize >> 16) & 0xFF;
1121 cdb[8] = (bufsize >> 8) & 0xFF;
1122 cdb[9] = bufsize & 0xFF;
1123 cdb[10] = 0;
1124 cdb[11] = 0;
1125
1126 rc = cciss_scsi_do_simple_cmd(c, cp, scsi3addr,
1127 cdb, 12,
1128 (unsigned char *) buf,
1129 bufsize, XFER_READ);
1130
1131 if (rc != 0) return rc; /* something went wrong */
1132
1133 ei = cp->err_info;
1134 if (ei->CommandStatus != 0 &&
1135 ei->CommandStatus != CMD_DATA_UNDERRUN) {
1136 cciss_scsi_interpret_error(cp);
1137 rc = -1;
1138 }
1139 spin_lock_irqsave(CCISS_LOCK(c->ctlr), flags);
1140 scsi_cmd_free(c, cp);
1141 spin_unlock_irqrestore(CCISS_LOCK(c->ctlr), flags);
1142 return rc;
1143}
1144
1145static void
1146cciss_update_non_disk_devices(int cntl_num, int hostno)
1147{
1148 /* the idea here is we could get notified from /proc
1149 that some devices have changed, so we do a report
1150 physical luns cmd, and adjust our list of devices
1151 accordingly. (We can't rely on the scsi-mid layer just
1152 doing inquiries, because the "busses" that the scsi
1153 mid-layer probes are totally fabricated by this driver,
1154 so new devices wouldn't show up.
1155
1156 the scsi3addr's of devices won't change so long as the
1157 adapter is not reset. That means we can rescan and
1158 tell which devices we already know about, vs. new
1159 devices, vs. disappearing devices.
1160
1161 Also, if you yank out a tape drive, then put in a disk
1162 in it's place, (say, a configured volume from another
1163 array controller for instance) _don't_ poke this driver
1164 (so it thinks it's still a tape, but _do_ poke the scsi
1165 mid layer, so it does an inquiry... the scsi mid layer
1166 will see the physical disk. This would be bad. Need to
1167 think about how to prevent that. One idea would be to
1168 snoop all scsi responses and if an inquiry repsonse comes
1169 back that reports a disk, chuck it an return selection
1170 timeout instead and adjust our table... Not sure i like
1171 that though.
1172
1173 */
Mike Miller47922d02005-09-13 01:25:25 -07001174#define OBDR_TAPE_INQ_SIZE 49
1175#define OBDR_TAPE_SIG "$DR-10"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 ReportLunData_struct *ld_buff;
Mike Miller47922d02005-09-13 01:25:25 -07001177 unsigned char *inq_buff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 unsigned char scsi3addr[8];
1179 ctlr_info_t *c;
1180 __u32 num_luns=0;
1181 unsigned char *ch;
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001182 struct cciss_scsi_dev_t *currentsd, *this_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 int ncurrent=0;
1184 int reportlunsize = sizeof(*ld_buff) + CISS_MAX_PHYS_LUN * 8;
1185 int i;
1186
1187 c = (ctlr_info_t *) hba[cntl_num];
Eric Sesterhenn06ff37f2006-03-08 11:21:52 +01001188 ld_buff = kzalloc(reportlunsize, GFP_KERNEL);
Mike Miller47922d02005-09-13 01:25:25 -07001189 inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001190 currentsd = kzalloc(sizeof(*currentsd) *
1191 (CCISS_MAX_SCSI_DEVS_PER_HBA+1), GFP_KERNEL);
1192 if (ld_buff == NULL || inq_buff == NULL || currentsd == NULL) {
1193 printk(KERN_ERR "cciss: out of memory\n");
1194 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195 }
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001196 this_device = &currentsd[CCISS_MAX_SCSI_DEVS_PER_HBA];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 if (cciss_scsi_do_report_phys_luns(c, ld_buff, reportlunsize) == 0) {
1198 ch = &ld_buff->LUNListLength[0];
1199 num_luns = ((ch[0]<<24) | (ch[1]<<16) | (ch[2]<<8) | ch[3]) / 8;
1200 if (num_luns > CISS_MAX_PHYS_LUN) {
1201 printk(KERN_WARNING
1202 "cciss: Maximum physical LUNs (%d) exceeded. "
1203 "%d LUNs ignored.\n", CISS_MAX_PHYS_LUN,
1204 num_luns - CISS_MAX_PHYS_LUN);
1205 num_luns = CISS_MAX_PHYS_LUN;
1206 }
1207 }
1208 else {
1209 printk(KERN_ERR "cciss: Report physical LUNs failed.\n");
1210 goto out;
1211 }
1212
1213
1214 /* adjust our table of devices */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001215 for (i = 0; i < num_luns; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 /* for each physical lun, do an inquiry */
1217 if (ld_buff->LUN[i][3] & 0xC0) continue;
Mike Miller47922d02005-09-13 01:25:25 -07001218 memset(inq_buff, 0, OBDR_TAPE_INQ_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8);
1220
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001221 if (cciss_scsi_do_inquiry(hba[cntl_num], scsi3addr, 0, inq_buff,
1222 (unsigned char) OBDR_TAPE_INQ_SIZE) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 /* Inquiry failed (msg printed already) */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001224 continue; /* so we will skip this device. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001226 this_device->devtype = (inq_buff[0] & 0x1f);
1227 this_device->bus = -1;
1228 this_device->target = -1;
1229 this_device->lun = -1;
1230 memcpy(this_device->scsi3addr, scsi3addr, 8);
1231 memcpy(this_device->vendor, &inq_buff[8],
1232 sizeof(this_device->vendor));
1233 memcpy(this_device->model, &inq_buff[16],
1234 sizeof(this_device->model));
1235 memcpy(this_device->revision, &inq_buff[32],
1236 sizeof(this_device->revision));
1237 memset(this_device->device_id, 0,
1238 sizeof(this_device->device_id));
1239 cciss_scsi_get_device_id(hba[cntl_num], scsi3addr,
1240 this_device->device_id, sizeof(this_device->device_id));
1241
1242 switch (this_device->devtype)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 {
Mike Miller47922d02005-09-13 01:25:25 -07001244 case 0x05: /* CD-ROM */ {
1245
1246 /* We don't *really* support actual CD-ROM devices,
1247 * just this "One Button Disaster Recovery" tape drive
1248 * which temporarily pretends to be a CD-ROM drive.
1249 * So we check that the device is really an OBDR tape
1250 * device by checking for "$DR-10" in bytes 43-48 of
1251 * the inquiry data.
1252 */
1253 char obdr_sig[7];
1254
1255 strncpy(obdr_sig, &inq_buff[43], 6);
1256 obdr_sig[6] = '\0';
1257 if (strncmp(obdr_sig, OBDR_TAPE_SIG, 6) != 0)
1258 /* Not OBDR device, ignore it. */
1259 break;
1260 }
1261 /* fall through . . . */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 case 0x01: /* sequential access, (tape) */
1263 case 0x08: /* medium changer */
1264 if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) {
1265 printk(KERN_INFO "cciss%d: %s ignored, "
1266 "too many devices.\n", cntl_num,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001267 scsi_device_type(this_device->devtype));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 break;
1269 }
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001270 currentsd[ncurrent] = *this_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 ncurrent++;
1272 break;
1273 default:
1274 break;
1275 }
1276 }
1277
1278 adjust_cciss_scsi_table(cntl_num, hostno, currentsd, ncurrent);
1279out:
1280 kfree(inq_buff);
1281 kfree(ld_buff);
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001282 kfree(currentsd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283 return;
1284}
1285
1286static int
1287is_keyword(char *ptr, int len, char *verb) // Thanks to ncr53c8xx.c
1288{
1289 int verb_len = strlen(verb);
1290 if (len >= verb_len && !memcmp(verb,ptr,verb_len))
1291 return verb_len;
1292 else
1293 return 0;
1294}
1295
1296static int
1297cciss_scsi_user_command(int ctlr, int hostno, char *buffer, int length)
1298{
1299 int arg_len;
1300
1301 if ((arg_len = is_keyword(buffer, length, "rescan")) != 0)
1302 cciss_update_non_disk_devices(ctlr, hostno);
1303 else
1304 return -EINVAL;
1305 return length;
1306}
1307
1308
1309static int
1310cciss_scsi_proc_info(struct Scsi_Host *sh,
1311 char *buffer, /* data buffer */
1312 char **start, /* where data in buffer starts */
1313 off_t offset, /* offset from start of imaginary file */
1314 int length, /* length of data in buffer */
1315 int func) /* 0 == read, 1 == write */
1316{
1317
1318 int buflen, datalen;
1319 ctlr_info_t *ci;
Mike Millerb9f0bd02005-09-13 01:25:26 -07001320 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321 int cntl_num;
1322
1323
1324 ci = (ctlr_info_t *) sh->hostdata[0];
1325 if (ci == NULL) /* This really shouldn't ever happen. */
1326 return -EINVAL;
1327
1328 cntl_num = ci->ctlr; /* Get our index into the hba[] array */
1329
1330 if (func == 0) { /* User is reading from /proc/scsi/ciss*?/?* */
Mike Millerb9f0bd02005-09-13 01:25:26 -07001331 buflen = sprintf(buffer, "cciss%d: SCSI host: %d\n",
1332 cntl_num, sh->host_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333
Mike Millerb9f0bd02005-09-13 01:25:26 -07001334 /* this information is needed by apps to know which cciss
1335 device corresponds to which scsi host number without
1336 having to open a scsi target device node. The device
1337 information is not a duplicate of /proc/scsi/scsi because
1338 the two may be out of sync due to scsi hotplug, rather
1339 this info is for an app to be able to use to know how to
1340 get them back in sync. */
1341
1342 for (i=0;i<ccissscsi[cntl_num].ndevices;i++) {
1343 struct cciss_scsi_dev_t *sd = &ccissscsi[cntl_num].dev[i];
1344 buflen += sprintf(&buffer[buflen], "c%db%dt%dl%d %02d "
1345 "0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
1346 sh->host_no, sd->bus, sd->target, sd->lun,
1347 sd->devtype,
1348 sd->scsi3addr[0], sd->scsi3addr[1],
1349 sd->scsi3addr[2], sd->scsi3addr[3],
1350 sd->scsi3addr[4], sd->scsi3addr[5],
1351 sd->scsi3addr[6], sd->scsi3addr[7]);
1352 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 datalen = buflen - offset;
1354 if (datalen < 0) { /* they're reading past EOF. */
1355 datalen = 0;
1356 *start = buffer+buflen;
1357 } else
1358 *start = buffer + offset;
1359 return(datalen);
1360 } else /* User is writing to /proc/scsi/cciss*?/?* ... */
1361 return cciss_scsi_user_command(cntl_num, sh->host_no,
1362 buffer, length);
1363}
1364
1365/* cciss_scatter_gather takes a struct scsi_cmnd, (cmd), and does the pci
1366 dma mapping and fills in the scatter gather entries of the
1367 cciss command, cp. */
1368
1369static void
1370cciss_scatter_gather(struct pci_dev *pdev,
1371 CommandList_struct *cp,
1372 struct scsi_cmnd *cmd)
1373{
FUJITA Tomonori41ce6392007-05-26 02:45:17 +09001374 unsigned int len;
1375 struct scatterlist *sg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376 __u64 addr64;
FUJITA Tomonori41ce6392007-05-26 02:45:17 +09001377 int use_sg, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378
FUJITA Tomonori41ce6392007-05-26 02:45:17 +09001379 BUG_ON(scsi_sg_count(cmd) > MAXSGENTRIES);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380
FUJITA Tomonori41ce6392007-05-26 02:45:17 +09001381 use_sg = scsi_dma_map(cmd);
1382 if (use_sg) { /* not too many addrs? */
1383 scsi_for_each_sg(cmd, sg, use_sg, i) {
1384 addr64 = (__u64) sg_dma_address(sg);
1385 len = sg_dma_len(sg);
1386 cp->SG[i].Addr.lower =
1387 (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF);
1388 cp->SG[i].Addr.upper =
1389 (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF);
1390 cp->SG[i].Len = len;
1391 cp->SG[i].Ext = 0; // we are not chaining
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 }
FUJITA Tomonori41ce6392007-05-26 02:45:17 +09001393 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394
FUJITA Tomonori41ce6392007-05-26 02:45:17 +09001395 cp->Header.SGList = (__u8) use_sg; /* no. SGs contig in this cmd */
1396 cp->Header.SGTotal = (__u16) use_sg; /* total sgs in this cmd list */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 return;
1398}
1399
1400
1401static int
1402cciss_scsi_queue_command (struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
1403{
1404 ctlr_info_t **c;
1405 int ctlr, rc;
1406 unsigned char scsi3addr[8];
1407 CommandList_struct *cp;
1408 unsigned long flags;
1409
1410 // Get the ptr to our adapter structure (hba[i]) out of cmd->host.
1411 // We violate cmd->host privacy here. (Is there another way?)
1412 c = (ctlr_info_t **) &cmd->device->host->hostdata[0];
1413 ctlr = (*c)->ctlr;
1414
1415 rc = lookup_scsi3addr(ctlr, cmd->device->channel, cmd->device->id,
1416 cmd->device->lun, scsi3addr);
1417 if (rc != 0) {
1418 /* the scsi nexus does not match any that we presented... */
1419 /* pretend to mid layer that we got selection timeout */
1420 cmd->result = DID_NO_CONNECT << 16;
1421 done(cmd);
1422 /* we might want to think about registering controller itself
1423 as a processor device on the bus so sg binds to it. */
1424 return 0;
1425 }
1426
1427 /* printk("cciss_queue_command, p=%p, cmd=0x%02x, c%db%dt%dl%d\n",
1428 cmd, cmd->cmnd[0], ctlr, cmd->channel, cmd->target, cmd->lun);*/
1429 // printk("q:%p:c%db%dt%dl%d ", cmd, ctlr, cmd->channel,
1430 // cmd->target, cmd->lun);
1431
1432 /* Ok, we have a reasonable scsi nexus, so send the cmd down, and
1433 see what the device thinks of it. */
1434
1435 spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
1436 cp = scsi_cmd_alloc(*c);
1437 spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
1438 if (cp == NULL) { /* trouble... */
1439 printk("scsi_cmd_alloc returned NULL!\n");
1440 /* FIXME: next 3 lines are -> BAD! <- */
1441 cmd->result = DID_NO_CONNECT << 16;
1442 done(cmd);
1443 return 0;
1444 }
1445
1446 // Fill in the command list header
1447
1448 cmd->scsi_done = done; // save this for use by completion code
1449
1450 // save cp in case we have to abort it
1451 cmd->host_scribble = (unsigned char *) cp;
1452
1453 cp->cmd_type = CMD_SCSI;
1454 cp->scsi_cmd = cmd;
1455 cp->Header.ReplyQueue = 0; // unused in simple mode
1456 memcpy(&cp->Header.LUN.LunAddrBytes[0], &scsi3addr[0], 8);
1457 cp->Header.Tag.lower = cp->busaddr; // Use k. address of cmd as tag
1458
1459 // Fill in the request block...
1460
1461 cp->Request.Timeout = 0;
1462 memset(cp->Request.CDB, 0, sizeof(cp->Request.CDB));
Eric Sesterhenn089fe1b2006-03-24 18:50:27 +01001463 BUG_ON(cmd->cmd_len > sizeof(cp->Request.CDB));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464 cp->Request.CDBLen = cmd->cmd_len;
1465 memcpy(cp->Request.CDB, cmd->cmnd, cmd->cmd_len);
1466 cp->Request.Type.Type = TYPE_CMD;
1467 cp->Request.Type.Attribute = ATTR_SIMPLE;
1468 switch(cmd->sc_data_direction)
1469 {
1470 case DMA_TO_DEVICE: cp->Request.Type.Direction = XFER_WRITE; break;
1471 case DMA_FROM_DEVICE: cp->Request.Type.Direction = XFER_READ; break;
1472 case DMA_NONE: cp->Request.Type.Direction = XFER_NONE; break;
1473 case DMA_BIDIRECTIONAL:
1474 // This can happen if a buggy application does a scsi passthru
1475 // and sets both inlen and outlen to non-zero. ( see
1476 // ../scsi/scsi_ioctl.c:scsi_ioctl_send_command() )
1477
1478 cp->Request.Type.Direction = XFER_RSVD;
1479 // This is technically wrong, and cciss controllers should
1480 // reject it with CMD_INVALID, which is the most correct
1481 // response, but non-fibre backends appear to let it
1482 // slide by, and give the same results as if this field
1483 // were set correctly. Either way is acceptable for
1484 // our purposes here.
1485
1486 break;
1487
1488 default:
1489 printk("cciss: unknown data direction: %d\n",
1490 cmd->sc_data_direction);
1491 BUG();
1492 break;
1493 }
1494
1495 cciss_scatter_gather((*c)->pdev, cp, cmd); // Fill the SG list
1496
1497 /* Put the request on the tail of the request queue */
1498
1499 spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
1500 addQ(&(*c)->reqQ, cp);
1501 (*c)->Qdepth++;
1502 start_io(*c);
1503 spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
1504
1505 /* the cmd'll come back via intr handler in complete_scsi_command() */
1506 return 0;
1507}
1508
1509static void
1510cciss_unregister_scsi(int ctlr)
1511{
1512 struct cciss_scsi_adapter_data_t *sa;
1513 struct cciss_scsi_cmd_stack_t *stk;
1514 unsigned long flags;
1515
1516 /* we are being forcibly unloaded, and may not refuse. */
1517
1518 spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
1519 sa = (struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr;
1520 stk = &sa->cmd_stack;
1521
1522 /* if we weren't ever actually registered, don't unregister */
1523 if (sa->registered) {
1524 spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
1525 scsi_remove_host(sa->scsi_host);
1526 scsi_host_put(sa->scsi_host);
1527 spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
1528 }
1529
1530 /* set scsi_host to NULL so our detect routine will
1531 find us on register */
1532 sa->scsi_host = NULL;
scameron@beardog.cca.cpqcorp.net61950572008-04-17 13:19:04 +02001533 spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534 scsi_cmd_stack_free(ctlr);
1535 kfree(sa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536}
1537
1538static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539cciss_engage_scsi(int ctlr)
1540{
1541 struct cciss_scsi_adapter_data_t *sa;
1542 struct cciss_scsi_cmd_stack_t *stk;
1543 unsigned long flags;
1544
1545 spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
1546 sa = (struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr;
1547 stk = &sa->cmd_stack;
1548
Mike Millerf4a93bc2008-08-04 11:54:53 +02001549 if (sa->registered) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 printk("cciss%d: SCSI subsystem already engaged.\n", ctlr);
1551 spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
1552 return ENXIO;
1553 }
Mike Millerf4a93bc2008-08-04 11:54:53 +02001554 sa->registered = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555 spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
1556 cciss_update_non_disk_devices(ctlr, -1);
Mike Millerf4a93bc2008-08-04 11:54:53 +02001557 cciss_scsi_detect(ctlr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558 return 0;
1559}
1560
1561static void
Mike Miller89b6e742008-02-21 08:54:03 +01001562cciss_seq_tape_report(struct seq_file *seq, int ctlr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563{
1564 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565
1566 CPQ_TAPE_LOCK(ctlr, flags);
Mike Miller89b6e742008-02-21 08:54:03 +01001567 seq_printf(seq,
Mike Millerb9f0bd02005-09-13 01:25:26 -07001568 "Sequential access devices: %d\n\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569 ccissscsi[ctlr].ndevices);
1570 CPQ_TAPE_UNLOCK(ctlr, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571}
1572
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001573static int wait_for_device_to_become_ready(ctlr_info_t *h,
1574 unsigned char lunaddr[])
1575{
1576 int rc;
1577 int count = 0;
1578 int waittime = HZ;
1579 CommandList_struct *c;
1580
1581 c = cmd_alloc(h, 1);
1582 if (!c) {
1583 printk(KERN_WARNING "cciss%d: out of memory in "
1584 "wait_for_device_to_become_ready.\n", h->ctlr);
1585 return IO_ERROR;
1586 }
1587
1588 /* Send test unit ready until device ready, or give up. */
1589 while (count < 20) {
1590
1591 /* Wait for a bit. do this first, because if we send
1592 * the TUR right away, the reset will just abort it.
1593 */
scameron@beardog.cca.cpqcorp.net40df6ae2009-06-08 15:59:38 -05001594 schedule_timeout_uninterruptible(waittime);
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001595 count++;
1596
1597 /* Increase wait time with each try, up to a point. */
1598 if (waittime < (HZ * 30))
1599 waittime = waittime * 2;
1600
1601 /* Send the Test Unit Ready */
scameron@beardog.cca.cpqcorp.netb57695f2009-06-08 16:02:17 -05001602 rc = fill_cmd(c, TEST_UNIT_READY, h->ctlr, NULL, 0, 0,
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001603 lunaddr, TYPE_CMD);
1604 if (rc == 0) {
1605 rc = sendcmd_core(h, c);
1606 /* sendcmd turned off interrupts, turn 'em back on. */
1607 h->access.set_intr_mask(h, CCISS_INTR_ON);
1608 }
1609
1610 if (rc == 0 && c->err_info->CommandStatus == CMD_SUCCESS)
1611 break;
1612
1613 if (rc == 0 &&
1614 c->err_info->CommandStatus == CMD_TARGET_STATUS &&
1615 c->err_info->ScsiStatus == SAM_STAT_CHECK_CONDITION &&
1616 (c->err_info->SenseInfo[2] == NO_SENSE ||
1617 c->err_info->SenseInfo[2] == UNIT_ATTENTION))
1618 break;
1619
1620 printk(KERN_WARNING "cciss%d: Waiting %d secs "
1621 "for device to become ready.\n",
1622 h->ctlr, waittime / HZ);
1623 rc = 1; /* device not ready. */
1624 }
1625
1626 if (rc)
1627 printk("cciss%d: giving up on device.\n", h->ctlr);
1628 else
1629 printk(KERN_WARNING "cciss%d: device is ready.\n", h->ctlr);
1630
1631 cmd_free(h, c, 1);
1632 return rc;
1633}
Mike Miller89b6e742008-02-21 08:54:03 +01001634
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001635/* Need at least one of these error handlers to keep ../scsi/hosts.c from
1636 * complaining. Doing a host- or bus-reset can't do anything good here.
1637 * Despite what it might say in scsi_error.c, there may well be commands
1638 * on the controller, as the cciss driver registers twice, once as a block
1639 * device for the logical drives, and once as a scsi device, for any tape
1640 * drives. So we know there are no commands out on the tape drives, but we
1641 * don't know there are no commands on the controller, and it is likely
1642 * that there probably are, as the cciss block device is most commonly used
1643 * as a boot device (embedded controller on HP/Compaq systems.)
1644*/
1645
1646static int cciss_eh_device_reset_handler(struct scsi_cmnd *scsicmd)
1647{
1648 int rc;
1649 CommandList_struct *cmd_in_trouble;
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001650 unsigned char lunaddr[8];
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001651 ctlr_info_t **c;
1652 int ctlr;
1653
1654 /* find the controller to which the command to be aborted was sent */
1655 c = (ctlr_info_t **) &scsicmd->device->host->hostdata[0];
1656 if (c == NULL) /* paranoia */
1657 return FAILED;
1658 ctlr = (*c)->ctlr;
1659 printk(KERN_WARNING "cciss%d: resetting tape drive or medium changer.\n", ctlr);
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001660 /* find the command that's giving us trouble */
1661 cmd_in_trouble = (CommandList_struct *) scsicmd->host_scribble;
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001662 if (cmd_in_trouble == NULL) /* paranoia */
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001663 return FAILED;
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001664 memcpy(lunaddr, &cmd_in_trouble->Header.LUN.LunAddrBytes[0], 8);
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001665 /* send a reset to the SCSI LUN which the command was sent to */
scameron@beardog.cca.cpqcorp.netb57695f2009-06-08 16:02:17 -05001666 rc = sendcmd(CCISS_RESET_MSG, ctlr, NULL, 0, 0, lunaddr,
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001667 TYPE_MSG);
Joe Perchesf66083c2008-02-03 17:09:38 +02001668 /* sendcmd turned off interrupts on the board, turn 'em back on. */
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001669 (*c)->access.set_intr_mask(*c, CCISS_INTR_ON);
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001670 if (rc == 0 && wait_for_device_to_become_ready(*c, lunaddr) == 0)
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001671 return SUCCESS;
1672 printk(KERN_WARNING "cciss%d: resetting device failed.\n", ctlr);
1673 return FAILED;
1674}
1675
1676static int cciss_eh_abort_handler(struct scsi_cmnd *scsicmd)
1677{
1678 int rc;
1679 CommandList_struct *cmd_to_abort;
1680 ctlr_info_t **c;
1681 int ctlr;
1682
1683 /* find the controller to which the command to be aborted was sent */
1684 c = (ctlr_info_t **) &scsicmd->device->host->hostdata[0];
1685 if (c == NULL) /* paranoia */
1686 return FAILED;
1687 ctlr = (*c)->ctlr;
1688 printk(KERN_WARNING "cciss%d: aborting tardy SCSI cmd\n", ctlr);
1689
1690 /* find the command to be aborted */
1691 cmd_to_abort = (CommandList_struct *) scsicmd->host_scribble;
1692 if (cmd_to_abort == NULL) /* paranoia */
1693 return FAILED;
scameron@beardog.cca.cpqcorp.netb57695f2009-06-08 16:02:17 -05001694 rc = sendcmd(CCISS_ABORT_MSG, ctlr, &cmd_to_abort->Header.Tag, 0, 0,
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001695 (unsigned char *) &cmd_to_abort->Header.LUN.LunAddrBytes[0],
1696 TYPE_MSG);
Joe Perchesf66083c2008-02-03 17:09:38 +02001697 /* sendcmd turned off interrupts on the board, turn 'em back on. */
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001698 (*c)->access.set_intr_mask(*c, CCISS_INTR_ON);
1699 if (rc == 0)
1700 return SUCCESS;
1701 return FAILED;
1702
1703}
1704
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705#else /* no CONFIG_CISS_SCSI_TAPE */
1706
1707/* If no tape support, then these become defined out of existence */
1708
1709#define cciss_scsi_setup(cntl_num)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710
1711#endif /* CONFIG_CISS_SCSI_TAPE */