blob: 5faf903ca8c8257f879c9c07f7b77dbb242fa496 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 3w-xxxx.c -- 3ware Storage Controller device driver for Linux.
3
4 Written By: Adam Radford <linuxraid@amcc.com>
5 Modifications By: Joel Jacobson <linux@3ware.com>
6 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
7 Brad Strand <linux@3ware.com>
8
adam radford7b14f582009-05-11 14:55:55 -07009 Copyright (C) 1999-2009 3ware Inc.
Linus Torvalds1da177e2005-04-16 15:20:36 -070010
Dirk Hohndel06fe9fb2009-09-28 21:43:57 -040011 Kernel compatibility By: Andre Hedrick <andre@suse.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -070012 Non-Copyright (C) 2000 Andre Hedrick <andre@suse.com>
13
14 Further tiny build fixes and trivial hoovering Alan Cox
15
16 This program is free software; you can redistribute it and/or modify
17 it under the terms of the GNU General Public License as published by
18 the Free Software Foundation; version 2 of the License.
19
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
24
25 NO WARRANTY
26 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
27 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
28 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
29 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
30 solely responsible for determining the appropriateness of using and
31 distributing the Program and assumes all risks associated with its
32 exercise of rights under this Agreement, including but not limited to
33 the risks and costs of program errors, damage to or loss of data,
34 programs or equipment, and unavailability or interruption of operations.
35
36 DISCLAIMER OF LIABILITY
37 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
38 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
40 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
41 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
42 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
43 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
44
45 You should have received a copy of the GNU General Public License
46 along with this program; if not, write to the Free Software
47 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
48
49 Bugs/Comments/Suggestions should be mailed to:
50 linuxraid@amcc.com
51
52 For more information, goto:
53 http://www.amcc.com
54
55 History
56 -------
57 0.1.000 - Initial release.
58 0.4.000 - Added support for Asynchronous Event Notification through
59 ioctls for 3DM.
60 1.0.000 - Added DPO & FUA bit support for WRITE_10 & WRITE_6 cdb
61 to disable drive write-cache before writes.
62 1.1.000 - Fixed performance bug with DPO & FUA not existing for WRITE_6.
63 1.2.000 - Added support for clean shutdown notification/feature table.
64 1.02.00.001 - Added support for full command packet posts through ioctls
65 for 3DM.
66 Bug fix so hot spare drives don't show up.
67 1.02.00.002 - Fix bug with tw_setfeature() call that caused oops on some
68 systems.
69 08/21/00 - release previously allocated resources on failure at
70 tw_allocate_memory (acme)
71 1.02.00.003 - Fix tw_interrupt() to report error to scsi layer when
72 controller status is non-zero.
73 Added handling of request_sense opcode.
74 Fix possible null pointer dereference in
75 tw_reset_device_extension()
76 1.02.00.004 - Add support for device id of 3ware 7000 series controllers.
77 Make tw_setfeature() call with interrupts disabled.
78 Register interrupt handler before enabling interrupts.
79 Clear attention interrupt before draining aen queue.
80 1.02.00.005 - Allocate bounce buffers and custom queue depth for raid5 for
81 6000 and 5000 series controllers.
82 Reduce polling mdelays causing problems on some systems.
83 Fix use_sg = 1 calculation bug.
84 Check for scsi_register returning NULL.
85 Add aen count to /proc/scsi/3w-xxxx.
86 Remove aen code unit masking in tw_aen_complete().
87 1.02.00.006 - Remove unit from printk in tw_scsi_eh_abort(), causing
88 possible oops.
89 Fix possible null pointer dereference in tw_scsi_queue()
90 if done function pointer was invalid.
91 1.02.00.007 - Fix possible null pointer dereferences in tw_ioctl().
92 Remove check for invalid done function pointer from
93 tw_scsi_queue().
94 1.02.00.008 - Set max sectors per io to TW_MAX_SECTORS in tw_findcards().
95 Add tw_decode_error() for printing readable error messages.
96 Print some useful information on certain aen codes.
97 Add tw_decode_bits() for interpreting status register output.
98 Make scsi_set_pci_device() for kernels >= 2.4.4
99 Fix bug where aen's could be lost before a reset.
100 Re-add spinlocks in tw_scsi_detect().
101 Fix possible null pointer dereference in tw_aen_drain_queue()
102 during initialization.
103 Clear pci parity errors during initialization and during io.
104 1.02.00.009 - Remove redundant increment in tw_state_request_start().
105 Add ioctl support for direct ATA command passthru.
106 Add entire aen code string list.
107 1.02.00.010 - Cleanup queueing code, fix jbod thoughput.
108 Fix get_param for specific units.
109 1.02.00.011 - Fix bug in tw_aen_complete() where aen's could be lost.
110 Fix tw_aen_drain_queue() to display useful info at init.
111 Set tw_host->max_id for 12 port cards.
112 Add ioctl support for raw command packet post from userspace
113 with sglist fragments (parameter and io).
114 1.02.00.012 - Fix read capacity to under report by 1 sector to fix get
115 last sector ioctl.
116 1.02.00.013 - Fix bug where more AEN codes weren't coming out during
117 driver initialization.
118 Improved handling of PCI aborts.
119 1.02.00.014 - Fix bug in tw_findcards() where AEN code could be lost.
120 Increase timeout in tw_aen_drain_queue() to 30 seconds.
121 1.02.00.015 - Re-write raw command post with data ioctl method.
122 Remove raid5 bounce buffers for raid5 for 6XXX for kernel 2.5
123 Add tw_map/unmap_scsi_sg/single_data() for kernel 2.5
124 Replace io_request_lock with host_lock for kernel 2.5
125 Set max_cmd_len to 16 for 3dm for kernel 2.5
126 1.02.00.016 - Set host->max_sectors back up to 256.
127 1.02.00.017 - Modified pci parity error handling/clearing from config space
128 during initialization.
129 1.02.00.018 - Better handling of request sense opcode and sense information
130 for failed commands. Add tw_decode_sense().
131 Replace all mdelay()'s with scsi_sleep().
132 1.02.00.019 - Revert mdelay's and scsi_sleep's, this caused problems on
133 some SMP systems.
134 1.02.00.020 - Add pci_set_dma_mask(), rewrite kmalloc()/virt_to_bus() to
135 pci_alloc/free_consistent().
136 Better alignment checking in tw_allocate_memory().
137 Cleanup tw_initialize_device_extension().
138 1.02.00.021 - Bump cmd_per_lun in SHT to 255 for better jbod performance.
139 Improve handling of errors in tw_interrupt().
140 Add handling/clearing of controller queue error.
141 Empty stale responses before draining aen queue.
142 Fix tw_scsi_eh_abort() to not reset on every io abort.
143 Set can_queue in SHT to 255 to prevent hang from AEN.
144 1.02.00.022 - Fix possible null pointer dereference in tw_scsi_release().
145 1.02.00.023 - Fix bug in tw_aen_drain_queue() where unit # was always zero.
146 1.02.00.024 - Add severity levels to AEN strings.
147 1.02.00.025 - Fix command interrupt spurious error messages.
148 Fix bug in raw command post with data ioctl method.
149 Fix bug where rollcall sometimes failed with cable errors.
150 Print unit # on all command timeouts.
151 1.02.00.026 - Fix possible infinite retry bug with power glitch induced
152 drive timeouts.
153 Cleanup some AEN severity levels.
154 1.02.00.027 - Add drive not supported AEN code for SATA controllers.
155 Remove spurious unknown ioctl error message.
156 1.02.00.028 - Fix bug where multiple controllers with no units were the
157 same card number.
158 Fix bug where cards were being shut down more than once.
159 1.02.00.029 - Add missing pci_free_consistent() in tw_allocate_memory().
160 Replace pci_map_single() with pci_map_page() for highmem.
161 Check for tw_setfeature() failure.
162 1.02.00.030 - Make driver 64-bit clean.
163 1.02.00.031 - Cleanup polling timeouts/routines in several places.
164 Add support for mode sense opcode.
165 Add support for cache mode page.
166 Add support for synchronize cache opcode.
167 1.02.00.032 - Fix small multicard rollcall bug.
168 Make driver stay loaded with no units for hot add/swap.
169 Add support for "twe" character device for ioctls.
170 Clean up request_id queueing code.
171 Fix tw_scsi_queue() spinlocks.
172 1.02.00.033 - Fix tw_aen_complete() to not queue 'queue empty' AEN's.
173 Initialize queues correctly when loading with no valid units.
174 1.02.00.034 - Fix tw_decode_bits() to handle multiple errors.
175 Add support for user configurable cmd_per_lun.
176 Add support for sht->slave_configure().
177 1.02.00.035 - Improve tw_allocate_memory() memory allocation.
178 Fix tw_chrdev_ioctl() to sleep correctly.
179 1.02.00.036 - Increase character ioctl timeout to 60 seconds.
180 1.02.00.037 - Fix tw_ioctl() to handle all non-data ATA passthru cmds
181 for 'smartmontools' support.
182 1.26.00.038 - Roll driver minor version to 26 to denote kernel 2.6.
183 Add support for cmds_per_lun module parameter.
184 1.26.00.039 - Fix bug in tw_chrdev_ioctl() polling code.
185 Fix data_buffer_length usage in tw_chrdev_ioctl().
186 Update contact information.
187 1.26.02.000 - Convert driver to pci_driver format.
188 1.26.02.001 - Increase max ioctl buffer size to 512 sectors.
189 Make tw_scsi_queue() return 0 for 'Unknown scsi opcode'.
190 Fix tw_remove() to free irq handler/unregister_chrdev()
191 before shutting down card.
192 Change to new 'change_queue_depth' api.
193 Fix 'handled=1' ISR usage, remove bogus IRQ check.
adam radford4fe48182007-01-04 18:16:56 -0800194 1.26.02.002 - Free irq handler in __tw_shutdown().
195 Turn on RCD bit for caching mode page.
196 Serialize reset code.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197*/
198
199#include <linux/module.h>
200#include <linux/reboot.h>
Jonathan Corbetf2b98572008-05-18 15:32:43 -0600201#include <linux/smp_lock.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202#include <linux/spinlock.h>
203#include <linux/interrupt.h>
204#include <linux/moduleparam.h>
205#include <linux/errno.h>
206#include <linux/types.h>
207#include <linux/delay.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +0900208#include <linux/gfp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209#include <linux/pci.h>
210#include <linux/time.h>
Jes Sorensena12e25bd2006-01-11 08:39:45 -0500211#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212#include <asm/io.h>
213#include <asm/irq.h>
214#include <asm/uaccess.h>
215#include <scsi/scsi.h>
216#include <scsi/scsi_host.h>
217#include <scsi/scsi_tcq.h>
218#include <scsi/scsi_cmnd.h>
219#include "3w-xxxx.h"
220
221/* Globals */
adam radford4fe48182007-01-04 18:16:56 -0800222#define TW_DRIVER_VERSION "1.26.02.002"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223static TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
224static int tw_device_extension_count = 0;
225static int twe_major = -1;
226
227/* Module parameters */
228MODULE_AUTHOR("AMCC");
229MODULE_DESCRIPTION("3ware Storage Controller Linux Driver");
230MODULE_LICENSE("GPL");
231MODULE_VERSION(TW_DRIVER_VERSION);
232
233/* Function prototypes */
adam radford4fe48182007-01-04 18:16:56 -0800234static int tw_reset_device_extension(TW_Device_Extension *tw_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235
236/* Functions */
237
238/* This function will check the status register for unexpected bits */
239static int tw_check_bits(u32 status_reg_value)
240{
241 if ((status_reg_value & TW_STATUS_EXPECTED_BITS) != TW_STATUS_EXPECTED_BITS) {
242 dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): No expected bits (0x%x).\n", status_reg_value);
243 return 1;
244 }
245 if ((status_reg_value & TW_STATUS_UNEXPECTED_BITS) != 0) {
246 dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): Found unexpected bits (0x%x).\n", status_reg_value);
247 return 1;
248 }
249
250 return 0;
251} /* End tw_check_bits() */
252
253/* This function will print readable messages from status register errors */
254static int tw_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value, int print_host)
255{
256 char host[16];
257
258 dprintk(KERN_WARNING "3w-xxxx: tw_decode_bits()\n");
259
260 if (print_host)
261 sprintf(host, " scsi%d:", tw_dev->host->host_no);
262 else
263 host[0] = '\0';
264
265 if (status_reg_value & TW_STATUS_PCI_PARITY_ERROR) {
266 printk(KERN_WARNING "3w-xxxx:%s PCI Parity Error: clearing.\n", host);
267 outl(TW_CONTROL_CLEAR_PARITY_ERROR, TW_CONTROL_REG_ADDR(tw_dev));
268 }
269
270 if (status_reg_value & TW_STATUS_PCI_ABORT) {
271 printk(KERN_WARNING "3w-xxxx:%s PCI Abort: clearing.\n", host);
272 outl(TW_CONTROL_CLEAR_PCI_ABORT, TW_CONTROL_REG_ADDR(tw_dev));
273 pci_write_config_word(tw_dev->tw_pci_dev, PCI_STATUS, TW_PCI_CLEAR_PCI_ABORT);
274 }
275
276 if (status_reg_value & TW_STATUS_QUEUE_ERROR) {
277 printk(KERN_WARNING "3w-xxxx:%s Controller Queue Error: clearing.\n", host);
278 outl(TW_CONTROL_CLEAR_QUEUE_ERROR, TW_CONTROL_REG_ADDR(tw_dev));
279 }
280
281 if (status_reg_value & TW_STATUS_SBUF_WRITE_ERROR) {
282 printk(KERN_WARNING "3w-xxxx:%s SBUF Write Error: clearing.\n", host);
283 outl(TW_CONTROL_CLEAR_SBUF_WRITE_ERROR, TW_CONTROL_REG_ADDR(tw_dev));
284 }
285
286 if (status_reg_value & TW_STATUS_MICROCONTROLLER_ERROR) {
287 if (tw_dev->reset_print == 0) {
288 printk(KERN_WARNING "3w-xxxx:%s Microcontroller Error: clearing.\n", host);
289 tw_dev->reset_print = 1;
290 }
291 return 1;
292 }
293
294 return 0;
295} /* End tw_decode_bits() */
296
297/* This function will poll the status register for a flag */
298static int tw_poll_status(TW_Device_Extension *tw_dev, u32 flag, int seconds)
299{
300 u32 status_reg_value;
301 unsigned long before;
302 int retval = 1;
303
304 status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
305 before = jiffies;
306
307 if (tw_check_bits(status_reg_value))
308 tw_decode_bits(tw_dev, status_reg_value, 0);
309
310 while ((status_reg_value & flag) != flag) {
311 status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
312
313 if (tw_check_bits(status_reg_value))
314 tw_decode_bits(tw_dev, status_reg_value, 0);
315
316 if (time_after(jiffies, before + HZ * seconds))
317 goto out;
318
319 msleep(50);
320 }
321 retval = 0;
322out:
323 return retval;
324} /* End tw_poll_status() */
325
326/* This function will poll the status register for disappearance of a flag */
327static int tw_poll_status_gone(TW_Device_Extension *tw_dev, u32 flag, int seconds)
328{
329 u32 status_reg_value;
330 unsigned long before;
331 int retval = 1;
332
333 status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
334 before = jiffies;
335
336 if (tw_check_bits(status_reg_value))
337 tw_decode_bits(tw_dev, status_reg_value, 0);
338
339 while ((status_reg_value & flag) != 0) {
340 status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
341
342 if (tw_check_bits(status_reg_value))
343 tw_decode_bits(tw_dev, status_reg_value, 0);
344
345 if (time_after(jiffies, before + HZ * seconds))
346 goto out;
347
348 msleep(50);
349 }
350 retval = 0;
351out:
352 return retval;
353} /* End tw_poll_status_gone() */
354
355/* This function will attempt to post a command packet to the board */
356static int tw_post_command_packet(TW_Device_Extension *tw_dev, int request_id)
357{
358 u32 status_reg_value;
359 unsigned long command_que_value;
360
361 dprintk(KERN_NOTICE "3w-xxxx: tw_post_command_packet()\n");
362 command_que_value = tw_dev->command_packet_physical_address[request_id];
363 status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
364
365 if (tw_check_bits(status_reg_value)) {
366 dprintk(KERN_WARNING "3w-xxxx: tw_post_command_packet(): Unexpected bits.\n");
367 tw_decode_bits(tw_dev, status_reg_value, 1);
368 }
369
370 if ((status_reg_value & TW_STATUS_COMMAND_QUEUE_FULL) == 0) {
371 /* We successfully posted the command packet */
372 outl(command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
373 tw_dev->state[request_id] = TW_S_POSTED;
374 tw_dev->posted_request_count++;
375 if (tw_dev->posted_request_count > tw_dev->max_posted_request_count) {
376 tw_dev->max_posted_request_count = tw_dev->posted_request_count;
377 }
378 } else {
379 /* Couldn't post the command packet, so we do it in the isr */
380 if (tw_dev->state[request_id] != TW_S_PENDING) {
381 tw_dev->state[request_id] = TW_S_PENDING;
382 tw_dev->pending_request_count++;
383 if (tw_dev->pending_request_count > tw_dev->max_pending_request_count) {
384 tw_dev->max_pending_request_count = tw_dev->pending_request_count;
385 }
386 tw_dev->pending_queue[tw_dev->pending_tail] = request_id;
387 if (tw_dev->pending_tail == TW_Q_LENGTH-1) {
388 tw_dev->pending_tail = TW_Q_START;
389 } else {
390 tw_dev->pending_tail = tw_dev->pending_tail + 1;
391 }
392 }
393 TW_UNMASK_COMMAND_INTERRUPT(tw_dev);
394 return 1;
395 }
396 return 0;
397} /* End tw_post_command_packet() */
398
399/* This function will return valid sense buffer information for failed cmds */
400static int tw_decode_sense(TW_Device_Extension *tw_dev, int request_id, int fill_sense)
401{
402 int i;
403 TW_Command *command;
404
405 dprintk(KERN_WARNING "3w-xxxx: tw_decode_sense()\n");
406 command = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
407
408 printk(KERN_WARNING "3w-xxxx: scsi%d: Command failed: status = 0x%x, flags = 0x%x, unit #%d.\n", tw_dev->host->host_no, command->status, command->flags, TW_UNIT_OUT(command->unit__hostid));
409
410 /* Attempt to return intelligent sense information */
411 if (fill_sense) {
412 if ((command->status == 0xc7) || (command->status == 0xcb)) {
Tobias Klauser6391a112006-06-08 22:23:48 -0700413 for (i = 0; i < ARRAY_SIZE(tw_sense_table); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 if (command->flags == tw_sense_table[i][0]) {
415
416 /* Valid bit and 'current errors' */
417 tw_dev->srb[request_id]->sense_buffer[0] = (0x1 << 7 | 0x70);
418
419 /* Sense key */
420 tw_dev->srb[request_id]->sense_buffer[2] = tw_sense_table[i][1];
421
422 /* Additional sense length */
423 tw_dev->srb[request_id]->sense_buffer[7] = 0xa; /* 10 bytes */
424
425 /* Additional sense code */
426 tw_dev->srb[request_id]->sense_buffer[12] = tw_sense_table[i][2];
427
428 /* Additional sense code qualifier */
429 tw_dev->srb[request_id]->sense_buffer[13] = tw_sense_table[i][3];
430
431 tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
432 return TW_ISR_DONT_RESULT; /* Special case for isr to not over-write result */
433 }
434 }
435 }
436
437 /* If no table match, error so we get a reset */
438 return 1;
439 }
440
441 return 0;
442} /* End tw_decode_sense() */
443
444/* This function will report controller error status */
445static int tw_check_errors(TW_Device_Extension *tw_dev)
446{
447 u32 status_reg_value;
448
449 status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
450
451 if (TW_STATUS_ERRORS(status_reg_value) || tw_check_bits(status_reg_value)) {
452 tw_decode_bits(tw_dev, status_reg_value, 0);
453 return 1;
454 }
455
456 return 0;
457} /* End tw_check_errors() */
458
459/* This function will empty the response que */
460static void tw_empty_response_que(TW_Device_Extension *tw_dev)
461{
462 u32 status_reg_value, response_que_value;
463
464 status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
465
466 while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
467 response_que_value = inl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev));
468 status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
469 }
470} /* End tw_empty_response_que() */
471
472/* This function will free a request_id */
473static void tw_state_request_finish(TW_Device_Extension *tw_dev, int request_id)
474{
475 tw_dev->free_queue[tw_dev->free_tail] = request_id;
476 tw_dev->state[request_id] = TW_S_FINISHED;
477 tw_dev->free_tail = (tw_dev->free_tail + 1) % TW_Q_LENGTH;
478} /* End tw_state_request_finish() */
479
480/* This function will assign an available request_id */
481static void tw_state_request_start(TW_Device_Extension *tw_dev, int *request_id)
482{
483 *request_id = tw_dev->free_queue[tw_dev->free_head];
484 tw_dev->free_head = (tw_dev->free_head + 1) % TW_Q_LENGTH;
485 tw_dev->state[*request_id] = TW_S_STARTED;
486} /* End tw_state_request_start() */
487
488/* Show some statistics about the card */
Tony Jonesee959b02008-02-22 00:13:36 +0100489static ssize_t tw_show_stats(struct device *dev, struct device_attribute *attr,
490 char *buf)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491{
Tony Jonesee959b02008-02-22 00:13:36 +0100492 struct Scsi_Host *host = class_to_shost(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
494 unsigned long flags = 0;
495 ssize_t len;
496
497 spin_lock_irqsave(tw_dev->host->host_lock, flags);
498 len = snprintf(buf, PAGE_SIZE, "3w-xxxx Driver version: %s\n"
499 "Current commands posted: %4d\n"
500 "Max commands posted: %4d\n"
501 "Current pending commands: %4d\n"
502 "Max pending commands: %4d\n"
503 "Last sgl length: %4d\n"
504 "Max sgl length: %4d\n"
505 "Last sector count: %4d\n"
506 "Max sector count: %4d\n"
507 "SCSI Host Resets: %4d\n"
508 "AEN's: %4d\n",
509 TW_DRIVER_VERSION,
510 tw_dev->posted_request_count,
511 tw_dev->max_posted_request_count,
512 tw_dev->pending_request_count,
513 tw_dev->max_pending_request_count,
514 tw_dev->sgl_entries,
515 tw_dev->max_sgl_entries,
516 tw_dev->sector_count,
517 tw_dev->max_sector_count,
518 tw_dev->num_resets,
519 tw_dev->aen_count);
520 spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
521 return len;
522} /* End tw_show_stats() */
523
524/* This function will set a devices queue depth */
Mike Christiee881a172009-10-15 17:46:39 -0700525static int tw_change_queue_depth(struct scsi_device *sdev, int queue_depth,
526 int reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527{
Mike Christiee881a172009-10-15 17:46:39 -0700528 if (reason != SCSI_QDEPTH_DEFAULT)
529 return -EOPNOTSUPP;
530
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 if (queue_depth > TW_Q_LENGTH-2)
532 queue_depth = TW_Q_LENGTH-2;
533 scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
534 return queue_depth;
535} /* End tw_change_queue_depth() */
536
537/* Create sysfs 'stats' entry */
Tony Jonesee959b02008-02-22 00:13:36 +0100538static struct device_attribute tw_host_stats_attr = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 .attr = {
540 .name = "stats",
541 .mode = S_IRUGO,
542 },
543 .show = tw_show_stats
544};
545
546/* Host attributes initializer */
Tony Jonesee959b02008-02-22 00:13:36 +0100547static struct device_attribute *tw_host_attrs[] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 &tw_host_stats_attr,
549 NULL,
550};
551
552/* This function will read the aen queue from the isr */
553static int tw_aen_read_queue(TW_Device_Extension *tw_dev, int request_id)
554{
555 TW_Command *command_packet;
556 TW_Param *param;
557 unsigned long command_que_value;
558 u32 status_reg_value;
559 unsigned long param_value = 0;
560
561 dprintk(KERN_NOTICE "3w-xxxx: tw_aen_read_queue()\n");
562
563 status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
564 if (tw_check_bits(status_reg_value)) {
565 dprintk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Unexpected bits.\n");
566 tw_decode_bits(tw_dev, status_reg_value, 1);
567 return 1;
568 }
569 if (tw_dev->command_packet_virtual_address[request_id] == NULL) {
570 printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Bad command packet virtual address.\n");
571 return 1;
572 }
573 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
574 memset(command_packet, 0, sizeof(TW_Sector));
575 command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM);
576 command_packet->size = 4;
577 command_packet->request_id = request_id;
578 command_packet->status = 0;
579 command_packet->flags = 0;
580 command_packet->byte6.parameter_count = 1;
581 command_que_value = tw_dev->command_packet_physical_address[request_id];
582 if (command_que_value == 0) {
583 printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Bad command packet physical address.\n");
584 return 1;
585 }
586 /* Now setup the param */
587 if (tw_dev->alignment_virtual_address[request_id] == NULL) {
588 printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Bad alignment virtual address.\n");
589 return 1;
590 }
591 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
592 memset(param, 0, sizeof(TW_Sector));
593 param->table_id = 0x401; /* AEN table */
594 param->parameter_id = 2; /* Unit code */
595 param->parameter_size_bytes = 2;
596 param_value = tw_dev->alignment_physical_address[request_id];
597 if (param_value == 0) {
598 printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Bad alignment physical address.\n");
599 return 1;
600 }
601 command_packet->byte8.param.sgl[0].address = param_value;
602 command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
603
604 /* Now post the command packet */
605 if ((status_reg_value & TW_STATUS_COMMAND_QUEUE_FULL) == 0) {
606 dprintk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Post succeeded.\n");
607 tw_dev->srb[request_id] = NULL; /* Flag internal command */
608 tw_dev->state[request_id] = TW_S_POSTED;
609 outl(command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
610 } else {
611 printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Post failed, will retry.\n");
612 return 1;
613 }
614
615 return 0;
616} /* End tw_aen_read_queue() */
617
618/* This function will complete an aen request from the isr */
619static int tw_aen_complete(TW_Device_Extension *tw_dev, int request_id)
620{
621 TW_Param *param;
622 unsigned short aen;
623 int error = 0, table_max = 0;
624
625 dprintk(KERN_WARNING "3w-xxxx: tw_aen_complete()\n");
626 if (tw_dev->alignment_virtual_address[request_id] == NULL) {
627 printk(KERN_WARNING "3w-xxxx: tw_aen_complete(): Bad alignment virtual address.\n");
628 return 1;
629 }
630 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
631 aen = *(unsigned short *)(param->data);
632 dprintk(KERN_NOTICE "3w-xxxx: tw_aen_complete(): Queue'd code 0x%x\n", aen);
633
634 /* Print some useful info when certain aen codes come out */
635 if (aen == 0x0ff) {
636 printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: INFO: AEN queue overflow.\n", tw_dev->host->host_no);
637 } else {
Tobias Klauser6391a112006-06-08 22:23:48 -0700638 table_max = ARRAY_SIZE(tw_aen_string);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 if ((aen & 0x0ff) < table_max) {
640 if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') {
641 printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: %s%d.\n", tw_dev->host->host_no, tw_aen_string[aen & 0xff], aen >> 8);
642 } else {
643 if (aen != 0x0)
644 printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: %s.\n", tw_dev->host->host_no, tw_aen_string[aen & 0xff]);
645 }
646 } else {
647 printk(KERN_WARNING "3w-xxxx: scsi%d: Received AEN %d.\n", tw_dev->host->host_no, aen);
648 }
649 }
650 if (aen != TW_AEN_QUEUE_EMPTY) {
651 tw_dev->aen_count++;
652
653 /* Now queue the code */
654 tw_dev->aen_queue[tw_dev->aen_tail] = aen;
655 if (tw_dev->aen_tail == TW_Q_LENGTH - 1) {
656 tw_dev->aen_tail = TW_Q_START;
657 } else {
658 tw_dev->aen_tail = tw_dev->aen_tail + 1;
659 }
660 if (tw_dev->aen_head == tw_dev->aen_tail) {
661 if (tw_dev->aen_head == TW_Q_LENGTH - 1) {
662 tw_dev->aen_head = TW_Q_START;
663 } else {
664 tw_dev->aen_head = tw_dev->aen_head + 1;
665 }
666 }
667
668 error = tw_aen_read_queue(tw_dev, request_id);
669 if (error) {
670 printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing AEN.\n", tw_dev->host->host_no);
671 tw_dev->state[request_id] = TW_S_COMPLETED;
672 tw_state_request_finish(tw_dev, request_id);
673 }
674 } else {
675 tw_dev->state[request_id] = TW_S_COMPLETED;
676 tw_state_request_finish(tw_dev, request_id);
677 }
678
679 return 0;
680} /* End tw_aen_complete() */
681
682/* This function will drain the aen queue after a soft reset */
683static int tw_aen_drain_queue(TW_Device_Extension *tw_dev)
684{
685 TW_Command *command_packet;
686 TW_Param *param;
687 int request_id = 0;
688 unsigned long command_que_value;
689 unsigned long param_value;
690 TW_Response_Queue response_queue;
691 unsigned short aen;
692 unsigned short aen_code;
693 int finished = 0;
694 int first_reset = 0;
695 int queue = 0;
696 int found = 0, table_max = 0;
697
698 dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue()\n");
699
700 if (tw_poll_status(tw_dev, TW_STATUS_ATTENTION_INTERRUPT | TW_STATUS_MICROCONTROLLER_READY, 30)) {
701 dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): No attention interrupt for card %d.\n", tw_device_extension_count);
702 return 1;
703 }
704 TW_CLEAR_ATTENTION_INTERRUPT(tw_dev);
705
706 /* Empty response queue */
707 tw_empty_response_que(tw_dev);
708
709 /* Initialize command packet */
710 if (tw_dev->command_packet_virtual_address[request_id] == NULL) {
711 printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad command packet virtual address.\n");
712 return 1;
713 }
714 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
715 memset(command_packet, 0, sizeof(TW_Sector));
716 command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM);
717 command_packet->size = 4;
718 command_packet->request_id = request_id;
719 command_packet->status = 0;
720 command_packet->flags = 0;
721 command_packet->byte6.parameter_count = 1;
722 command_que_value = tw_dev->command_packet_physical_address[request_id];
723 if (command_que_value == 0) {
724 printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad command packet physical address.\n");
725 return 1;
726 }
727
728 /* Now setup the param */
729 if (tw_dev->alignment_virtual_address[request_id] == NULL) {
730 printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad alignment virtual address.\n");
731 return 1;
732 }
733 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
734 memset(param, 0, sizeof(TW_Sector));
735 param->table_id = 0x401; /* AEN table */
736 param->parameter_id = 2; /* Unit code */
737 param->parameter_size_bytes = 2;
738 param_value = tw_dev->alignment_physical_address[request_id];
739 if (param_value == 0) {
740 printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad alignment physical address.\n");
741 return 1;
742 }
743 command_packet->byte8.param.sgl[0].address = param_value;
744 command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
745
746 /* Now drain the controller's aen queue */
747 do {
748 /* Post command packet */
749 outl(command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
750
751 /* Now poll for completion */
752 if (tw_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, 30) == 0) {
753 response_queue.value = inl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev));
754 request_id = TW_RESID_OUT(response_queue.response_id);
755
756 if (request_id != 0) {
757 /* Unexpected request id */
758 printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Unexpected request id.\n");
759 return 1;
760 }
761
762 if (command_packet->status != 0) {
763 if (command_packet->flags != TW_AEN_TABLE_UNDEFINED) {
764 /* Bad response */
765 tw_decode_sense(tw_dev, request_id, 0);
766 return 1;
767 } else {
768 /* We know this is a 3w-1x00, and doesn't support aen's */
769 return 0;
770 }
771 }
772
773 /* Now check the aen */
774 aen = *(unsigned short *)(param->data);
775 aen_code = (aen & 0x0ff);
776 queue = 0;
777 switch (aen_code) {
778 case TW_AEN_QUEUE_EMPTY:
779 dprintk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]);
780 if (first_reset != 1) {
781 return 1;
782 } else {
783 finished = 1;
784 }
785 break;
786 case TW_AEN_SOFT_RESET:
787 if (first_reset == 0) {
788 first_reset = 1;
789 } else {
790 printk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]);
791 tw_dev->aen_count++;
792 queue = 1;
793 }
794 break;
795 default:
796 if (aen == 0x0ff) {
797 printk(KERN_WARNING "3w-xxxx: AEN: INFO: AEN queue overflow.\n");
798 } else {
Tobias Klauser6391a112006-06-08 22:23:48 -0700799 table_max = ARRAY_SIZE(tw_aen_string);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 if ((aen & 0x0ff) < table_max) {
801 if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') {
802 printk(KERN_WARNING "3w-xxxx: AEN: %s%d.\n", tw_aen_string[aen & 0xff], aen >> 8);
803 } else {
804 printk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]);
805 }
806 } else
807 printk(KERN_WARNING "3w-xxxx: Received AEN %d.\n", aen);
808 }
809 tw_dev->aen_count++;
810 queue = 1;
811 }
812
813 /* Now put the aen on the aen_queue */
814 if (queue == 1) {
815 tw_dev->aen_queue[tw_dev->aen_tail] = aen;
816 if (tw_dev->aen_tail == TW_Q_LENGTH - 1) {
817 tw_dev->aen_tail = TW_Q_START;
818 } else {
819 tw_dev->aen_tail = tw_dev->aen_tail + 1;
820 }
821 if (tw_dev->aen_head == tw_dev->aen_tail) {
822 if (tw_dev->aen_head == TW_Q_LENGTH - 1) {
823 tw_dev->aen_head = TW_Q_START;
824 } else {
825 tw_dev->aen_head = tw_dev->aen_head + 1;
826 }
827 }
828 }
829 found = 1;
830 }
831 if (found == 0) {
832 printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Response never received.\n");
833 return 1;
834 }
835 } while (finished == 0);
836
837 return 0;
838} /* End tw_aen_drain_queue() */
839
840/* This function will allocate memory */
841static int tw_allocate_memory(TW_Device_Extension *tw_dev, int size, int which)
842{
843 int i;
844 dma_addr_t dma_handle;
845 unsigned long *cpu_addr = NULL;
846
847 dprintk(KERN_NOTICE "3w-xxxx: tw_allocate_memory()\n");
848
849 cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, size*TW_Q_LENGTH, &dma_handle);
850 if (cpu_addr == NULL) {
851 printk(KERN_WARNING "3w-xxxx: pci_alloc_consistent() failed.\n");
852 return 1;
853 }
854
855 if ((unsigned long)cpu_addr % (tw_dev->tw_pci_dev->device == TW_DEVICE_ID ? TW_ALIGNMENT_6000 : TW_ALIGNMENT_7000)) {
856 printk(KERN_WARNING "3w-xxxx: Couldn't allocate correctly aligned memory.\n");
857 pci_free_consistent(tw_dev->tw_pci_dev, size*TW_Q_LENGTH, cpu_addr, dma_handle);
858 return 1;
859 }
860
861 memset(cpu_addr, 0, size*TW_Q_LENGTH);
862
863 for (i=0;i<TW_Q_LENGTH;i++) {
864 switch(which) {
865 case 0:
866 tw_dev->command_packet_physical_address[i] = dma_handle+(i*size);
867 tw_dev->command_packet_virtual_address[i] = (unsigned long *)((unsigned char *)cpu_addr + (i*size));
868 break;
869 case 1:
870 tw_dev->alignment_physical_address[i] = dma_handle+(i*size);
871 tw_dev->alignment_virtual_address[i] = (unsigned long *)((unsigned char *)cpu_addr + (i*size));
872 break;
873 default:
874 printk(KERN_WARNING "3w-xxxx: tw_allocate_memory(): case slip in tw_allocate_memory()\n");
875 return 1;
876 }
877 }
878
879 return 0;
880} /* End tw_allocate_memory() */
881
882/* This function handles ioctl for the character device */
883static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
884{
885 int request_id;
886 dma_addr_t dma_handle;
887 unsigned short tw_aen_code;
888 unsigned long flags;
889 unsigned int data_buffer_length = 0;
890 unsigned long data_buffer_length_adjusted = 0;
891 unsigned long *cpu_addr;
892 long timeout;
893 TW_New_Ioctl *tw_ioctl;
894 TW_Passthru *passthru;
895 TW_Device_Extension *tw_dev = tw_device_extension_list[iminor(inode)];
896 int retval = -EFAULT;
897 void __user *argp = (void __user *)arg;
898
899 dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl()\n");
900
901 /* Only let one of these through at a time */
Jes Sorensena12e25bd2006-01-11 08:39:45 -0500902 if (mutex_lock_interruptible(&tw_dev->ioctl_lock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 return -EINTR;
904
905 /* First copy down the buffer length */
906 if (copy_from_user(&data_buffer_length, argp, sizeof(unsigned int)))
907 goto out;
908
909 /* Check size */
910 if (data_buffer_length > TW_MAX_IOCTL_SECTORS * 512) {
911 retval = -EINVAL;
912 goto out;
913 }
914
915 /* Hardware can only do multiple of 512 byte transfers */
916 data_buffer_length_adjusted = (data_buffer_length + 511) & ~511;
917
918 /* Now allocate ioctl buf memory */
919 cpu_addr = dma_alloc_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, &dma_handle, GFP_KERNEL);
920 if (cpu_addr == NULL) {
921 retval = -ENOMEM;
922 goto out;
923 }
924
925 tw_ioctl = (TW_New_Ioctl *)cpu_addr;
926
927 /* Now copy down the entire ioctl */
928 if (copy_from_user(tw_ioctl, argp, data_buffer_length + sizeof(TW_New_Ioctl) - 1))
929 goto out2;
930
931 passthru = (TW_Passthru *)&tw_ioctl->firmware_command;
932
933 /* See which ioctl we are doing */
934 switch (cmd) {
935 case TW_OP_NOP:
936 dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): caught TW_OP_NOP.\n");
937 break;
938 case TW_OP_AEN_LISTEN:
939 dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): caught TW_AEN_LISTEN.\n");
940 memset(tw_ioctl->data_buffer, 0, data_buffer_length);
941
942 spin_lock_irqsave(tw_dev->host->host_lock, flags);
943 if (tw_dev->aen_head == tw_dev->aen_tail) {
944 tw_aen_code = TW_AEN_QUEUE_EMPTY;
945 } else {
946 tw_aen_code = tw_dev->aen_queue[tw_dev->aen_head];
947 if (tw_dev->aen_head == TW_Q_LENGTH - 1) {
948 tw_dev->aen_head = TW_Q_START;
949 } else {
950 tw_dev->aen_head = tw_dev->aen_head + 1;
951 }
952 }
953 spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
954 memcpy(tw_ioctl->data_buffer, &tw_aen_code, sizeof(tw_aen_code));
955 break;
956 case TW_CMD_PACKET_WITH_DATA:
957 dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): caught TW_CMD_PACKET_WITH_DATA.\n");
958 spin_lock_irqsave(tw_dev->host->host_lock, flags);
959
960 tw_state_request_start(tw_dev, &request_id);
961
962 /* Flag internal command */
963 tw_dev->srb[request_id] = NULL;
964
965 /* Flag chrdev ioctl */
966 tw_dev->chrdev_request_id = request_id;
967
968 tw_ioctl->firmware_command.request_id = request_id;
969
970 /* Load the sg list */
971 switch (TW_SGL_OUT(tw_ioctl->firmware_command.opcode__sgloffset)) {
972 case 2:
973 tw_ioctl->firmware_command.byte8.param.sgl[0].address = dma_handle + sizeof(TW_New_Ioctl) - 1;
974 tw_ioctl->firmware_command.byte8.param.sgl[0].length = data_buffer_length_adjusted;
975 break;
976 case 3:
977 tw_ioctl->firmware_command.byte8.io.sgl[0].address = dma_handle + sizeof(TW_New_Ioctl) - 1;
978 tw_ioctl->firmware_command.byte8.io.sgl[0].length = data_buffer_length_adjusted;
979 break;
980 case 5:
981 passthru->sg_list[0].address = dma_handle + sizeof(TW_New_Ioctl) - 1;
982 passthru->sg_list[0].length = data_buffer_length_adjusted;
983 break;
984 }
985
986 memcpy(tw_dev->command_packet_virtual_address[request_id], &(tw_ioctl->firmware_command), sizeof(TW_Command));
987
988 /* Now post the command packet to the controller */
989 tw_post_command_packet(tw_dev, request_id);
990 spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
991
992 timeout = TW_IOCTL_CHRDEV_TIMEOUT*HZ;
993
994 /* Now wait for the command to complete */
995 timeout = wait_event_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout);
996
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 /* We timed out, and didn't get an interrupt */
998 if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) {
999 /* Now we need to reset the board */
1000 printk(KERN_WARNING "3w-xxxx: scsi%d: Character ioctl (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, cmd);
1001 retval = -EIO;
adam radford4fe48182007-01-04 18:16:56 -08001002 if (tw_reset_device_extension(tw_dev)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 printk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): Reset failed for card %d.\n", tw_dev->host->host_no);
1004 }
1005 goto out2;
1006 }
1007
1008 /* Now copy in the command packet response */
1009 memcpy(&(tw_ioctl->firmware_command), tw_dev->command_packet_virtual_address[request_id], sizeof(TW_Command));
1010
1011 /* Now complete the io */
1012 spin_lock_irqsave(tw_dev->host->host_lock, flags);
1013 tw_dev->posted_request_count--;
1014 tw_dev->state[request_id] = TW_S_COMPLETED;
1015 tw_state_request_finish(tw_dev, request_id);
1016 spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
1017 break;
1018 default:
1019 retval = -ENOTTY;
1020 goto out2;
1021 }
1022
1023 /* Now copy the response to userspace */
1024 if (copy_to_user(argp, tw_ioctl, sizeof(TW_New_Ioctl) + data_buffer_length - 1))
1025 goto out2;
1026 retval = 0;
1027out2:
1028 /* Now free ioctl buf memory */
1029 dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle);
1030out:
Jes Sorensena12e25bd2006-01-11 08:39:45 -05001031 mutex_unlock(&tw_dev->ioctl_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 return retval;
1033} /* End tw_chrdev_ioctl() */
1034
1035/* This function handles open for the character device */
Jonathan Corbetf2b98572008-05-18 15:32:43 -06001036/* NOTE that this function races with remove. */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037static int tw_chrdev_open(struct inode *inode, struct file *file)
1038{
1039 unsigned int minor_number;
1040
Jonathan Corbetf2b98572008-05-18 15:32:43 -06001041 cycle_kernel_lock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_open()\n");
1043
1044 minor_number = iminor(inode);
1045 if (minor_number >= tw_device_extension_count)
1046 return -ENODEV;
1047
1048 return 0;
1049} /* End tw_chrdev_open() */
1050
1051/* File operations struct for character device */
Arjan van de Ven00977a52007-02-12 00:55:34 -08001052static const struct file_operations tw_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 .owner = THIS_MODULE,
1054 .ioctl = tw_chrdev_ioctl,
1055 .open = tw_chrdev_open,
1056 .release = NULL
1057};
1058
1059/* This function will free up device extension resources */
1060static void tw_free_device_extension(TW_Device_Extension *tw_dev)
1061{
1062 dprintk(KERN_NOTICE "3w-xxxx: tw_free_device_extension()\n");
1063
1064 /* Free command packet and generic buffer memory */
1065 if (tw_dev->command_packet_virtual_address[0])
1066 pci_free_consistent(tw_dev->tw_pci_dev, sizeof(TW_Command)*TW_Q_LENGTH, tw_dev->command_packet_virtual_address[0], tw_dev->command_packet_physical_address[0]);
1067
1068 if (tw_dev->alignment_virtual_address[0])
1069 pci_free_consistent(tw_dev->tw_pci_dev, sizeof(TW_Sector)*TW_Q_LENGTH, tw_dev->alignment_virtual_address[0], tw_dev->alignment_physical_address[0]);
1070} /* End tw_free_device_extension() */
1071
1072/* This function will send an initconnection command to controller */
1073static int tw_initconnection(TW_Device_Extension *tw_dev, int message_credits)
1074{
1075 unsigned long command_que_value;
1076 TW_Command *command_packet;
1077 TW_Response_Queue response_queue;
1078 int request_id = 0;
1079
1080 dprintk(KERN_NOTICE "3w-xxxx: tw_initconnection()\n");
1081
1082 /* Initialize InitConnection command packet */
1083 if (tw_dev->command_packet_virtual_address[request_id] == NULL) {
1084 printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad command packet virtual address.\n");
1085 return 1;
1086 }
1087
1088 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
1089 memset(command_packet, 0, sizeof(TW_Sector));
1090 command_packet->opcode__sgloffset = TW_OPSGL_IN(0, TW_OP_INIT_CONNECTION);
1091 command_packet->size = TW_INIT_COMMAND_PACKET_SIZE;
1092 command_packet->request_id = request_id;
1093 command_packet->status = 0x0;
1094 command_packet->flags = 0x0;
1095 command_packet->byte6.message_credits = message_credits;
1096 command_packet->byte8.init_connection.response_queue_pointer = 0x0;
1097 command_que_value = tw_dev->command_packet_physical_address[request_id];
1098
1099 if (command_que_value == 0) {
1100 printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad command packet physical address.\n");
1101 return 1;
1102 }
1103
1104 /* Send command packet to the board */
1105 outl(command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
1106
1107 /* Poll for completion */
1108 if (tw_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, 30) == 0) {
1109 response_queue.value = inl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev));
1110 request_id = TW_RESID_OUT(response_queue.response_id);
1111
1112 if (request_id != 0) {
1113 /* unexpected request id */
1114 printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Unexpected request id.\n");
1115 return 1;
1116 }
1117 if (command_packet->status != 0) {
1118 /* bad response */
1119 tw_decode_sense(tw_dev, request_id, 0);
1120 return 1;
1121 }
1122 }
1123 return 0;
1124} /* End tw_initconnection() */
1125
1126/* Set a value in the features table */
1127static int tw_setfeature(TW_Device_Extension *tw_dev, int parm, int param_size,
1128 unsigned char *val)
1129{
1130 TW_Param *param;
1131 TW_Command *command_packet;
1132 TW_Response_Queue response_queue;
1133 int request_id = 0;
1134 unsigned long command_que_value;
1135 unsigned long param_value;
1136
1137 /* Initialize SetParam command packet */
1138 if (tw_dev->command_packet_virtual_address[request_id] == NULL) {
1139 printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad command packet virtual address.\n");
1140 return 1;
1141 }
1142 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
1143 memset(command_packet, 0, sizeof(TW_Sector));
1144 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
1145
1146 command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_SET_PARAM);
1147 param->table_id = 0x404; /* Features table */
1148 param->parameter_id = parm;
1149 param->parameter_size_bytes = param_size;
1150 memcpy(param->data, val, param_size);
1151
1152 param_value = tw_dev->alignment_physical_address[request_id];
1153 if (param_value == 0) {
1154 printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad alignment physical address.\n");
1155 tw_dev->state[request_id] = TW_S_COMPLETED;
1156 tw_state_request_finish(tw_dev, request_id);
1157 tw_dev->srb[request_id]->result = (DID_OK << 16);
1158 tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
1159 }
1160 command_packet->byte8.param.sgl[0].address = param_value;
1161 command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
1162
1163 command_packet->size = 4;
1164 command_packet->request_id = request_id;
1165 command_packet->byte6.parameter_count = 1;
1166
1167 command_que_value = tw_dev->command_packet_physical_address[request_id];
1168 if (command_que_value == 0) {
1169 printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad command packet physical address.\n");
1170 return 1;
1171 }
1172
1173 /* Send command packet to the board */
1174 outl(command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
1175
1176 /* Poll for completion */
1177 if (tw_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, 30) == 0) {
1178 response_queue.value = inl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev));
1179 request_id = TW_RESID_OUT(response_queue.response_id);
1180
1181 if (request_id != 0) {
1182 /* unexpected request id */
1183 printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Unexpected request id.\n");
1184 return 1;
1185 }
1186 if (command_packet->status != 0) {
1187 /* bad response */
1188 tw_decode_sense(tw_dev, request_id, 0);
1189 return 1;
1190 }
1191 }
1192
1193 return 0;
1194} /* End tw_setfeature() */
1195
1196/* This function will reset a controller */
1197static int tw_reset_sequence(TW_Device_Extension *tw_dev)
1198{
1199 int error = 0;
1200 int tries = 0;
1201 unsigned char c = 1;
1202
1203 /* Reset the board */
1204 while (tries < TW_MAX_RESET_TRIES) {
1205 TW_SOFT_RESET(tw_dev);
1206
1207 error = tw_aen_drain_queue(tw_dev);
1208 if (error) {
1209 printk(KERN_WARNING "3w-xxxx: scsi%d: AEN drain failed, retrying.\n", tw_dev->host->host_no);
1210 tries++;
1211 continue;
1212 }
1213
1214 /* Check for controller errors */
1215 if (tw_check_errors(tw_dev)) {
1216 printk(KERN_WARNING "3w-xxxx: scsi%d: Controller errors found, retrying.\n", tw_dev->host->host_no);
1217 tries++;
1218 continue;
1219 }
1220
1221 /* Now the controller is in a good state */
1222 break;
1223 }
1224
1225 if (tries >= TW_MAX_RESET_TRIES) {
1226 printk(KERN_WARNING "3w-xxxx: scsi%d: Controller errors, card not responding, check all cabling.\n", tw_dev->host->host_no);
1227 return 1;
1228 }
1229
1230 error = tw_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS);
1231 if (error) {
1232 printk(KERN_WARNING "3w-xxxx: scsi%d: Connection initialization failed.\n", tw_dev->host->host_no);
1233 return 1;
1234 }
1235
1236 error = tw_setfeature(tw_dev, 2, 1, &c);
1237 if (error) {
1238 printk(KERN_WARNING "3w-xxxx: Unable to set features for card, probable old firmware or card.\n");
1239 }
1240
1241 return 0;
1242} /* End tw_reset_sequence() */
1243
1244/* This function will initialize the fields of a device extension */
1245static int tw_initialize_device_extension(TW_Device_Extension *tw_dev)
1246{
1247 int i, error=0;
1248
1249 dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_device_extension()\n");
1250
1251 /* Initialize command packet buffers */
1252 error = tw_allocate_memory(tw_dev, sizeof(TW_Command), 0);
1253 if (error) {
1254 printk(KERN_WARNING "3w-xxxx: Command packet memory allocation failed.\n");
1255 return 1;
1256 }
1257
1258 /* Initialize generic buffer */
1259 error = tw_allocate_memory(tw_dev, sizeof(TW_Sector), 1);
1260 if (error) {
1261 printk(KERN_WARNING "3w-xxxx: Generic memory allocation failed.\n");
1262 return 1;
1263 }
1264
1265 for (i=0;i<TW_Q_LENGTH;i++) {
1266 tw_dev->free_queue[i] = i;
1267 tw_dev->state[i] = TW_S_INITIAL;
1268 }
1269
1270 tw_dev->pending_head = TW_Q_START;
1271 tw_dev->pending_tail = TW_Q_START;
1272 tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
1273
Jes Sorensena12e25bd2006-01-11 08:39:45 -05001274 mutex_init(&tw_dev->ioctl_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 init_waitqueue_head(&tw_dev->ioctl_wqueue);
1276
1277 return 0;
1278} /* End tw_initialize_device_extension() */
1279
1280static int tw_map_scsi_sg_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
1281{
1282 int use_sg;
1283
1284 dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data()\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285
FUJITA Tomonori6edae702007-05-14 20:20:27 +09001286 use_sg = scsi_dma_map(cmd);
1287 if (use_sg < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n");
1289 return 0;
1290 }
1291
1292 cmd->SCp.phase = TW_PHASE_SGLIST;
1293 cmd->SCp.have_data_in = use_sg;
FUJITA Tomonori6edae702007-05-14 20:20:27 +09001294
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 return use_sg;
1296} /* End tw_map_scsi_sg_data() */
1297
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298static void tw_unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
1299{
1300 dprintk(KERN_WARNING "3w-xxxx: tw_unmap_scsi_data()\n");
1301
adam radford7b14f582009-05-11 14:55:55 -07001302 if (cmd->SCp.phase == TW_PHASE_SGLIST)
1303 scsi_dma_unmap(cmd);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304} /* End tw_unmap_scsi_data() */
1305
1306/* This function will reset a device extension */
adam radford4fe48182007-01-04 18:16:56 -08001307static int tw_reset_device_extension(TW_Device_Extension *tw_dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308{
1309 int i = 0;
1310 struct scsi_cmnd *srb;
1311 unsigned long flags = 0;
1312
1313 dprintk(KERN_NOTICE "3w-xxxx: tw_reset_device_extension()\n");
1314
1315 set_bit(TW_IN_RESET, &tw_dev->flags);
1316 TW_DISABLE_INTERRUPTS(tw_dev);
1317 TW_MASK_COMMAND_INTERRUPT(tw_dev);
1318 spin_lock_irqsave(tw_dev->host->host_lock, flags);
1319
1320 /* Abort all requests that are in progress */
1321 for (i=0;i<TW_Q_LENGTH;i++) {
1322 if ((tw_dev->state[i] != TW_S_FINISHED) &&
1323 (tw_dev->state[i] != TW_S_INITIAL) &&
1324 (tw_dev->state[i] != TW_S_COMPLETED)) {
1325 srb = tw_dev->srb[i];
1326 if (srb != NULL) {
1327 srb->result = (DID_RESET << 16);
1328 tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);
1329 tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[i]);
1330 }
1331 }
1332 }
1333
1334 /* Reset queues and counts */
1335 for (i=0;i<TW_Q_LENGTH;i++) {
1336 tw_dev->free_queue[i] = i;
1337 tw_dev->state[i] = TW_S_INITIAL;
1338 }
1339 tw_dev->free_head = TW_Q_START;
1340 tw_dev->free_tail = TW_Q_START;
1341 tw_dev->posted_request_count = 0;
1342 tw_dev->pending_request_count = 0;
1343 tw_dev->pending_head = TW_Q_START;
1344 tw_dev->pending_tail = TW_Q_START;
1345 tw_dev->reset_print = 0;
1346
1347 spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
1348
1349 if (tw_reset_sequence(tw_dev)) {
1350 printk(KERN_WARNING "3w-xxxx: scsi%d: Reset sequence failed.\n", tw_dev->host->host_no);
1351 return 1;
1352 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353
adam radford4fe48182007-01-04 18:16:56 -08001354 TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);
1355 clear_bit(TW_IN_RESET, &tw_dev->flags);
1356 tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357
1358 return 0;
1359} /* End tw_reset_device_extension() */
1360
1361/* This funciton returns unit geometry in cylinders/heads/sectors */
1362static int tw_scsi_biosparam(struct scsi_device *sdev, struct block_device *bdev,
1363 sector_t capacity, int geom[])
1364{
1365 int heads, sectors, cylinders;
1366 TW_Device_Extension *tw_dev;
1367
1368 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_biosparam()\n");
1369 tw_dev = (TW_Device_Extension *)sdev->host->hostdata;
1370
1371 heads = 64;
1372 sectors = 32;
1373 cylinders = sector_div(capacity, heads * sectors);
1374
1375 if (capacity >= 0x200000) {
1376 heads = 255;
1377 sectors = 63;
1378 cylinders = sector_div(capacity, heads * sectors);
1379 }
1380
1381 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_biosparam(): heads = %d, sectors = %d, cylinders = %d\n", heads, sectors, cylinders);
1382 geom[0] = heads;
1383 geom[1] = sectors;
1384 geom[2] = cylinders;
1385
1386 return 0;
1387} /* End tw_scsi_biosparam() */
1388
1389/* This is the new scsi eh reset function */
1390static int tw_scsi_eh_reset(struct scsi_cmnd *SCpnt)
1391{
1392 TW_Device_Extension *tw_dev=NULL;
1393 int retval = FAILED;
1394
1395 tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
1396
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 tw_dev->num_resets++;
1398
Jeff Garzik017560f2005-10-24 18:04:36 -04001399 sdev_printk(KERN_WARNING, SCpnt->device,
1400 "WARNING: Command (0x%x) timed out, resetting card.\n",
1401 SCpnt->cmnd[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402
adam radford4fe48182007-01-04 18:16:56 -08001403 /* Make sure we are not issuing an ioctl or resetting from ioctl */
1404 mutex_lock(&tw_dev->ioctl_lock);
1405
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406 /* Now reset the card and some of the device extension data */
adam radford4fe48182007-01-04 18:16:56 -08001407 if (tw_reset_device_extension(tw_dev)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 printk(KERN_WARNING "3w-xxxx: scsi%d: Reset failed.\n", tw_dev->host->host_no);
1409 goto out;
1410 }
1411
1412 retval = SUCCESS;
1413out:
adam radford4fe48182007-01-04 18:16:56 -08001414 mutex_unlock(&tw_dev->ioctl_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415 return retval;
1416} /* End tw_scsi_eh_reset() */
1417
1418/* This function handles scsi inquiry commands */
1419static int tw_scsiop_inquiry(TW_Device_Extension *tw_dev, int request_id)
1420{
1421 TW_Param *param;
1422 TW_Command *command_packet;
1423 unsigned long command_que_value;
1424 unsigned long param_value;
1425
1426 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry()\n");
1427
1428 /* Initialize command packet */
1429 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
1430 if (command_packet == NULL) {
1431 printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad command packet virtual address.\n");
1432 return 1;
1433 }
1434 memset(command_packet, 0, sizeof(TW_Sector));
1435 command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM);
1436 command_packet->size = 4;
1437 command_packet->request_id = request_id;
1438 command_packet->status = 0;
1439 command_packet->flags = 0;
1440 command_packet->byte6.parameter_count = 1;
1441
1442 /* Now setup the param */
1443 if (tw_dev->alignment_virtual_address[request_id] == NULL) {
1444 printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad alignment virtual address.\n");
1445 return 1;
1446 }
1447 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
1448 memset(param, 0, sizeof(TW_Sector));
1449 param->table_id = 3; /* unit summary table */
1450 param->parameter_id = 3; /* unitsstatus parameter */
1451 param->parameter_size_bytes = TW_MAX_UNITS;
1452 param_value = tw_dev->alignment_physical_address[request_id];
1453 if (param_value == 0) {
1454 printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad alignment physical address.\n");
1455 return 1;
1456 }
1457
1458 command_packet->byte8.param.sgl[0].address = param_value;
1459 command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
1460 command_que_value = tw_dev->command_packet_physical_address[request_id];
1461 if (command_que_value == 0) {
1462 printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad command packet physical address.\n");
1463 return 1;
1464 }
1465
1466 /* Now try to post the command packet */
1467 tw_post_command_packet(tw_dev, request_id);
1468
1469 return 0;
1470} /* End tw_scsiop_inquiry() */
1471
James Bottomleyc9d297c2005-06-28 09:18:21 -05001472static void tw_transfer_internal(TW_Device_Extension *tw_dev, int request_id,
1473 void *data, unsigned int len)
1474{
FUJITA Tomonori0723d4a2008-10-09 11:25:42 +09001475 scsi_sg_copy_from_buffer(tw_dev->srb[request_id], data, len);
James Bottomleyc9d297c2005-06-28 09:18:21 -05001476}
1477
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478/* This function is called by the isr to complete an inquiry command */
1479static int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_id)
1480{
1481 unsigned char *is_unit_present;
James Bottomleyc9d297c2005-06-28 09:18:21 -05001482 unsigned char request_buffer[36];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 TW_Param *param;
1484
1485 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry_complete()\n");
1486
James Bottomleyc9d297c2005-06-28 09:18:21 -05001487 memset(request_buffer, 0, sizeof(request_buffer));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 request_buffer[0] = TYPE_DISK; /* Peripheral device type */
1489 request_buffer[1] = 0; /* Device type modifier */
1490 request_buffer[2] = 0; /* No ansi/iso compliance */
1491 request_buffer[4] = 31; /* Additional length */
1492 memcpy(&request_buffer[8], "3ware ", 8); /* Vendor ID */
1493 sprintf(&request_buffer[16], "Logical Disk %-2d ", tw_dev->srb[request_id]->device->id);
1494 memcpy(&request_buffer[32], TW_DRIVER_VERSION, 3);
James Bottomleyc9d297c2005-06-28 09:18:21 -05001495 tw_transfer_internal(tw_dev, request_id, request_buffer,
1496 sizeof(request_buffer));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497
1498 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
1499 if (param == NULL) {
1500 printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry_complete(): Bad alignment virtual address.\n");
1501 return 1;
1502 }
1503 is_unit_present = &(param->data[0]);
1504
1505 if (is_unit_present[tw_dev->srb[request_id]->device->id] & TW_UNIT_ONLINE) {
1506 tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = 1;
1507 } else {
1508 tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = 0;
1509 tw_dev->srb[request_id]->result = (DID_BAD_TARGET << 16);
1510 return TW_ISR_DONT_RESULT;
1511 }
1512
1513 return 0;
1514} /* End tw_scsiop_inquiry_complete() */
1515
1516/* This function handles scsi mode_sense commands */
1517static int tw_scsiop_mode_sense(TW_Device_Extension *tw_dev, int request_id)
1518{
1519 TW_Param *param;
1520 TW_Command *command_packet;
1521 unsigned long command_que_value;
1522 unsigned long param_value;
1523
1524 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_mode_sense()\n");
1525
1526 /* Only page control = 0, page code = 0x8 (cache page) supported */
1527 if (tw_dev->srb[request_id]->cmnd[2] != 0x8) {
1528 tw_dev->state[request_id] = TW_S_COMPLETED;
1529 tw_state_request_finish(tw_dev, request_id);
1530 tw_dev->srb[request_id]->result = (DID_OK << 16);
1531 tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
1532 return 0;
1533 }
1534
1535 /* Now read firmware cache setting for this unit */
1536 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
1537 if (command_packet == NULL) {
1538 printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad command packet virtual address.\n");
1539 return 1;
1540 }
1541
1542 /* Setup the command packet */
1543 memset(command_packet, 0, sizeof(TW_Sector));
1544 command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM);
1545 command_packet->size = 4;
1546 command_packet->request_id = request_id;
1547 command_packet->status = 0;
1548 command_packet->flags = 0;
1549 command_packet->byte6.parameter_count = 1;
1550
1551 /* Setup the param */
1552 if (tw_dev->alignment_virtual_address[request_id] == NULL) {
1553 printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad alignment virtual address.\n");
1554 return 1;
1555 }
1556
1557 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
1558 memset(param, 0, sizeof(TW_Sector));
1559 param->table_id = TW_UNIT_INFORMATION_TABLE_BASE + tw_dev->srb[request_id]->device->id;
1560 param->parameter_id = 7; /* unit flags */
1561 param->parameter_size_bytes = 1;
1562 param_value = tw_dev->alignment_physical_address[request_id];
1563 if (param_value == 0) {
1564 printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad alignment physical address.\n");
1565 return 1;
1566 }
1567
1568 command_packet->byte8.param.sgl[0].address = param_value;
1569 command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
1570 command_que_value = tw_dev->command_packet_physical_address[request_id];
1571 if (command_que_value == 0) {
1572 printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad command packet physical address.\n");
1573 return 1;
1574 }
1575
1576 /* Now try to post the command packet */
1577 tw_post_command_packet(tw_dev, request_id);
1578
1579 return 0;
1580} /* End tw_scsiop_mode_sense() */
1581
1582/* This function is called by the isr to complete a mode sense command */
1583static int tw_scsiop_mode_sense_complete(TW_Device_Extension *tw_dev, int request_id)
1584{
1585 TW_Param *param;
1586 unsigned char *flags;
James Bottomleyc9d297c2005-06-28 09:18:21 -05001587 unsigned char request_buffer[8];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588
1589 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_mode_sense_complete()\n");
1590
1591 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
1592 if (param == NULL) {
1593 printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense_complete(): Bad alignment virtual address.\n");
1594 return 1;
1595 }
1596 flags = (char *)&(param->data[0]);
James Bottomleyc9d297c2005-06-28 09:18:21 -05001597 memset(request_buffer, 0, sizeof(request_buffer));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598
1599 request_buffer[0] = 0xf; /* mode data length */
1600 request_buffer[1] = 0; /* default medium type */
1601 request_buffer[2] = 0x10; /* dpo/fua support on */
1602 request_buffer[3] = 0; /* no block descriptors */
1603 request_buffer[4] = 0x8; /* caching page */
1604 request_buffer[5] = 0xa; /* page length */
1605 if (*flags & 0x1)
adam radford4fe48182007-01-04 18:16:56 -08001606 request_buffer[6] = 0x5; /* WCE on, RCD on */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607 else
adam radford4fe48182007-01-04 18:16:56 -08001608 request_buffer[6] = 0x1; /* WCE off, RCD on */
James Bottomleyc9d297c2005-06-28 09:18:21 -05001609 tw_transfer_internal(tw_dev, request_id, request_buffer,
1610 sizeof(request_buffer));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611
1612 return 0;
1613} /* End tw_scsiop_mode_sense_complete() */
1614
1615/* This function handles scsi read_capacity commands */
1616static int tw_scsiop_read_capacity(TW_Device_Extension *tw_dev, int request_id)
1617{
1618 TW_Param *param;
1619 TW_Command *command_packet;
1620 unsigned long command_que_value;
1621 unsigned long param_value;
1622
1623 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity()\n");
1624
1625 /* Initialize command packet */
1626 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
1627
1628 if (command_packet == NULL) {
1629 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad command packet virtual address.\n");
1630 return 1;
1631 }
1632 memset(command_packet, 0, sizeof(TW_Sector));
1633 command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM);
1634 command_packet->size = 4;
1635 command_packet->request_id = request_id;
1636 command_packet->unit__hostid = TW_UNITHOST_IN(0, tw_dev->srb[request_id]->device->id);
1637 command_packet->status = 0;
1638 command_packet->flags = 0;
1639 command_packet->byte6.block_count = 1;
1640
1641 /* Now setup the param */
1642 if (tw_dev->alignment_virtual_address[request_id] == NULL) {
1643 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad alignment virtual address.\n");
1644 return 1;
1645 }
1646 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
1647 memset(param, 0, sizeof(TW_Sector));
1648 param->table_id = TW_UNIT_INFORMATION_TABLE_BASE +
1649 tw_dev->srb[request_id]->device->id;
1650 param->parameter_id = 4; /* unitcapacity parameter */
1651 param->parameter_size_bytes = 4;
1652 param_value = tw_dev->alignment_physical_address[request_id];
1653 if (param_value == 0) {
1654 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad alignment physical address.\n");
1655 return 1;
1656 }
1657
1658 command_packet->byte8.param.sgl[0].address = param_value;
1659 command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
1660 command_que_value = tw_dev->command_packet_physical_address[request_id];
1661 if (command_que_value == 0) {
1662 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad command packet physical address.\n");
1663 return 1;
1664 }
1665
1666 /* Now try to post the command to the board */
1667 tw_post_command_packet(tw_dev, request_id);
1668
1669 return 0;
1670} /* End tw_scsiop_read_capacity() */
1671
1672/* This function is called by the isr to complete a readcapacity command */
1673static int tw_scsiop_read_capacity_complete(TW_Device_Extension *tw_dev, int request_id)
1674{
1675 unsigned char *param_data;
1676 u32 capacity;
James Bottomleyc9d297c2005-06-28 09:18:21 -05001677 char buff[8];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 TW_Param *param;
1679
1680 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete()\n");
1681
James Bottomleyc9d297c2005-06-28 09:18:21 -05001682 memset(buff, 0, sizeof(buff));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
1684 if (param == NULL) {
1685 printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Bad alignment virtual address.\n");
1686 return 1;
1687 }
1688 param_data = &(param->data[0]);
1689
1690 capacity = (param_data[3] << 24) | (param_data[2] << 16) |
1691 (param_data[1] << 8) | param_data[0];
1692
1693 /* Subtract one sector to fix get last sector ioctl */
1694 capacity -= 1;
1695
1696 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete(): Capacity = 0x%x.\n", capacity);
1697
1698 /* Number of LBA's */
1699 buff[0] = (capacity >> 24);
1700 buff[1] = (capacity >> 16) & 0xff;
1701 buff[2] = (capacity >> 8) & 0xff;
1702 buff[3] = capacity & 0xff;
1703
1704 /* Block size in bytes (512) */
1705 buff[4] = (TW_BLOCK_SIZE >> 24);
1706 buff[5] = (TW_BLOCK_SIZE >> 16) & 0xff;
1707 buff[6] = (TW_BLOCK_SIZE >> 8) & 0xff;
1708 buff[7] = TW_BLOCK_SIZE & 0xff;
1709
James Bottomleyc9d297c2005-06-28 09:18:21 -05001710 tw_transfer_internal(tw_dev, request_id, buff, sizeof(buff));
1711
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 return 0;
1713} /* End tw_scsiop_read_capacity_complete() */
1714
1715/* This function handles scsi read or write commands */
1716static int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id)
1717{
1718 TW_Command *command_packet;
1719 unsigned long command_que_value;
FUJITA Tomonori6edae702007-05-14 20:20:27 +09001720 u32 lba = 0x0, num_sectors = 0x0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721 int i, use_sg;
1722 struct scsi_cmnd *srb;
FUJITA Tomonori6edae702007-05-14 20:20:27 +09001723 struct scatterlist *sglist, *sg;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724
1725 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write()\n");
1726
FUJITA Tomonori6edae702007-05-14 20:20:27 +09001727 srb = tw_dev->srb[request_id];
1728
1729 sglist = scsi_sglist(srb);
1730 if (!sglist) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_write(): Request buffer NULL.\n");
1732 return 1;
1733 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734
1735 /* Initialize command packet */
1736 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
1737 if (command_packet == NULL) {
1738 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): Bad command packet virtual address.\n");
1739 return 1;
1740 }
1741
1742 if (srb->cmnd[0] == READ_6 || srb->cmnd[0] == READ_10) {
1743 command_packet->opcode__sgloffset = TW_OPSGL_IN(3, TW_OP_READ);
1744 } else {
1745 command_packet->opcode__sgloffset = TW_OPSGL_IN(3, TW_OP_WRITE);
1746 }
1747
1748 command_packet->size = 3;
1749 command_packet->request_id = request_id;
1750 command_packet->unit__hostid = TW_UNITHOST_IN(0, srb->device->id);
1751 command_packet->status = 0;
1752 command_packet->flags = 0;
1753
1754 if (srb->cmnd[0] == WRITE_10) {
1755 if ((srb->cmnd[1] & 0x8) || (srb->cmnd[1] & 0x10))
1756 command_packet->flags = 1;
1757 }
1758
1759 if (srb->cmnd[0] == READ_6 || srb->cmnd[0] == WRITE_6) {
1760 lba = ((u32)srb->cmnd[1] << 16) | ((u32)srb->cmnd[2] << 8) | (u32)srb->cmnd[3];
1761 num_sectors = (u32)srb->cmnd[4];
1762 } else {
1763 lba = ((u32)srb->cmnd[2] << 24) | ((u32)srb->cmnd[3] << 16) | ((u32)srb->cmnd[4] << 8) | (u32)srb->cmnd[5];
1764 num_sectors = (u32)srb->cmnd[8] | ((u32)srb->cmnd[7] << 8);
1765 }
1766
1767 /* Update sector statistic */
1768 tw_dev->sector_count = num_sectors;
1769 if (tw_dev->sector_count > tw_dev->max_sector_count)
1770 tw_dev->max_sector_count = tw_dev->sector_count;
1771
1772 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): lba = 0x%x num_sectors = 0x%x\n", lba, num_sectors);
1773 command_packet->byte8.io.lba = lba;
1774 command_packet->byte6.block_count = num_sectors;
1775
FUJITA Tomonori6edae702007-05-14 20:20:27 +09001776 use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
1777 if (!use_sg)
1778 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779
FUJITA Tomonori6edae702007-05-14 20:20:27 +09001780 scsi_for_each_sg(tw_dev->srb[request_id], sg, use_sg, i) {
1781 command_packet->byte8.io.sgl[i].address = sg_dma_address(sg);
1782 command_packet->byte8.io.sgl[i].length = sg_dma_len(sg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001783 command_packet->size+=2;
1784 }
1785
Linus Torvalds1da177e2005-04-16 15:20:36 -07001786 /* Update SG statistics */
FUJITA Tomonori6edae702007-05-14 20:20:27 +09001787 tw_dev->sgl_entries = scsi_sg_count(tw_dev->srb[request_id]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788 if (tw_dev->sgl_entries > tw_dev->max_sgl_entries)
1789 tw_dev->max_sgl_entries = tw_dev->sgl_entries;
1790
1791 command_que_value = tw_dev->command_packet_physical_address[request_id];
1792 if (command_que_value == 0) {
1793 dprintk(KERN_WARNING "3w-xxxx: tw_scsiop_read_write(): Bad command packet physical address.\n");
1794 return 1;
1795 }
1796
1797 /* Now try to post the command to the board */
1798 tw_post_command_packet(tw_dev, request_id);
1799
1800 return 0;
1801} /* End tw_scsiop_read_write() */
1802
1803/* This function will handle the request sense scsi command */
1804static int tw_scsiop_request_sense(TW_Device_Extension *tw_dev, int request_id)
1805{
James Bottomley6e3b2bb2007-04-06 11:14:56 -05001806 char request_buffer[18];
1807
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_request_sense()\n");
1809
James Bottomley6e3b2bb2007-04-06 11:14:56 -05001810 memset(request_buffer, 0, sizeof(request_buffer));
1811 request_buffer[0] = 0x70; /* Immediate fixed format */
1812 request_buffer[7] = 10; /* minimum size per SPC: 18 bytes */
1813 /* leave all other fields zero, giving effectively NO_SENSE return */
1814 tw_transfer_internal(tw_dev, request_id, request_buffer,
1815 sizeof(request_buffer));
1816
Linus Torvalds1da177e2005-04-16 15:20:36 -07001817 tw_dev->state[request_id] = TW_S_COMPLETED;
1818 tw_state_request_finish(tw_dev, request_id);
1819
1820 /* If we got a request_sense, we probably want a reset, return error */
1821 tw_dev->srb[request_id]->result = (DID_ERROR << 16);
1822 tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
1823
1824 return 0;
1825} /* End tw_scsiop_request_sense() */
1826
1827/* This function will handle synchronize cache scsi command */
1828static int tw_scsiop_synchronize_cache(TW_Device_Extension *tw_dev, int request_id)
1829{
1830 TW_Command *command_packet;
1831 unsigned long command_que_value;
1832
1833 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_synchronize_cache()\n");
1834
1835 /* Send firmware flush command for this unit */
1836 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
1837 if (command_packet == NULL) {
1838 printk(KERN_WARNING "3w-xxxx: tw_scsiop_synchronize_cache(): Bad command packet virtual address.\n");
1839 return 1;
1840 }
1841
1842 /* Setup the command packet */
1843 memset(command_packet, 0, sizeof(TW_Sector));
1844 command_packet->opcode__sgloffset = TW_OPSGL_IN(0, TW_OP_FLUSH_CACHE);
1845 command_packet->size = 2;
1846 command_packet->request_id = request_id;
1847 command_packet->unit__hostid = TW_UNITHOST_IN(0, tw_dev->srb[request_id]->device->id);
1848 command_packet->status = 0;
1849 command_packet->flags = 0;
1850 command_packet->byte6.parameter_count = 1;
1851 command_que_value = tw_dev->command_packet_physical_address[request_id];
1852 if (command_que_value == 0) {
1853 printk(KERN_WARNING "3w-xxxx: tw_scsiop_synchronize_cache(): Bad command packet physical address.\n");
1854 return 1;
1855 }
1856
1857 /* Now try to post the command packet */
1858 tw_post_command_packet(tw_dev, request_id);
1859
1860 return 0;
1861} /* End tw_scsiop_synchronize_cache() */
1862
1863/* This function will handle test unit ready scsi command */
1864static int tw_scsiop_test_unit_ready(TW_Device_Extension *tw_dev, int request_id)
1865{
1866 TW_Param *param;
1867 TW_Command *command_packet;
1868 unsigned long command_que_value;
1869 unsigned long param_value;
1870
1871 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_test_unit_ready()\n");
1872
1873 /* Initialize command packet */
1874 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
1875 if (command_packet == NULL) {
1876 printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad command packet virtual address.\n");
1877 return 1;
1878 }
1879 memset(command_packet, 0, sizeof(TW_Sector));
1880 command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM);
1881 command_packet->size = 4;
1882 command_packet->request_id = request_id;
1883 command_packet->status = 0;
1884 command_packet->flags = 0;
1885 command_packet->byte6.parameter_count = 1;
1886
1887 /* Now setup the param */
1888 if (tw_dev->alignment_virtual_address[request_id] == NULL) {
1889 printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad alignment virtual address.\n");
1890 return 1;
1891 }
1892 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
1893 memset(param, 0, sizeof(TW_Sector));
1894 param->table_id = 3; /* unit summary table */
1895 param->parameter_id = 3; /* unitsstatus parameter */
1896 param->parameter_size_bytes = TW_MAX_UNITS;
1897 param_value = tw_dev->alignment_physical_address[request_id];
1898 if (param_value == 0) {
1899 printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad alignment physical address.\n");
1900 return 1;
1901 }
1902
1903 command_packet->byte8.param.sgl[0].address = param_value;
1904 command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
1905 command_que_value = tw_dev->command_packet_physical_address[request_id];
1906 if (command_que_value == 0) {
1907 printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad command packet physical address.\n");
1908 return 1;
1909 }
1910
1911 /* Now try to post the command packet */
1912 tw_post_command_packet(tw_dev, request_id);
1913
1914 return 0;
1915} /* End tw_scsiop_test_unit_ready() */
1916
1917/* This function is called by the isr to complete a testunitready command */
1918static int tw_scsiop_test_unit_ready_complete(TW_Device_Extension *tw_dev, int request_id)
1919{
1920 unsigned char *is_unit_present;
1921 TW_Param *param;
1922
1923 dprintk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready_complete()\n");
1924
1925 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
1926 if (param == NULL) {
1927 printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready_complete(): Bad alignment virtual address.\n");
1928 return 1;
1929 }
1930 is_unit_present = &(param->data[0]);
1931
1932 if (is_unit_present[tw_dev->srb[request_id]->device->id] & TW_UNIT_ONLINE) {
1933 tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = 1;
1934 } else {
1935 tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = 0;
1936 tw_dev->srb[request_id]->result = (DID_BAD_TARGET << 16);
1937 return TW_ISR_DONT_RESULT;
1938 }
1939
1940 return 0;
1941} /* End tw_scsiop_test_unit_ready_complete() */
1942
1943/* This is the main scsi queue function to handle scsi opcodes */
1944static int tw_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
1945{
1946 unsigned char *command = SCpnt->cmnd;
1947 int request_id = 0;
1948 int retval = 1;
1949 TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
1950
adam radford4fe48182007-01-04 18:16:56 -08001951 /* If we are resetting due to timed out ioctl, report as busy */
1952 if (test_bit(TW_IN_RESET, &tw_dev->flags))
1953 return SCSI_MLQUEUE_HOST_BUSY;
1954
Linus Torvalds1da177e2005-04-16 15:20:36 -07001955 /* Save done function into Scsi_Cmnd struct */
1956 SCpnt->scsi_done = done;
1957
1958 /* Queue the command and get a request id */
1959 tw_state_request_start(tw_dev, &request_id);
1960
1961 /* Save the scsi command for use by the ISR */
1962 tw_dev->srb[request_id] = SCpnt;
1963
1964 /* Initialize phase to zero */
1965 SCpnt->SCp.phase = TW_PHASE_INITIAL;
1966
1967 switch (*command) {
1968 case READ_10:
1969 case READ_6:
1970 case WRITE_10:
1971 case WRITE_6:
1972 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ/WRITE.\n");
1973 retval = tw_scsiop_read_write(tw_dev, request_id);
1974 break;
1975 case TEST_UNIT_READY:
1976 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught TEST_UNIT_READY.\n");
1977 retval = tw_scsiop_test_unit_ready(tw_dev, request_id);
1978 break;
1979 case INQUIRY:
1980 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught INQUIRY.\n");
1981 retval = tw_scsiop_inquiry(tw_dev, request_id);
1982 break;
1983 case READ_CAPACITY:
1984 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ_CAPACITY.\n");
1985 retval = tw_scsiop_read_capacity(tw_dev, request_id);
1986 break;
1987 case REQUEST_SENSE:
1988 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught REQUEST_SENSE.\n");
1989 retval = tw_scsiop_request_sense(tw_dev, request_id);
1990 break;
1991 case MODE_SENSE:
1992 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught MODE_SENSE.\n");
1993 retval = tw_scsiop_mode_sense(tw_dev, request_id);
1994 break;
1995 case SYNCHRONIZE_CACHE:
1996 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught SYNCHRONIZE_CACHE.\n");
1997 retval = tw_scsiop_synchronize_cache(tw_dev, request_id);
1998 break;
1999 case TW_IOCTL:
2000 printk(KERN_WARNING "3w-xxxx: SCSI_IOCTL_SEND_COMMAND deprecated, please update your 3ware tools.\n");
2001 break;
2002 default:
2003 printk(KERN_NOTICE "3w-xxxx: scsi%d: Unknown scsi opcode: 0x%x\n", tw_dev->host->host_no, *command);
2004 tw_dev->state[request_id] = TW_S_COMPLETED;
2005 tw_state_request_finish(tw_dev, request_id);
2006 SCpnt->result = (DID_BAD_TARGET << 16);
2007 done(SCpnt);
2008 retval = 0;
2009 }
2010 if (retval) {
2011 tw_dev->state[request_id] = TW_S_COMPLETED;
2012 tw_state_request_finish(tw_dev, request_id);
2013 SCpnt->result = (DID_ERROR << 16);
2014 done(SCpnt);
2015 retval = 0;
2016 }
2017 return retval;
2018} /* End tw_scsi_queue() */
2019
2020/* This function is the interrupt service routine */
David Howells7d12e782006-10-05 14:55:46 +01002021static irqreturn_t tw_interrupt(int irq, void *dev_instance)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002022{
2023 int request_id;
2024 u32 status_reg_value;
2025 TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance;
2026 TW_Response_Queue response_que;
2027 int error = 0, retval = 0;
2028 TW_Command *command_packet;
2029 int handled = 0;
2030
2031 /* Get the host lock for io completions */
2032 spin_lock(tw_dev->host->host_lock);
2033
2034 /* Read the registers */
2035 status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
2036
2037 /* Check if this is our interrupt, otherwise bail */
2038 if (!(status_reg_value & TW_STATUS_VALID_INTERRUPT))
2039 goto tw_interrupt_bail;
2040
2041 handled = 1;
2042
adam radford4fe48182007-01-04 18:16:56 -08002043 /* If we are resetting, bail */
2044 if (test_bit(TW_IN_RESET, &tw_dev->flags))
2045 goto tw_interrupt_bail;
2046
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047 /* Check controller for errors */
2048 if (tw_check_bits(status_reg_value)) {
2049 dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
2050 if (tw_decode_bits(tw_dev, status_reg_value, 1)) {
2051 TW_CLEAR_ALL_INTERRUPTS(tw_dev);
2052 goto tw_interrupt_bail;
2053 }
2054 }
2055
2056 /* Handle host interrupt */
2057 if (status_reg_value & TW_STATUS_HOST_INTERRUPT) {
2058 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received host interrupt.\n");
2059 TW_CLEAR_HOST_INTERRUPT(tw_dev);
2060 }
2061
2062 /* Handle attention interrupt */
2063 if (status_reg_value & TW_STATUS_ATTENTION_INTERRUPT) {
2064 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received attention interrupt.\n");
2065 TW_CLEAR_ATTENTION_INTERRUPT(tw_dev);
2066 tw_state_request_start(tw_dev, &request_id);
2067 error = tw_aen_read_queue(tw_dev, request_id);
2068 if (error) {
2069 printk(KERN_WARNING "3w-xxxx: scsi%d: Error reading aen queue.\n", tw_dev->host->host_no);
2070 tw_dev->state[request_id] = TW_S_COMPLETED;
2071 tw_state_request_finish(tw_dev, request_id);
2072 }
2073 }
2074
2075 /* Handle command interrupt */
2076 if (status_reg_value & TW_STATUS_COMMAND_INTERRUPT) {
2077 /* Drain as many pending commands as we can */
2078 while (tw_dev->pending_request_count > 0) {
2079 request_id = tw_dev->pending_queue[tw_dev->pending_head];
2080 if (tw_dev->state[request_id] != TW_S_PENDING) {
2081 printk(KERN_WARNING "3w-xxxx: scsi%d: Found request id that wasn't pending.\n", tw_dev->host->host_no);
2082 break;
2083 }
2084 if (tw_post_command_packet(tw_dev, request_id)==0) {
2085 if (tw_dev->pending_head == TW_Q_LENGTH-1) {
2086 tw_dev->pending_head = TW_Q_START;
2087 } else {
2088 tw_dev->pending_head = tw_dev->pending_head + 1;
2089 }
2090 tw_dev->pending_request_count--;
2091 } else {
2092 /* If we get here, we will continue re-posting on the next command interrupt */
2093 break;
2094 }
2095 }
2096 /* If there are no more pending requests, we mask command interrupt */
2097 if (tw_dev->pending_request_count == 0)
2098 TW_MASK_COMMAND_INTERRUPT(tw_dev);
2099 }
2100
2101 /* Handle response interrupt */
2102 if (status_reg_value & TW_STATUS_RESPONSE_INTERRUPT) {
2103 /* Drain the response queue from the board */
2104 while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
2105 /* Read response queue register */
2106 response_que.value = inl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev));
2107 request_id = TW_RESID_OUT(response_que.response_id);
2108 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
2109 error = 0;
2110
2111 /* Check for bad response */
2112 if (command_packet->status != 0) {
2113 /* If internal command, don't error, don't fill sense */
2114 if (tw_dev->srb[request_id] == NULL) {
2115 tw_decode_sense(tw_dev, request_id, 0);
2116 } else {
2117 error = tw_decode_sense(tw_dev, request_id, 1);
2118 }
2119 }
2120
2121 /* Check for correct state */
2122 if (tw_dev->state[request_id] != TW_S_POSTED) {
2123 if (tw_dev->srb[request_id] != NULL) {
2124 printk(KERN_WARNING "3w-xxxx: scsi%d: Received a request id that wasn't posted.\n", tw_dev->host->host_no);
2125 error = 1;
2126 }
2127 }
2128
2129 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Response queue request id: %d.\n", request_id);
2130
2131 /* Check for internal command completion */
2132 if (tw_dev->srb[request_id] == NULL) {
2133 dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found internally posted command.\n");
2134 /* Check for chrdev ioctl completion */
2135 if (request_id != tw_dev->chrdev_request_id) {
2136 retval = tw_aen_complete(tw_dev, request_id);
2137 if (retval) {
2138 printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing aen.\n", tw_dev->host->host_no);
2139 }
2140 } else {
2141 tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
2142 wake_up(&tw_dev->ioctl_wqueue);
2143 }
2144 } else {
2145 switch (tw_dev->srb[request_id]->cmnd[0]) {
2146 case READ_10:
2147 case READ_6:
2148 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_10/READ_6\n");
2149 break;
2150 case WRITE_10:
2151 case WRITE_6:
2152 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_10/WRITE_6\n");
2153 break;
2154 case TEST_UNIT_READY:
2155 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught TEST_UNIT_READY\n");
2156 error = tw_scsiop_test_unit_ready_complete(tw_dev, request_id);
2157 break;
2158 case INQUIRY:
2159 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught INQUIRY\n");
2160 error = tw_scsiop_inquiry_complete(tw_dev, request_id);
2161 break;
2162 case READ_CAPACITY:
2163 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_CAPACITY\n");
2164 error = tw_scsiop_read_capacity_complete(tw_dev, request_id);
2165 break;
2166 case MODE_SENSE:
2167 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught MODE_SENSE\n");
2168 error = tw_scsiop_mode_sense_complete(tw_dev, request_id);
2169 break;
2170 case SYNCHRONIZE_CACHE:
2171 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught SYNCHRONIZE_CACHE\n");
2172 break;
2173 default:
2174 printk(KERN_WARNING "3w-xxxx: case slip in tw_interrupt()\n");
2175 error = 1;
2176 }
2177
2178 /* If no error command was a success */
2179 if (error == 0) {
2180 tw_dev->srb[request_id]->result = (DID_OK << 16);
2181 }
2182
2183 /* If error, command failed */
2184 if (error == 1) {
2185 /* Ask for a host reset */
2186 tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
2187 }
2188
2189 /* Now complete the io */
2190 if ((error != TW_ISR_DONT_COMPLETE)) {
2191 tw_dev->state[request_id] = TW_S_COMPLETED;
2192 tw_state_request_finish(tw_dev, request_id);
2193 tw_dev->posted_request_count--;
2194 tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
2195
2196 tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
2197 }
2198 }
2199
2200 /* Check for valid status after each drain */
2201 status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
2202 if (tw_check_bits(status_reg_value)) {
2203 dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
2204 if (tw_decode_bits(tw_dev, status_reg_value, 1)) {
2205 TW_CLEAR_ALL_INTERRUPTS(tw_dev);
2206 goto tw_interrupt_bail;
2207 }
2208 }
2209 }
2210 }
2211
2212tw_interrupt_bail:
2213 spin_unlock(tw_dev->host->host_lock);
2214 return IRQ_RETVAL(handled);
2215} /* End tw_interrupt() */
2216
2217/* This function tells the controller to shut down */
2218static void __tw_shutdown(TW_Device_Extension *tw_dev)
2219{
2220 /* Disable interrupts */
2221 TW_DISABLE_INTERRUPTS(tw_dev);
2222
adam radford4fe48182007-01-04 18:16:56 -08002223 /* Free up the IRQ */
2224 free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
2225
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226 printk(KERN_WARNING "3w-xxxx: Shutting down host %d.\n", tw_dev->host->host_no);
2227
2228 /* Tell the card we are shutting down */
2229 if (tw_initconnection(tw_dev, 1)) {
2230 printk(KERN_WARNING "3w-xxxx: Connection shutdown failed.\n");
2231 } else {
2232 printk(KERN_WARNING "3w-xxxx: Shutdown complete.\n");
2233 }
2234
2235 /* Clear all interrupts just before exit */
2236 TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);
2237} /* End __tw_shutdown() */
2238
2239/* Wrapper for __tw_shutdown */
Greg Kroah-Hartmand18c3db2005-06-23 17:35:56 -07002240static void tw_shutdown(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002241{
Greg Kroah-Hartmand18c3db2005-06-23 17:35:56 -07002242 struct Scsi_Host *host = pci_get_drvdata(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
2244
2245 __tw_shutdown(tw_dev);
2246} /* End tw_shutdown() */
2247
2248static struct scsi_host_template driver_template = {
2249 .module = THIS_MODULE,
2250 .name = "3ware Storage Controller",
2251 .queuecommand = tw_scsi_queue,
2252 .eh_host_reset_handler = tw_scsi_eh_reset,
2253 .bios_param = tw_scsi_biosparam,
2254 .change_queue_depth = tw_change_queue_depth,
2255 .can_queue = TW_Q_LENGTH-2,
2256 .this_id = -1,
2257 .sg_tablesize = TW_MAX_SGL_LENGTH,
2258 .max_sectors = TW_MAX_SECTORS,
2259 .cmd_per_lun = TW_MAX_CMDS_PER_LUN,
2260 .use_clustering = ENABLE_CLUSTERING,
2261 .shost_attrs = tw_host_attrs,
2262 .emulated = 1
2263};
2264
2265/* This function will probe and initialize a card */
2266static int __devinit tw_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
2267{
2268 struct Scsi_Host *host = NULL;
2269 TW_Device_Extension *tw_dev;
2270 int retval = -ENODEV;
2271
2272 retval = pci_enable_device(pdev);
2273 if (retval) {
2274 printk(KERN_WARNING "3w-xxxx: Failed to enable pci device.");
2275 goto out_disable_device;
2276 }
2277
2278 pci_set_master(pdev);
2279
2280 retval = pci_set_dma_mask(pdev, TW_DMA_MASK);
2281 if (retval) {
2282 printk(KERN_WARNING "3w-xxxx: Failed to set dma mask.");
2283 goto out_disable_device;
2284 }
2285
2286 host = scsi_host_alloc(&driver_template, sizeof(TW_Device_Extension));
2287 if (!host) {
2288 printk(KERN_WARNING "3w-xxxx: Failed to allocate memory for device extension.");
2289 retval = -ENOMEM;
2290 goto out_disable_device;
2291 }
2292 tw_dev = (TW_Device_Extension *)host->hostdata;
2293
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 /* Save values to device extension */
2295 tw_dev->host = host;
2296 tw_dev->tw_pci_dev = pdev;
2297
2298 if (tw_initialize_device_extension(tw_dev)) {
2299 printk(KERN_WARNING "3w-xxxx: Failed to initialize device extension.");
2300 goto out_free_device_extension;
2301 }
2302
2303 /* Request IO regions */
2304 retval = pci_request_regions(pdev, "3w-xxxx");
2305 if (retval) {
2306 printk(KERN_WARNING "3w-xxxx: Failed to get mem region.");
2307 goto out_free_device_extension;
2308 }
2309
2310 /* Save base address */
2311 tw_dev->base_addr = pci_resource_start(pdev, 0);
2312 if (!tw_dev->base_addr) {
2313 printk(KERN_WARNING "3w-xxxx: Failed to get io address.");
2314 goto out_release_mem_region;
2315 }
2316
2317 /* Disable interrupts on the card */
2318 TW_DISABLE_INTERRUPTS(tw_dev);
2319
2320 /* Initialize the card */
2321 if (tw_reset_sequence(tw_dev))
2322 goto out_release_mem_region;
2323
2324 /* Set host specific parameters */
2325 host->max_id = TW_MAX_UNITS;
2326 host->max_cmd_len = TW_MAX_CDB_LEN;
2327
2328 /* Luns and channels aren't supported by adapter */
2329 host->max_lun = 0;
2330 host->max_channel = 0;
2331
2332 /* Register the card with the kernel SCSI layer */
2333 retval = scsi_add_host(host, &pdev->dev);
2334 if (retval) {
2335 printk(KERN_WARNING "3w-xxxx: scsi add host failed");
2336 goto out_release_mem_region;
2337 }
2338
2339 pci_set_drvdata(pdev, host);
2340
2341 printk(KERN_WARNING "3w-xxxx: scsi%d: Found a 3ware Storage Controller at 0x%x, IRQ: %d.\n", host->host_no, tw_dev->base_addr, pdev->irq);
2342
2343 /* Now setup the interrupt handler */
Thomas Gleixner1d6f3592006-07-01 19:29:42 -07002344 retval = request_irq(pdev->irq, tw_interrupt, IRQF_SHARED, "3w-xxxx", tw_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002345 if (retval) {
2346 printk(KERN_WARNING "3w-xxxx: Error requesting IRQ.");
2347 goto out_remove_host;
2348 }
2349
2350 tw_device_extension_list[tw_device_extension_count] = tw_dev;
2351 tw_device_extension_count++;
2352
2353 /* Re-enable interrupts on the card */
2354 TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);
2355
2356 /* Finally, scan the host */
2357 scsi_scan_host(host);
2358
2359 if (twe_major == -1) {
2360 if ((twe_major = register_chrdev (0, "twe", &tw_fops)) < 0)
2361 printk(KERN_WARNING "3w-xxxx: Failed to register character device.");
2362 }
2363 return 0;
2364
2365out_remove_host:
2366 scsi_remove_host(host);
2367out_release_mem_region:
2368 pci_release_regions(pdev);
2369out_free_device_extension:
2370 tw_free_device_extension(tw_dev);
2371 scsi_host_put(host);
2372out_disable_device:
2373 pci_disable_device(pdev);
2374
2375 return retval;
2376} /* End tw_probe() */
2377
2378/* This function is called to remove a device */
2379static void tw_remove(struct pci_dev *pdev)
2380{
2381 struct Scsi_Host *host = pci_get_drvdata(pdev);
2382 TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
2383
2384 scsi_remove_host(tw_dev->host);
2385
2386 /* Unregister character device */
2387 if (twe_major >= 0) {
2388 unregister_chrdev(twe_major, "twe");
2389 twe_major = -1;
2390 }
2391
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392 /* Shutdown the card */
2393 __tw_shutdown(tw_dev);
2394
2395 /* Free up the mem region */
2396 pci_release_regions(pdev);
2397
2398 /* Free up device extension resources */
2399 tw_free_device_extension(tw_dev);
2400
2401 scsi_host_put(tw_dev->host);
2402 pci_disable_device(pdev);
2403 tw_device_extension_count--;
2404} /* End tw_remove() */
2405
2406/* PCI Devices supported by this driver */
2407static struct pci_device_id tw_pci_tbl[] __devinitdata = {
2408 { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_1000,
2409 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2410 { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_7000,
2411 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2412 { }
2413};
2414MODULE_DEVICE_TABLE(pci, tw_pci_tbl);
2415
2416/* pci_driver initializer */
2417static struct pci_driver tw_driver = {
2418 .name = "3w-xxxx",
2419 .id_table = tw_pci_tbl,
2420 .probe = tw_probe,
2421 .remove = tw_remove,
Greg Kroah-Hartmand18c3db2005-06-23 17:35:56 -07002422 .shutdown = tw_shutdown,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423};
2424
2425/* This function is called on driver initialization */
2426static int __init tw_init(void)
2427{
2428 printk(KERN_WARNING "3ware Storage Controller device driver for Linux v%s.\n", TW_DRIVER_VERSION);
2429
Henrik Kretzschmardcbccbde2006-09-25 16:58:58 -07002430 return pci_register_driver(&tw_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431} /* End tw_init() */
2432
2433/* This function is called on driver exit */
2434static void __exit tw_exit(void)
2435{
2436 pci_unregister_driver(&tw_driver);
2437} /* End tw_exit() */
2438
2439module_init(tw_init);
2440module_exit(tw_exit);
2441