aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/3w-sas.c1924
-rw-r--r--drivers/scsi/3w-sas.h396
-rw-r--r--drivers/scsi/Kconfig11
-rw-r--r--drivers/scsi/Makefile1
4 files changed, 2332 insertions, 0 deletions
diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c
new file mode 100644
index 000000000000..4d314d740de4
--- /dev/null
+++ b/drivers/scsi/3w-sas.c
@@ -0,0 +1,1924 @@
1/*
2 3w-sas.c -- LSI 3ware SAS/SATA-RAID Controller device driver for Linux.
3
4 Written By: Adam Radford <linuxraid@lsi.com>
5
6 Copyright (C) 2009 LSI Corporation.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; version 2 of the License.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 NO WARRANTY
18 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
19 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
20 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
21 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
22 solely responsible for determining the appropriateness of using and
23 distributing the Program and assumes all risks associated with its
24 exercise of rights under this Agreement, including but not limited to
25 the risks and costs of program errors, damage to or loss of data,
26 programs or equipment, and unavailability or interruption of operations.
27
28 DISCLAIMER OF LIABILITY
29 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
30 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
32 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
33 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
34 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
35 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
36
37 You should have received a copy of the GNU General Public License
38 along with this program; if not, write to the Free Software
39 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
40
41 Controllers supported by this driver:
42
43 LSI 3ware 9750 6Gb/s SAS/SATA-RAID
44
45 Bugs/Comments/Suggestions should be mailed to:
46 linuxraid@lsi.com
47
48 For more information, goto:
49 http://www.lsi.com
50
51 History
52 -------
53 3.26.02.000 - Initial driver release.
54*/
55
56#include <linux/module.h>
57#include <linux/reboot.h>
58#include <linux/spinlock.h>
59#include <linux/interrupt.h>
60#include <linux/moduleparam.h>
61#include <linux/errno.h>
62#include <linux/types.h>
63#include <linux/delay.h>
64#include <linux/pci.h>
65#include <linux/time.h>
66#include <linux/mutex.h>
67#include <linux/smp_lock.h>
68#include <asm/io.h>
69#include <asm/irq.h>
70#include <asm/uaccess.h>
71#include <scsi/scsi.h>
72#include <scsi/scsi_host.h>
73#include <scsi/scsi_tcq.h>
74#include <scsi/scsi_cmnd.h>
75#include "3w-sas.h"
76
77/* Globals */
78#define TW_DRIVER_VERSION "3.26.02.000"
79static TW_Device_Extension *twl_device_extension_list[TW_MAX_SLOT];
80static unsigned int twl_device_extension_count;
81static int twl_major = -1;
82extern struct timezone sys_tz;
83
84/* Module parameters */
85MODULE_AUTHOR ("LSI");
86MODULE_DESCRIPTION ("LSI 3ware SAS/SATA-RAID Linux Driver");
87MODULE_LICENSE("GPL");
88MODULE_VERSION(TW_DRIVER_VERSION);
89
90static int use_msi;
91module_param(use_msi, int, S_IRUGO);
92MODULE_PARM_DESC(use_msi, "Use Message Signaled Interrupts. Default: 0");
93
94/* Function prototypes */
95static int twl_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset);
96
97/* Functions */
98
99/* This function returns AENs through sysfs */
100static ssize_t twl_sysfs_aen_read(struct kobject *kobj,
101 struct bin_attribute *bin_attr,
102 char *outbuf, loff_t offset, size_t count)
103{
104 struct device *dev = container_of(kobj, struct device, kobj);
105 struct Scsi_Host *shost = class_to_shost(dev);
106 TW_Device_Extension *tw_dev = (TW_Device_Extension *)shost->hostdata;
107 unsigned long flags = 0;
108 ssize_t ret;
109
110 if (!capable(CAP_SYS_ADMIN))
111 return -EACCES;
112
113 spin_lock_irqsave(tw_dev->host->host_lock, flags);
114 ret = memory_read_from_buffer(outbuf, count, &offset, tw_dev->event_queue[0], sizeof(TW_Event) * TW_Q_LENGTH);
115 spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
116
117 return ret;
118} /* End twl_sysfs_aen_read() */
119
120/* aen_read sysfs attribute initializer */
121static struct bin_attribute twl_sysfs_aen_read_attr = {
122 .attr = {
123 .name = "3ware_aen_read",
124 .mode = S_IRUSR,
125 },
126 .size = 0,
127 .read = twl_sysfs_aen_read
128};
129
130/* This function returns driver compatibility info through sysfs */
131static ssize_t twl_sysfs_compat_info(struct kobject *kobj,
132 struct bin_attribute *bin_attr,
133 char *outbuf, loff_t offset, size_t count)
134{
135 struct device *dev = container_of(kobj, struct device, kobj);
136 struct Scsi_Host *shost = class_to_shost(dev);
137 TW_Device_Extension *tw_dev = (TW_Device_Extension *)shost->hostdata;
138 unsigned long flags = 0;
139 ssize_t ret;
140
141 if (!capable(CAP_SYS_ADMIN))
142 return -EACCES;
143
144 spin_lock_irqsave(tw_dev->host->host_lock, flags);
145 ret = memory_read_from_buffer(outbuf, count, &offset, &tw_dev->tw_compat_info, sizeof(TW_Compatibility_Info));
146 spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
147
148 return ret;
149} /* End twl_sysfs_compat_info() */
150
151/* compat_info sysfs attribute initializer */
152static struct bin_attribute twl_sysfs_compat_info_attr = {
153 .attr = {
154 .name = "3ware_compat_info",
155 .mode = S_IRUSR,
156 },
157 .size = 0,
158 .read = twl_sysfs_compat_info
159};
160
161/* Show some statistics about the card */
162static ssize_t twl_show_stats(struct device *dev,
163 struct device_attribute *attr, char *buf)
164{
165 struct Scsi_Host *host = class_to_shost(dev);
166 TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
167 unsigned long flags = 0;
168 ssize_t len;
169
170 spin_lock_irqsave(tw_dev->host->host_lock, flags);
171 len = snprintf(buf, PAGE_SIZE, "3w-sas Driver version: %s\n"
172 "Current commands posted: %4d\n"
173 "Max commands posted: %4d\n"
174 "Last sgl length: %4d\n"
175 "Max sgl length: %4d\n"
176 "Last sector count: %4d\n"
177 "Max sector count: %4d\n"
178 "SCSI Host Resets: %4d\n"
179 "AEN's: %4d\n",
180 TW_DRIVER_VERSION,
181 tw_dev->posted_request_count,
182 tw_dev->max_posted_request_count,
183 tw_dev->sgl_entries,
184 tw_dev->max_sgl_entries,
185 tw_dev->sector_count,
186 tw_dev->max_sector_count,
187 tw_dev->num_resets,
188 tw_dev->aen_count);
189 spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
190 return len;
191} /* End twl_show_stats() */
192
193/* This function will set a devices queue depth */
194static int twl_change_queue_depth(struct scsi_device *sdev, int queue_depth,
195 int reason)
196{
197 if (reason != SCSI_QDEPTH_DEFAULT)
198 return -EOPNOTSUPP;
199
200 if (queue_depth > TW_Q_LENGTH-2)
201 queue_depth = TW_Q_LENGTH-2;
202 scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
203 return queue_depth;
204} /* End twl_change_queue_depth() */
205
206/* stats sysfs attribute initializer */
207static struct device_attribute twl_host_stats_attr = {
208 .attr = {
209 .name = "3ware_stats",
210 .mode = S_IRUGO,
211 },
212 .show = twl_show_stats
213};
214
215/* Host attributes initializer */
216static struct device_attribute *twl_host_attrs[] = {
217 &twl_host_stats_attr,
218 NULL,
219};
220
221/* This function will look up an AEN severity string */
222static char *twl_aen_severity_lookup(unsigned char severity_code)
223{
224 char *retval = NULL;
225
226 if ((severity_code < (unsigned char) TW_AEN_SEVERITY_ERROR) ||
227 (severity_code > (unsigned char) TW_AEN_SEVERITY_DEBUG))
228 goto out;
229
230 retval = twl_aen_severity_table[severity_code];
231out:
232 return retval;
233} /* End twl_aen_severity_lookup() */
234
235/* This function will queue an event */
236static void twl_aen_queue_event(TW_Device_Extension *tw_dev, TW_Command_Apache_Header *header)
237{
238 u32 local_time;
239 struct timeval time;
240 TW_Event *event;
241 unsigned short aen;
242 char host[16];
243 char *error_str;
244
245 tw_dev->aen_count++;
246
247 /* Fill out event info */
248 event = tw_dev->event_queue[tw_dev->error_index];
249
250 host[0] = '\0';
251 if (tw_dev->host)
252 sprintf(host, " scsi%d:", tw_dev->host->host_no);
253
254 aen = le16_to_cpu(header->status_block.error);
255 memset(event, 0, sizeof(TW_Event));
256
257 event->severity = TW_SEV_OUT(header->status_block.severity__reserved);
258 do_gettimeofday(&time);
259 local_time = (u32)(time.tv_sec - (sys_tz.tz_minuteswest * 60));
260 event->time_stamp_sec = local_time;
261 event->aen_code = aen;
262 event->retrieved = TW_AEN_NOT_RETRIEVED;
263 event->sequence_id = tw_dev->error_sequence_id;
264 tw_dev->error_sequence_id++;
265
266 /* Check for embedded error string */
267 error_str = &(header->err_specific_desc[strlen(header->err_specific_desc)+1]);
268
269 header->err_specific_desc[sizeof(header->err_specific_desc) - 1] = '\0';
270 event->parameter_len = strlen(header->err_specific_desc);
271 memcpy(event->parameter_data, header->err_specific_desc, event->parameter_len + 1 + strlen(error_str));
272 if (event->severity != TW_AEN_SEVERITY_DEBUG)
273 printk(KERN_WARNING "3w-sas:%s AEN: %s (0x%02X:0x%04X): %s:%s.\n",
274 host,
275 twl_aen_severity_lookup(TW_SEV_OUT(header->status_block.severity__reserved)),
276 TW_MESSAGE_SOURCE_CONTROLLER_EVENT, aen, error_str,
277 header->err_specific_desc);
278 else
279 tw_dev->aen_count--;
280
281 tw_dev->error_index = (tw_dev->error_index + 1 ) % TW_Q_LENGTH;
282} /* End twl_aen_queue_event() */
283
284/* This function will attempt to post a command packet to the board */
285static int twl_post_command_packet(TW_Device_Extension *tw_dev, int request_id)
286{
287 dma_addr_t command_que_value;
288
289 command_que_value = tw_dev->command_packet_phys[request_id];
290 command_que_value += TW_COMMAND_OFFSET;
291
292 /* First write upper 4 bytes */
293 writel((u32)((u64)command_que_value >> 32), TWL_HIBQPH_REG_ADDR(tw_dev));
294 /* Then the lower 4 bytes */
295 writel((u32)(command_que_value | TWL_PULL_MODE), TWL_HIBQPL_REG_ADDR(tw_dev));
296
297 tw_dev->state[request_id] = TW_S_POSTED;
298 tw_dev->posted_request_count++;
299 if (tw_dev->posted_request_count > tw_dev->max_posted_request_count)
300 tw_dev->max_posted_request_count = tw_dev->posted_request_count;
301
302 return 0;
303} /* End twl_post_command_packet() */
304
305/* This function will perform a pci-dma mapping for a scatter gather list */
306static int twl_map_scsi_sg_data(TW_Device_Extension *tw_dev, int request_id)
307{
308 int use_sg;
309 struct scsi_cmnd *cmd = tw_dev->srb[request_id];
310
311 use_sg = scsi_dma_map(cmd);
312 if (!use_sg)
313 return 0;
314 else if (use_sg < 0) {
315 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1, "Failed to map scatter gather list");
316 return 0;
317 }
318
319 cmd->SCp.phase = TW_PHASE_SGLIST;
320 cmd->SCp.have_data_in = use_sg;
321
322 return use_sg;
323} /* End twl_map_scsi_sg_data() */
324
325/* This function hands scsi cdb's to the firmware */
326static int twl_scsiop_execute_scsi(TW_Device_Extension *tw_dev, int request_id, char *cdb, int use_sg, TW_SG_Entry_ISO *sglistarg)
327{
328 TW_Command_Full *full_command_packet;
329 TW_Command_Apache *command_packet;
330 int i, sg_count;
331 struct scsi_cmnd *srb = NULL;
332 struct scatterlist *sglist = NULL, *sg;
333 int retval = 1;
334
335 if (tw_dev->srb[request_id]) {
336 srb = tw_dev->srb[request_id];
337 if (scsi_sglist(srb))
338 sglist = scsi_sglist(srb);
339 }
340
341 /* Initialize command packet */
342 full_command_packet = tw_dev->command_packet_virt[request_id];
343 full_command_packet->header.header_desc.size_header = 128;
344 full_command_packet->header.status_block.error = 0;
345 full_command_packet->header.status_block.severity__reserved = 0;
346
347 command_packet = &full_command_packet->command.newcommand;
348 command_packet->status = 0;
349 command_packet->opcode__reserved = TW_OPRES_IN(0, TW_OP_EXECUTE_SCSI);
350
351 /* We forced 16 byte cdb use earlier */
352 if (!cdb)
353 memcpy(command_packet->cdb, srb->cmnd, TW_MAX_CDB_LEN);
354 else
355 memcpy(command_packet->cdb, cdb, TW_MAX_CDB_LEN);
356
357 if (srb) {
358 command_packet->unit = srb->device->id;
359 command_packet->request_id__lunl =
360 cpu_to_le16(TW_REQ_LUN_IN(srb->device->lun, request_id));
361 } else {
362 command_packet->request_id__lunl =
363 cpu_to_le16(TW_REQ_LUN_IN(0, request_id));
364 command_packet->unit = 0;
365 }
366
367 command_packet->sgl_offset = 16;
368
369 if (!sglistarg) {
370 /* Map sglist from scsi layer to cmd packet */
371 if (scsi_sg_count(srb)) {
372 sg_count = twl_map_scsi_sg_data(tw_dev, request_id);
373 if (sg_count == 0)
374 goto out;
375
376 scsi_for_each_sg(srb, sg, sg_count, i) {
377 command_packet->sg_list[i].address = TW_CPU_TO_SGL(sg_dma_address(sg));
378 command_packet->sg_list[i].length = TW_CPU_TO_SGL(sg_dma_len(sg));
379 }
380 command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN((srb->device->lun >> 4), scsi_sg_count(tw_dev->srb[request_id])));
381 }
382 } else {
383 /* Internal cdb post */
384 for (i = 0; i < use_sg; i++) {
385 command_packet->sg_list[i].address = TW_CPU_TO_SGL(sglistarg[i].address);
386 command_packet->sg_list[i].length = TW_CPU_TO_SGL(sglistarg[i].length);
387 }
388 command_packet->sgl_entries__lunh = cpu_to_le16(TW_REQ_LUN_IN(0, use_sg));
389 }
390
391 /* Update some stats */
392 if (srb) {
393 tw_dev->sector_count = scsi_bufflen(srb) / 512;
394 if (tw_dev->sector_count > tw_dev->max_sector_count)
395 tw_dev->max_sector_count = tw_dev->sector_count;
396 tw_dev->sgl_entries = scsi_sg_count(srb);
397 if (tw_dev->sgl_entries > tw_dev->max_sgl_entries)
398 tw_dev->max_sgl_entries = tw_dev->sgl_entries;
399 }
400
401 /* Now post the command to the board */
402 retval = twl_post_command_packet(tw_dev, request_id);
403
404out:
405 return retval;
406} /* End twl_scsiop_execute_scsi() */
407
408/* This function will read the aen queue from the isr */
409static int twl_aen_read_queue(TW_Device_Extension *tw_dev, int request_id)
410{
411 char cdb[TW_MAX_CDB_LEN];
412 TW_SG_Entry_ISO sglist[1];
413 TW_Command_Full *full_command_packet;
414 int retval = 1;
415
416 full_command_packet = tw_dev->command_packet_virt[request_id];
417 memset(full_command_packet, 0, sizeof(TW_Command_Full));
418
419 /* Initialize cdb */
420 memset(&cdb, 0, TW_MAX_CDB_LEN);
421 cdb[0] = REQUEST_SENSE; /* opcode */
422 cdb[4] = TW_ALLOCATION_LENGTH; /* allocation length */
423
424 /* Initialize sglist */
425 memset(&sglist, 0, sizeof(TW_SG_Entry_ISO));
426 sglist[0].length = TW_SECTOR_SIZE;
427 sglist[0].address = tw_dev->generic_buffer_phys[request_id];
428
429 /* Mark internal command */
430 tw_dev->srb[request_id] = NULL;
431
432 /* Now post the command packet */
433 if (twl_scsiop_execute_scsi(tw_dev, request_id, cdb, 1, sglist)) {
434 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2, "Post failed while reading AEN queue");
435 goto out;
436 }
437 retval = 0;
438out:
439 return retval;
440} /* End twl_aen_read_queue() */
441
442/* This function will sync firmware time with the host time */
443static void twl_aen_sync_time(TW_Device_Extension *tw_dev, int request_id)
444{
445 u32 schedulertime;
446 struct timeval utc;
447 TW_Command_Full *full_command_packet;
448 TW_Command *command_packet;
449 TW_Param_Apache *param;
450 u32 local_time;
451
452 /* Fill out the command packet */
453 full_command_packet = tw_dev->command_packet_virt[request_id];
454 memset(full_command_packet, 0, sizeof(TW_Command_Full));
455 command_packet = &full_command_packet->command.oldcommand;
456 command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_SET_PARAM);
457 command_packet->request_id = request_id;
458 command_packet->byte8_offset.param.sgl[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
459 command_packet->byte8_offset.param.sgl[0].length = TW_CPU_TO_SGL(TW_SECTOR_SIZE);
460 command_packet->size = TW_COMMAND_SIZE;
461 command_packet->byte6_offset.parameter_count = cpu_to_le16(1);
462
463 /* Setup the param */
464 param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id];
465 memset(param, 0, TW_SECTOR_SIZE);
466 param->table_id = cpu_to_le16(TW_TIMEKEEP_TABLE | 0x8000); /* Controller time keep table */
467 param->parameter_id = cpu_to_le16(0x3); /* SchedulerTime */
468 param->parameter_size_bytes = cpu_to_le16(4);
469
470 /* Convert system time in UTC to local time seconds since last
471 Sunday 12:00AM */
472 do_gettimeofday(&utc);
473 local_time = (u32)(utc.tv_sec - (sys_tz.tz_minuteswest * 60));
474 schedulertime = local_time - (3 * 86400);
475 schedulertime = cpu_to_le32(schedulertime % 604800);
476
477 memcpy(param->data, &schedulertime, sizeof(u32));
478
479 /* Mark internal command */
480 tw_dev->srb[request_id] = NULL;
481
482 /* Now post the command */
483 twl_post_command_packet(tw_dev, request_id);
484} /* End twl_aen_sync_time() */
485
486/* This function will assign an available request id */
487static void twl_get_request_id(TW_Device_Extension *tw_dev, int *request_id)
488{
489 *request_id = tw_dev->free_queue[tw_dev->free_head];
490 tw_dev->free_head = (tw_dev->free_head + 1) % TW_Q_LENGTH;
491 tw_dev->state[*request_id] = TW_S_STARTED;
492} /* End twl_get_request_id() */
493
494/* This function will free a request id */
495static void twl_free_request_id(TW_Device_Extension *tw_dev, int request_id)
496{
497 tw_dev->free_queue[tw_dev->free_tail] = request_id;
498 tw_dev->state[request_id] = TW_S_FINISHED;
499 tw_dev->free_tail = (tw_dev->free_tail + 1) % TW_Q_LENGTH;
500} /* End twl_free_request_id() */
501
502/* This function will complete an aen request from the isr */
503static int twl_aen_complete(TW_Device_Extension *tw_dev, int request_id)
504{
505 TW_Command_Full *full_command_packet;
506 TW_Command *command_packet;
507 TW_Command_Apache_Header *header;
508 unsigned short aen;
509 int retval = 1;
510
511 header = (TW_Command_Apache_Header *)tw_dev->generic_buffer_virt[request_id];
512 tw_dev->posted_request_count--;
513 aen = le16_to_cpu(header->status_block.error);
514 full_command_packet = tw_dev->command_packet_virt[request_id];
515 command_packet = &full_command_packet->command.oldcommand;
516
517 /* First check for internal completion of set param for time sync */
518 if (TW_OP_OUT(command_packet->opcode__sgloffset) == TW_OP_SET_PARAM) {
519 /* Keep reading the queue in case there are more aen's */
520 if (twl_aen_read_queue(tw_dev, request_id))
521 goto out2;
522 else {
523 retval = 0;
524 goto out;
525 }
526 }
527
528 switch (aen) {
529 case TW_AEN_QUEUE_EMPTY:
530 /* Quit reading the queue if this is the last one */
531 break;
532 case TW_AEN_SYNC_TIME_WITH_HOST:
533 twl_aen_sync_time(tw_dev, request_id);
534 retval = 0;
535 goto out;
536 default:
537 twl_aen_queue_event(tw_dev, header);
538
539 /* If there are more aen's, keep reading the queue */
540 if (twl_aen_read_queue(tw_dev, request_id))
541 goto out2;
542 else {
543 retval = 0;
544 goto out;
545 }
546 }
547 retval = 0;
548out2:
549 tw_dev->state[request_id] = TW_S_COMPLETED;
550 twl_free_request_id(tw_dev, request_id);
551 clear_bit(TW_IN_ATTENTION_LOOP, &tw_dev->flags);
552out:
553 return retval;
554} /* End twl_aen_complete() */
555
556/* This function will poll for a response */
557static int twl_poll_response(TW_Device_Extension *tw_dev, int request_id, int seconds)
558{
559 unsigned long before;
560 dma_addr_t mfa;
561 u32 regh, regl;
562 u32 response;
563 int retval = 1;
564 int found = 0;
565
566 before = jiffies;
567
568 while (!found) {
569 if (sizeof(dma_addr_t) > 4) {
570 regh = readl(TWL_HOBQPH_REG_ADDR(tw_dev));
571 regl = readl(TWL_HOBQPL_REG_ADDR(tw_dev));
572 mfa = ((u64)regh << 32) | regl;
573 } else
574 mfa = readl(TWL_HOBQPL_REG_ADDR(tw_dev));
575
576 response = (u32)mfa;
577
578 if (TW_RESID_OUT(response) == request_id)
579 found = 1;
580
581 if (time_after(jiffies, before + HZ * seconds))
582 goto out;
583
584 msleep(50);
585 }
586 retval = 0;
587out:
588 return retval;
589} /* End twl_poll_response() */
590
591/* This function will drain the aen queue */
592static int twl_aen_drain_queue(TW_Device_Extension *tw_dev, int no_check_reset)
593{
594 int request_id = 0;
595 char cdb[TW_MAX_CDB_LEN];
596 TW_SG_Entry_ISO sglist[1];
597 int finished = 0, count = 0;
598 TW_Command_Full *full_command_packet;
599 TW_Command_Apache_Header *header;
600 unsigned short aen;
601 int first_reset = 0, queue = 0, retval = 1;
602
603 if (no_check_reset)
604 first_reset = 0;
605 else
606 first_reset = 1;
607
608 full_command_packet = tw_dev->command_packet_virt[request_id];
609 memset(full_command_packet, 0, sizeof(TW_Command_Full));
610
611 /* Initialize cdb */
612 memset(&cdb, 0, TW_MAX_CDB_LEN);
613 cdb[0] = REQUEST_SENSE; /* opcode */
614 cdb[4] = TW_ALLOCATION_LENGTH; /* allocation length */
615
616 /* Initialize sglist */
617 memset(&sglist, 0, sizeof(TW_SG_Entry_ISO));
618 sglist[0].length = TW_SECTOR_SIZE;
619 sglist[0].address = tw_dev->generic_buffer_phys[request_id];
620
621 /* Mark internal command */
622 tw_dev->srb[request_id] = NULL;
623
624 do {
625 /* Send command to the board */
626 if (twl_scsiop_execute_scsi(tw_dev, request_id, cdb, 1, sglist)) {
627 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x3, "Error posting request sense");
628 goto out;
629 }
630
631 /* Now poll for completion */
632 if (twl_poll_response(tw_dev, request_id, 30)) {
633 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x4, "No valid response while draining AEN queue");
634 tw_dev->posted_request_count--;
635 goto out;
636 }
637
638 tw_dev->posted_request_count--;
639 header = (TW_Command_Apache_Header *)tw_dev->generic_buffer_virt[request_id];
640 aen = le16_to_cpu(header->status_block.error);
641 queue = 0;
642 count++;
643
644 switch (aen) {
645 case TW_AEN_QUEUE_EMPTY:
646 if (first_reset != 1)
647 goto out;
648 else
649 finished = 1;
650 break;
651 case TW_AEN_SOFT_RESET:
652 if (first_reset == 0)
653 first_reset = 1;
654 else
655 queue = 1;
656 break;
657 case TW_AEN_SYNC_TIME_WITH_HOST:
658 break;
659 default:
660 queue = 1;
661 }
662
663 /* Now queue an event info */
664 if (queue)
665 twl_aen_queue_event(tw_dev, header);
666 } while ((finished == 0) && (count < TW_MAX_AEN_DRAIN));
667
668 if (count == TW_MAX_AEN_DRAIN)
669 goto out;
670
671 retval = 0;
672out:
673 tw_dev->state[request_id] = TW_S_INITIAL;
674 return retval;
675} /* End twl_aen_drain_queue() */
676
677/* This function will allocate memory and check if it is correctly aligned */
678static int twl_allocate_memory(TW_Device_Extension *tw_dev, int size, int which)
679{
680 int i;
681 dma_addr_t dma_handle;
682 unsigned long *cpu_addr;
683 int retval = 1;
684
685 cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, size*TW_Q_LENGTH, &dma_handle);
686 if (!cpu_addr) {
687 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x5, "Memory allocation failed");
688 goto out;
689 }
690
691 memset(cpu_addr, 0, size*TW_Q_LENGTH);
692
693 for (i = 0; i < TW_Q_LENGTH; i++) {
694 switch(which) {
695 case 0:
696 tw_dev->command_packet_phys[i] = dma_handle+(i*size);
697 tw_dev->command_packet_virt[i] = (TW_Command_Full *)((unsigned char *)cpu_addr + (i*size));
698 break;
699 case 1:
700 tw_dev->generic_buffer_phys[i] = dma_handle+(i*size);
701 tw_dev->generic_buffer_virt[i] = (unsigned long *)((unsigned char *)cpu_addr + (i*size));
702 break;
703 case 2:
704 tw_dev->sense_buffer_phys[i] = dma_handle+(i*size);
705 tw_dev->sense_buffer_virt[i] = (TW_Command_Apache_Header *)((unsigned char *)cpu_addr + (i*size));
706 break;
707 }
708 }
709 retval = 0;
710out:
711 return retval;
712} /* End twl_allocate_memory() */
713
714/* This function will load the request id and various sgls for ioctls */
715static void twl_load_sgl(TW_Device_Extension *tw_dev, TW_Command_Full *full_command_packet, int request_id, dma_addr_t dma_handle, int length)
716{
717 TW_Command *oldcommand;
718 TW_Command_Apache *newcommand;
719 TW_SG_Entry_ISO *sgl;
720 unsigned int pae = 0;
721
722 if ((sizeof(long) < 8) && (sizeof(dma_addr_t) > 4))
723 pae = 1;
724
725 if (TW_OP_OUT(full_command_packet->command.newcommand.opcode__reserved) == TW_OP_EXECUTE_SCSI) {
726 newcommand = &full_command_packet->command.newcommand;
727 newcommand->request_id__lunl =
728 cpu_to_le16(TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->request_id__lunl), request_id));
729 if (length) {
730 newcommand->sg_list[0].address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1);
731 newcommand->sg_list[0].length = TW_CPU_TO_SGL(length);
732 }
733 newcommand->sgl_entries__lunh =
734 cpu_to_le16(TW_REQ_LUN_IN(TW_LUN_OUT(newcommand->sgl_entries__lunh), length ? 1 : 0));
735 } else {
736 oldcommand = &full_command_packet->command.oldcommand;
737 oldcommand->request_id = request_id;
738
739 if (TW_SGL_OUT(oldcommand->opcode__sgloffset)) {
740 /* Load the sg list */
741 sgl = (TW_SG_Entry_ISO *)((u32 *)oldcommand+oldcommand->size - (sizeof(TW_SG_Entry_ISO)/4) + pae + (sizeof(dma_addr_t) > 4 ? 1 : 0));
742 sgl->address = TW_CPU_TO_SGL(dma_handle + sizeof(TW_Ioctl_Buf_Apache) - 1);
743 sgl->length = TW_CPU_TO_SGL(length);
744 oldcommand->size += pae;
745 oldcommand->size += sizeof(dma_addr_t) > 4 ? 1 : 0;
746 }
747 }
748} /* End twl_load_sgl() */
749
750/* This function handles ioctl for the character device
751 This interface is used by smartmontools open source software */
752static int twl_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
753{
754 long timeout;
755 unsigned long *cpu_addr, data_buffer_length_adjusted = 0, flags = 0;
756 dma_addr_t dma_handle;
757 int request_id = 0;
758 TW_Ioctl_Driver_Command driver_command;
759 TW_Ioctl_Buf_Apache *tw_ioctl;
760 TW_Command_Full *full_command_packet;
761 TW_Device_Extension *tw_dev = twl_device_extension_list[iminor(inode)];
762 int retval = -EFAULT;
763 void __user *argp = (void __user *)arg;
764
765 /* Only let one of these through at a time */
766 if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) {
767 retval = -EINTR;
768 goto out;
769 }
770
771 /* First copy down the driver command */
772 if (copy_from_user(&driver_command, argp, sizeof(TW_Ioctl_Driver_Command)))
773 goto out2;
774
775 /* Check data buffer size */
776 if (driver_command.buffer_length > TW_MAX_SECTORS * 2048) {
777 retval = -EINVAL;
778 goto out2;
779 }
780
781 /* Hardware can only do multiple of 512 byte transfers */
782 data_buffer_length_adjusted = (driver_command.buffer_length + 511) & ~511;
783
784 /* Now allocate ioctl buf memory */
785 cpu_addr = dma_alloc_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, &dma_handle, GFP_KERNEL);
786 if (!cpu_addr) {
787 retval = -ENOMEM;
788 goto out2;
789 }
790
791 tw_ioctl = (TW_Ioctl_Buf_Apache *)cpu_addr;
792
793 /* Now copy down the entire ioctl */
794 if (copy_from_user(tw_ioctl, argp, driver_command.buffer_length + sizeof(TW_Ioctl_Buf_Apache) - 1))
795 goto out3;
796
797 /* See which ioctl we are doing */
798 switch (cmd) {
799 case TW_IOCTL_FIRMWARE_PASS_THROUGH:
800 spin_lock_irqsave(tw_dev->host->host_lock, flags);
801 twl_get_request_id(tw_dev, &request_id);
802
803 /* Flag internal command */
804 tw_dev->srb[request_id] = NULL;
805
806 /* Flag chrdev ioctl */
807 tw_dev->chrdev_request_id = request_id;
808
809 full_command_packet = (TW_Command_Full *)&tw_ioctl->firmware_command;
810
811 /* Load request id and sglist for both command types */
812 twl_load_sgl(tw_dev, full_command_packet, request_id, dma_handle, data_buffer_length_adjusted);
813
814 memcpy(tw_dev->command_packet_virt[request_id], &(tw_ioctl->firmware_command), sizeof(TW_Command_Full));
815
816 /* Now post the command packet to the controller */
817 twl_post_command_packet(tw_dev, request_id);
818 spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
819
820 timeout = TW_IOCTL_CHRDEV_TIMEOUT*HZ;
821
822 /* Now wait for command to complete */
823 timeout = wait_event_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout);
824
825 /* We timed out, and didn't get an interrupt */
826 if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) {
827 /* Now we need to reset the board */
828 printk(KERN_WARNING "3w-sas: scsi%d: WARNING: (0x%02X:0x%04X): Character ioctl (0x%x) timed out, resetting card.\n",
829 tw_dev->host->host_no, TW_DRIVER, 0x6,
830 cmd);
831 retval = -EIO;
832 twl_reset_device_extension(tw_dev, 1);
833 goto out3;
834 }
835
836 /* Now copy in the command packet response */
837 memcpy(&(tw_ioctl->firmware_command), tw_dev->command_packet_virt[request_id], sizeof(TW_Command_Full));
838
839 /* Now complete the io */
840 spin_lock_irqsave(tw_dev->host->host_lock, flags);
841 tw_dev->posted_request_count--;
842 tw_dev->state[request_id] = TW_S_COMPLETED;
843 twl_free_request_id(tw_dev, request_id);
844 spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
845 break;
846 default:
847 retval = -ENOTTY;
848 goto out3;
849 }
850
851 /* Now copy the entire response to userspace */
852 if (copy_to_user(argp, tw_ioctl, sizeof(TW_Ioctl_Buf_Apache) + driver_command.buffer_length - 1) == 0)
853 retval = 0;
854out3:
855 /* Now free ioctl buf memory */
856 dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, cpu_addr, dma_handle);
857out2:
858 mutex_unlock(&tw_dev->ioctl_lock);
859out:
860 return retval;
861} /* End twl_chrdev_ioctl() */
862
863/* This function handles open for the character device */
864static int twl_chrdev_open(struct inode *inode, struct file *file)
865{
866 unsigned int minor_number;
867 int retval = -ENODEV;
868
869 if (!capable(CAP_SYS_ADMIN)) {
870 retval = -EACCES;
871 goto out;
872 }
873
874 cycle_kernel_lock();
875 minor_number = iminor(inode);
876 if (minor_number >= twl_device_extension_count)
877 goto out;
878 retval = 0;
879out:
880 return retval;
881} /* End twl_chrdev_open() */
882
883/* File operations struct for character device */
884static const struct file_operations twl_fops = {
885 .owner = THIS_MODULE,
886 .ioctl = twl_chrdev_ioctl,
887 .open = twl_chrdev_open,
888 .release = NULL
889};
890
891/* This function passes sense data from firmware to scsi layer */
892static int twl_fill_sense(TW_Device_Extension *tw_dev, int i, int request_id, int copy_sense, int print_host)
893{
894 TW_Command_Apache_Header *header;
895 TW_Command_Full *full_command_packet;
896 unsigned short error;
897 char *error_str;
898 int retval = 1;
899
900 header = tw_dev->sense_buffer_virt[i];
901 full_command_packet = tw_dev->command_packet_virt[request_id];
902
903 /* Get embedded firmware error string */
904 error_str = &(header->err_specific_desc[strlen(header->err_specific_desc) + 1]);
905
906 /* Don't print error for Logical unit not supported during rollcall */
907 error = le16_to_cpu(header->status_block.error);
908 if ((error != TW_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) && (error != TW_ERROR_UNIT_OFFLINE) && (error != TW_ERROR_INVALID_FIELD_IN_CDB)) {
909 if (print_host)
910 printk(KERN_WARNING "3w-sas: scsi%d: ERROR: (0x%02X:0x%04X): %s:%s.\n",
911 tw_dev->host->host_no,
912 TW_MESSAGE_SOURCE_CONTROLLER_ERROR,
913 header->status_block.error,
914 error_str,
915 header->err_specific_desc);
916 else
917 printk(KERN_WARNING "3w-sas: ERROR: (0x%02X:0x%04X): %s:%s.\n",
918 TW_MESSAGE_SOURCE_CONTROLLER_ERROR,
919 header->status_block.error,
920 error_str,
921 header->err_specific_desc);
922 }
923
924 if (copy_sense) {
925 memcpy(tw_dev->srb[request_id]->sense_buffer, header->sense_data, TW_SENSE_DATA_LENGTH);
926 tw_dev->srb[request_id]->result = (full_command_packet->command.newcommand.status << 1);
927 goto out;
928 }
929out:
930 return retval;
931} /* End twl_fill_sense() */
932
933/* This function will free up device extension resources */
934static void twl_free_device_extension(TW_Device_Extension *tw_dev)
935{
936 if (tw_dev->command_packet_virt[0])
937 pci_free_consistent(tw_dev->tw_pci_dev,
938 sizeof(TW_Command_Full)*TW_Q_LENGTH,
939 tw_dev->command_packet_virt[0],
940 tw_dev->command_packet_phys[0]);
941
942 if (tw_dev->generic_buffer_virt[0])
943 pci_free_consistent(tw_dev->tw_pci_dev,
944 TW_SECTOR_SIZE*TW_Q_LENGTH,
945 tw_dev->generic_buffer_virt[0],
946 tw_dev->generic_buffer_phys[0]);
947
948 if (tw_dev->sense_buffer_virt[0])
949 pci_free_consistent(tw_dev->tw_pci_dev,
950 sizeof(TW_Command_Apache_Header)*
951 TW_Q_LENGTH,
952 tw_dev->sense_buffer_virt[0],
953 tw_dev->sense_buffer_phys[0]);
954
955 kfree(tw_dev->event_queue[0]);
956} /* End twl_free_device_extension() */
957
958/* This function will get parameter table entries from the firmware */
959static void *twl_get_param(TW_Device_Extension *tw_dev, int request_id, int table_id, int parameter_id, int parameter_size_bytes)
960{
961 TW_Command_Full *full_command_packet;
962 TW_Command *command_packet;
963 TW_Param_Apache *param;
964 void *retval = NULL;
965
966 /* Setup the command packet */
967 full_command_packet = tw_dev->command_packet_virt[request_id];
968 memset(full_command_packet, 0, sizeof(TW_Command_Full));
969 command_packet = &full_command_packet->command.oldcommand;
970
971 command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM);
972 command_packet->size = TW_COMMAND_SIZE;
973 command_packet->request_id = request_id;
974 command_packet->byte6_offset.block_count = cpu_to_le16(1);
975
976 /* Now setup the param */
977 param = (TW_Param_Apache *)tw_dev->generic_buffer_virt[request_id];
978 memset(param, 0, TW_SECTOR_SIZE);
979 param->table_id = cpu_to_le16(table_id | 0x8000);
980 param->parameter_id = cpu_to_le16(parameter_id);
981 param->parameter_size_bytes = cpu_to_le16(parameter_size_bytes);
982
983 command_packet->byte8_offset.param.sgl[0].address = TW_CPU_TO_SGL(tw_dev->generic_buffer_phys[request_id]);
984 command_packet->byte8_offset.param.sgl[0].length = TW_CPU_TO_SGL(TW_SECTOR_SIZE);
985
986 /* Post the command packet to the board */
987 twl_post_command_packet(tw_dev, request_id);
988
989 /* Poll for completion */
990 if (twl_poll_response(tw_dev, request_id, 30))
991 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x7, "No valid response during get param")
992 else
993 retval = (void *)&(param->data[0]);
994
995 tw_dev->posted_request_count--;
996 tw_dev->state[request_id] = TW_S_INITIAL;
997
998 return retval;
999} /* End twl_get_param() */
1000
1001/* This function will send an initconnection command to controller */
1002static int twl_initconnection(TW_Device_Extension *tw_dev, int message_credits,
1003 u32 set_features, unsigned short current_fw_srl,
1004 unsigned short current_fw_arch_id,
1005 unsigned short current_fw_branch,
1006 unsigned short current_fw_build,
1007 unsigned short *fw_on_ctlr_srl,
1008 unsigned short *fw_on_ctlr_arch_id,
1009 unsigned short *fw_on_ctlr_branch,
1010 unsigned short *fw_on_ctlr_build,
1011 u32 *init_connect_result)
1012{
1013 TW_Command_Full *full_command_packet;
1014 TW_Initconnect *tw_initconnect;
1015 int request_id = 0, retval = 1;
1016
1017 /* Initialize InitConnection command packet */
1018 full_command_packet = tw_dev->command_packet_virt[request_id];
1019 memset(full_command_packet, 0, sizeof(TW_Command_Full));
1020 full_command_packet->header.header_desc.size_header = 128;
1021
1022 tw_initconnect = (TW_Initconnect *)&full_command_packet->command.oldcommand;
1023 tw_initconnect->opcode__reserved = TW_OPRES_IN(0, TW_OP_INIT_CONNECTION);
1024 tw_initconnect->request_id = request_id;
1025 tw_initconnect->message_credits = cpu_to_le16(message_credits);
1026 tw_initconnect->features = set_features;
1027
1028 /* Turn on 64-bit sgl support if we need to */
1029 tw_initconnect->features |= sizeof(dma_addr_t) > 4 ? 1 : 0;
1030
1031 tw_initconnect->features = cpu_to_le32(tw_initconnect->features);
1032
1033 if (set_features & TW_EXTENDED_INIT_CONNECT) {
1034 tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE_EXTENDED;
1035 tw_initconnect->fw_srl = cpu_to_le16(current_fw_srl);
1036 tw_initconnect->fw_arch_id = cpu_to_le16(current_fw_arch_id);
1037 tw_initconnect->fw_branch = cpu_to_le16(current_fw_branch);
1038 tw_initconnect->fw_build = cpu_to_le16(current_fw_build);
1039 } else
1040 tw_initconnect->size = TW_INIT_COMMAND_PACKET_SIZE;
1041
1042 /* Send command packet to the board */
1043 twl_post_command_packet(tw_dev, request_id);
1044
1045 /* Poll for completion */
1046 if (twl_poll_response(tw_dev, request_id, 30)) {
1047 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x8, "No valid response during init connection");
1048 } else {
1049 if (set_features & TW_EXTENDED_INIT_CONNECT) {
1050 *fw_on_ctlr_srl = le16_to_cpu(tw_initconnect->fw_srl);
1051 *fw_on_ctlr_arch_id = le16_to_cpu(tw_initconnect->fw_arch_id);
1052 *fw_on_ctlr_branch = le16_to_cpu(tw_initconnect->fw_branch);
1053 *fw_on_ctlr_build = le16_to_cpu(tw_initconnect->fw_build);
1054 *init_connect_result = le32_to_cpu(tw_initconnect->result);
1055 }
1056 retval = 0;
1057 }
1058
1059 tw_dev->posted_request_count--;
1060 tw_dev->state[request_id] = TW_S_INITIAL;
1061
1062 return retval;
1063} /* End twl_initconnection() */
1064
1065/* This function will initialize the fields of a device extension */
1066static int twl_initialize_device_extension(TW_Device_Extension *tw_dev)
1067{
1068 int i, retval = 1;
1069
1070 /* Initialize command packet buffers */
1071 if (twl_allocate_memory(tw_dev, sizeof(TW_Command_Full), 0)) {
1072 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x9, "Command packet memory allocation failed");
1073 goto out;
1074 }
1075
1076 /* Initialize generic buffer */
1077 if (twl_allocate_memory(tw_dev, TW_SECTOR_SIZE, 1)) {
1078 TW_PRINTK(tw_dev->host, TW_DRIVER, 0xa, "Generic memory allocation failed");
1079 goto out;
1080 }
1081
1082 /* Allocate sense buffers */
1083 if (twl_allocate_memory(tw_dev, sizeof(TW_Command_Apache_Header), 2)) {
1084 TW_PRINTK(tw_dev->host, TW_DRIVER, 0xb, "Sense buffer allocation failed");
1085 goto out;
1086 }
1087
1088 /* Allocate event info space */
1089 tw_dev->event_queue[0] = kcalloc(TW_Q_LENGTH, sizeof(TW_Event), GFP_KERNEL);
1090 if (!tw_dev->event_queue[0]) {
1091 TW_PRINTK(tw_dev->host, TW_DRIVER, 0xc, "Event info memory allocation failed");
1092 goto out;
1093 }
1094
1095 for (i = 0; i < TW_Q_LENGTH; i++) {
1096 tw_dev->event_queue[i] = (TW_Event *)((unsigned char *)tw_dev->event_queue[0] + (i * sizeof(TW_Event)));
1097 tw_dev->free_queue[i] = i;
1098 tw_dev->state[i] = TW_S_INITIAL;
1099 }
1100
1101 tw_dev->free_head = TW_Q_START;
1102 tw_dev->free_tail = TW_Q_START;
1103 tw_dev->error_sequence_id = 1;
1104 tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
1105
1106 mutex_init(&tw_dev->ioctl_lock);
1107 init_waitqueue_head(&tw_dev->ioctl_wqueue);
1108
1109 retval = 0;
1110out:
1111 return retval;
1112} /* End twl_initialize_device_extension() */
1113
1114/* This function will perform a pci-dma unmap */
1115static void twl_unmap_scsi_data(TW_Device_Extension *tw_dev, int request_id)
1116{
1117 struct scsi_cmnd *cmd = tw_dev->srb[request_id];
1118
1119 if (cmd->SCp.phase == TW_PHASE_SGLIST)
1120 scsi_dma_unmap(cmd);
1121} /* End twl_unmap_scsi_data() */
1122
1123/* This function will handle attention interrupts */
1124static int twl_handle_attention_interrupt(TW_Device_Extension *tw_dev)
1125{
1126 int retval = 1;
1127 u32 request_id, doorbell;
1128
1129 /* Read doorbell status */
1130 doorbell = readl(TWL_HOBDB_REG_ADDR(tw_dev));
1131
1132 /* Check for controller errors */
1133 if (doorbell & TWL_DOORBELL_CONTROLLER_ERROR) {
1134 TW_PRINTK(tw_dev->host, TW_DRIVER, 0xd, "Microcontroller Error: clearing");
1135 goto out;
1136 }
1137
1138 /* Check if we need to perform an AEN drain */
1139 if (doorbell & TWL_DOORBELL_ATTENTION_INTERRUPT) {
1140 if (!(test_and_set_bit(TW_IN_ATTENTION_LOOP, &tw_dev->flags))) {
1141 twl_get_request_id(tw_dev, &request_id);
1142 if (twl_aen_read_queue(tw_dev, request_id)) {
1143 tw_dev->state[request_id] = TW_S_COMPLETED;
1144 twl_free_request_id(tw_dev, request_id);
1145 clear_bit(TW_IN_ATTENTION_LOOP, &tw_dev->flags);
1146 }
1147 }
1148 }
1149
1150 retval = 0;
1151out:
1152 /* Clear doorbell interrupt */
1153 TWL_CLEAR_DB_INTERRUPT(tw_dev);
1154
1155 /* Make sure the clear was flushed by reading it back */
1156 readl(TWL_HOBDBC_REG_ADDR(tw_dev));
1157
1158 return retval;
1159} /* End twl_handle_attention_interrupt() */
1160
1161/* Interrupt service routine */
1162static irqreturn_t twl_interrupt(int irq, void *dev_instance)
1163{
1164 TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance;
1165 int i, handled = 0, error = 0;
1166 dma_addr_t mfa = 0;
1167 u32 reg, regl, regh, response, request_id = 0;
1168 struct scsi_cmnd *cmd;
1169 TW_Command_Full *full_command_packet;
1170
1171 spin_lock(tw_dev->host->host_lock);
1172
1173 /* Read host interrupt status */
1174 reg = readl(TWL_HISTAT_REG_ADDR(tw_dev));
1175
1176 /* Check if this is our interrupt, otherwise bail */
1177 if (!(reg & TWL_HISTATUS_VALID_INTERRUPT))
1178 goto twl_interrupt_bail;
1179
1180 handled = 1;
1181
1182 /* If we are resetting, bail */
1183 if (test_bit(TW_IN_RESET, &tw_dev->flags))
1184 goto twl_interrupt_bail;
1185
1186 /* Attention interrupt */
1187 if (reg & TWL_HISTATUS_ATTENTION_INTERRUPT) {
1188 if (twl_handle_attention_interrupt(tw_dev)) {
1189 TWL_MASK_INTERRUPTS(tw_dev);
1190 goto twl_interrupt_bail;
1191 }
1192 }
1193
1194 /* Response interrupt */
1195 while (reg & TWL_HISTATUS_RESPONSE_INTERRUPT) {
1196 if (sizeof(dma_addr_t) > 4) {
1197 regh = readl(TWL_HOBQPH_REG_ADDR(tw_dev));
1198 regl = readl(TWL_HOBQPL_REG_ADDR(tw_dev));
1199 mfa = ((u64)regh << 32) | regl;
1200 } else
1201 mfa = readl(TWL_HOBQPL_REG_ADDR(tw_dev));
1202
1203 error = 0;
1204 response = (u32)mfa;
1205
1206 /* Check for command packet error */
1207 if (!TW_NOTMFA_OUT(response)) {
1208 for (i=0;i<TW_Q_LENGTH;i++) {
1209 if (tw_dev->sense_buffer_phys[i] == mfa) {
1210 request_id = le16_to_cpu(tw_dev->sense_buffer_virt[i]->header_desc.request_id);
1211 if (tw_dev->srb[request_id] != NULL)
1212 error = twl_fill_sense(tw_dev, i, request_id, 1, 1);
1213 else {
1214 /* Skip ioctl error prints */
1215 if (request_id != tw_dev->chrdev_request_id)
1216 error = twl_fill_sense(tw_dev, i, request_id, 0, 1);
1217 else
1218 memcpy(tw_dev->command_packet_virt[request_id], tw_dev->sense_buffer_virt[i], sizeof(TW_Command_Apache_Header));
1219 }
1220
1221 /* Now re-post the sense buffer */
1222 writel((u32)((u64)tw_dev->sense_buffer_phys[i] >> 32), TWL_HOBQPH_REG_ADDR(tw_dev));
1223 writel((u32)tw_dev->sense_buffer_phys[i], TWL_HOBQPL_REG_ADDR(tw_dev));
1224 break;
1225 }
1226 }
1227 } else
1228 request_id = TW_RESID_OUT(response);
1229
1230 full_command_packet = tw_dev->command_packet_virt[request_id];
1231
1232 /* Check for correct state */
1233 if (tw_dev->state[request_id] != TW_S_POSTED) {
1234 if (tw_dev->srb[request_id] != NULL) {
1235 TW_PRINTK(tw_dev->host, TW_DRIVER, 0xe, "Received a request id that wasn't posted");
1236 TWL_MASK_INTERRUPTS(tw_dev);
1237 goto twl_interrupt_bail;
1238 }
1239 }
1240
1241 /* Check for internal command completion */
1242 if (tw_dev->srb[request_id] == NULL) {
1243 if (request_id != tw_dev->chrdev_request_id) {
1244 if (twl_aen_complete(tw_dev, request_id))
1245 TW_PRINTK(tw_dev->host, TW_DRIVER, 0xf, "Error completing AEN during attention interrupt");
1246 } else {
1247 tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
1248 wake_up(&tw_dev->ioctl_wqueue);
1249 }
1250 } else {
1251 cmd = tw_dev->srb[request_id];
1252
1253 if (!error)
1254 cmd->result = (DID_OK << 16);
1255
1256 /* Report residual bytes for single sgl */
1257 if ((scsi_sg_count(cmd) <= 1) && (full_command_packet->command.newcommand.status == 0)) {
1258 if (full_command_packet->command.newcommand.sg_list[0].length < scsi_bufflen(tw_dev->srb[request_id]))
1259 scsi_set_resid(cmd, scsi_bufflen(cmd) - full_command_packet->command.newcommand.sg_list[0].length);
1260 }
1261
1262 /* Now complete the io */
1263 tw_dev->state[request_id] = TW_S_COMPLETED;
1264 twl_free_request_id(tw_dev, request_id);
1265 tw_dev->posted_request_count--;
1266 tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
1267 twl_unmap_scsi_data(tw_dev, request_id);
1268 }
1269
1270 /* Check for another response interrupt */
1271 reg = readl(TWL_HISTAT_REG_ADDR(tw_dev));
1272 }
1273
1274twl_interrupt_bail:
1275 spin_unlock(tw_dev->host->host_lock);
1276 return IRQ_RETVAL(handled);
1277} /* End twl_interrupt() */
1278
1279/* This function will poll for a register change */
1280static int twl_poll_register(TW_Device_Extension *tw_dev, void *reg, u32 value, u32 result, int seconds)
1281{
1282 unsigned long before;
1283 int retval = 1;
1284 u32 reg_value;
1285
1286 reg_value = readl(reg);
1287 before = jiffies;
1288
1289 while ((reg_value & value) != result) {
1290 reg_value = readl(reg);
1291 if (time_after(jiffies, before + HZ * seconds))
1292 goto out;
1293 msleep(50);
1294 }
1295 retval = 0;
1296out:
1297 return retval;
1298} /* End twl_poll_register() */
1299
1300/* This function will reset a controller */
1301static int twl_reset_sequence(TW_Device_Extension *tw_dev, int soft_reset)
1302{
1303 int retval = 1;
1304 int i = 0;
1305 u32 status = 0;
1306 unsigned short fw_on_ctlr_srl = 0, fw_on_ctlr_arch_id = 0;
1307 unsigned short fw_on_ctlr_branch = 0, fw_on_ctlr_build = 0;
1308 u32 init_connect_result = 0;
1309 int tries = 0;
1310 int do_soft_reset = soft_reset;
1311
1312 while (tries < TW_MAX_RESET_TRIES) {
1313 /* Do a soft reset if one is needed */
1314 if (do_soft_reset) {
1315 TWL_SOFT_RESET(tw_dev);
1316
1317 /* Make sure controller is in a good state */
1318 if (twl_poll_register(tw_dev, TWL_SCRPD3_REG_ADDR(tw_dev), TWL_CONTROLLER_READY, 0x0, 30)) {
1319 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x10, "Controller never went non-ready during reset sequence");
1320 tries++;
1321 continue;
1322 }
1323 if (twl_poll_register(tw_dev, TWL_SCRPD3_REG_ADDR(tw_dev), TWL_CONTROLLER_READY, TWL_CONTROLLER_READY, 60)) {
1324 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x11, "Controller not ready during reset sequence");
1325 tries++;
1326 continue;
1327 }
1328 }
1329
1330 /* Initconnect */
1331 if (twl_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS,
1332 TW_EXTENDED_INIT_CONNECT, TW_CURRENT_DRIVER_SRL,
1333 TW_9750_ARCH_ID, TW_CURRENT_DRIVER_BRANCH,
1334 TW_CURRENT_DRIVER_BUILD, &fw_on_ctlr_srl,
1335 &fw_on_ctlr_arch_id, &fw_on_ctlr_branch,
1336 &fw_on_ctlr_build, &init_connect_result)) {
1337 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x12, "Initconnection failed while checking SRL");
1338 do_soft_reset = 1;
1339 tries++;
1340 continue;
1341 }
1342
1343 /* Load sense buffers */
1344 while (i < TW_Q_LENGTH) {
1345 writel((u32)((u64)tw_dev->sense_buffer_phys[i] >> 32), TWL_HOBQPH_REG_ADDR(tw_dev));
1346 writel((u32)tw_dev->sense_buffer_phys[i], TWL_HOBQPL_REG_ADDR(tw_dev));
1347
1348 /* Check status for over-run after each write */
1349 status = readl(TWL_STATUS_REG_ADDR(tw_dev));
1350 if (!(status & TWL_STATUS_OVERRUN_SUBMIT))
1351 i++;
1352 }
1353
1354 /* Now check status */
1355 status = readl(TWL_STATUS_REG_ADDR(tw_dev));
1356 if (status) {
1357 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x13, "Bad controller status after loading sense buffers");
1358 do_soft_reset = 1;
1359 tries++;
1360 continue;
1361 }
1362
1363 /* Drain the AEN queue */
1364 if (twl_aen_drain_queue(tw_dev, soft_reset)) {
1365 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x14, "AEN drain failed during reset sequence");
1366 do_soft_reset = 1;
1367 tries++;
1368 continue;
1369 }
1370
1371 /* Load rest of compatibility struct */
1372 strncpy(tw_dev->tw_compat_info.driver_version, TW_DRIVER_VERSION, strlen(TW_DRIVER_VERSION));
1373 tw_dev->tw_compat_info.driver_srl_high = TW_CURRENT_DRIVER_SRL;
1374 tw_dev->tw_compat_info.driver_branch_high = TW_CURRENT_DRIVER_BRANCH;
1375 tw_dev->tw_compat_info.driver_build_high = TW_CURRENT_DRIVER_BUILD;
1376 tw_dev->tw_compat_info.driver_srl_low = TW_BASE_FW_SRL;
1377 tw_dev->tw_compat_info.driver_branch_low = TW_BASE_FW_BRANCH;
1378 tw_dev->tw_compat_info.driver_build_low = TW_BASE_FW_BUILD;
1379 tw_dev->tw_compat_info.fw_on_ctlr_srl = fw_on_ctlr_srl;
1380 tw_dev->tw_compat_info.fw_on_ctlr_branch = fw_on_ctlr_branch;
1381 tw_dev->tw_compat_info.fw_on_ctlr_build = fw_on_ctlr_build;
1382
1383 /* If we got here, controller is in a good state */
1384 retval = 0;
1385 goto out;
1386 }
1387out:
1388 return retval;
1389} /* End twl_reset_sequence() */
1390
1391/* This function will reset a device extension */
1392static int twl_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset)
1393{
1394 int i = 0, retval = 1;
1395 unsigned long flags = 0;
1396
1397 /* Block SCSI requests while we are resetting */
1398 if (ioctl_reset)
1399 scsi_block_requests(tw_dev->host);
1400
1401 set_bit(TW_IN_RESET, &tw_dev->flags);
1402 TWL_MASK_INTERRUPTS(tw_dev);
1403 TWL_CLEAR_DB_INTERRUPT(tw_dev);
1404
1405 spin_lock_irqsave(tw_dev->host->host_lock, flags);
1406
1407 /* Abort all requests that are in progress */
1408 for (i = 0; i < TW_Q_LENGTH; i++) {
1409 if ((tw_dev->state[i] != TW_S_FINISHED) &&
1410 (tw_dev->state[i] != TW_S_INITIAL) &&
1411 (tw_dev->state[i] != TW_S_COMPLETED)) {
1412 if (tw_dev->srb[i]) {
1413 tw_dev->srb[i]->result = (DID_RESET << 16);
1414 tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);
1415 twl_unmap_scsi_data(tw_dev, i);
1416 }
1417 }
1418 }
1419
1420 /* Reset queues and counts */
1421 for (i = 0; i < TW_Q_LENGTH; i++) {
1422 tw_dev->free_queue[i] = i;
1423 tw_dev->state[i] = TW_S_INITIAL;
1424 }
1425 tw_dev->free_head = TW_Q_START;
1426 tw_dev->free_tail = TW_Q_START;
1427 tw_dev->posted_request_count = 0;
1428
1429 spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
1430
1431 if (twl_reset_sequence(tw_dev, 1))
1432 goto out;
1433
1434 TWL_UNMASK_INTERRUPTS(tw_dev);
1435
1436 clear_bit(TW_IN_RESET, &tw_dev->flags);
1437 tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
1438
1439 retval = 0;
1440out:
1441 if (ioctl_reset)
1442 scsi_unblock_requests(tw_dev->host);
1443 return retval;
1444} /* End twl_reset_device_extension() */
1445
1446/* This funciton returns unit geometry in cylinders/heads/sectors */
1447static int twl_scsi_biosparam(struct scsi_device *sdev, struct block_device *bdev, sector_t capacity, int geom[])
1448{
1449 int heads, sectors;
1450 TW_Device_Extension *tw_dev;
1451
1452 tw_dev = (TW_Device_Extension *)sdev->host->hostdata;
1453
1454 if (capacity >= 0x200000) {
1455 heads = 255;
1456 sectors = 63;
1457 } else {
1458 heads = 64;
1459 sectors = 32;
1460 }
1461
1462 geom[0] = heads;
1463 geom[1] = sectors;
1464 geom[2] = sector_div(capacity, heads * sectors); /* cylinders */
1465
1466 return 0;
1467} /* End twl_scsi_biosparam() */
1468
1469/* This is the new scsi eh reset function */
1470static int twl_scsi_eh_reset(struct scsi_cmnd *SCpnt)
1471{
1472 TW_Device_Extension *tw_dev = NULL;
1473 int retval = FAILED;
1474
1475 tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
1476
1477 tw_dev->num_resets++;
1478
1479 sdev_printk(KERN_WARNING, SCpnt->device,
1480 "WARNING: (0x%02X:0x%04X): Command (0x%x) timed out, resetting card.\n",
1481 TW_DRIVER, 0x2c, SCpnt->cmnd[0]);
1482
1483 /* Make sure we are not issuing an ioctl or resetting from ioctl */
1484 mutex_lock(&tw_dev->ioctl_lock);
1485
1486 /* Now reset the card and some of the device extension data */
1487 if (twl_reset_device_extension(tw_dev, 0)) {
1488 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x15, "Controller reset failed during scsi host reset");
1489 goto out;
1490 }
1491
1492 retval = SUCCESS;
1493out:
1494 mutex_unlock(&tw_dev->ioctl_lock);
1495 return retval;
1496} /* End twl_scsi_eh_reset() */
1497
1498/* This is the main scsi queue function to handle scsi opcodes */
1499static int twl_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1500{
1501 int request_id, retval;
1502 TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
1503
1504 /* If we are resetting due to timed out ioctl, report as busy */
1505 if (test_bit(TW_IN_RESET, &tw_dev->flags)) {
1506 retval = SCSI_MLQUEUE_HOST_BUSY;
1507 goto out;
1508 }
1509
1510 /* Save done function into scsi_cmnd struct */
1511 SCpnt->scsi_done = done;
1512
1513 /* Get a free request id */
1514 twl_get_request_id(tw_dev, &request_id);
1515
1516 /* Save the scsi command for use by the ISR */
1517 tw_dev->srb[request_id] = SCpnt;
1518
1519 /* Initialize phase to zero */
1520 SCpnt->SCp.phase = TW_PHASE_INITIAL;
1521
1522 retval = twl_scsiop_execute_scsi(tw_dev, request_id, NULL, 0, NULL);
1523 if (retval) {
1524 tw_dev->state[request_id] = TW_S_COMPLETED;
1525 twl_free_request_id(tw_dev, request_id);
1526 SCpnt->result = (DID_ERROR << 16);
1527 done(SCpnt);
1528 retval = 0;
1529 }
1530out:
1531 return retval;
1532} /* End twl_scsi_queue() */
1533
1534/* This function tells the controller to shut down */
1535static void __twl_shutdown(TW_Device_Extension *tw_dev)
1536{
1537 /* Disable interrupts */
1538 TWL_MASK_INTERRUPTS(tw_dev);
1539
1540 /* Free up the IRQ */
1541 free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
1542
1543 printk(KERN_WARNING "3w-sas: Shutting down host %d.\n", tw_dev->host->host_no);
1544
1545 /* Tell the card we are shutting down */
1546 if (twl_initconnection(tw_dev, 1, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL)) {
1547 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x16, "Connection shutdown failed");
1548 } else {
1549 printk(KERN_WARNING "3w-sas: Shutdown complete.\n");
1550 }
1551
1552 /* Clear doorbell interrupt just before exit */
1553 TWL_CLEAR_DB_INTERRUPT(tw_dev);
1554} /* End __twl_shutdown() */
1555
1556/* Wrapper for __twl_shutdown */
1557static void twl_shutdown(struct pci_dev *pdev)
1558{
1559 struct Scsi_Host *host = pci_get_drvdata(pdev);
1560 TW_Device_Extension *tw_dev;
1561
1562 if (!host)
1563 return;
1564
1565 tw_dev = (TW_Device_Extension *)host->hostdata;
1566
1567 if (tw_dev->online)
1568 __twl_shutdown(tw_dev);
1569} /* End twl_shutdown() */
1570
1571/* This function configures unit settings when a unit is coming on-line */
1572static int twl_slave_configure(struct scsi_device *sdev)
1573{
1574 /* Force 60 second timeout */
1575 blk_queue_rq_timeout(sdev->request_queue, 60 * HZ);
1576
1577 return 0;
1578} /* End twl_slave_configure() */
1579
1580/* scsi_host_template initializer */
1581static struct scsi_host_template driver_template = {
1582 .module = THIS_MODULE,
1583 .name = "3w-sas",
1584 .queuecommand = twl_scsi_queue,
1585 .eh_host_reset_handler = twl_scsi_eh_reset,
1586 .bios_param = twl_scsi_biosparam,
1587 .change_queue_depth = twl_change_queue_depth,
1588 .can_queue = TW_Q_LENGTH-2,
1589 .slave_configure = twl_slave_configure,
1590 .this_id = -1,
1591 .sg_tablesize = TW_LIBERATOR_MAX_SGL_LENGTH,
1592 .max_sectors = TW_MAX_SECTORS,
1593 .cmd_per_lun = TW_MAX_CMDS_PER_LUN,
1594 .use_clustering = ENABLE_CLUSTERING,
1595 .shost_attrs = twl_host_attrs,
1596 .emulated = 1
1597};
1598
1599/* This function will probe and initialize a card */
1600static int __devinit twl_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
1601{
1602 struct Scsi_Host *host = NULL;
1603 TW_Device_Extension *tw_dev;
1604 int retval = -ENODEV;
1605 int *ptr_phycount, phycount=0;
1606
1607 retval = pci_enable_device(pdev);
1608 if (retval) {
1609 TW_PRINTK(host, TW_DRIVER, 0x17, "Failed to enable pci device");
1610 goto out_disable_device;
1611 }
1612
1613 pci_set_master(pdev);
1614 pci_try_set_mwi(pdev);
1615
1616 if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))
1617 || pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)))
1618 if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
1619 || pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
1620 TW_PRINTK(host, TW_DRIVER, 0x18, "Failed to set dma mask");
1621 retval = -ENODEV;
1622 goto out_disable_device;
1623 }
1624
1625 host = scsi_host_alloc(&driver_template, sizeof(TW_Device_Extension));
1626 if (!host) {
1627 TW_PRINTK(host, TW_DRIVER, 0x19, "Failed to allocate memory for device extension");
1628 retval = -ENOMEM;
1629 goto out_disable_device;
1630 }
1631 tw_dev = shost_priv(host);
1632
1633 /* Save values to device extension */
1634 tw_dev->host = host;
1635 tw_dev->tw_pci_dev = pdev;
1636
1637 if (twl_initialize_device_extension(tw_dev)) {
1638 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1a, "Failed to initialize device extension");
1639 goto out_free_device_extension;
1640 }
1641
1642 /* Request IO regions */
1643 retval = pci_request_regions(pdev, "3w-sas");
1644 if (retval) {
1645 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1b, "Failed to get mem region");
1646 goto out_free_device_extension;
1647 }
1648
1649 /* Save base address, use region 1 */
1650 tw_dev->base_addr = pci_iomap(pdev, 1, 0);
1651 if (!tw_dev->base_addr) {
1652 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to ioremap");
1653 goto out_release_mem_region;
1654 }
1655
1656 /* Disable interrupts on the card */
1657 TWL_MASK_INTERRUPTS(tw_dev);
1658
1659 /* Initialize the card */
1660 if (twl_reset_sequence(tw_dev, 0)) {
1661 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1d, "Controller reset failed during probe");
1662 goto out_iounmap;
1663 }
1664
1665 /* Set host specific parameters */
1666 host->max_id = TW_MAX_UNITS;
1667 host->max_cmd_len = TW_MAX_CDB_LEN;
1668 host->max_lun = TW_MAX_LUNS;
1669 host->max_channel = 0;
1670
1671 /* Register the card with the kernel SCSI layer */
1672 retval = scsi_add_host(host, &pdev->dev);
1673 if (retval) {
1674 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1e, "scsi add host failed");
1675 goto out_iounmap;
1676 }
1677
1678 pci_set_drvdata(pdev, host);
1679
1680 printk(KERN_WARNING "3w-sas: scsi%d: Found an LSI 3ware %s Controller at 0x%llx, IRQ: %d.\n",
1681 host->host_no,
1682 (char *)twl_get_param(tw_dev, 1, TW_VERSION_TABLE,
1683 TW_PARAM_MODEL, TW_PARAM_MODEL_LENGTH),
1684 (u64)pci_resource_start(pdev, 1), pdev->irq);
1685
1686 ptr_phycount = twl_get_param(tw_dev, 2, TW_PARAM_PHY_SUMMARY_TABLE,
1687 TW_PARAM_PHYCOUNT, TW_PARAM_PHYCOUNT_LENGTH);
1688 if (ptr_phycount)
1689 phycount = le32_to_cpu(*(int *)ptr_phycount);
1690
1691 printk(KERN_WARNING "3w-sas: scsi%d: Firmware %s, BIOS %s, Phys: %d.\n",
1692 host->host_no,
1693 (char *)twl_get_param(tw_dev, 1, TW_VERSION_TABLE,
1694 TW_PARAM_FWVER, TW_PARAM_FWVER_LENGTH),
1695 (char *)twl_get_param(tw_dev, 2, TW_VERSION_TABLE,
1696 TW_PARAM_BIOSVER, TW_PARAM_BIOSVER_LENGTH),
1697 phycount);
1698
1699 /* Try to enable MSI */
1700 if (use_msi && !pci_enable_msi(pdev))
1701 set_bit(TW_USING_MSI, &tw_dev->flags);
1702
1703 /* Now setup the interrupt handler */
1704 retval = request_irq(pdev->irq, twl_interrupt, IRQF_SHARED, "3w-sas", tw_dev);
1705 if (retval) {
1706 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1f, "Error requesting IRQ");
1707 goto out_remove_host;
1708 }
1709
1710 twl_device_extension_list[twl_device_extension_count] = tw_dev;
1711 twl_device_extension_count++;
1712
1713 /* Re-enable interrupts on the card */
1714 TWL_UNMASK_INTERRUPTS(tw_dev);
1715
1716 /* Finally, scan the host */
1717 scsi_scan_host(host);
1718
1719 /* Add sysfs binary files */
1720 if (sysfs_create_bin_file(&host->shost_dev.kobj, &twl_sysfs_aen_read_attr))
1721 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x20, "Failed to create sysfs binary file: 3ware_aen_read");
1722 if (sysfs_create_bin_file(&host->shost_dev.kobj, &twl_sysfs_compat_info_attr))
1723 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x21, "Failed to create sysfs binary file: 3ware_compat_info");
1724
1725 if (twl_major == -1) {
1726 if ((twl_major = register_chrdev (0, "twl", &twl_fops)) < 0)
1727 TW_PRINTK(host, TW_DRIVER, 0x22, "Failed to register character device");
1728 }
1729 tw_dev->online = 1;
1730 return 0;
1731
1732out_remove_host:
1733 if (test_bit(TW_USING_MSI, &tw_dev->flags))
1734 pci_disable_msi(pdev);
1735 scsi_remove_host(host);
1736out_iounmap:
1737 iounmap(tw_dev->base_addr);
1738out_release_mem_region:
1739 pci_release_regions(pdev);
1740out_free_device_extension:
1741 twl_free_device_extension(tw_dev);
1742 scsi_host_put(host);
1743out_disable_device:
1744 pci_disable_device(pdev);
1745
1746 return retval;
1747} /* End twl_probe() */
1748
1749/* This function is called to remove a device */
1750static void twl_remove(struct pci_dev *pdev)
1751{
1752 struct Scsi_Host *host = pci_get_drvdata(pdev);
1753 TW_Device_Extension *tw_dev;
1754
1755 if (!host)
1756 return;
1757
1758 tw_dev = (TW_Device_Extension *)host->hostdata;
1759
1760 if (!tw_dev->online)
1761 return;
1762
1763 /* Remove sysfs binary files */
1764 sysfs_remove_bin_file(&host->shost_dev.kobj, &twl_sysfs_aen_read_attr);
1765 sysfs_remove_bin_file(&host->shost_dev.kobj, &twl_sysfs_compat_info_attr);
1766
1767 scsi_remove_host(tw_dev->host);
1768
1769 /* Unregister character device */
1770 if (twl_major >= 0) {
1771 unregister_chrdev(twl_major, "twl");
1772 twl_major = -1;
1773 }
1774
1775 /* Shutdown the card */
1776 __twl_shutdown(tw_dev);
1777
1778 /* Disable MSI if enabled */
1779 if (test_bit(TW_USING_MSI, &tw_dev->flags))
1780 pci_disable_msi(pdev);
1781
1782 /* Free IO remapping */
1783 iounmap(tw_dev->base_addr);
1784
1785 /* Free up the mem region */
1786 pci_release_regions(pdev);
1787
1788 /* Free up device extension resources */
1789 twl_free_device_extension(tw_dev);
1790
1791 scsi_host_put(tw_dev->host);
1792 pci_disable_device(pdev);
1793 twl_device_extension_count--;
1794} /* End twl_remove() */
1795
1796#ifdef CONFIG_PM
1797/* This function is called on PCI suspend */
1798static int twl_suspend(struct pci_dev *pdev, pm_message_t state)
1799{
1800 struct Scsi_Host *host = pci_get_drvdata(pdev);
1801 TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
1802
1803 printk(KERN_WARNING "3w-sas: Suspending host %d.\n", tw_dev->host->host_no);
1804 /* Disable interrupts */
1805 TWL_MASK_INTERRUPTS(tw_dev);
1806
1807 free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
1808
1809 /* Tell the card we are shutting down */
1810 if (twl_initconnection(tw_dev, 1, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL)) {
1811 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x23, "Connection shutdown failed during suspend");
1812 } else {
1813 printk(KERN_WARNING "3w-sas: Suspend complete.\n");
1814 }
1815
1816 /* Clear doorbell interrupt */
1817 TWL_CLEAR_DB_INTERRUPT(tw_dev);
1818
1819 pci_save_state(pdev);
1820 pci_disable_device(pdev);
1821 pci_set_power_state(pdev, pci_choose_state(pdev, state));
1822
1823 return 0;
1824} /* End twl_suspend() */
1825
1826/* This function is called on PCI resume */
1827static int twl_resume(struct pci_dev *pdev)
1828{
1829 int retval = 0;
1830 struct Scsi_Host *host = pci_get_drvdata(pdev);
1831 TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
1832
1833 printk(KERN_WARNING "3w-sas: Resuming host %d.\n", tw_dev->host->host_no);
1834 pci_set_power_state(pdev, PCI_D0);
1835 pci_enable_wake(pdev, PCI_D0, 0);
1836 pci_restore_state(pdev);
1837
1838 retval = pci_enable_device(pdev);
1839 if (retval) {
1840 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x24, "Enable device failed during resume");
1841 return retval;
1842 }
1843
1844 pci_set_master(pdev);
1845 pci_try_set_mwi(pdev);
1846
1847 if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64))
1848 || pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)))
1849 if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))
1850 || pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
1851 TW_PRINTK(host, TW_DRIVER, 0x25, "Failed to set dma mask during resume");
1852 retval = -ENODEV;
1853 goto out_disable_device;
1854 }
1855
1856 /* Initialize the card */
1857 if (twl_reset_sequence(tw_dev, 0)) {
1858 retval = -ENODEV;
1859 goto out_disable_device;
1860 }
1861
1862 /* Now setup the interrupt handler */
1863 retval = request_irq(pdev->irq, twl_interrupt, IRQF_SHARED, "3w-sas", tw_dev);
1864 if (retval) {
1865 TW_PRINTK(tw_dev->host, TW_DRIVER, 0x26, "Error requesting IRQ during resume");
1866 retval = -ENODEV;
1867 goto out_disable_device;
1868 }
1869
1870 /* Now enable MSI if enabled */
1871 if (test_bit(TW_USING_MSI, &tw_dev->flags))
1872 pci_enable_msi(pdev);
1873
1874 /* Re-enable interrupts on the card */
1875 TWL_UNMASK_INTERRUPTS(tw_dev);
1876
1877 printk(KERN_WARNING "3w-sas: Resume complete.\n");
1878 return 0;
1879
1880out_disable_device:
1881 scsi_remove_host(host);
1882 pci_disable_device(pdev);
1883
1884 return retval;
1885} /* End twl_resume() */
1886#endif
1887
1888/* PCI Devices supported by this driver */
1889static struct pci_device_id twl_pci_tbl[] __devinitdata = {
1890 { PCI_VDEVICE(3WARE, PCI_DEVICE_ID_3WARE_9750) },
1891 { }
1892};
1893MODULE_DEVICE_TABLE(pci, twl_pci_tbl);
1894
1895/* pci_driver initializer */
1896static struct pci_driver twl_driver = {
1897 .name = "3w-sas",
1898 .id_table = twl_pci_tbl,
1899 .probe = twl_probe,
1900 .remove = twl_remove,
1901#ifdef CONFIG_PM
1902 .suspend = twl_suspend,
1903 .resume = twl_resume,
1904#endif
1905 .shutdown = twl_shutdown
1906};
1907
1908/* This function is called on driver initialization */
1909static int __init twl_init(void)
1910{
1911 printk(KERN_INFO "LSI 3ware SAS/SATA-RAID Controller device driver for Linux v%s.\n", TW_DRIVER_VERSION);
1912
1913 return pci_register_driver(&twl_driver);
1914} /* End twl_init() */
1915
1916/* This function is called on driver exit */
1917static void __exit twl_exit(void)
1918{
1919 pci_unregister_driver(&twl_driver);
1920} /* End twl_exit() */
1921
1922module_init(twl_init);
1923module_exit(twl_exit);
1924
diff --git a/drivers/scsi/3w-sas.h b/drivers/scsi/3w-sas.h
new file mode 100644
index 000000000000..d474892701d4
--- /dev/null
+++ b/drivers/scsi/3w-sas.h
@@ -0,0 +1,396 @@
1/*
2 3w-sas.h -- LSI 3ware SAS/SATA-RAID Controller device driver for Linux.
3
4 Written By: Adam Radford <linuxraid@lsi.com>
5
6 Copyright (C) 2009 LSI Corporation.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; version 2 of the License.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 NO WARRANTY
18 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
19 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
20 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
21 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
22 solely responsible for determining the appropriateness of using and
23 distributing the Program and assumes all risks associated with its
24 exercise of rights under this Agreement, including but not limited to
25 the risks and costs of program errors, damage to or loss of data,
26 programs or equipment, and unavailability or interruption of operations.
27
28 DISCLAIMER OF LIABILITY
29 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
30 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
32 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
33 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
34 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
35 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
36
37 You should have received a copy of the GNU General Public License
38 along with this program; if not, write to the Free Software
39 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
40
41 Bugs/Comments/Suggestions should be mailed to:
42 linuxraid@lsi.com
43
44 For more information, goto:
45 http://www.lsi.com
46*/
47
48#ifndef _3W_SAS_H
49#define _3W_SAS_H
50
51/* AEN severity table */
52static char *twl_aen_severity_table[] =
53{
54 "None", "ERROR", "WARNING", "INFO", "DEBUG", NULL
55};
56
57/* Liberator register offsets */
58#define TWL_STATUS 0x0 /* Status */
59#define TWL_HIBDB 0x20 /* Inbound doorbell */
60#define TWL_HISTAT 0x30 /* Host interrupt status */
61#define TWL_HIMASK 0x34 /* Host interrupt mask */
62#define TWL_HOBDB 0x9C /* Outbound doorbell */
63#define TWL_HOBDBC 0xA0 /* Outbound doorbell clear */
64#define TWL_SCRPD3 0xBC /* Scratchpad */
65#define TWL_HIBQPL 0xC0 /* Host inbound Q low */
66#define TWL_HIBQPH 0xC4 /* Host inbound Q high */
67#define TWL_HOBQPL 0xC8 /* Host outbound Q low */
68#define TWL_HOBQPH 0xCC /* Host outbound Q high */
69#define TWL_HISTATUS_VALID_INTERRUPT 0xC
70#define TWL_HISTATUS_ATTENTION_INTERRUPT 0x4
71#define TWL_HISTATUS_RESPONSE_INTERRUPT 0x8
72#define TWL_STATUS_OVERRUN_SUBMIT 0x2000
73#define TWL_ISSUE_SOFT_RESET 0x100
74#define TWL_CONTROLLER_READY 0x2000
75#define TWL_DOORBELL_CONTROLLER_ERROR 0x200000
76#define TWL_DOORBELL_ATTENTION_INTERRUPT 0x40000
77#define TWL_PULL_MODE 0x1
78
79/* Command packet opcodes used by the driver */
80#define TW_OP_INIT_CONNECTION 0x1
81#define TW_OP_GET_PARAM 0x12
82#define TW_OP_SET_PARAM 0x13
83#define TW_OP_EXECUTE_SCSI 0x10
84
85/* Asynchronous Event Notification (AEN) codes used by the driver */
86#define TW_AEN_QUEUE_EMPTY 0x0000
87#define TW_AEN_SOFT_RESET 0x0001
88#define TW_AEN_SYNC_TIME_WITH_HOST 0x031
89#define TW_AEN_SEVERITY_ERROR 0x1
90#define TW_AEN_SEVERITY_DEBUG 0x4
91#define TW_AEN_NOT_RETRIEVED 0x1
92
93/* Command state defines */
94#define TW_S_INITIAL 0x1 /* Initial state */
95#define TW_S_STARTED 0x2 /* Id in use */
96#define TW_S_POSTED 0x4 /* Posted to the controller */
97#define TW_S_COMPLETED 0x8 /* Completed by isr */
98#define TW_S_FINISHED 0x10 /* I/O completely done */
99
100/* Compatibility defines */
101#define TW_9750_ARCH_ID 10
102#define TW_CURRENT_DRIVER_SRL 40
103#define TW_CURRENT_DRIVER_BUILD 0
104#define TW_CURRENT_DRIVER_BRANCH 0
105
106/* Phase defines */
107#define TW_PHASE_INITIAL 0
108#define TW_PHASE_SGLIST 2
109
110/* Misc defines */
111#define TW_SECTOR_SIZE 512
112#define TW_MAX_UNITS 32
113#define TW_INIT_MESSAGE_CREDITS 0x100
114#define TW_INIT_COMMAND_PACKET_SIZE 0x3
115#define TW_INIT_COMMAND_PACKET_SIZE_EXTENDED 0x6
116#define TW_EXTENDED_INIT_CONNECT 0x2
117#define TW_BASE_FW_SRL 24
118#define TW_BASE_FW_BRANCH 0
119#define TW_BASE_FW_BUILD 1
120#define TW_Q_LENGTH 256
121#define TW_Q_START 0
122#define TW_MAX_SLOT 32
123#define TW_MAX_RESET_TRIES 2
124#define TW_MAX_CMDS_PER_LUN 254
125#define TW_MAX_AEN_DRAIN 255
126#define TW_IN_RESET 2
127#define TW_USING_MSI 3
128#define TW_IN_ATTENTION_LOOP 4
129#define TW_MAX_SECTORS 256
130#define TW_MAX_CDB_LEN 16
131#define TW_IOCTL_CHRDEV_TIMEOUT 60 /* 60 seconds */
132#define TW_IOCTL_CHRDEV_FREE -1
133#define TW_COMMAND_OFFSET 128 /* 128 bytes */
134#define TW_VERSION_TABLE 0x0402
135#define TW_TIMEKEEP_TABLE 0x040A
136#define TW_INFORMATION_TABLE 0x0403
137#define TW_PARAM_FWVER 3
138#define TW_PARAM_FWVER_LENGTH 16
139#define TW_PARAM_BIOSVER 4
140#define TW_PARAM_BIOSVER_LENGTH 16
141#define TW_PARAM_MODEL 8
142#define TW_PARAM_MODEL_LENGTH 16
143#define TW_PARAM_PHY_SUMMARY_TABLE 1
144#define TW_PARAM_PHYCOUNT 2
145#define TW_PARAM_PHYCOUNT_LENGTH 1
146#define TW_IOCTL_FIRMWARE_PASS_THROUGH 0x108 // Used by smartmontools
147#define TW_ALLOCATION_LENGTH 128
148#define TW_SENSE_DATA_LENGTH 18
149#define TW_ERROR_LOGICAL_UNIT_NOT_SUPPORTED 0x10a
150#define TW_ERROR_INVALID_FIELD_IN_CDB 0x10d
151#define TW_ERROR_UNIT_OFFLINE 0x128
152#define TW_MESSAGE_SOURCE_CONTROLLER_ERROR 3
153#define TW_MESSAGE_SOURCE_CONTROLLER_EVENT 4
154#define TW_DRIVER 6
155#ifndef PCI_DEVICE_ID_3WARE_9750
156#define PCI_DEVICE_ID_3WARE_9750 0x1010
157#endif
158
159/* Bitmask macros to eliminate bitfields */
160
161/* opcode: 5, reserved: 3 */
162#define TW_OPRES_IN(x,y) ((x << 5) | (y & 0x1f))
163#define TW_OP_OUT(x) (x & 0x1f)
164
165/* opcode: 5, sgloffset: 3 */
166#define TW_OPSGL_IN(x,y) ((x << 5) | (y & 0x1f))
167#define TW_SGL_OUT(x) ((x >> 5) & 0x7)
168
169/* severity: 3, reserved: 5 */
170#define TW_SEV_OUT(x) (x & 0x7)
171
172/* not_mfa: 1, reserved: 7, status: 8, request_id: 16 */
173#define TW_RESID_OUT(x) ((x >> 16) & 0xffff)
174#define TW_NOTMFA_OUT(x) (x & 0x1)
175
176/* request_id: 12, lun: 4 */
177#define TW_REQ_LUN_IN(lun, request_id) (((lun << 12) & 0xf000) | (request_id & 0xfff))
178#define TW_LUN_OUT(lun) ((lun >> 12) & 0xf)
179
180/* Register access macros */
181#define TWL_STATUS_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + TWL_STATUS)
182#define TWL_HOBQPL_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + TWL_HOBQPL)
183#define TWL_HOBQPH_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + TWL_HOBQPH)
184#define TWL_HOBDB_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + TWL_HOBDB)
185#define TWL_HOBDBC_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + TWL_HOBDBC)
186#define TWL_HIMASK_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + TWL_HIMASK)
187#define TWL_HISTAT_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + TWL_HISTAT)
188#define TWL_HIBQPH_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + TWL_HIBQPH)
189#define TWL_HIBQPL_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + TWL_HIBQPL)
190#define TWL_HIBDB_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + TWL_HIBDB)
191#define TWL_SCRPD3_REG_ADDR(x) ((unsigned char __iomem *)x->base_addr + TWL_SCRPD3)
192#define TWL_MASK_INTERRUPTS(x) (writel(~0, TWL_HIMASK_REG_ADDR(tw_dev)))
193#define TWL_UNMASK_INTERRUPTS(x) (writel(~TWL_HISTATUS_VALID_INTERRUPT, TWL_HIMASK_REG_ADDR(tw_dev)))
194#define TWL_CLEAR_DB_INTERRUPT(x) (writel(~0, TWL_HOBDBC_REG_ADDR(tw_dev)))
195#define TWL_SOFT_RESET(x) (writel(TWL_ISSUE_SOFT_RESET, TWL_HIBDB_REG_ADDR(tw_dev)))
196
197/* Macros */
198#define TW_PRINTK(h,a,b,c) { \
199if (h) \
200printk(KERN_WARNING "3w-sas: scsi%d: ERROR: (0x%02X:0x%04X): %s.\n",h->host_no,a,b,c); \
201else \
202printk(KERN_WARNING "3w-sas: ERROR: (0x%02X:0x%04X): %s.\n",a,b,c); \
203}
204#define TW_MAX_LUNS 16
205#define TW_COMMAND_SIZE (sizeof(dma_addr_t) > 4 ? 6 : 4)
206#define TW_LIBERATOR_MAX_SGL_LENGTH (sizeof(dma_addr_t) > 4 ? 46 : 92)
207#define TW_LIBERATOR_MAX_SGL_LENGTH_OLD (sizeof(dma_addr_t) > 4 ? 47 : 94)
208#define TW_PADDING_LENGTH_LIBERATOR 136
209#define TW_PADDING_LENGTH_LIBERATOR_OLD 132
210#define TW_CPU_TO_SGL(x) (sizeof(dma_addr_t) > 4 ? cpu_to_le64(x) : cpu_to_le32(x))
211
212#pragma pack(1)
213
214/* SGL entry */
215typedef struct TAG_TW_SG_Entry_ISO {
216 dma_addr_t address;
217 dma_addr_t length;
218} TW_SG_Entry_ISO;
219
220/* Old Command Packet with ISO SGL */
221typedef struct TW_Command {
222 unsigned char opcode__sgloffset;
223 unsigned char size;
224 unsigned char request_id;
225 unsigned char unit__hostid;
226 /* Second DWORD */
227 unsigned char status;
228 unsigned char flags;
229 union {
230 unsigned short block_count;
231 unsigned short parameter_count;
232 } byte6_offset;
233 union {
234 struct {
235 u32 lba;
236 TW_SG_Entry_ISO sgl[TW_LIBERATOR_MAX_SGL_LENGTH_OLD];
237 unsigned char padding[TW_PADDING_LENGTH_LIBERATOR_OLD];
238 } io;
239 struct {
240 TW_SG_Entry_ISO sgl[TW_LIBERATOR_MAX_SGL_LENGTH_OLD];
241 u32 padding;
242 unsigned char padding2[TW_PADDING_LENGTH_LIBERATOR_OLD];
243 } param;
244 } byte8_offset;
245} TW_Command;
246
247/* New Command Packet with ISO SGL */
248typedef struct TAG_TW_Command_Apache {
249 unsigned char opcode__reserved;
250 unsigned char unit;
251 unsigned short request_id__lunl;
252 unsigned char status;
253 unsigned char sgl_offset;
254 unsigned short sgl_entries__lunh;
255 unsigned char cdb[16];
256 TW_SG_Entry_ISO sg_list[TW_LIBERATOR_MAX_SGL_LENGTH];
257 unsigned char padding[TW_PADDING_LENGTH_LIBERATOR];
258} TW_Command_Apache;
259
260/* New command packet header */
261typedef struct TAG_TW_Command_Apache_Header {
262 unsigned char sense_data[TW_SENSE_DATA_LENGTH];
263 struct {
264 char reserved[4];
265 unsigned short error;
266 unsigned char padding;
267 unsigned char severity__reserved;
268 } status_block;
269 unsigned char err_specific_desc[98];
270 struct {
271 unsigned char size_header;
272 unsigned short request_id;
273 unsigned char size_sense;
274 } header_desc;
275} TW_Command_Apache_Header;
276
277/* This struct is a union of the 2 command packets */
278typedef struct TAG_TW_Command_Full {
279 TW_Command_Apache_Header header;
280 union {
281 TW_Command oldcommand;
282 TW_Command_Apache newcommand;
283 } command;
284} TW_Command_Full;
285
286/* Initconnection structure */
287typedef struct TAG_TW_Initconnect {
288 unsigned char opcode__reserved;
289 unsigned char size;
290 unsigned char request_id;
291 unsigned char res2;
292 unsigned char status;
293 unsigned char flags;
294 unsigned short message_credits;
295 u32 features;
296 unsigned short fw_srl;
297 unsigned short fw_arch_id;
298 unsigned short fw_branch;
299 unsigned short fw_build;
300 u32 result;
301} TW_Initconnect;
302
303/* Event info structure */
304typedef struct TAG_TW_Event
305{
306 unsigned int sequence_id;
307 unsigned int time_stamp_sec;
308 unsigned short aen_code;
309 unsigned char severity;
310 unsigned char retrieved;
311 unsigned char repeat_count;
312 unsigned char parameter_len;
313 unsigned char parameter_data[98];
314} TW_Event;
315
316typedef struct TAG_TW_Ioctl_Driver_Command {
317 unsigned int control_code;
318 unsigned int status;
319 unsigned int unique_id;
320 unsigned int sequence_id;
321 unsigned int os_specific;
322 unsigned int buffer_length;
323} TW_Ioctl_Driver_Command;
324
325typedef struct TAG_TW_Ioctl_Apache {
326 TW_Ioctl_Driver_Command driver_command;
327 char padding[488];
328 TW_Command_Full firmware_command;
329 char data_buffer[1];
330} TW_Ioctl_Buf_Apache;
331
332/* GetParam descriptor */
333typedef struct {
334 unsigned short table_id;
335 unsigned short parameter_id;
336 unsigned short parameter_size_bytes;
337 unsigned short actual_parameter_size_bytes;
338 unsigned char data[1];
339} TW_Param_Apache;
340
341/* Compatibility information structure */
342typedef struct TAG_TW_Compatibility_Info
343{
344 char driver_version[32];
345 unsigned short working_srl;
346 unsigned short working_branch;
347 unsigned short working_build;
348 unsigned short driver_srl_high;
349 unsigned short driver_branch_high;
350 unsigned short driver_build_high;
351 unsigned short driver_srl_low;
352 unsigned short driver_branch_low;
353 unsigned short driver_build_low;
354 unsigned short fw_on_ctlr_srl;
355 unsigned short fw_on_ctlr_branch;
356 unsigned short fw_on_ctlr_build;
357} TW_Compatibility_Info;
358
359#pragma pack()
360
361typedef struct TAG_TW_Device_Extension {
362 void __iomem *base_addr;
363 unsigned long *generic_buffer_virt[TW_Q_LENGTH];
364 dma_addr_t generic_buffer_phys[TW_Q_LENGTH];
365 TW_Command_Full *command_packet_virt[TW_Q_LENGTH];
366 dma_addr_t command_packet_phys[TW_Q_LENGTH];
367 TW_Command_Apache_Header *sense_buffer_virt[TW_Q_LENGTH];
368 dma_addr_t sense_buffer_phys[TW_Q_LENGTH];
369 struct pci_dev *tw_pci_dev;
370 struct scsi_cmnd *srb[TW_Q_LENGTH];
371 unsigned char free_queue[TW_Q_LENGTH];
372 unsigned char free_head;
373 unsigned char free_tail;
374 int state[TW_Q_LENGTH];
375 unsigned int posted_request_count;
376 unsigned int max_posted_request_count;
377 unsigned int max_sgl_entries;
378 unsigned int sgl_entries;
379 unsigned int num_resets;
380 unsigned int sector_count;
381 unsigned int max_sector_count;
382 unsigned int aen_count;
383 struct Scsi_Host *host;
384 long flags;
385 TW_Event *event_queue[TW_Q_LENGTH];
386 unsigned char error_index;
387 unsigned int error_sequence_id;
388 int chrdev_request_id;
389 wait_queue_head_t ioctl_wqueue;
390 struct mutex ioctl_lock;
391 TW_Compatibility_Info tw_compat_info;
392 char online;
393} TW_Device_Extension;
394
395#endif /* _3W_SAS_H */
396
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 1895259fff0f..b4d8d63a34b2 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -399,6 +399,17 @@ config SCSI_3W_9XXX
399 Please read the comments at the top of 399 Please read the comments at the top of
400 <file:drivers/scsi/3w-9xxx.c>. 400 <file:drivers/scsi/3w-9xxx.c>.
401 401
402config SCSI_3W_SAS
403 tristate "3ware 97xx SAS/SATA-RAID support"
404 depends on PCI && SCSI
405 help
406 This driver supports the LSI 3ware 9750 6Gb/s SAS/SATA-RAID cards.
407
408 <http://www.lsi.com>
409
410 Please read the comments at the top of
411 <file:drivers/scsi/3w-sas.c>.
412
402config SCSI_7000FASST 413config SCSI_7000FASST
403 tristate "7000FASST SCSI support" 414 tristate "7000FASST SCSI support"
404 depends on ISA && SCSI && ISA_DMA_API 415 depends on ISA && SCSI && ISA_DMA_API
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 5026bdc7b2b7..280d3c657d60 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -114,6 +114,7 @@ obj-$(CONFIG_SCSI_MESH) += mesh.o
114obj-$(CONFIG_SCSI_MAC53C94) += mac53c94.o 114obj-$(CONFIG_SCSI_MAC53C94) += mac53c94.o
115obj-$(CONFIG_BLK_DEV_3W_XXXX_RAID) += 3w-xxxx.o 115obj-$(CONFIG_BLK_DEV_3W_XXXX_RAID) += 3w-xxxx.o
116obj-$(CONFIG_SCSI_3W_9XXX) += 3w-9xxx.o 116obj-$(CONFIG_SCSI_3W_9XXX) += 3w-9xxx.o
117obj-$(CONFIG_SCSI_3W_SAS) += 3w-sas.o
117obj-$(CONFIG_SCSI_PPA) += ppa.o 118obj-$(CONFIG_SCSI_PPA) += ppa.o
118obj-$(CONFIG_SCSI_IMM) += imm.o 119obj-$(CONFIG_SCSI_IMM) += imm.o
119obj-$(CONFIG_JAZZ_ESP) += esp_scsi.o jazz_esp.o 120obj-$(CONFIG_JAZZ_ESP) += esp_scsi.o jazz_esp.o