blob: 8fa2a2e90b9f423dfddd2437a5401d11736bcd5d [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. Cameron6b4d96b2010-07-19 13:46:43 -050052static CommandList_struct *cmd_alloc(ctlr_info_t *h);
53static CommandList_struct *cmd_special_alloc(ctlr_info_t *h);
54static void cmd_free(ctlr_info_t *h, CommandList_struct *c);
55static void cmd_special_free(ctlr_info_t *h, CommandList_struct *c);
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
Jeff Garzikf2812332010-11-16 02:10:29 -050065static int cciss_scsi_queue_command (struct Scsi_Host *h,
66 struct scsi_cmnd *cmd);
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,
Linus Torvalds1da177e2005-04-16 15:20:36 -070089 .cmd_per_lun = 1,
90 .use_clustering = DISABLE_CLUSTERING,
mike.miller@hp.com3da8b712005-11-04 12:30:37 -060091 /* Can't have eh_bus_reset_handler or eh_host_reset_handler for cciss */
92 .eh_device_reset_handler= cciss_eh_device_reset_handler,
93 .eh_abort_handler = cciss_eh_abort_handler,
Linus Torvalds1da177e2005-04-16 15:20:36 -070094};
95
96#pragma pack(1)
Stephen M. Cameron1b7d0d22010-02-26 16:01:17 -060097
Mike Miller5e216152010-06-02 12:58:06 -070098#define SCSI_PAD_32 8
99#define SCSI_PAD_64 8
Stephen M. Cameron1b7d0d22010-02-26 16:01:17 -0600100
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101struct cciss_scsi_cmd_stack_elem_t {
102 CommandList_struct cmd;
103 ErrorInfo_struct Err;
104 __u32 busaddr;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600105 int cmdindex;
Stephen M. Cameron1b7d0d22010-02-26 16:01:17 -0600106 u8 pad[IS_32_BIT * SCSI_PAD_32 + IS_64_BIT * SCSI_PAD_64];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107};
108
109#pragma pack()
110
111#define CMD_STACK_SIZE (SCSI_CCISS_CAN_QUEUE * \
112 CCISS_MAX_SCSI_DEVS_PER_HBA + 2)
113 // plus two for init time usage
114
115#pragma pack(1)
116struct cciss_scsi_cmd_stack_t {
117 struct cciss_scsi_cmd_stack_elem_t *pool;
118 struct cciss_scsi_cmd_stack_elem_t *elem[CMD_STACK_SIZE];
119 dma_addr_t cmd_pool_handle;
120 int top;
121};
122#pragma pack()
123
124struct cciss_scsi_adapter_data_t {
125 struct Scsi_Host *scsi_host;
126 struct cciss_scsi_cmd_stack_t cmd_stack;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600127 SGDescriptor_struct **cmd_sg_list;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 int registered;
129 spinlock_t lock; // to protect ccissscsi[ctlr];
130};
131
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500132#define CPQ_TAPE_LOCK(h, flags) spin_lock_irqsave( \
133 &h->scsi_ctlr->lock, flags);
134#define CPQ_TAPE_UNLOCK(h, flags) spin_unlock_irqrestore( \
135 &h->scsi_ctlr->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136
137static CommandList_struct *
138scsi_cmd_alloc(ctlr_info_t *h)
139{
140 /* assume only one process in here at a time, locking done by caller. */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500141 /* use h->lock */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 /* might be better to rewrite how we allocate scsi commands in a way that */
143 /* needs no locking at all. */
144
145 /* take the top memory chunk off the stack and return it, if any. */
146 struct cciss_scsi_cmd_stack_elem_t *c;
147 struct cciss_scsi_adapter_data_t *sa;
148 struct cciss_scsi_cmd_stack_t *stk;
149 u64bit temp64;
150
Stephen M. Cameronaad9fb62010-02-26 16:01:42 -0600151 sa = h->scsi_ctlr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 stk = &sa->cmd_stack;
153
154 if (stk->top < 0)
155 return NULL;
156 c = stk->elem[stk->top];
157 /* memset(c, 0, sizeof(*c)); */
158 memset(&c->cmd, 0, sizeof(c->cmd));
159 memset(&c->Err, 0, sizeof(c->Err));
160 /* set physical addr of cmd and addr of scsi parameters */
161 c->cmd.busaddr = c->busaddr;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600162 c->cmd.cmdindex = c->cmdindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163 /* (__u32) (stk->cmd_pool_handle +
164 (sizeof(struct cciss_scsi_cmd_stack_elem_t)*stk->top)); */
165
166 temp64.val = (__u64) (c->busaddr + sizeof(CommandList_struct));
167 /* (__u64) (stk->cmd_pool_handle +
168 (sizeof(struct cciss_scsi_cmd_stack_elem_t)*stk->top) +
169 sizeof(CommandList_struct)); */
170 stk->top--;
171 c->cmd.ErrDesc.Addr.lower = temp64.val32.lower;
172 c->cmd.ErrDesc.Addr.upper = temp64.val32.upper;
173 c->cmd.ErrDesc.Len = sizeof(ErrorInfo_struct);
174
175 c->cmd.ctlr = h->ctlr;
176 c->cmd.err_info = &c->Err;
177
178 return (CommandList_struct *) c;
179}
180
181static void
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500182scsi_cmd_free(ctlr_info_t *h, CommandList_struct *c)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183{
184 /* assume only one process in here at a time, locking done by caller. */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500185 /* use h->lock */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700186 /* drop the free memory chunk on top of the stack. */
187
188 struct cciss_scsi_adapter_data_t *sa;
189 struct cciss_scsi_cmd_stack_t *stk;
190
Stephen M. Cameronaad9fb62010-02-26 16:01:42 -0600191 sa = h->scsi_ctlr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 stk = &sa->cmd_stack;
Dan Carpenter713b6862010-06-01 12:17:48 +0200193 stk->top++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 if (stk->top >= CMD_STACK_SIZE) {
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500195 dev_err(&h->pdev->dev,
196 "scsi_cmd_free called too many times.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197 BUG();
198 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500199 stk->elem[stk->top] = (struct cciss_scsi_cmd_stack_elem_t *) c;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200}
201
202static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500203scsi_cmd_stack_setup(ctlr_info_t *h, struct cciss_scsi_adapter_data_t *sa)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204{
205 int i;
206 struct cciss_scsi_cmd_stack_t *stk;
207 size_t size;
208
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500209 sa->cmd_sg_list = cciss_allocate_sg_chain_blocks(h,
210 h->chainsize, CMD_STACK_SIZE);
211 if (!sa->cmd_sg_list && h->chainsize > 0)
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600212 return -ENOMEM;
213
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 stk = &sa->cmd_stack;
215 size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE;
216
Stephen M. Cameron1b7d0d22010-02-26 16:01:17 -0600217 /* Check alignment, see cciss_cmd.h near CommandList_struct def. */
218 BUILD_BUG_ON((sizeof(*stk->pool) % COMMANDLIST_ALIGNMENT) != 0);
219 /* pci_alloc_consistent guarantees 32-bit DMA address will be used */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 stk->pool = (struct cciss_scsi_cmd_stack_elem_t *)
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500221 pci_alloc_consistent(h->pdev, size, &stk->cmd_pool_handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222
223 if (stk->pool == NULL) {
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600224 cciss_free_sg_chain_blocks(sa->cmd_sg_list, CMD_STACK_SIZE);
225 sa->cmd_sg_list = NULL;
226 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 }
228
Stephen M. Cameron978eb512011-03-11 20:07:38 +0100229 stk->elem = kmalloc(sizeof(stk->elem[0]) * stk->nelems, GFP_KERNEL);
230 if (!stk->elem) {
231 pci_free_consistent(h->pdev, size, stk->pool,
232 stk->cmd_pool_handle);
233 return -1;
234 }
235
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 for (i=0; i<CMD_STACK_SIZE; i++) {
237 stk->elem[i] = &stk->pool[i];
238 stk->elem[i]->busaddr = (__u32) (stk->cmd_pool_handle +
239 (sizeof(struct cciss_scsi_cmd_stack_elem_t) * i));
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600240 stk->elem[i]->cmdindex = i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 }
242 stk->top = CMD_STACK_SIZE-1;
243 return 0;
244}
245
246static void
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500247scsi_cmd_stack_free(ctlr_info_t *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248{
249 struct cciss_scsi_adapter_data_t *sa;
250 struct cciss_scsi_cmd_stack_t *stk;
251 size_t size;
252
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500253 sa = h->scsi_ctlr;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 stk = &sa->cmd_stack;
255 if (stk->top != CMD_STACK_SIZE-1) {
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500256 dev_warn(&h->pdev->dev,
257 "bug: %d scsi commands are still outstanding.\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 CMD_STACK_SIZE - stk->top);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 }
260 size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE;
261
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500262 pci_free_consistent(h->pdev, size, stk->pool, stk->cmd_pool_handle);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 stk->pool = NULL;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -0600264 cciss_free_sg_chain_blocks(sa->cmd_sg_list, CMD_STACK_SIZE);
Stephen M. Cameron978eb512011-03-11 20:07:38 +0100265 kfree(stk->elem);
266 stk->elem = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267}
268
Grant Coady400bb232005-11-15 00:09:20 -0800269#if 0
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270static int xmargin=8;
271static int amargin=60;
272
273static void
274print_bytes (unsigned char *c, int len, int hex, int ascii)
275{
276
277 int i;
278 unsigned char *x;
279
280 if (hex)
281 {
282 x = c;
283 for (i=0;i<len;i++)
284 {
285 if ((i % xmargin) == 0 && i>0) printk("\n");
286 if ((i % xmargin) == 0) printk("0x%04x:", i);
287 printk(" %02x", *x);
288 x++;
289 }
290 printk("\n");
291 }
292 if (ascii)
293 {
294 x = c;
295 for (i=0;i<len;i++)
296 {
297 if ((i % amargin) == 0 && i>0) printk("\n");
298 if ((i % amargin) == 0) printk("0x%04x:", i);
299 if (*x > 26 && *x < 128) printk("%c", *x);
300 else printk(".");
301 x++;
302 }
303 printk("\n");
304 }
305}
306
307static void
308print_cmd(CommandList_struct *cp)
309{
310 printk("queue:%d\n", cp->Header.ReplyQueue);
311 printk("sglist:%d\n", cp->Header.SGList);
312 printk("sgtot:%d\n", cp->Header.SGTotal);
313 printk("Tag:0x%08x/0x%08x\n", cp->Header.Tag.upper,
314 cp->Header.Tag.lower);
315 printk("LUN:0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
316 cp->Header.LUN.LunAddrBytes[0],
317 cp->Header.LUN.LunAddrBytes[1],
318 cp->Header.LUN.LunAddrBytes[2],
319 cp->Header.LUN.LunAddrBytes[3],
320 cp->Header.LUN.LunAddrBytes[4],
321 cp->Header.LUN.LunAddrBytes[5],
322 cp->Header.LUN.LunAddrBytes[6],
323 cp->Header.LUN.LunAddrBytes[7]);
324 printk("CDBLen:%d\n", cp->Request.CDBLen);
325 printk("Type:%d\n",cp->Request.Type.Type);
326 printk("Attr:%d\n",cp->Request.Type.Attribute);
327 printk(" Dir:%d\n",cp->Request.Type.Direction);
328 printk("Timeout:%d\n",cp->Request.Timeout);
329 printk( "CDB: %02x %02x %02x %02x %02x %02x %02x %02x"
330 " %02x %02x %02x %02x %02x %02x %02x %02x\n",
331 cp->Request.CDB[0], cp->Request.CDB[1],
332 cp->Request.CDB[2], cp->Request.CDB[3],
333 cp->Request.CDB[4], cp->Request.CDB[5],
334 cp->Request.CDB[6], cp->Request.CDB[7],
335 cp->Request.CDB[8], cp->Request.CDB[9],
336 cp->Request.CDB[10], cp->Request.CDB[11],
337 cp->Request.CDB[12], cp->Request.CDB[13],
338 cp->Request.CDB[14], cp->Request.CDB[15]),
339 printk("edesc.Addr: 0x%08x/0%08x, Len = %d\n",
340 cp->ErrDesc.Addr.upper, cp->ErrDesc.Addr.lower,
341 cp->ErrDesc.Len);
342 printk("sgs..........Errorinfo:\n");
343 printk("scsistatus:%d\n", cp->err_info->ScsiStatus);
344 printk("senselen:%d\n", cp->err_info->SenseLen);
345 printk("cmd status:%d\n", cp->err_info->CommandStatus);
346 printk("resid cnt:%d\n", cp->err_info->ResidualCnt);
347 printk("offense size:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_size);
348 printk("offense byte:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_num);
349 printk("offense value:%d\n", cp->err_info->MoreErrInfo.Invalid_Cmd.offense_value);
350
351}
352
353#endif
354
355static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500356find_bus_target_lun(ctlr_info_t *h, int *bus, int *target, int *lun)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357{
358 /* finds an unused bus, target, lun for a new device */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500359 /* assumes h->scsi_ctlr->lock is held */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 int i, found=0;
361 unsigned char target_taken[CCISS_MAX_SCSI_DEVS_PER_HBA];
362
363 memset(&target_taken[0], 0, CCISS_MAX_SCSI_DEVS_PER_HBA);
364
365 target_taken[SELF_SCSI_ID] = 1;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500366 for (i = 0; i < ccissscsi[h->ctlr].ndevices; i++)
367 target_taken[ccissscsi[h->ctlr].dev[i].target] = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500369 for (i = 0; i < CCISS_MAX_SCSI_DEVS_PER_HBA; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 if (!target_taken[i]) {
371 *bus = 0; *target=i; *lun = 0; found=1;
372 break;
373 }
374 }
375 return (!found);
376}
Mike Millerf4a93bc2008-08-04 11:54:53 +0200377struct scsi2map {
378 char scsi3addr[8];
379 int bus, target, lun;
380};
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381
382static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500383cciss_scsi_add_entry(ctlr_info_t *h, int hostno,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700384 struct cciss_scsi_dev_t *device,
Mike Millerf4a93bc2008-08-04 11:54:53 +0200385 struct scsi2map *added, int *nadded)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386{
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500387 /* assumes h->scsi_ctlr->lock is held */
388 int n = ccissscsi[h->ctlr].ndevices;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 struct cciss_scsi_dev_t *sd;
Mike Miller935dc8d2008-08-04 11:54:54 +0200390 int i, bus, target, lun;
391 unsigned char addr1[8], addr2[8];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392
393 if (n >= CCISS_MAX_SCSI_DEVS_PER_HBA) {
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500394 dev_warn(&h->pdev->dev, "Too many devices, "
395 "some will be inaccessible.\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 return -1;
397 }
Mike Millerf4a93bc2008-08-04 11:54:53 +0200398
Mike Miller935dc8d2008-08-04 11:54:54 +0200399 bus = target = -1;
400 lun = 0;
401 /* Is this device a non-zero lun of a multi-lun device */
402 /* byte 4 of the 8-byte LUN addr will contain the logical unit no. */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700403 if (device->scsi3addr[4] != 0) {
Mike Miller935dc8d2008-08-04 11:54:54 +0200404 /* Search through our list and find the device which */
405 /* has the same 8 byte LUN address, excepting byte 4. */
406 /* Assign the same bus and target for this new LUN. */
407 /* Use the logical unit number from the firmware. */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700408 memcpy(addr1, device->scsi3addr, 8);
Mike Miller935dc8d2008-08-04 11:54:54 +0200409 addr1[4] = 0;
410 for (i = 0; i < n; i++) {
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500411 sd = &ccissscsi[h->ctlr].dev[i];
Mike Miller935dc8d2008-08-04 11:54:54 +0200412 memcpy(addr2, sd->scsi3addr, 8);
413 addr2[4] = 0;
414 /* differ only in byte 4? */
415 if (memcmp(addr1, addr2, 8) == 0) {
416 bus = sd->bus;
417 target = sd->target;
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700418 lun = device->scsi3addr[4];
Mike Miller935dc8d2008-08-04 11:54:54 +0200419 break;
420 }
421 }
422 }
423
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500424 sd = &ccissscsi[h->ctlr].dev[n];
Mike Miller935dc8d2008-08-04 11:54:54 +0200425 if (lun == 0) {
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500426 if (find_bus_target_lun(h,
Mike Miller935dc8d2008-08-04 11:54:54 +0200427 &sd->bus, &sd->target, &sd->lun) != 0)
428 return -1;
429 } else {
430 sd->bus = bus;
431 sd->target = target;
432 sd->lun = lun;
433 }
Mike Millerf4a93bc2008-08-04 11:54:53 +0200434 added[*nadded].bus = sd->bus;
435 added[*nadded].target = sd->target;
436 added[*nadded].lun = sd->lun;
437 (*nadded)++;
438
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700439 memcpy(sd->scsi3addr, device->scsi3addr, 8);
440 memcpy(sd->vendor, device->vendor, sizeof(sd->vendor));
441 memcpy(sd->revision, device->revision, sizeof(sd->revision));
442 memcpy(sd->device_id, device->device_id, sizeof(sd->device_id));
443 sd->devtype = device->devtype;
444
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500445 ccissscsi[h->ctlr].ndevices++;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446
447 /* initially, (before registering with scsi layer) we don't
448 know our hostno and we don't want to print anything first
449 time anyway (the scsi layer's inquiries will show that info) */
450 if (hostno != -1)
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500451 dev_info(&h->pdev->dev, "%s device c%db%dt%dl%d added.\n",
452 scsi_device_type(sd->devtype), hostno,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 sd->bus, sd->target, sd->lun);
454 return 0;
455}
456
457static void
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500458cciss_scsi_remove_entry(ctlr_info_t *h, int hostno, int entry,
Mike Millerf4a93bc2008-08-04 11:54:53 +0200459 struct scsi2map *removed, int *nremoved)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460{
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500461 /* assumes h->ctlr]->scsi_ctlr->lock is held */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 int i;
463 struct cciss_scsi_dev_t sd;
464
465 if (entry < 0 || entry >= CCISS_MAX_SCSI_DEVS_PER_HBA) return;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500466 sd = ccissscsi[h->ctlr].dev[entry];
Mike Millerf4a93bc2008-08-04 11:54:53 +0200467 removed[*nremoved].bus = sd.bus;
468 removed[*nremoved].target = sd.target;
469 removed[*nremoved].lun = sd.lun;
470 (*nremoved)++;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500471 for (i = entry; i < ccissscsi[h->ctlr].ndevices-1; i++)
472 ccissscsi[h->ctlr].dev[i] = ccissscsi[h->ctlr].dev[i+1];
473 ccissscsi[h->ctlr].ndevices--;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500474 dev_info(&h->pdev->dev, "%s device c%db%dt%dl%d removed.\n",
475 scsi_device_type(sd.devtype), hostno,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 sd.bus, sd.target, sd.lun);
477}
478
479
480#define SCSI3ADDR_EQ(a,b) ( \
481 (a)[7] == (b)[7] && \
482 (a)[6] == (b)[6] && \
483 (a)[5] == (b)[5] && \
484 (a)[4] == (b)[4] && \
485 (a)[3] == (b)[3] && \
486 (a)[2] == (b)[2] && \
487 (a)[1] == (b)[1] && \
488 (a)[0] == (b)[0])
489
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500490static void fixup_botched_add(ctlr_info_t *h, char *scsi3addr)
Mike Millerf4a93bc2008-08-04 11:54:53 +0200491{
492 /* called when scsi_add_device fails in order to re-adjust */
493 /* ccissscsi[] to match the mid layer's view. */
494 unsigned long flags;
495 int i, j;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500496 CPQ_TAPE_LOCK(h, flags);
497 for (i = 0; i < ccissscsi[h->ctlr].ndevices; i++) {
Mike Millerf4a93bc2008-08-04 11:54:53 +0200498 if (memcmp(scsi3addr,
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500499 ccissscsi[h->ctlr].dev[i].scsi3addr, 8) == 0) {
500 for (j = i; j < ccissscsi[h->ctlr].ndevices-1; j++)
501 ccissscsi[h->ctlr].dev[j] =
502 ccissscsi[h->ctlr].dev[j+1];
503 ccissscsi[h->ctlr].ndevices--;
Mike Millerf4a93bc2008-08-04 11:54:53 +0200504 break;
505 }
506 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500507 CPQ_TAPE_UNLOCK(h, flags);
Mike Millerf4a93bc2008-08-04 11:54:53 +0200508}
509
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700510static int device_is_the_same(struct cciss_scsi_dev_t *dev1,
511 struct cciss_scsi_dev_t *dev2)
512{
513 return dev1->devtype == dev2->devtype &&
514 memcmp(dev1->scsi3addr, dev2->scsi3addr,
515 sizeof(dev1->scsi3addr)) == 0 &&
516 memcmp(dev1->device_id, dev2->device_id,
517 sizeof(dev1->device_id)) == 0 &&
518 memcmp(dev1->vendor, dev2->vendor,
519 sizeof(dev1->vendor)) == 0 &&
520 memcmp(dev1->model, dev2->model,
521 sizeof(dev1->model)) == 0 &&
522 memcmp(dev1->revision, dev2->revision,
523 sizeof(dev1->revision)) == 0;
524}
525
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500527adjust_cciss_scsi_table(ctlr_info_t *h, int hostno,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 struct cciss_scsi_dev_t sd[], int nsds)
529{
530 /* sd contains scsi3 addresses and devtypes, but
531 bus target and lun are not filled in. This funciton
532 takes what's in sd to be the current and adjusts
533 ccissscsi[] to be in line with what's in sd. */
534
535 int i,j, found, changes=0;
536 struct cciss_scsi_dev_t *csd;
537 unsigned long flags;
Mike Millerf4a93bc2008-08-04 11:54:53 +0200538 struct scsi2map *added, *removed;
539 int nadded, nremoved;
540 struct Scsi_Host *sh = NULL;
541
542 added = kzalloc(sizeof(*added) * CCISS_MAX_SCSI_DEVS_PER_HBA,
543 GFP_KERNEL);
544 removed = kzalloc(sizeof(*removed) * CCISS_MAX_SCSI_DEVS_PER_HBA,
545 GFP_KERNEL);
546
547 if (!added || !removed) {
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500548 dev_warn(&h->pdev->dev,
549 "Out of memory in adjust_cciss_scsi_table\n");
Mike Millerf4a93bc2008-08-04 11:54:53 +0200550 goto free_and_out;
551 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500553 CPQ_TAPE_LOCK(h, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554
Mike Millerf4a93bc2008-08-04 11:54:53 +0200555 if (hostno != -1) /* if it's not the first time... */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500556 sh = h->scsi_ctlr->scsi_host;
Mike Millerf4a93bc2008-08-04 11:54:53 +0200557
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558 /* find any devices in ccissscsi[] that are not in
559 sd[] and remove them from ccissscsi[] */
560
561 i = 0;
Mike Millerf4a93bc2008-08-04 11:54:53 +0200562 nremoved = 0;
563 nadded = 0;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500564 while (i < ccissscsi[h->ctlr].ndevices) {
565 csd = &ccissscsi[h->ctlr].dev[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 found=0;
567 for (j=0;j<nsds;j++) {
568 if (SCSI3ADDR_EQ(sd[j].scsi3addr,
569 csd->scsi3addr)) {
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700570 if (device_is_the_same(&sd[j], csd))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 found=2;
572 else
573 found=1;
574 break;
575 }
576 }
577
578 if (found == 0) { /* device no longer present. */
579 changes++;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500580 cciss_scsi_remove_entry(h, hostno, i,
Mike Millerf4a93bc2008-08-04 11:54:53 +0200581 removed, &nremoved);
582 /* remove ^^^, hence i not incremented */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700583 } else if (found == 1) { /* device is different in some way */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584 changes++;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500585 dev_info(&h->pdev->dev,
586 "device c%db%dt%dl%d has changed.\n",
587 hostno, csd->bus, csd->target, csd->lun);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500588 cciss_scsi_remove_entry(h, hostno, i,
Mike Millerf4a93bc2008-08-04 11:54:53 +0200589 removed, &nremoved);
590 /* remove ^^^, hence i not incremented */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500591 if (cciss_scsi_add_entry(h, hostno, &sd[j],
Mike Millerf4a93bc2008-08-04 11:54:53 +0200592 added, &nadded) != 0)
593 /* we just removed one, so add can't fail. */
594 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 csd->devtype = sd[j].devtype;
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700596 memcpy(csd->device_id, sd[j].device_id,
597 sizeof(csd->device_id));
598 memcpy(csd->vendor, sd[j].vendor,
599 sizeof(csd->vendor));
600 memcpy(csd->model, sd[j].model,
601 sizeof(csd->model));
602 memcpy(csd->revision, sd[j].revision,
603 sizeof(csd->revision));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 } else /* device is same as it ever was, */
605 i++; /* so just move along. */
606 }
607
608 /* Now, make sure every device listed in sd[] is also
609 listed in ccissscsi[], adding them if they aren't found */
610
611 for (i=0;i<nsds;i++) {
612 found=0;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500613 for (j = 0; j < ccissscsi[h->ctlr].ndevices; j++) {
614 csd = &ccissscsi[h->ctlr].dev[j];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 if (SCSI3ADDR_EQ(sd[i].scsi3addr,
616 csd->scsi3addr)) {
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -0700617 if (device_is_the_same(&sd[i], csd))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 found=2; /* found device */
619 else
620 found=1; /* found a bug. */
621 break;
622 }
623 }
624 if (!found) {
625 changes++;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500626 if (cciss_scsi_add_entry(h, hostno, &sd[i],
Mike Millerf4a93bc2008-08-04 11:54:53 +0200627 added, &nadded) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 break;
629 } else if (found == 1) {
630 /* should never happen... */
631 changes++;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500632 dev_warn(&h->pdev->dev,
633 "device unexpectedly changed\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 /* but if it does happen, we just ignore that device */
635 }
636 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500637 CPQ_TAPE_UNLOCK(h, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638
Mike Millerf4a93bc2008-08-04 11:54:53 +0200639 /* Don't notify scsi mid layer of any changes the first time through */
640 /* (or if there are no changes) scsi_scan_host will do it later the */
641 /* first time through. */
642 if (hostno == -1 || !changes)
643 goto free_and_out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644
Mike Millerf4a93bc2008-08-04 11:54:53 +0200645 /* Notify scsi mid layer of any removed devices */
646 for (i = 0; i < nremoved; i++) {
647 struct scsi_device *sdev =
648 scsi_device_lookup(sh, removed[i].bus,
649 removed[i].target, removed[i].lun);
650 if (sdev != NULL) {
651 scsi_remove_device(sdev);
652 scsi_device_put(sdev);
653 } else {
654 /* We don't expect to get here. */
655 /* future cmds to this device will get selection */
656 /* timeout as if the device was gone. */
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500657 dev_warn(&h->pdev->dev, "didn't find "
Mike Millerf4a93bc2008-08-04 11:54:53 +0200658 "c%db%dt%dl%d\n for removal.",
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500659 hostno, removed[i].bus,
Mike Millerf4a93bc2008-08-04 11:54:53 +0200660 removed[i].target, removed[i].lun);
661 }
662 }
663
664 /* Notify scsi mid layer of any added devices */
665 for (i = 0; i < nadded; i++) {
666 int rc;
667 rc = scsi_add_device(sh, added[i].bus,
668 added[i].target, added[i].lun);
669 if (rc == 0)
670 continue;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500671 dev_warn(&h->pdev->dev, "scsi_add_device "
Mike Millerf4a93bc2008-08-04 11:54:53 +0200672 "c%db%dt%dl%d failed, device not added.\n",
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500673 hostno, added[i].bus, added[i].target, added[i].lun);
Mike Millerf4a93bc2008-08-04 11:54:53 +0200674 /* now we have to remove it from ccissscsi, */
675 /* since it didn't get added to scsi mid layer */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500676 fixup_botched_add(h, added[i].scsi3addr);
Mike Millerf4a93bc2008-08-04 11:54:53 +0200677 }
678
679free_and_out:
680 kfree(added);
681 kfree(removed);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 return 0;
683}
684
685static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500686lookup_scsi3addr(ctlr_info_t *h, int bus, int target, int lun, char *scsi3addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687{
688 int i;
689 struct cciss_scsi_dev_t *sd;
690 unsigned long flags;
691
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500692 CPQ_TAPE_LOCK(h, flags);
693 for (i = 0; i < ccissscsi[h->ctlr].ndevices; i++) {
694 sd = &ccissscsi[h->ctlr].dev[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695 if (sd->bus == bus &&
696 sd->target == target &&
697 sd->lun == lun) {
698 memcpy(scsi3addr, &sd->scsi3addr[0], 8);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500699 CPQ_TAPE_UNLOCK(h, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 return 0;
701 }
702 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500703 CPQ_TAPE_UNLOCK(h, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 return -1;
705}
706
707static void
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500708cciss_scsi_setup(ctlr_info_t *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709{
710 struct cciss_scsi_adapter_data_t * shba;
711
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500712 ccissscsi[h->ctlr].ndevices = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 shba = (struct cciss_scsi_adapter_data_t *)
714 kmalloc(sizeof(*shba), GFP_KERNEL);
715 if (shba == NULL)
716 return;
717 shba->scsi_host = NULL;
718 spin_lock_init(&shba->lock);
719 shba->registered = 0;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500720 if (scsi_cmd_stack_setup(h, shba) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 kfree(shba);
722 shba = NULL;
723 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500724 h->scsi_ctlr = shba;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 return;
726}
727
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500728static void complete_scsi_command(CommandList_struct *c, int timeout,
729 __u32 tag)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730{
731 struct scsi_cmnd *cmd;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500732 ctlr_info_t *h;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 ErrorInfo_struct *ei;
734
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500735 ei = c->err_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736
737 /* First, see if it was a message rather than a command */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500738 if (c->Request.Type.Type == TYPE_MSG) {
739 c->cmd_type = CMD_MSG_DONE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 return;
741 }
742
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500743 cmd = (struct scsi_cmnd *) c->scsi_cmd;
744 h = hba[c->ctlr];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745
FUJITA Tomonori41ce6392007-05-26 02:45:17 +0900746 scsi_dma_unmap(cmd);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500747 if (c->Header.SGTotal > h->max_cmd_sgentries)
748 cciss_unmap_sg_chain_block(h, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749
750 cmd->result = (DID_OK << 16); /* host byte */
751 cmd->result |= (COMMAND_COMPLETE << 8); /* msg byte */
752 /* cmd->result |= (GOOD < 1); */ /* status byte */
753
754 cmd->result |= (ei->ScsiStatus);
755 /* printk("Scsistatus is 0x%02x\n", ei->ScsiStatus); */
756
757 /* copy the sense data whether we need to or not. */
758
759 memcpy(cmd->sense_buffer, ei->SenseInfo,
760 ei->SenseLen > SCSI_SENSE_BUFFERSIZE ?
761 SCSI_SENSE_BUFFERSIZE :
762 ei->SenseLen);
FUJITA Tomonori41ce6392007-05-26 02:45:17 +0900763 scsi_set_resid(cmd, ei->ResidualCnt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764
765 if(ei->CommandStatus != 0)
766 { /* an error has occurred */
767 switch(ei->CommandStatus)
768 {
769 case CMD_TARGET_STATUS:
770 /* Pass it up to the upper layers... */
771 if( ei->ScsiStatus)
772 {
773#if 0
774 printk(KERN_WARNING "cciss: cmd %p "
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500775 "has SCSI Status = %x\n",
776 c, ei->ScsiStatus);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777#endif
Stephen M. Cameronb0e15f62009-11-12 12:49:45 -0600778 cmd->result |= (ei->ScsiStatus << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 }
780 else { /* scsi status is zero??? How??? */
781
782 /* Ordinarily, this case should never happen, but there is a bug
783 in some released firmware revisions that allows it to happen
784 if, for example, a 4100 backplane loses power and the tape
785 drive is in it. We assume that it's a fatal error of some
786 kind because we can't show that it wasn't. We will make it
787 look like selection timeout since that is the most common
788 reason for this to occur, and it's severe enough. */
789
790 cmd->result = DID_NO_CONNECT << 16;
791 }
792 break;
793 case CMD_DATA_UNDERRUN: /* let mid layer handle it. */
794 break;
795 case CMD_DATA_OVERRUN:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500796 dev_warn(&h->pdev->dev, "%p has"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 " completed with data overrun "
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500798 "reported\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 break;
800 case CMD_INVALID: {
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500801 /* print_bytes(c, sizeof(*c), 1, 0);
802 print_cmd(c); */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 /* We get CMD_INVALID if you address a non-existent tape drive instead
804 of a selection timeout (no response). You will see this if you yank
805 out a tape drive, then try to access it. This is kind of a shame
806 because it means that any other CMD_INVALID (e.g. driver bug) will
807 get interpreted as a missing target. */
808 cmd->result = DID_NO_CONNECT << 16;
809 }
810 break;
811 case CMD_PROTOCOL_ERR:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500812 dev_warn(&h->pdev->dev,
813 "%p has protocol error\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 break;
815 case CMD_HARDWARE_ERR:
816 cmd->result = DID_ERROR << 16;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500817 dev_warn(&h->pdev->dev,
818 "%p had hardware error\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 break;
820 case CMD_CONNECTION_LOST:
821 cmd->result = DID_ERROR << 16;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500822 dev_warn(&h->pdev->dev,
823 "%p had connection lost\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 break;
825 case CMD_ABORTED:
826 cmd->result = DID_ABORT << 16;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500827 dev_warn(&h->pdev->dev, "%p was aborted\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 break;
829 case CMD_ABORT_FAILED:
830 cmd->result = DID_ERROR << 16;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500831 dev_warn(&h->pdev->dev,
832 "%p reports abort failed\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 break;
834 case CMD_UNSOLICITED_ABORT:
835 cmd->result = DID_ABORT << 16;
Stephen M. Cameron6d9a4f92011-03-12 10:02:30 +0100836 dev_warn(&h->pdev->dev, "%p aborted due to an "
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500837 "unsolicited abort\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 break;
839 case CMD_TIMEOUT:
840 cmd->result = DID_TIME_OUT << 16;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500841 dev_warn(&h->pdev->dev, "%p timedout\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 break;
Stephen M. Cameron6d9a4f92011-03-12 10:02:30 +0100843 case CMD_UNABORTABLE:
844 cmd->result = DID_ERROR << 16;
845 dev_warn(&h->pdev->dev, "c %p command "
846 "unabortable\n", c);
847 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 default:
849 cmd->result = DID_ERROR << 16;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500850 dev_warn(&h->pdev->dev,
851 "%p returned unknown status %x\n", c,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 ei->CommandStatus);
853 }
854 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 cmd->scsi_done(cmd);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500856 scsi_cmd_free(h, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857}
858
859static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500860cciss_scsi_detect(ctlr_info_t *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861{
862 struct Scsi_Host *sh;
863 int error;
864
865 sh = scsi_host_alloc(&cciss_driver_template, sizeof(struct ctlr_info *));
866 if (sh == NULL)
867 goto fail;
868 sh->io_port = 0; // good enough? FIXME,
869 sh->n_io_port = 0; // I don't think we use these two...
870 sh->this_id = SELF_SCSI_ID;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500871 sh->sg_tablesize = h->maxsgentries;
Stephen M. Cameron79600aa2010-06-15 08:12:34 +0200872 sh->max_cmd_len = MAX_COMMAND_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700873
874 ((struct cciss_scsi_adapter_data_t *)
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500875 h->scsi_ctlr)->scsi_host = sh;
876 sh->hostdata[0] = (unsigned long) h;
877 sh->irq = h->intr[SIMPLE_MODE_INT];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700878 sh->unique_id = sh->irq;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500879 error = scsi_add_host(sh, &h->pdev->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 if (error)
881 goto fail_host_put;
882 scsi_scan_host(sh);
883 return 1;
884
885 fail_host_put:
886 scsi_host_put(sh);
887 fail:
888 return 0;
889}
890
891static void
892cciss_unmap_one(struct pci_dev *pdev,
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500893 CommandList_struct *c,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 size_t buflen,
895 int data_direction)
896{
897 u64bit addr64;
898
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500899 addr64.val32.lower = c->SG[0].Addr.lower;
900 addr64.val32.upper = c->SG[0].Addr.upper;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 pci_unmap_single(pdev, (dma_addr_t) addr64.val, buflen, data_direction);
902}
903
904static void
905cciss_map_one(struct pci_dev *pdev,
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500906 CommandList_struct *c,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 unsigned char *buf,
908 size_t buflen,
909 int data_direction)
910{
911 __u64 addr64;
912
913 addr64 = (__u64) pci_map_single(pdev, buf, buflen, data_direction);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500914 c->SG[0].Addr.lower =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500916 c->SG[0].Addr.upper =
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500918 c->SG[0].Len = buflen;
919 c->Header.SGList = (__u8) 1; /* no. SGs contig in this cmd */
920 c->Header.SGTotal = (__u16) 1; /* total sgs in this cmd list */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921}
922
923static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500924cciss_scsi_do_simple_cmd(ctlr_info_t *h,
925 CommandList_struct *c,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 unsigned char *scsi3addr,
927 unsigned char *cdb,
928 unsigned char cdblen,
929 unsigned char *buf, int bufsize,
930 int direction)
931{
Peter Zijlstra6e9a4732006-09-30 23:28:10 -0700932 DECLARE_COMPLETION_ONSTACK(wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500934 c->cmd_type = CMD_IOCTL_PEND; /* treat this like an ioctl */
935 c->scsi_cmd = NULL;
936 c->Header.ReplyQueue = 0; /* unused in simple mode */
937 memcpy(&c->Header.LUN, scsi3addr, sizeof(c->Header.LUN));
938 c->Header.Tag.lower = c->busaddr; /* Use k. address of cmd as tag */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 // Fill in the request block...
940
941 /* printk("Using scsi3addr 0x%02x%0x2%0x2%0x2%0x2%0x2%0x2%0x2\n",
942 scsi3addr[0], scsi3addr[1], scsi3addr[2], scsi3addr[3],
943 scsi3addr[4], scsi3addr[5], scsi3addr[6], scsi3addr[7]); */
944
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500945 memset(c->Request.CDB, 0, sizeof(c->Request.CDB));
946 memcpy(c->Request.CDB, cdb, cdblen);
947 c->Request.Timeout = 0;
948 c->Request.CDBLen = cdblen;
949 c->Request.Type.Type = TYPE_CMD;
950 c->Request.Type.Attribute = ATTR_SIMPLE;
951 c->Request.Type.Direction = direction;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952
953 /* Fill in the SG list and do dma mapping */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500954 cciss_map_one(h->pdev, c, (unsigned char *) buf,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 bufsize, DMA_FROM_DEVICE);
956
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500957 c->waiting = &wait;
958 enqueue_cmd_and_start_io(h, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959 wait_for_completion(&wait);
960
961 /* undo the dma mapping */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500962 cciss_unmap_one(h->pdev, c, bufsize, DMA_FROM_DEVICE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 return(0);
964}
965
966static void
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500967cciss_scsi_interpret_error(ctlr_info_t *h, CommandList_struct *c)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968{
969 ErrorInfo_struct *ei;
970
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500971 ei = c->err_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 switch(ei->CommandStatus)
973 {
974 case CMD_TARGET_STATUS:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500975 dev_warn(&h->pdev->dev,
976 "cmd %p has completed with errors\n", c);
977 dev_warn(&h->pdev->dev,
978 "cmd %p has SCSI Status = %x\n",
979 c, ei->ScsiStatus);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 if (ei->ScsiStatus == 0)
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500981 dev_warn(&h->pdev->dev,
982 "SCSI status is abnormally zero. "
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 "(probably indicates selection timeout "
984 "reported incorrectly due to a known "
985 "firmware bug, circa July, 2001.)\n");
986 break;
987 case CMD_DATA_UNDERRUN: /* let mid layer handle it. */
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500988 dev_info(&h->pdev->dev, "UNDERRUN\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 break;
990 case CMD_DATA_OVERRUN:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500991 dev_warn(&h->pdev->dev, "%p has"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 " completed with data overrun "
Stephen M. Cameronf70dba82010-07-19 13:46:38 -0500993 "reported\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 break;
995 case CMD_INVALID: {
996 /* controller unfortunately reports SCSI passthru's */
997 /* to non-existent targets as invalid commands. */
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -0500998 dev_warn(&h->pdev->dev,
999 "%p is reported invalid (probably means "
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001000 "target device no longer present)\n", c);
1001 /* print_bytes((unsigned char *) c, sizeof(*c), 1, 0);
1002 print_cmd(c); */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 }
1004 break;
1005 case CMD_PROTOCOL_ERR:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001006 dev_warn(&h->pdev->dev, "%p has protocol error\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 break;
1008 case CMD_HARDWARE_ERR:
1009 /* cmd->result = DID_ERROR << 16; */
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001010 dev_warn(&h->pdev->dev, "%p had hardware error\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 break;
1012 case CMD_CONNECTION_LOST:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001013 dev_warn(&h->pdev->dev, "%p had connection lost\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 break;
1015 case CMD_ABORTED:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001016 dev_warn(&h->pdev->dev, "%p was aborted\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 break;
1018 case CMD_ABORT_FAILED:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001019 dev_warn(&h->pdev->dev,
1020 "%p reports abort failed\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 break;
1022 case CMD_UNSOLICITED_ABORT:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001023 dev_warn(&h->pdev->dev,
Stephen M. Cameron6d9a4f92011-03-12 10:02:30 +01001024 "%p aborted due to an unsolicited abort\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 break;
1026 case CMD_TIMEOUT:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001027 dev_warn(&h->pdev->dev, "%p timedout\n", c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 break;
Stephen M. Cameron6d9a4f92011-03-12 10:02:30 +01001029 case CMD_UNABORTABLE:
1030 dev_warn(&h->pdev->dev,
1031 "%p unabortable\n", c);
1032 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 default:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001034 dev_warn(&h->pdev->dev,
1035 "%p returned unknown status %x\n",
1036 c, ei->CommandStatus);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 }
1038}
1039
1040static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001041cciss_scsi_do_inquiry(ctlr_info_t *h, unsigned char *scsi3addr,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001042 unsigned char page, unsigned char *buf,
1043 unsigned char bufsize)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044{
1045 int rc;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001046 CommandList_struct *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 char cdb[6];
1048 ErrorInfo_struct *ei;
1049 unsigned long flags;
1050
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001051 spin_lock_irqsave(&h->lock, flags);
1052 c = scsi_cmd_alloc(h);
1053 spin_unlock_irqrestore(&h->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001055 if (c == NULL) { /* trouble... */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 printk("cmd_alloc returned NULL!\n");
1057 return -1;
1058 }
1059
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001060 ei = c->err_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061
1062 cdb[0] = CISS_INQUIRY;
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001063 cdb[1] = (page != 0);
1064 cdb[2] = page;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 cdb[3] = 0;
Mike Miller47922d02005-09-13 01:25:25 -07001066 cdb[4] = bufsize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 cdb[5] = 0;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001068 rc = cciss_scsi_do_simple_cmd(h, c, scsi3addr, cdb,
Mike Miller47922d02005-09-13 01:25:25 -07001069 6, buf, bufsize, XFER_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070
1071 if (rc != 0) return rc; /* something went wrong */
1072
1073 if (ei->CommandStatus != 0 &&
1074 ei->CommandStatus != CMD_DATA_UNDERRUN) {
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001075 cciss_scsi_interpret_error(h, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 rc = -1;
1077 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001078 spin_lock_irqsave(&h->lock, flags);
1079 scsi_cmd_free(h, c);
1080 spin_unlock_irqrestore(&h->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 return rc;
1082}
1083
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001084/* Get the device id from inquiry page 0x83 */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001085static int cciss_scsi_get_device_id(ctlr_info_t *h, unsigned char *scsi3addr,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001086 unsigned char *device_id, int buflen)
1087{
1088 int rc;
1089 unsigned char *buf;
1090
1091 if (buflen > 16)
1092 buflen = 16;
1093 buf = kzalloc(64, GFP_KERNEL);
1094 if (!buf)
1095 return -1;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001096 rc = cciss_scsi_do_inquiry(h, scsi3addr, 0x83, buf, 64);
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001097 if (rc == 0)
1098 memcpy(device_id, &buf[8], buflen);
1099 kfree(buf);
1100 return rc != 0;
1101}
1102
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001104cciss_scsi_do_report_phys_luns(ctlr_info_t *h,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105 ReportLunData_struct *buf, int bufsize)
1106{
1107 int rc;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001108 CommandList_struct *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 unsigned char cdb[12];
1110 unsigned char scsi3addr[8];
1111 ErrorInfo_struct *ei;
1112 unsigned long flags;
1113
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001114 spin_lock_irqsave(&h->lock, flags);
1115 c = scsi_cmd_alloc(h);
1116 spin_unlock_irqrestore(&h->lock, flags);
1117 if (c == NULL) { /* trouble... */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 printk("cmd_alloc returned NULL!\n");
1119 return -1;
1120 }
1121
1122 memset(&scsi3addr[0], 0, 8); /* address the controller */
1123 cdb[0] = CISS_REPORT_PHYS;
1124 cdb[1] = 0;
1125 cdb[2] = 0;
1126 cdb[3] = 0;
1127 cdb[4] = 0;
1128 cdb[5] = 0;
1129 cdb[6] = (bufsize >> 24) & 0xFF; //MSB
1130 cdb[7] = (bufsize >> 16) & 0xFF;
1131 cdb[8] = (bufsize >> 8) & 0xFF;
1132 cdb[9] = bufsize & 0xFF;
1133 cdb[10] = 0;
1134 cdb[11] = 0;
1135
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001136 rc = cciss_scsi_do_simple_cmd(h, c, scsi3addr,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 cdb, 12,
1138 (unsigned char *) buf,
1139 bufsize, XFER_READ);
1140
1141 if (rc != 0) return rc; /* something went wrong */
1142
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001143 ei = c->err_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 if (ei->CommandStatus != 0 &&
1145 ei->CommandStatus != CMD_DATA_UNDERRUN) {
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001146 cciss_scsi_interpret_error(h, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 rc = -1;
1148 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001149 spin_lock_irqsave(&h->lock, flags);
1150 scsi_cmd_free(h, c);
1151 spin_unlock_irqrestore(&h->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 return rc;
1153}
1154
1155static void
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001156cciss_update_non_disk_devices(ctlr_info_t *h, int hostno)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157{
1158 /* the idea here is we could get notified from /proc
1159 that some devices have changed, so we do a report
1160 physical luns cmd, and adjust our list of devices
1161 accordingly. (We can't rely on the scsi-mid layer just
1162 doing inquiries, because the "busses" that the scsi
1163 mid-layer probes are totally fabricated by this driver,
1164 so new devices wouldn't show up.
1165
1166 the scsi3addr's of devices won't change so long as the
1167 adapter is not reset. That means we can rescan and
1168 tell which devices we already know about, vs. new
1169 devices, vs. disappearing devices.
1170
1171 Also, if you yank out a tape drive, then put in a disk
1172 in it's place, (say, a configured volume from another
1173 array controller for instance) _don't_ poke this driver
1174 (so it thinks it's still a tape, but _do_ poke the scsi
1175 mid layer, so it does an inquiry... the scsi mid layer
1176 will see the physical disk. This would be bad. Need to
1177 think about how to prevent that. One idea would be to
1178 snoop all scsi responses and if an inquiry repsonse comes
1179 back that reports a disk, chuck it an return selection
1180 timeout instead and adjust our table... Not sure i like
1181 that though.
1182
1183 */
Mike Miller47922d02005-09-13 01:25:25 -07001184#define OBDR_TAPE_INQ_SIZE 49
1185#define OBDR_TAPE_SIG "$DR-10"
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 ReportLunData_struct *ld_buff;
Mike Miller47922d02005-09-13 01:25:25 -07001187 unsigned char *inq_buff;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 unsigned char scsi3addr[8];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 __u32 num_luns=0;
1190 unsigned char *ch;
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001191 struct cciss_scsi_dev_t *currentsd, *this_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 int ncurrent=0;
1193 int reportlunsize = sizeof(*ld_buff) + CISS_MAX_PHYS_LUN * 8;
1194 int i;
1195
Eric Sesterhenn06ff37f2006-03-08 11:21:52 +01001196 ld_buff = kzalloc(reportlunsize, GFP_KERNEL);
Mike Miller47922d02005-09-13 01:25:25 -07001197 inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001198 currentsd = kzalloc(sizeof(*currentsd) *
1199 (CCISS_MAX_SCSI_DEVS_PER_HBA+1), GFP_KERNEL);
1200 if (ld_buff == NULL || inq_buff == NULL || currentsd == NULL) {
1201 printk(KERN_ERR "cciss: out of memory\n");
1202 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 }
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001204 this_device = &currentsd[CCISS_MAX_SCSI_DEVS_PER_HBA];
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001205 if (cciss_scsi_do_report_phys_luns(h, ld_buff, reportlunsize) == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 ch = &ld_buff->LUNListLength[0];
1207 num_luns = ((ch[0]<<24) | (ch[1]<<16) | (ch[2]<<8) | ch[3]) / 8;
1208 if (num_luns > CISS_MAX_PHYS_LUN) {
1209 printk(KERN_WARNING
1210 "cciss: Maximum physical LUNs (%d) exceeded. "
1211 "%d LUNs ignored.\n", CISS_MAX_PHYS_LUN,
1212 num_luns - CISS_MAX_PHYS_LUN);
1213 num_luns = CISS_MAX_PHYS_LUN;
1214 }
1215 }
1216 else {
1217 printk(KERN_ERR "cciss: Report physical LUNs failed.\n");
1218 goto out;
1219 }
1220
1221
1222 /* adjust our table of devices */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001223 for (i = 0; i < num_luns; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 /* for each physical lun, do an inquiry */
1225 if (ld_buff->LUN[i][3] & 0xC0) continue;
Mike Miller47922d02005-09-13 01:25:25 -07001226 memset(inq_buff, 0, OBDR_TAPE_INQ_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 memcpy(&scsi3addr[0], &ld_buff->LUN[i][0], 8);
1228
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001229 if (cciss_scsi_do_inquiry(h, scsi3addr, 0, inq_buff,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001230 (unsigned char) OBDR_TAPE_INQ_SIZE) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 /* Inquiry failed (msg printed already) */
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001232 continue; /* so we will skip this device. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001234 this_device->devtype = (inq_buff[0] & 0x1f);
1235 this_device->bus = -1;
1236 this_device->target = -1;
1237 this_device->lun = -1;
1238 memcpy(this_device->scsi3addr, scsi3addr, 8);
1239 memcpy(this_device->vendor, &inq_buff[8],
1240 sizeof(this_device->vendor));
1241 memcpy(this_device->model, &inq_buff[16],
1242 sizeof(this_device->model));
1243 memcpy(this_device->revision, &inq_buff[32],
1244 sizeof(this_device->revision));
1245 memset(this_device->device_id, 0,
1246 sizeof(this_device->device_id));
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001247 cciss_scsi_get_device_id(h, scsi3addr,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001248 this_device->device_id, sizeof(this_device->device_id));
1249
1250 switch (this_device->devtype)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 {
Mike Miller47922d02005-09-13 01:25:25 -07001252 case 0x05: /* CD-ROM */ {
1253
1254 /* We don't *really* support actual CD-ROM devices,
1255 * just this "One Button Disaster Recovery" tape drive
1256 * which temporarily pretends to be a CD-ROM drive.
1257 * So we check that the device is really an OBDR tape
1258 * device by checking for "$DR-10" in bytes 43-48 of
1259 * the inquiry data.
1260 */
1261 char obdr_sig[7];
1262
1263 strncpy(obdr_sig, &inq_buff[43], 6);
1264 obdr_sig[6] = '\0';
1265 if (strncmp(obdr_sig, OBDR_TAPE_SIG, 6) != 0)
1266 /* Not OBDR device, ignore it. */
1267 break;
1268 }
1269 /* fall through . . . */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 case 0x01: /* sequential access, (tape) */
1271 case 0x08: /* medium changer */
1272 if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) {
1273 printk(KERN_INFO "cciss%d: %s ignored, "
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001274 "too many devices.\n", h->ctlr,
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001275 scsi_device_type(this_device->devtype));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 break;
1277 }
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001278 currentsd[ncurrent] = *this_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279 ncurrent++;
1280 break;
1281 default:
1282 break;
1283 }
1284 }
1285
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001286 adjust_cciss_scsi_table(h, hostno, currentsd, ncurrent);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287out:
1288 kfree(inq_buff);
1289 kfree(ld_buff);
scameron@beardog.cca.cpqcorp.net905bd782008-09-19 18:27:47 -07001290 kfree(currentsd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 return;
1292}
1293
1294static int
1295is_keyword(char *ptr, int len, char *verb) // Thanks to ncr53c8xx.c
1296{
1297 int verb_len = strlen(verb);
1298 if (len >= verb_len && !memcmp(verb,ptr,verb_len))
1299 return verb_len;
1300 else
1301 return 0;
1302}
1303
1304static int
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001305cciss_scsi_user_command(ctlr_info_t *h, int hostno, char *buffer, int length)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306{
1307 int arg_len;
1308
1309 if ((arg_len = is_keyword(buffer, length, "rescan")) != 0)
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001310 cciss_update_non_disk_devices(h, hostno);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 else
1312 return -EINVAL;
1313 return length;
1314}
1315
1316
1317static int
1318cciss_scsi_proc_info(struct Scsi_Host *sh,
1319 char *buffer, /* data buffer */
1320 char **start, /* where data in buffer starts */
1321 off_t offset, /* offset from start of imaginary file */
1322 int length, /* length of data in buffer */
1323 int func) /* 0 == read, 1 == write */
1324{
1325
1326 int buflen, datalen;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001327 ctlr_info_t *h;
Mike Millerb9f0bd02005-09-13 01:25:26 -07001328 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001330 h = (ctlr_info_t *) sh->hostdata[0];
1331 if (h == NULL) /* This really shouldn't ever happen. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 return -EINVAL;
1333
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 if (func == 0) { /* User is reading from /proc/scsi/ciss*?/?* */
Mike Millerb9f0bd02005-09-13 01:25:26 -07001335 buflen = sprintf(buffer, "cciss%d: SCSI host: %d\n",
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001336 h->ctlr, sh->host_no);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337
Mike Millerb9f0bd02005-09-13 01:25:26 -07001338 /* this information is needed by apps to know which cciss
1339 device corresponds to which scsi host number without
1340 having to open a scsi target device node. The device
1341 information is not a duplicate of /proc/scsi/scsi because
1342 the two may be out of sync due to scsi hotplug, rather
1343 this info is for an app to be able to use to know how to
1344 get them back in sync. */
1345
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001346 for (i = 0; i < ccissscsi[h->ctlr].ndevices; i++) {
1347 struct cciss_scsi_dev_t *sd =
1348 &ccissscsi[h->ctlr].dev[i];
Mike Millerb9f0bd02005-09-13 01:25:26 -07001349 buflen += sprintf(&buffer[buflen], "c%db%dt%dl%d %02d "
1350 "0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
1351 sh->host_no, sd->bus, sd->target, sd->lun,
1352 sd->devtype,
1353 sd->scsi3addr[0], sd->scsi3addr[1],
1354 sd->scsi3addr[2], sd->scsi3addr[3],
1355 sd->scsi3addr[4], sd->scsi3addr[5],
1356 sd->scsi3addr[6], sd->scsi3addr[7]);
1357 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358 datalen = buflen - offset;
1359 if (datalen < 0) { /* they're reading past EOF. */
1360 datalen = 0;
1361 *start = buffer+buflen;
1362 } else
1363 *start = buffer + offset;
1364 return(datalen);
1365 } else /* User is writing to /proc/scsi/cciss*?/?* ... */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001366 return cciss_scsi_user_command(h, sh->host_no,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 buffer, length);
1368}
1369
1370/* cciss_scatter_gather takes a struct scsi_cmnd, (cmd), and does the pci
1371 dma mapping and fills in the scatter gather entries of the
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001372 cciss command, c. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001374static void cciss_scatter_gather(ctlr_info_t *h, CommandList_struct *c,
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001375 struct scsi_cmnd *cmd)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376{
FUJITA Tomonori41ce6392007-05-26 02:45:17 +09001377 unsigned int len;
1378 struct scatterlist *sg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 __u64 addr64;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001380 int request_nsgs, i, chained, sg_index;
1381 struct cciss_scsi_adapter_data_t *sa = h->scsi_ctlr;
1382 SGDescriptor_struct *curr_sg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001384 BUG_ON(scsi_sg_count(cmd) > h->maxsgentries);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001386 chained = 0;
1387 sg_index = 0;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001388 curr_sg = c->SG;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001389 request_nsgs = scsi_dma_map(cmd);
1390 if (request_nsgs) {
1391 scsi_for_each_sg(cmd, sg, request_nsgs, i) {
1392 if (sg_index + 1 == h->max_cmd_sgentries &&
1393 !chained && request_nsgs - i > 1) {
1394 chained = 1;
1395 sg_index = 0;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001396 curr_sg = sa->cmd_sg_list[c->cmdindex];
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001397 }
FUJITA Tomonori41ce6392007-05-26 02:45:17 +09001398 addr64 = (__u64) sg_dma_address(sg);
1399 len = sg_dma_len(sg);
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001400 curr_sg[sg_index].Addr.lower =
1401 (__u32) (addr64 & 0x0FFFFFFFFULL);
1402 curr_sg[sg_index].Addr.upper =
1403 (__u32) ((addr64 >> 32) & 0x0FFFFFFFFULL);
1404 curr_sg[sg_index].Len = len;
1405 curr_sg[sg_index].Ext = 0;
1406 ++sg_index;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 }
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001408 if (chained)
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001409 cciss_map_sg_chain_block(h, c,
1410 sa->cmd_sg_list[c->cmdindex],
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001411 (request_nsgs - (h->max_cmd_sgentries - 1)) *
1412 sizeof(SGDescriptor_struct));
FUJITA Tomonori41ce6392007-05-26 02:45:17 +09001413 }
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001414 /* track how many SG entries we are using */
1415 if (request_nsgs > h->maxSG)
1416 h->maxSG = request_nsgs;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001417 c->Header.SGTotal = (__u8) request_nsgs + chained;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001418 if (request_nsgs > h->max_cmd_sgentries)
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001419 c->Header.SGList = h->max_cmd_sgentries;
Stephen M. Cameron87c3a922010-02-26 16:01:53 -06001420 else
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001421 c->Header.SGList = c->Header.SGTotal;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 return;
1423}
1424
1425
1426static int
Jeff Garzikf2812332010-11-16 02:10:29 -05001427cciss_scsi_queue_command_lck(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428{
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001429 ctlr_info_t *h;
1430 int rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431 unsigned char scsi3addr[8];
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001432 CommandList_struct *c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 unsigned long flags;
1434
1435 // Get the ptr to our adapter structure (hba[i]) out of cmd->host.
1436 // We violate cmd->host privacy here. (Is there another way?)
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001437 h = (ctlr_info_t *) cmd->device->host->hostdata[0];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001439 rc = lookup_scsi3addr(h, cmd->device->channel, cmd->device->id,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 cmd->device->lun, scsi3addr);
1441 if (rc != 0) {
1442 /* the scsi nexus does not match any that we presented... */
1443 /* pretend to mid layer that we got selection timeout */
1444 cmd->result = DID_NO_CONNECT << 16;
1445 done(cmd);
1446 /* we might want to think about registering controller itself
1447 as a processor device on the bus so sg binds to it. */
1448 return 0;
1449 }
1450
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451 /* Ok, we have a reasonable scsi nexus, so send the cmd down, and
1452 see what the device thinks of it. */
1453
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001454 spin_lock_irqsave(&h->lock, flags);
1455 c = scsi_cmd_alloc(h);
1456 spin_unlock_irqrestore(&h->lock, flags);
1457 if (c == NULL) { /* trouble... */
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001458 dev_warn(&h->pdev->dev, "scsi_cmd_alloc returned NULL!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459 /* FIXME: next 3 lines are -> BAD! <- */
1460 cmd->result = DID_NO_CONNECT << 16;
1461 done(cmd);
1462 return 0;
1463 }
1464
1465 // Fill in the command list header
1466
1467 cmd->scsi_done = done; // save this for use by completion code
1468
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001469 /* save c in case we have to abort it */
1470 cmd->host_scribble = (unsigned char *) c;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001472 c->cmd_type = CMD_SCSI;
1473 c->scsi_cmd = cmd;
1474 c->Header.ReplyQueue = 0; /* unused in simple mode */
1475 memcpy(&c->Header.LUN.LunAddrBytes[0], &scsi3addr[0], 8);
1476 c->Header.Tag.lower = c->busaddr; /* Use k. address of cmd as tag */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477
1478 // Fill in the request block...
1479
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001480 c->Request.Timeout = 0;
1481 memset(c->Request.CDB, 0, sizeof(c->Request.CDB));
1482 BUG_ON(cmd->cmd_len > sizeof(c->Request.CDB));
1483 c->Request.CDBLen = cmd->cmd_len;
1484 memcpy(c->Request.CDB, cmd->cmnd, cmd->cmd_len);
1485 c->Request.Type.Type = TYPE_CMD;
1486 c->Request.Type.Attribute = ATTR_SIMPLE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 switch(cmd->sc_data_direction)
1488 {
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001489 case DMA_TO_DEVICE:
1490 c->Request.Type.Direction = XFER_WRITE;
1491 break;
1492 case DMA_FROM_DEVICE:
1493 c->Request.Type.Direction = XFER_READ;
1494 break;
1495 case DMA_NONE:
1496 c->Request.Type.Direction = XFER_NONE;
1497 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498 case DMA_BIDIRECTIONAL:
1499 // This can happen if a buggy application does a scsi passthru
1500 // and sets both inlen and outlen to non-zero. ( see
1501 // ../scsi/scsi_ioctl.c:scsi_ioctl_send_command() )
1502
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001503 c->Request.Type.Direction = XFER_RSVD;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 // This is technically wrong, and cciss controllers should
1505 // reject it with CMD_INVALID, which is the most correct
1506 // response, but non-fibre backends appear to let it
1507 // slide by, and give the same results as if this field
1508 // were set correctly. Either way is acceptable for
1509 // our purposes here.
1510
1511 break;
1512
1513 default:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001514 dev_warn(&h->pdev->dev, "unknown data direction: %d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 cmd->sc_data_direction);
1516 BUG();
1517 break;
1518 }
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001519 cciss_scatter_gather(h, c, cmd);
1520 enqueue_cmd_and_start_io(h, c);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 /* the cmd'll come back via intr handler in complete_scsi_command() */
1522 return 0;
1523}
1524
Jeff Garzikf2812332010-11-16 02:10:29 -05001525static DEF_SCSI_QCMD(cciss_scsi_queue_command)
1526
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001527static void cciss_unregister_scsi(ctlr_info_t *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528{
1529 struct cciss_scsi_adapter_data_t *sa;
1530 struct cciss_scsi_cmd_stack_t *stk;
1531 unsigned long flags;
1532
1533 /* we are being forcibly unloaded, and may not refuse. */
1534
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001535 spin_lock_irqsave(&h->lock, flags);
1536 sa = h->scsi_ctlr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537 stk = &sa->cmd_stack;
1538
1539 /* if we weren't ever actually registered, don't unregister */
1540 if (sa->registered) {
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001541 spin_unlock_irqrestore(&h->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 scsi_remove_host(sa->scsi_host);
1543 scsi_host_put(sa->scsi_host);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001544 spin_lock_irqsave(&h->lock, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545 }
1546
1547 /* set scsi_host to NULL so our detect routine will
1548 find us on register */
1549 sa->scsi_host = NULL;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001550 spin_unlock_irqrestore(&h->lock, flags);
1551 scsi_cmd_stack_free(h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 kfree(sa);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553}
1554
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001555static int cciss_engage_scsi(ctlr_info_t *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556{
1557 struct cciss_scsi_adapter_data_t *sa;
1558 struct cciss_scsi_cmd_stack_t *stk;
1559 unsigned long flags;
1560
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001561 spin_lock_irqsave(&h->lock, flags);
1562 sa = h->scsi_ctlr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563 stk = &sa->cmd_stack;
1564
Mike Millerf4a93bc2008-08-04 11:54:53 +02001565 if (sa->registered) {
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001566 dev_info(&h->pdev->dev, "SCSI subsystem already engaged.\n");
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001567 spin_unlock_irqrestore(&h->lock, flags);
Stephen M. Cameron8721c812009-11-12 12:50:06 -06001568 return -ENXIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569 }
Mike Millerf4a93bc2008-08-04 11:54:53 +02001570 sa->registered = 1;
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001571 spin_unlock_irqrestore(&h->lock, flags);
1572 cciss_update_non_disk_devices(h, -1);
1573 cciss_scsi_detect(h);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574 return 0;
1575}
1576
1577static void
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001578cciss_seq_tape_report(struct seq_file *seq, ctlr_info_t *h)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579{
1580 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001582 CPQ_TAPE_LOCK(h, flags);
Mike Miller89b6e742008-02-21 08:54:03 +01001583 seq_printf(seq,
Mike Millerb9f0bd02005-09-13 01:25:26 -07001584 "Sequential access devices: %d\n\n",
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001585 ccissscsi[h->ctlr].ndevices);
1586 CPQ_TAPE_UNLOCK(h, flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587}
1588
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001589static int wait_for_device_to_become_ready(ctlr_info_t *h,
1590 unsigned char lunaddr[])
1591{
1592 int rc;
1593 int count = 0;
1594 int waittime = HZ;
1595 CommandList_struct *c;
1596
Stephen M. Cameron6b4d96b2010-07-19 13:46:43 -05001597 c = cmd_alloc(h);
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001598 if (!c) {
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001599 dev_warn(&h->pdev->dev, "out of memory in "
1600 "wait_for_device_to_become_ready.\n");
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001601 return IO_ERROR;
1602 }
1603
1604 /* Send test unit ready until device ready, or give up. */
1605 while (count < 20) {
1606
1607 /* Wait for a bit. do this first, because if we send
1608 * the TUR right away, the reset will just abort it.
1609 */
scameron@beardog.cca.cpqcorp.net40df6ae2009-06-08 15:59:38 -05001610 schedule_timeout_uninterruptible(waittime);
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001611 count++;
1612
1613 /* Increase wait time with each try, up to a point. */
1614 if (waittime < (HZ * 30))
1615 waittime = waittime * 2;
1616
1617 /* Send the Test Unit Ready */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001618 rc = fill_cmd(h, c, TEST_UNIT_READY, NULL, 0, 0,
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001619 lunaddr, TYPE_CMD);
scameron@beardog.cca.cpqcorp.net85cc61a2009-06-08 16:07:45 -05001620 if (rc == 0)
1621 rc = sendcmd_withirq_core(h, c, 0);
1622
1623 (void) process_sendcmd_error(h, c);
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001624
scameron@beardog.cca.cpqcorp.net39692512009-06-08 16:10:57 -05001625 if (rc != 0)
1626 goto retry_tur;
1627
1628 if (c->err_info->CommandStatus == CMD_SUCCESS)
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001629 break;
1630
scameron@beardog.cca.cpqcorp.net39692512009-06-08 16:10:57 -05001631 if (c->err_info->CommandStatus == CMD_TARGET_STATUS &&
1632 c->err_info->ScsiStatus == SAM_STAT_CHECK_CONDITION) {
1633 if (c->err_info->SenseInfo[2] == NO_SENSE)
1634 break;
1635 if (c->err_info->SenseInfo[2] == UNIT_ATTENTION) {
1636 unsigned char asc;
1637 asc = c->err_info->SenseInfo[12];
1638 check_for_unit_attention(h, c);
1639 if (asc == POWER_OR_RESET)
1640 break;
1641 }
1642 }
1643retry_tur:
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001644 dev_warn(&h->pdev->dev, "Waiting %d secs "
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001645 "for device to become ready.\n",
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001646 waittime / HZ);
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001647 rc = 1; /* device not ready. */
1648 }
1649
1650 if (rc)
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001651 dev_warn(&h->pdev->dev, "giving up on device.\n");
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001652 else
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001653 dev_warn(&h->pdev->dev, "device is ready.\n");
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001654
Stephen M. Cameron6b4d96b2010-07-19 13:46:43 -05001655 cmd_free(h, c);
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001656 return rc;
1657}
Mike Miller89b6e742008-02-21 08:54:03 +01001658
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001659/* Need at least one of these error handlers to keep ../scsi/hosts.c from
1660 * complaining. Doing a host- or bus-reset can't do anything good here.
1661 * Despite what it might say in scsi_error.c, there may well be commands
1662 * on the controller, as the cciss driver registers twice, once as a block
1663 * device for the logical drives, and once as a scsi device, for any tape
1664 * drives. So we know there are no commands out on the tape drives, but we
1665 * don't know there are no commands on the controller, and it is likely
1666 * that there probably are, as the cciss block device is most commonly used
1667 * as a boot device (embedded controller on HP/Compaq systems.)
1668*/
1669
1670static int cciss_eh_device_reset_handler(struct scsi_cmnd *scsicmd)
1671{
1672 int rc;
1673 CommandList_struct *cmd_in_trouble;
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001674 unsigned char lunaddr[8];
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001675 ctlr_info_t *h;
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001676
1677 /* find the controller to which the command to be aborted was sent */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001678 h = (ctlr_info_t *) scsicmd->device->host->hostdata[0];
1679 if (h == NULL) /* paranoia */
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001680 return FAILED;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001681 dev_warn(&h->pdev->dev, "resetting tape drive or medium changer.\n");
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001682 /* find the command that's giving us trouble */
1683 cmd_in_trouble = (CommandList_struct *) scsicmd->host_scribble;
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001684 if (cmd_in_trouble == NULL) /* paranoia */
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001685 return FAILED;
Stephen M. Cameron88f627a2009-06-02 14:48:11 +02001686 memcpy(lunaddr, &cmd_in_trouble->Header.LUN.LunAddrBytes[0], 8);
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001687 /* send a reset to the SCSI LUN which the command was sent to */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001688 rc = sendcmd_withirq(h, CCISS_RESET_MSG, NULL, 0, 0, lunaddr,
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001689 TYPE_MSG);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001690 if (rc == 0 && wait_for_device_to_become_ready(h, lunaddr) == 0)
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001691 return SUCCESS;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001692 dev_warn(&h->pdev->dev, "resetting device failed.\n");
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001693 return FAILED;
1694}
1695
1696static int cciss_eh_abort_handler(struct scsi_cmnd *scsicmd)
1697{
1698 int rc;
1699 CommandList_struct *cmd_to_abort;
scameron@beardog.cca.cpqcorp.net85cc61a2009-06-08 16:07:45 -05001700 unsigned char lunaddr[8];
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001701 ctlr_info_t *h;
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001702
1703 /* find the controller to which the command to be aborted was sent */
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001704 h = (ctlr_info_t *) scsicmd->device->host->hostdata[0];
1705 if (h == NULL) /* paranoia */
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001706 return FAILED;
Stephen M. Cameronb2a4a432010-07-19 13:46:48 -05001707 dev_warn(&h->pdev->dev, "aborting tardy SCSI cmd\n");
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001708
1709 /* find the command to be aborted */
1710 cmd_to_abort = (CommandList_struct *) scsicmd->host_scribble;
1711 if (cmd_to_abort == NULL) /* paranoia */
1712 return FAILED;
scameron@beardog.cca.cpqcorp.net85cc61a2009-06-08 16:07:45 -05001713 memcpy(lunaddr, &cmd_to_abort->Header.LUN.LunAddrBytes[0], 8);
Stephen M. Cameronf70dba82010-07-19 13:46:38 -05001714 rc = sendcmd_withirq(h, CCISS_ABORT_MSG, &cmd_to_abort->Header.Tag,
scameron@beardog.cca.cpqcorp.net85cc61a2009-06-08 16:07:45 -05001715 0, 0, lunaddr, TYPE_MSG);
mike.miller@hp.com3da8b712005-11-04 12:30:37 -06001716 if (rc == 0)
1717 return SUCCESS;
1718 return FAILED;
1719
1720}
1721
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722#else /* no CONFIG_CISS_SCSI_TAPE */
1723
1724/* If no tape support, then these become defined out of existence */
1725
1726#define cciss_scsi_setup(cntl_num)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727
1728#endif /* CONFIG_CISS_SCSI_TAPE */