blob: 99a259c5a0c07c830b78936ee4983586d90c2dc9 [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
9 Copyright (C) 1999-2005 3ware Inc.
10
11 Kernel compatiblity By: Andre Hedrick <andre@suse.com>
12 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.
194*/
195
196#include <linux/module.h>
197#include <linux/reboot.h>
198#include <linux/spinlock.h>
199#include <linux/interrupt.h>
200#include <linux/moduleparam.h>
201#include <linux/errno.h>
202#include <linux/types.h>
203#include <linux/delay.h>
204#include <linux/pci.h>
205#include <linux/time.h>
Jes Sorensena12e25bd2006-01-11 08:39:45 -0500206#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207#include <asm/io.h>
208#include <asm/irq.h>
209#include <asm/uaccess.h>
210#include <scsi/scsi.h>
211#include <scsi/scsi_host.h>
212#include <scsi/scsi_tcq.h>
213#include <scsi/scsi_cmnd.h>
214#include "3w-xxxx.h"
215
216/* Globals */
217#define TW_DRIVER_VERSION "1.26.02.001"
218static TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
219static int tw_device_extension_count = 0;
220static int twe_major = -1;
221
222/* Module parameters */
223MODULE_AUTHOR("AMCC");
224MODULE_DESCRIPTION("3ware Storage Controller Linux Driver");
225MODULE_LICENSE("GPL");
226MODULE_VERSION(TW_DRIVER_VERSION);
227
228/* Function prototypes */
229static int tw_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset);
230
231/* Functions */
232
233/* This function will check the status register for unexpected bits */
234static int tw_check_bits(u32 status_reg_value)
235{
236 if ((status_reg_value & TW_STATUS_EXPECTED_BITS) != TW_STATUS_EXPECTED_BITS) {
237 dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): No expected bits (0x%x).\n", status_reg_value);
238 return 1;
239 }
240 if ((status_reg_value & TW_STATUS_UNEXPECTED_BITS) != 0) {
241 dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): Found unexpected bits (0x%x).\n", status_reg_value);
242 return 1;
243 }
244
245 return 0;
246} /* End tw_check_bits() */
247
248/* This function will print readable messages from status register errors */
249static int tw_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value, int print_host)
250{
251 char host[16];
252
253 dprintk(KERN_WARNING "3w-xxxx: tw_decode_bits()\n");
254
255 if (print_host)
256 sprintf(host, " scsi%d:", tw_dev->host->host_no);
257 else
258 host[0] = '\0';
259
260 if (status_reg_value & TW_STATUS_PCI_PARITY_ERROR) {
261 printk(KERN_WARNING "3w-xxxx:%s PCI Parity Error: clearing.\n", host);
262 outl(TW_CONTROL_CLEAR_PARITY_ERROR, TW_CONTROL_REG_ADDR(tw_dev));
263 }
264
265 if (status_reg_value & TW_STATUS_PCI_ABORT) {
266 printk(KERN_WARNING "3w-xxxx:%s PCI Abort: clearing.\n", host);
267 outl(TW_CONTROL_CLEAR_PCI_ABORT, TW_CONTROL_REG_ADDR(tw_dev));
268 pci_write_config_word(tw_dev->tw_pci_dev, PCI_STATUS, TW_PCI_CLEAR_PCI_ABORT);
269 }
270
271 if (status_reg_value & TW_STATUS_QUEUE_ERROR) {
272 printk(KERN_WARNING "3w-xxxx:%s Controller Queue Error: clearing.\n", host);
273 outl(TW_CONTROL_CLEAR_QUEUE_ERROR, TW_CONTROL_REG_ADDR(tw_dev));
274 }
275
276 if (status_reg_value & TW_STATUS_SBUF_WRITE_ERROR) {
277 printk(KERN_WARNING "3w-xxxx:%s SBUF Write Error: clearing.\n", host);
278 outl(TW_CONTROL_CLEAR_SBUF_WRITE_ERROR, TW_CONTROL_REG_ADDR(tw_dev));
279 }
280
281 if (status_reg_value & TW_STATUS_MICROCONTROLLER_ERROR) {
282 if (tw_dev->reset_print == 0) {
283 printk(KERN_WARNING "3w-xxxx:%s Microcontroller Error: clearing.\n", host);
284 tw_dev->reset_print = 1;
285 }
286 return 1;
287 }
288
289 return 0;
290} /* End tw_decode_bits() */
291
292/* This function will poll the status register for a flag */
293static int tw_poll_status(TW_Device_Extension *tw_dev, u32 flag, int seconds)
294{
295 u32 status_reg_value;
296 unsigned long before;
297 int retval = 1;
298
299 status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
300 before = jiffies;
301
302 if (tw_check_bits(status_reg_value))
303 tw_decode_bits(tw_dev, status_reg_value, 0);
304
305 while ((status_reg_value & flag) != flag) {
306 status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
307
308 if (tw_check_bits(status_reg_value))
309 tw_decode_bits(tw_dev, status_reg_value, 0);
310
311 if (time_after(jiffies, before + HZ * seconds))
312 goto out;
313
314 msleep(50);
315 }
316 retval = 0;
317out:
318 return retval;
319} /* End tw_poll_status() */
320
321/* This function will poll the status register for disappearance of a flag */
322static int tw_poll_status_gone(TW_Device_Extension *tw_dev, u32 flag, int seconds)
323{
324 u32 status_reg_value;
325 unsigned long before;
326 int retval = 1;
327
328 status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
329 before = jiffies;
330
331 if (tw_check_bits(status_reg_value))
332 tw_decode_bits(tw_dev, status_reg_value, 0);
333
334 while ((status_reg_value & flag) != 0) {
335 status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
336
337 if (tw_check_bits(status_reg_value))
338 tw_decode_bits(tw_dev, status_reg_value, 0);
339
340 if (time_after(jiffies, before + HZ * seconds))
341 goto out;
342
343 msleep(50);
344 }
345 retval = 0;
346out:
347 return retval;
348} /* End tw_poll_status_gone() */
349
350/* This function will attempt to post a command packet to the board */
351static int tw_post_command_packet(TW_Device_Extension *tw_dev, int request_id)
352{
353 u32 status_reg_value;
354 unsigned long command_que_value;
355
356 dprintk(KERN_NOTICE "3w-xxxx: tw_post_command_packet()\n");
357 command_que_value = tw_dev->command_packet_physical_address[request_id];
358 status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
359
360 if (tw_check_bits(status_reg_value)) {
361 dprintk(KERN_WARNING "3w-xxxx: tw_post_command_packet(): Unexpected bits.\n");
362 tw_decode_bits(tw_dev, status_reg_value, 1);
363 }
364
365 if ((status_reg_value & TW_STATUS_COMMAND_QUEUE_FULL) == 0) {
366 /* We successfully posted the command packet */
367 outl(command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
368 tw_dev->state[request_id] = TW_S_POSTED;
369 tw_dev->posted_request_count++;
370 if (tw_dev->posted_request_count > tw_dev->max_posted_request_count) {
371 tw_dev->max_posted_request_count = tw_dev->posted_request_count;
372 }
373 } else {
374 /* Couldn't post the command packet, so we do it in the isr */
375 if (tw_dev->state[request_id] != TW_S_PENDING) {
376 tw_dev->state[request_id] = TW_S_PENDING;
377 tw_dev->pending_request_count++;
378 if (tw_dev->pending_request_count > tw_dev->max_pending_request_count) {
379 tw_dev->max_pending_request_count = tw_dev->pending_request_count;
380 }
381 tw_dev->pending_queue[tw_dev->pending_tail] = request_id;
382 if (tw_dev->pending_tail == TW_Q_LENGTH-1) {
383 tw_dev->pending_tail = TW_Q_START;
384 } else {
385 tw_dev->pending_tail = tw_dev->pending_tail + 1;
386 }
387 }
388 TW_UNMASK_COMMAND_INTERRUPT(tw_dev);
389 return 1;
390 }
391 return 0;
392} /* End tw_post_command_packet() */
393
394/* This function will return valid sense buffer information for failed cmds */
395static int tw_decode_sense(TW_Device_Extension *tw_dev, int request_id, int fill_sense)
396{
397 int i;
398 TW_Command *command;
399
400 dprintk(KERN_WARNING "3w-xxxx: tw_decode_sense()\n");
401 command = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
402
403 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));
404
405 /* Attempt to return intelligent sense information */
406 if (fill_sense) {
407 if ((command->status == 0xc7) || (command->status == 0xcb)) {
Tobias Klauser6391a112006-06-08 22:23:48 -0700408 for (i = 0; i < ARRAY_SIZE(tw_sense_table); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 if (command->flags == tw_sense_table[i][0]) {
410
411 /* Valid bit and 'current errors' */
412 tw_dev->srb[request_id]->sense_buffer[0] = (0x1 << 7 | 0x70);
413
414 /* Sense key */
415 tw_dev->srb[request_id]->sense_buffer[2] = tw_sense_table[i][1];
416
417 /* Additional sense length */
418 tw_dev->srb[request_id]->sense_buffer[7] = 0xa; /* 10 bytes */
419
420 /* Additional sense code */
421 tw_dev->srb[request_id]->sense_buffer[12] = tw_sense_table[i][2];
422
423 /* Additional sense code qualifier */
424 tw_dev->srb[request_id]->sense_buffer[13] = tw_sense_table[i][3];
425
426 tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
427 return TW_ISR_DONT_RESULT; /* Special case for isr to not over-write result */
428 }
429 }
430 }
431
432 /* If no table match, error so we get a reset */
433 return 1;
434 }
435
436 return 0;
437} /* End tw_decode_sense() */
438
439/* This function will report controller error status */
440static int tw_check_errors(TW_Device_Extension *tw_dev)
441{
442 u32 status_reg_value;
443
444 status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
445
446 if (TW_STATUS_ERRORS(status_reg_value) || tw_check_bits(status_reg_value)) {
447 tw_decode_bits(tw_dev, status_reg_value, 0);
448 return 1;
449 }
450
451 return 0;
452} /* End tw_check_errors() */
453
454/* This function will empty the response que */
455static void tw_empty_response_que(TW_Device_Extension *tw_dev)
456{
457 u32 status_reg_value, response_que_value;
458
459 status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
460
461 while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
462 response_que_value = inl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev));
463 status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
464 }
465} /* End tw_empty_response_que() */
466
467/* This function will free a request_id */
468static void tw_state_request_finish(TW_Device_Extension *tw_dev, int request_id)
469{
470 tw_dev->free_queue[tw_dev->free_tail] = request_id;
471 tw_dev->state[request_id] = TW_S_FINISHED;
472 tw_dev->free_tail = (tw_dev->free_tail + 1) % TW_Q_LENGTH;
473} /* End tw_state_request_finish() */
474
475/* This function will assign an available request_id */
476static void tw_state_request_start(TW_Device_Extension *tw_dev, int *request_id)
477{
478 *request_id = tw_dev->free_queue[tw_dev->free_head];
479 tw_dev->free_head = (tw_dev->free_head + 1) % TW_Q_LENGTH;
480 tw_dev->state[*request_id] = TW_S_STARTED;
481} /* End tw_state_request_start() */
482
483/* Show some statistics about the card */
484static ssize_t tw_show_stats(struct class_device *class_dev, char *buf)
485{
486 struct Scsi_Host *host = class_to_shost(class_dev);
487 TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
488 unsigned long flags = 0;
489 ssize_t len;
490
491 spin_lock_irqsave(tw_dev->host->host_lock, flags);
492 len = snprintf(buf, PAGE_SIZE, "3w-xxxx Driver version: %s\n"
493 "Current commands posted: %4d\n"
494 "Max commands posted: %4d\n"
495 "Current pending commands: %4d\n"
496 "Max pending commands: %4d\n"
497 "Last sgl length: %4d\n"
498 "Max sgl length: %4d\n"
499 "Last sector count: %4d\n"
500 "Max sector count: %4d\n"
501 "SCSI Host Resets: %4d\n"
502 "AEN's: %4d\n",
503 TW_DRIVER_VERSION,
504 tw_dev->posted_request_count,
505 tw_dev->max_posted_request_count,
506 tw_dev->pending_request_count,
507 tw_dev->max_pending_request_count,
508 tw_dev->sgl_entries,
509 tw_dev->max_sgl_entries,
510 tw_dev->sector_count,
511 tw_dev->max_sector_count,
512 tw_dev->num_resets,
513 tw_dev->aen_count);
514 spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
515 return len;
516} /* End tw_show_stats() */
517
518/* This function will set a devices queue depth */
519static int tw_change_queue_depth(struct scsi_device *sdev, int queue_depth)
520{
521 if (queue_depth > TW_Q_LENGTH-2)
522 queue_depth = TW_Q_LENGTH-2;
523 scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
524 return queue_depth;
525} /* End tw_change_queue_depth() */
526
527/* Create sysfs 'stats' entry */
528static struct class_device_attribute tw_host_stats_attr = {
529 .attr = {
530 .name = "stats",
531 .mode = S_IRUGO,
532 },
533 .show = tw_show_stats
534};
535
536/* Host attributes initializer */
537static struct class_device_attribute *tw_host_attrs[] = {
538 &tw_host_stats_attr,
539 NULL,
540};
541
542/* This function will read the aen queue from the isr */
543static int tw_aen_read_queue(TW_Device_Extension *tw_dev, int request_id)
544{
545 TW_Command *command_packet;
546 TW_Param *param;
547 unsigned long command_que_value;
548 u32 status_reg_value;
549 unsigned long param_value = 0;
550
551 dprintk(KERN_NOTICE "3w-xxxx: tw_aen_read_queue()\n");
552
553 status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
554 if (tw_check_bits(status_reg_value)) {
555 dprintk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Unexpected bits.\n");
556 tw_decode_bits(tw_dev, status_reg_value, 1);
557 return 1;
558 }
559 if (tw_dev->command_packet_virtual_address[request_id] == NULL) {
560 printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Bad command packet virtual address.\n");
561 return 1;
562 }
563 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
564 memset(command_packet, 0, sizeof(TW_Sector));
565 command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM);
566 command_packet->size = 4;
567 command_packet->request_id = request_id;
568 command_packet->status = 0;
569 command_packet->flags = 0;
570 command_packet->byte6.parameter_count = 1;
571 command_que_value = tw_dev->command_packet_physical_address[request_id];
572 if (command_que_value == 0) {
573 printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Bad command packet physical address.\n");
574 return 1;
575 }
576 /* Now setup the param */
577 if (tw_dev->alignment_virtual_address[request_id] == NULL) {
578 printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Bad alignment virtual address.\n");
579 return 1;
580 }
581 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
582 memset(param, 0, sizeof(TW_Sector));
583 param->table_id = 0x401; /* AEN table */
584 param->parameter_id = 2; /* Unit code */
585 param->parameter_size_bytes = 2;
586 param_value = tw_dev->alignment_physical_address[request_id];
587 if (param_value == 0) {
588 printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Bad alignment physical address.\n");
589 return 1;
590 }
591 command_packet->byte8.param.sgl[0].address = param_value;
592 command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
593
594 /* Now post the command packet */
595 if ((status_reg_value & TW_STATUS_COMMAND_QUEUE_FULL) == 0) {
596 dprintk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Post succeeded.\n");
597 tw_dev->srb[request_id] = NULL; /* Flag internal command */
598 tw_dev->state[request_id] = TW_S_POSTED;
599 outl(command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
600 } else {
601 printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Post failed, will retry.\n");
602 return 1;
603 }
604
605 return 0;
606} /* End tw_aen_read_queue() */
607
608/* This function will complete an aen request from the isr */
609static int tw_aen_complete(TW_Device_Extension *tw_dev, int request_id)
610{
611 TW_Param *param;
612 unsigned short aen;
613 int error = 0, table_max = 0;
614
615 dprintk(KERN_WARNING "3w-xxxx: tw_aen_complete()\n");
616 if (tw_dev->alignment_virtual_address[request_id] == NULL) {
617 printk(KERN_WARNING "3w-xxxx: tw_aen_complete(): Bad alignment virtual address.\n");
618 return 1;
619 }
620 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
621 aen = *(unsigned short *)(param->data);
622 dprintk(KERN_NOTICE "3w-xxxx: tw_aen_complete(): Queue'd code 0x%x\n", aen);
623
624 /* Print some useful info when certain aen codes come out */
625 if (aen == 0x0ff) {
626 printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: INFO: AEN queue overflow.\n", tw_dev->host->host_no);
627 } else {
Tobias Klauser6391a112006-06-08 22:23:48 -0700628 table_max = ARRAY_SIZE(tw_aen_string);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 if ((aen & 0x0ff) < table_max) {
630 if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') {
631 printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: %s%d.\n", tw_dev->host->host_no, tw_aen_string[aen & 0xff], aen >> 8);
632 } else {
633 if (aen != 0x0)
634 printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: %s.\n", tw_dev->host->host_no, tw_aen_string[aen & 0xff]);
635 }
636 } else {
637 printk(KERN_WARNING "3w-xxxx: scsi%d: Received AEN %d.\n", tw_dev->host->host_no, aen);
638 }
639 }
640 if (aen != TW_AEN_QUEUE_EMPTY) {
641 tw_dev->aen_count++;
642
643 /* Now queue the code */
644 tw_dev->aen_queue[tw_dev->aen_tail] = aen;
645 if (tw_dev->aen_tail == TW_Q_LENGTH - 1) {
646 tw_dev->aen_tail = TW_Q_START;
647 } else {
648 tw_dev->aen_tail = tw_dev->aen_tail + 1;
649 }
650 if (tw_dev->aen_head == tw_dev->aen_tail) {
651 if (tw_dev->aen_head == TW_Q_LENGTH - 1) {
652 tw_dev->aen_head = TW_Q_START;
653 } else {
654 tw_dev->aen_head = tw_dev->aen_head + 1;
655 }
656 }
657
658 error = tw_aen_read_queue(tw_dev, request_id);
659 if (error) {
660 printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing AEN.\n", tw_dev->host->host_no);
661 tw_dev->state[request_id] = TW_S_COMPLETED;
662 tw_state_request_finish(tw_dev, request_id);
663 }
664 } else {
665 tw_dev->state[request_id] = TW_S_COMPLETED;
666 tw_state_request_finish(tw_dev, request_id);
667 }
668
669 return 0;
670} /* End tw_aen_complete() */
671
672/* This function will drain the aen queue after a soft reset */
673static int tw_aen_drain_queue(TW_Device_Extension *tw_dev)
674{
675 TW_Command *command_packet;
676 TW_Param *param;
677 int request_id = 0;
678 unsigned long command_que_value;
679 unsigned long param_value;
680 TW_Response_Queue response_queue;
681 unsigned short aen;
682 unsigned short aen_code;
683 int finished = 0;
684 int first_reset = 0;
685 int queue = 0;
686 int found = 0, table_max = 0;
687
688 dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue()\n");
689
690 if (tw_poll_status(tw_dev, TW_STATUS_ATTENTION_INTERRUPT | TW_STATUS_MICROCONTROLLER_READY, 30)) {
691 dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): No attention interrupt for card %d.\n", tw_device_extension_count);
692 return 1;
693 }
694 TW_CLEAR_ATTENTION_INTERRUPT(tw_dev);
695
696 /* Empty response queue */
697 tw_empty_response_que(tw_dev);
698
699 /* Initialize command packet */
700 if (tw_dev->command_packet_virtual_address[request_id] == NULL) {
701 printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad command packet virtual address.\n");
702 return 1;
703 }
704 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
705 memset(command_packet, 0, sizeof(TW_Sector));
706 command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM);
707 command_packet->size = 4;
708 command_packet->request_id = request_id;
709 command_packet->status = 0;
710 command_packet->flags = 0;
711 command_packet->byte6.parameter_count = 1;
712 command_que_value = tw_dev->command_packet_physical_address[request_id];
713 if (command_que_value == 0) {
714 printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad command packet physical address.\n");
715 return 1;
716 }
717
718 /* Now setup the param */
719 if (tw_dev->alignment_virtual_address[request_id] == NULL) {
720 printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad alignment virtual address.\n");
721 return 1;
722 }
723 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
724 memset(param, 0, sizeof(TW_Sector));
725 param->table_id = 0x401; /* AEN table */
726 param->parameter_id = 2; /* Unit code */
727 param->parameter_size_bytes = 2;
728 param_value = tw_dev->alignment_physical_address[request_id];
729 if (param_value == 0) {
730 printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad alignment physical address.\n");
731 return 1;
732 }
733 command_packet->byte8.param.sgl[0].address = param_value;
734 command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
735
736 /* Now drain the controller's aen queue */
737 do {
738 /* Post command packet */
739 outl(command_que_value, TW_COMMAND_QUEUE_REG_ADDR(tw_dev));
740
741 /* Now poll for completion */
742 if (tw_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, 30) == 0) {
743 response_queue.value = inl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev));
744 request_id = TW_RESID_OUT(response_queue.response_id);
745
746 if (request_id != 0) {
747 /* Unexpected request id */
748 printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Unexpected request id.\n");
749 return 1;
750 }
751
752 if (command_packet->status != 0) {
753 if (command_packet->flags != TW_AEN_TABLE_UNDEFINED) {
754 /* Bad response */
755 tw_decode_sense(tw_dev, request_id, 0);
756 return 1;
757 } else {
758 /* We know this is a 3w-1x00, and doesn't support aen's */
759 return 0;
760 }
761 }
762
763 /* Now check the aen */
764 aen = *(unsigned short *)(param->data);
765 aen_code = (aen & 0x0ff);
766 queue = 0;
767 switch (aen_code) {
768 case TW_AEN_QUEUE_EMPTY:
769 dprintk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]);
770 if (first_reset != 1) {
771 return 1;
772 } else {
773 finished = 1;
774 }
775 break;
776 case TW_AEN_SOFT_RESET:
777 if (first_reset == 0) {
778 first_reset = 1;
779 } else {
780 printk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]);
781 tw_dev->aen_count++;
782 queue = 1;
783 }
784 break;
785 default:
786 if (aen == 0x0ff) {
787 printk(KERN_WARNING "3w-xxxx: AEN: INFO: AEN queue overflow.\n");
788 } else {
Tobias Klauser6391a112006-06-08 22:23:48 -0700789 table_max = ARRAY_SIZE(tw_aen_string);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 if ((aen & 0x0ff) < table_max) {
791 if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') {
792 printk(KERN_WARNING "3w-xxxx: AEN: %s%d.\n", tw_aen_string[aen & 0xff], aen >> 8);
793 } else {
794 printk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]);
795 }
796 } else
797 printk(KERN_WARNING "3w-xxxx: Received AEN %d.\n", aen);
798 }
799 tw_dev->aen_count++;
800 queue = 1;
801 }
802
803 /* Now put the aen on the aen_queue */
804 if (queue == 1) {
805 tw_dev->aen_queue[tw_dev->aen_tail] = aen;
806 if (tw_dev->aen_tail == TW_Q_LENGTH - 1) {
807 tw_dev->aen_tail = TW_Q_START;
808 } else {
809 tw_dev->aen_tail = tw_dev->aen_tail + 1;
810 }
811 if (tw_dev->aen_head == tw_dev->aen_tail) {
812 if (tw_dev->aen_head == TW_Q_LENGTH - 1) {
813 tw_dev->aen_head = TW_Q_START;
814 } else {
815 tw_dev->aen_head = tw_dev->aen_head + 1;
816 }
817 }
818 }
819 found = 1;
820 }
821 if (found == 0) {
822 printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Response never received.\n");
823 return 1;
824 }
825 } while (finished == 0);
826
827 return 0;
828} /* End tw_aen_drain_queue() */
829
830/* This function will allocate memory */
831static int tw_allocate_memory(TW_Device_Extension *tw_dev, int size, int which)
832{
833 int i;
834 dma_addr_t dma_handle;
835 unsigned long *cpu_addr = NULL;
836
837 dprintk(KERN_NOTICE "3w-xxxx: tw_allocate_memory()\n");
838
839 cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, size*TW_Q_LENGTH, &dma_handle);
840 if (cpu_addr == NULL) {
841 printk(KERN_WARNING "3w-xxxx: pci_alloc_consistent() failed.\n");
842 return 1;
843 }
844
845 if ((unsigned long)cpu_addr % (tw_dev->tw_pci_dev->device == TW_DEVICE_ID ? TW_ALIGNMENT_6000 : TW_ALIGNMENT_7000)) {
846 printk(KERN_WARNING "3w-xxxx: Couldn't allocate correctly aligned memory.\n");
847 pci_free_consistent(tw_dev->tw_pci_dev, size*TW_Q_LENGTH, cpu_addr, dma_handle);
848 return 1;
849 }
850
851 memset(cpu_addr, 0, size*TW_Q_LENGTH);
852
853 for (i=0;i<TW_Q_LENGTH;i++) {
854 switch(which) {
855 case 0:
856 tw_dev->command_packet_physical_address[i] = dma_handle+(i*size);
857 tw_dev->command_packet_virtual_address[i] = (unsigned long *)((unsigned char *)cpu_addr + (i*size));
858 break;
859 case 1:
860 tw_dev->alignment_physical_address[i] = dma_handle+(i*size);
861 tw_dev->alignment_virtual_address[i] = (unsigned long *)((unsigned char *)cpu_addr + (i*size));
862 break;
863 default:
864 printk(KERN_WARNING "3w-xxxx: tw_allocate_memory(): case slip in tw_allocate_memory()\n");
865 return 1;
866 }
867 }
868
869 return 0;
870} /* End tw_allocate_memory() */
871
872/* This function handles ioctl for the character device */
873static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
874{
875 int request_id;
876 dma_addr_t dma_handle;
877 unsigned short tw_aen_code;
878 unsigned long flags;
879 unsigned int data_buffer_length = 0;
880 unsigned long data_buffer_length_adjusted = 0;
881 unsigned long *cpu_addr;
882 long timeout;
883 TW_New_Ioctl *tw_ioctl;
884 TW_Passthru *passthru;
885 TW_Device_Extension *tw_dev = tw_device_extension_list[iminor(inode)];
886 int retval = -EFAULT;
887 void __user *argp = (void __user *)arg;
888
889 dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl()\n");
890
891 /* Only let one of these through at a time */
Jes Sorensena12e25bd2006-01-11 08:39:45 -0500892 if (mutex_lock_interruptible(&tw_dev->ioctl_lock))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 return -EINTR;
894
895 /* First copy down the buffer length */
896 if (copy_from_user(&data_buffer_length, argp, sizeof(unsigned int)))
897 goto out;
898
899 /* Check size */
900 if (data_buffer_length > TW_MAX_IOCTL_SECTORS * 512) {
901 retval = -EINVAL;
902 goto out;
903 }
904
905 /* Hardware can only do multiple of 512 byte transfers */
906 data_buffer_length_adjusted = (data_buffer_length + 511) & ~511;
907
908 /* Now allocate ioctl buf memory */
909 cpu_addr = dma_alloc_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, &dma_handle, GFP_KERNEL);
910 if (cpu_addr == NULL) {
911 retval = -ENOMEM;
912 goto out;
913 }
914
915 tw_ioctl = (TW_New_Ioctl *)cpu_addr;
916
917 /* Now copy down the entire ioctl */
918 if (copy_from_user(tw_ioctl, argp, data_buffer_length + sizeof(TW_New_Ioctl) - 1))
919 goto out2;
920
921 passthru = (TW_Passthru *)&tw_ioctl->firmware_command;
922
923 /* See which ioctl we are doing */
924 switch (cmd) {
925 case TW_OP_NOP:
926 dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): caught TW_OP_NOP.\n");
927 break;
928 case TW_OP_AEN_LISTEN:
929 dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): caught TW_AEN_LISTEN.\n");
930 memset(tw_ioctl->data_buffer, 0, data_buffer_length);
931
932 spin_lock_irqsave(tw_dev->host->host_lock, flags);
933 if (tw_dev->aen_head == tw_dev->aen_tail) {
934 tw_aen_code = TW_AEN_QUEUE_EMPTY;
935 } else {
936 tw_aen_code = tw_dev->aen_queue[tw_dev->aen_head];
937 if (tw_dev->aen_head == TW_Q_LENGTH - 1) {
938 tw_dev->aen_head = TW_Q_START;
939 } else {
940 tw_dev->aen_head = tw_dev->aen_head + 1;
941 }
942 }
943 spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
944 memcpy(tw_ioctl->data_buffer, &tw_aen_code, sizeof(tw_aen_code));
945 break;
946 case TW_CMD_PACKET_WITH_DATA:
947 dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): caught TW_CMD_PACKET_WITH_DATA.\n");
948 spin_lock_irqsave(tw_dev->host->host_lock, flags);
949
950 tw_state_request_start(tw_dev, &request_id);
951
952 /* Flag internal command */
953 tw_dev->srb[request_id] = NULL;
954
955 /* Flag chrdev ioctl */
956 tw_dev->chrdev_request_id = request_id;
957
958 tw_ioctl->firmware_command.request_id = request_id;
959
960 /* Load the sg list */
961 switch (TW_SGL_OUT(tw_ioctl->firmware_command.opcode__sgloffset)) {
962 case 2:
963 tw_ioctl->firmware_command.byte8.param.sgl[0].address = dma_handle + sizeof(TW_New_Ioctl) - 1;
964 tw_ioctl->firmware_command.byte8.param.sgl[0].length = data_buffer_length_adjusted;
965 break;
966 case 3:
967 tw_ioctl->firmware_command.byte8.io.sgl[0].address = dma_handle + sizeof(TW_New_Ioctl) - 1;
968 tw_ioctl->firmware_command.byte8.io.sgl[0].length = data_buffer_length_adjusted;
969 break;
970 case 5:
971 passthru->sg_list[0].address = dma_handle + sizeof(TW_New_Ioctl) - 1;
972 passthru->sg_list[0].length = data_buffer_length_adjusted;
973 break;
974 }
975
976 memcpy(tw_dev->command_packet_virtual_address[request_id], &(tw_ioctl->firmware_command), sizeof(TW_Command));
977
978 /* Now post the command packet to the controller */
979 tw_post_command_packet(tw_dev, request_id);
980 spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
981
982 timeout = TW_IOCTL_CHRDEV_TIMEOUT*HZ;
983
984 /* Now wait for the command to complete */
985 timeout = wait_event_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout);
986
987 /* See if we reset while waiting for the ioctl to complete */
988 if (test_bit(TW_IN_RESET, &tw_dev->flags)) {
989 clear_bit(TW_IN_RESET, &tw_dev->flags);
990 retval = -ERESTARTSYS;
991 goto out2;
992 }
993
994 /* We timed out, and didn't get an interrupt */
995 if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) {
996 /* Now we need to reset the board */
997 printk(KERN_WARNING "3w-xxxx: scsi%d: Character ioctl (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, cmd);
998 retval = -EIO;
999 spin_lock_irqsave(tw_dev->host->host_lock, flags);
1000 tw_dev->state[request_id] = TW_S_COMPLETED;
1001 tw_state_request_finish(tw_dev, request_id);
1002 tw_dev->posted_request_count--;
1003 spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
1004 if (tw_reset_device_extension(tw_dev, 1)) {
1005 printk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): Reset failed for card %d.\n", tw_dev->host->host_no);
1006 }
1007 goto out2;
1008 }
1009
1010 /* Now copy in the command packet response */
1011 memcpy(&(tw_ioctl->firmware_command), tw_dev->command_packet_virtual_address[request_id], sizeof(TW_Command));
1012
1013 /* Now complete the io */
1014 spin_lock_irqsave(tw_dev->host->host_lock, flags);
1015 tw_dev->posted_request_count--;
1016 tw_dev->state[request_id] = TW_S_COMPLETED;
1017 tw_state_request_finish(tw_dev, request_id);
1018 spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
1019 break;
1020 default:
1021 retval = -ENOTTY;
1022 goto out2;
1023 }
1024
1025 /* Now copy the response to userspace */
1026 if (copy_to_user(argp, tw_ioctl, sizeof(TW_New_Ioctl) + data_buffer_length - 1))
1027 goto out2;
1028 retval = 0;
1029out2:
1030 /* Now free ioctl buf memory */
1031 dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle);
1032out:
Jes Sorensena12e25bd2006-01-11 08:39:45 -05001033 mutex_unlock(&tw_dev->ioctl_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 return retval;
1035} /* End tw_chrdev_ioctl() */
1036
1037/* This function handles open for the character device */
1038static int tw_chrdev_open(struct inode *inode, struct file *file)
1039{
1040 unsigned int minor_number;
1041
1042 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 */
1052static struct file_operations tw_fops = {
1053 .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");
1285
1286 if (cmd->use_sg == 0)
1287 return 0;
1288
Christoph Hellwig5d5ff442006-06-03 13:21:13 +02001289 use_sg = pci_map_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290
1291 if (use_sg == 0) {
1292 printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n");
1293 return 0;
1294 }
1295
1296 cmd->SCp.phase = TW_PHASE_SGLIST;
1297 cmd->SCp.have_data_in = use_sg;
1298
1299 return use_sg;
1300} /* End tw_map_scsi_sg_data() */
1301
1302static u32 tw_map_scsi_single_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
1303{
1304 dma_addr_t mapping;
1305
1306 dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_single_data()\n");
1307
1308 if (cmd->request_bufflen == 0)
1309 return 0;
1310
1311 mapping = pci_map_page(pdev, virt_to_page(cmd->request_buffer), offset_in_page(cmd->request_buffer), cmd->request_bufflen, DMA_BIDIRECTIONAL);
1312
1313 if (mapping == 0) {
1314 printk(KERN_WARNING "3w-xxxx: tw_map_scsi_single_data(): pci_map_page() failed.\n");
1315 return 0;
1316 }
1317
1318 cmd->SCp.phase = TW_PHASE_SINGLE;
1319 cmd->SCp.have_data_in = mapping;
1320
1321 return mapping;
1322} /* End tw_map_scsi_single_data() */
1323
1324static void tw_unmap_scsi_data(struct pci_dev *pdev, struct scsi_cmnd *cmd)
1325{
1326 dprintk(KERN_WARNING "3w-xxxx: tw_unmap_scsi_data()\n");
1327
1328 switch(cmd->SCp.phase) {
1329 case TW_PHASE_SINGLE:
1330 pci_unmap_page(pdev, cmd->SCp.have_data_in, cmd->request_bufflen, DMA_BIDIRECTIONAL);
1331 break;
1332 case TW_PHASE_SGLIST:
1333 pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, DMA_BIDIRECTIONAL);
1334 break;
1335 }
1336} /* End tw_unmap_scsi_data() */
1337
1338/* This function will reset a device extension */
1339static int tw_reset_device_extension(TW_Device_Extension *tw_dev, int ioctl_reset)
1340{
1341 int i = 0;
1342 struct scsi_cmnd *srb;
1343 unsigned long flags = 0;
1344
1345 dprintk(KERN_NOTICE "3w-xxxx: tw_reset_device_extension()\n");
1346
1347 set_bit(TW_IN_RESET, &tw_dev->flags);
1348 TW_DISABLE_INTERRUPTS(tw_dev);
1349 TW_MASK_COMMAND_INTERRUPT(tw_dev);
1350 spin_lock_irqsave(tw_dev->host->host_lock, flags);
1351
1352 /* Abort all requests that are in progress */
1353 for (i=0;i<TW_Q_LENGTH;i++) {
1354 if ((tw_dev->state[i] != TW_S_FINISHED) &&
1355 (tw_dev->state[i] != TW_S_INITIAL) &&
1356 (tw_dev->state[i] != TW_S_COMPLETED)) {
1357 srb = tw_dev->srb[i];
1358 if (srb != NULL) {
1359 srb->result = (DID_RESET << 16);
1360 tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);
1361 tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[i]);
1362 }
1363 }
1364 }
1365
1366 /* Reset queues and counts */
1367 for (i=0;i<TW_Q_LENGTH;i++) {
1368 tw_dev->free_queue[i] = i;
1369 tw_dev->state[i] = TW_S_INITIAL;
1370 }
1371 tw_dev->free_head = TW_Q_START;
1372 tw_dev->free_tail = TW_Q_START;
1373 tw_dev->posted_request_count = 0;
1374 tw_dev->pending_request_count = 0;
1375 tw_dev->pending_head = TW_Q_START;
1376 tw_dev->pending_tail = TW_Q_START;
1377 tw_dev->reset_print = 0;
1378
1379 spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
1380
1381 if (tw_reset_sequence(tw_dev)) {
1382 printk(KERN_WARNING "3w-xxxx: scsi%d: Reset sequence failed.\n", tw_dev->host->host_no);
1383 return 1;
1384 }
1385 TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);
1386
1387 /* Wake up any ioctl that was pending before the reset */
1388 if ((tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE) || (ioctl_reset)) {
1389 clear_bit(TW_IN_RESET, &tw_dev->flags);
1390 } else {
1391 tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
1392 wake_up(&tw_dev->ioctl_wqueue);
1393 }
1394
1395 return 0;
1396} /* End tw_reset_device_extension() */
1397
1398/* This funciton returns unit geometry in cylinders/heads/sectors */
1399static int tw_scsi_biosparam(struct scsi_device *sdev, struct block_device *bdev,
1400 sector_t capacity, int geom[])
1401{
1402 int heads, sectors, cylinders;
1403 TW_Device_Extension *tw_dev;
1404
1405 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_biosparam()\n");
1406 tw_dev = (TW_Device_Extension *)sdev->host->hostdata;
1407
1408 heads = 64;
1409 sectors = 32;
1410 cylinders = sector_div(capacity, heads * sectors);
1411
1412 if (capacity >= 0x200000) {
1413 heads = 255;
1414 sectors = 63;
1415 cylinders = sector_div(capacity, heads * sectors);
1416 }
1417
1418 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_biosparam(): heads = %d, sectors = %d, cylinders = %d\n", heads, sectors, cylinders);
1419 geom[0] = heads;
1420 geom[1] = sectors;
1421 geom[2] = cylinders;
1422
1423 return 0;
1424} /* End tw_scsi_biosparam() */
1425
1426/* This is the new scsi eh reset function */
1427static int tw_scsi_eh_reset(struct scsi_cmnd *SCpnt)
1428{
1429 TW_Device_Extension *tw_dev=NULL;
1430 int retval = FAILED;
1431
1432 tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
1433
Linus Torvalds1da177e2005-04-16 15:20:36 -07001434 tw_dev->num_resets++;
1435
Jeff Garzik017560f2005-10-24 18:04:36 -04001436 sdev_printk(KERN_WARNING, SCpnt->device,
1437 "WARNING: Command (0x%x) timed out, resetting card.\n",
1438 SCpnt->cmnd[0]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439
1440 /* Now reset the card and some of the device extension data */
1441 if (tw_reset_device_extension(tw_dev, 0)) {
1442 printk(KERN_WARNING "3w-xxxx: scsi%d: Reset failed.\n", tw_dev->host->host_no);
1443 goto out;
1444 }
1445
1446 retval = SUCCESS;
1447out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 return retval;
1449} /* End tw_scsi_eh_reset() */
1450
1451/* This function handles scsi inquiry commands */
1452static int tw_scsiop_inquiry(TW_Device_Extension *tw_dev, int request_id)
1453{
1454 TW_Param *param;
1455 TW_Command *command_packet;
1456 unsigned long command_que_value;
1457 unsigned long param_value;
1458
1459 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry()\n");
1460
1461 /* Initialize command packet */
1462 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
1463 if (command_packet == NULL) {
1464 printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad command packet virtual address.\n");
1465 return 1;
1466 }
1467 memset(command_packet, 0, sizeof(TW_Sector));
1468 command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM);
1469 command_packet->size = 4;
1470 command_packet->request_id = request_id;
1471 command_packet->status = 0;
1472 command_packet->flags = 0;
1473 command_packet->byte6.parameter_count = 1;
1474
1475 /* Now setup the param */
1476 if (tw_dev->alignment_virtual_address[request_id] == NULL) {
1477 printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad alignment virtual address.\n");
1478 return 1;
1479 }
1480 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
1481 memset(param, 0, sizeof(TW_Sector));
1482 param->table_id = 3; /* unit summary table */
1483 param->parameter_id = 3; /* unitsstatus parameter */
1484 param->parameter_size_bytes = TW_MAX_UNITS;
1485 param_value = tw_dev->alignment_physical_address[request_id];
1486 if (param_value == 0) {
1487 printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad alignment physical address.\n");
1488 return 1;
1489 }
1490
1491 command_packet->byte8.param.sgl[0].address = param_value;
1492 command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
1493 command_que_value = tw_dev->command_packet_physical_address[request_id];
1494 if (command_que_value == 0) {
1495 printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad command packet physical address.\n");
1496 return 1;
1497 }
1498
1499 /* Now try to post the command packet */
1500 tw_post_command_packet(tw_dev, request_id);
1501
1502 return 0;
1503} /* End tw_scsiop_inquiry() */
1504
James Bottomleyc9d297c2005-06-28 09:18:21 -05001505static void tw_transfer_internal(TW_Device_Extension *tw_dev, int request_id,
1506 void *data, unsigned int len)
1507{
1508 struct scsi_cmnd *cmd = tw_dev->srb[request_id];
1509 void *buf;
1510 unsigned int transfer_len;
Andrew Morton7551d9a2006-04-10 22:54:34 -07001511 unsigned long flags = 0;
James Bottomleyc9d297c2005-06-28 09:18:21 -05001512
1513 if (cmd->use_sg) {
1514 struct scatterlist *sg =
1515 (struct scatterlist *)cmd->request_buffer;
Andrew Morton7551d9a2006-04-10 22:54:34 -07001516 local_irq_save(flags);
James Bottomleyc9d297c2005-06-28 09:18:21 -05001517 buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;
1518 transfer_len = min(sg->length, len);
1519 } else {
1520 buf = cmd->request_buffer;
1521 transfer_len = min(cmd->request_bufflen, len);
1522 }
1523
1524 memcpy(buf, data, transfer_len);
1525
1526 if (cmd->use_sg) {
1527 struct scatterlist *sg;
1528
1529 sg = (struct scatterlist *)cmd->request_buffer;
1530 kunmap_atomic(buf - sg->offset, KM_IRQ0);
Andrew Morton7551d9a2006-04-10 22:54:34 -07001531 local_irq_restore(flags);
James Bottomleyc9d297c2005-06-28 09:18:21 -05001532 }
1533}
1534
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535/* This function is called by the isr to complete an inquiry command */
1536static int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_id)
1537{
1538 unsigned char *is_unit_present;
James Bottomleyc9d297c2005-06-28 09:18:21 -05001539 unsigned char request_buffer[36];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 TW_Param *param;
1541
1542 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry_complete()\n");
1543
James Bottomleyc9d297c2005-06-28 09:18:21 -05001544 memset(request_buffer, 0, sizeof(request_buffer));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545 request_buffer[0] = TYPE_DISK; /* Peripheral device type */
1546 request_buffer[1] = 0; /* Device type modifier */
1547 request_buffer[2] = 0; /* No ansi/iso compliance */
1548 request_buffer[4] = 31; /* Additional length */
1549 memcpy(&request_buffer[8], "3ware ", 8); /* Vendor ID */
1550 sprintf(&request_buffer[16], "Logical Disk %-2d ", tw_dev->srb[request_id]->device->id);
1551 memcpy(&request_buffer[32], TW_DRIVER_VERSION, 3);
James Bottomleyc9d297c2005-06-28 09:18:21 -05001552 tw_transfer_internal(tw_dev, request_id, request_buffer,
1553 sizeof(request_buffer));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554
1555 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
1556 if (param == NULL) {
1557 printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry_complete(): Bad alignment virtual address.\n");
1558 return 1;
1559 }
1560 is_unit_present = &(param->data[0]);
1561
1562 if (is_unit_present[tw_dev->srb[request_id]->device->id] & TW_UNIT_ONLINE) {
1563 tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = 1;
1564 } else {
1565 tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = 0;
1566 tw_dev->srb[request_id]->result = (DID_BAD_TARGET << 16);
1567 return TW_ISR_DONT_RESULT;
1568 }
1569
1570 return 0;
1571} /* End tw_scsiop_inquiry_complete() */
1572
1573/* This function handles scsi mode_sense commands */
1574static int tw_scsiop_mode_sense(TW_Device_Extension *tw_dev, int request_id)
1575{
1576 TW_Param *param;
1577 TW_Command *command_packet;
1578 unsigned long command_que_value;
1579 unsigned long param_value;
1580
1581 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_mode_sense()\n");
1582
1583 /* Only page control = 0, page code = 0x8 (cache page) supported */
1584 if (tw_dev->srb[request_id]->cmnd[2] != 0x8) {
1585 tw_dev->state[request_id] = TW_S_COMPLETED;
1586 tw_state_request_finish(tw_dev, request_id);
1587 tw_dev->srb[request_id]->result = (DID_OK << 16);
1588 tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
1589 return 0;
1590 }
1591
1592 /* Now read firmware cache setting for this unit */
1593 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
1594 if (command_packet == NULL) {
1595 printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad command packet virtual address.\n");
1596 return 1;
1597 }
1598
1599 /* Setup the command packet */
1600 memset(command_packet, 0, sizeof(TW_Sector));
1601 command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM);
1602 command_packet->size = 4;
1603 command_packet->request_id = request_id;
1604 command_packet->status = 0;
1605 command_packet->flags = 0;
1606 command_packet->byte6.parameter_count = 1;
1607
1608 /* Setup the param */
1609 if (tw_dev->alignment_virtual_address[request_id] == NULL) {
1610 printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad alignment virtual address.\n");
1611 return 1;
1612 }
1613
1614 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
1615 memset(param, 0, sizeof(TW_Sector));
1616 param->table_id = TW_UNIT_INFORMATION_TABLE_BASE + tw_dev->srb[request_id]->device->id;
1617 param->parameter_id = 7; /* unit flags */
1618 param->parameter_size_bytes = 1;
1619 param_value = tw_dev->alignment_physical_address[request_id];
1620 if (param_value == 0) {
1621 printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad alignment physical address.\n");
1622 return 1;
1623 }
1624
1625 command_packet->byte8.param.sgl[0].address = param_value;
1626 command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
1627 command_que_value = tw_dev->command_packet_physical_address[request_id];
1628 if (command_que_value == 0) {
1629 printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad command packet physical address.\n");
1630 return 1;
1631 }
1632
1633 /* Now try to post the command packet */
1634 tw_post_command_packet(tw_dev, request_id);
1635
1636 return 0;
1637} /* End tw_scsiop_mode_sense() */
1638
1639/* This function is called by the isr to complete a mode sense command */
1640static int tw_scsiop_mode_sense_complete(TW_Device_Extension *tw_dev, int request_id)
1641{
1642 TW_Param *param;
1643 unsigned char *flags;
James Bottomleyc9d297c2005-06-28 09:18:21 -05001644 unsigned char request_buffer[8];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645
1646 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_mode_sense_complete()\n");
1647
1648 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
1649 if (param == NULL) {
1650 printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense_complete(): Bad alignment virtual address.\n");
1651 return 1;
1652 }
1653 flags = (char *)&(param->data[0]);
James Bottomleyc9d297c2005-06-28 09:18:21 -05001654 memset(request_buffer, 0, sizeof(request_buffer));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655
1656 request_buffer[0] = 0xf; /* mode data length */
1657 request_buffer[1] = 0; /* default medium type */
1658 request_buffer[2] = 0x10; /* dpo/fua support on */
1659 request_buffer[3] = 0; /* no block descriptors */
1660 request_buffer[4] = 0x8; /* caching page */
1661 request_buffer[5] = 0xa; /* page length */
1662 if (*flags & 0x1)
1663 request_buffer[6] = 0x4; /* WCE on */
1664 else
1665 request_buffer[6] = 0x0; /* WCE off */
James Bottomleyc9d297c2005-06-28 09:18:21 -05001666 tw_transfer_internal(tw_dev, request_id, request_buffer,
1667 sizeof(request_buffer));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668
1669 return 0;
1670} /* End tw_scsiop_mode_sense_complete() */
1671
1672/* This function handles scsi read_capacity commands */
1673static int tw_scsiop_read_capacity(TW_Device_Extension *tw_dev, int request_id)
1674{
1675 TW_Param *param;
1676 TW_Command *command_packet;
1677 unsigned long command_que_value;
1678 unsigned long param_value;
1679
1680 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity()\n");
1681
1682 /* Initialize command packet */
1683 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
1684
1685 if (command_packet == NULL) {
1686 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad command packet virtual address.\n");
1687 return 1;
1688 }
1689 memset(command_packet, 0, sizeof(TW_Sector));
1690 command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM);
1691 command_packet->size = 4;
1692 command_packet->request_id = request_id;
1693 command_packet->unit__hostid = TW_UNITHOST_IN(0, tw_dev->srb[request_id]->device->id);
1694 command_packet->status = 0;
1695 command_packet->flags = 0;
1696 command_packet->byte6.block_count = 1;
1697
1698 /* Now setup the param */
1699 if (tw_dev->alignment_virtual_address[request_id] == NULL) {
1700 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad alignment virtual address.\n");
1701 return 1;
1702 }
1703 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
1704 memset(param, 0, sizeof(TW_Sector));
1705 param->table_id = TW_UNIT_INFORMATION_TABLE_BASE +
1706 tw_dev->srb[request_id]->device->id;
1707 param->parameter_id = 4; /* unitcapacity parameter */
1708 param->parameter_size_bytes = 4;
1709 param_value = tw_dev->alignment_physical_address[request_id];
1710 if (param_value == 0) {
1711 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad alignment physical address.\n");
1712 return 1;
1713 }
1714
1715 command_packet->byte8.param.sgl[0].address = param_value;
1716 command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
1717 command_que_value = tw_dev->command_packet_physical_address[request_id];
1718 if (command_que_value == 0) {
1719 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad command packet physical address.\n");
1720 return 1;
1721 }
1722
1723 /* Now try to post the command to the board */
1724 tw_post_command_packet(tw_dev, request_id);
1725
1726 return 0;
1727} /* End tw_scsiop_read_capacity() */
1728
1729/* This function is called by the isr to complete a readcapacity command */
1730static int tw_scsiop_read_capacity_complete(TW_Device_Extension *tw_dev, int request_id)
1731{
1732 unsigned char *param_data;
1733 u32 capacity;
James Bottomleyc9d297c2005-06-28 09:18:21 -05001734 char buff[8];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 TW_Param *param;
1736
1737 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete()\n");
1738
James Bottomleyc9d297c2005-06-28 09:18:21 -05001739 memset(buff, 0, sizeof(buff));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
1741 if (param == NULL) {
1742 printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Bad alignment virtual address.\n");
1743 return 1;
1744 }
1745 param_data = &(param->data[0]);
1746
1747 capacity = (param_data[3] << 24) | (param_data[2] << 16) |
1748 (param_data[1] << 8) | param_data[0];
1749
1750 /* Subtract one sector to fix get last sector ioctl */
1751 capacity -= 1;
1752
1753 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete(): Capacity = 0x%x.\n", capacity);
1754
1755 /* Number of LBA's */
1756 buff[0] = (capacity >> 24);
1757 buff[1] = (capacity >> 16) & 0xff;
1758 buff[2] = (capacity >> 8) & 0xff;
1759 buff[3] = capacity & 0xff;
1760
1761 /* Block size in bytes (512) */
1762 buff[4] = (TW_BLOCK_SIZE >> 24);
1763 buff[5] = (TW_BLOCK_SIZE >> 16) & 0xff;
1764 buff[6] = (TW_BLOCK_SIZE >> 8) & 0xff;
1765 buff[7] = TW_BLOCK_SIZE & 0xff;
1766
James Bottomleyc9d297c2005-06-28 09:18:21 -05001767 tw_transfer_internal(tw_dev, request_id, buff, sizeof(buff));
1768
Linus Torvalds1da177e2005-04-16 15:20:36 -07001769 return 0;
1770} /* End tw_scsiop_read_capacity_complete() */
1771
1772/* This function handles scsi read or write commands */
1773static int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id)
1774{
1775 TW_Command *command_packet;
1776 unsigned long command_que_value;
1777 u32 lba = 0x0, num_sectors = 0x0, buffaddr = 0x0;
1778 int i, use_sg;
1779 struct scsi_cmnd *srb;
1780 struct scatterlist *sglist;
1781
1782 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write()\n");
1783
1784 if (tw_dev->srb[request_id]->request_buffer == NULL) {
1785 printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_write(): Request buffer NULL.\n");
1786 return 1;
1787 }
1788 sglist = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
1789 srb = tw_dev->srb[request_id];
1790
1791 /* Initialize command packet */
1792 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
1793 if (command_packet == NULL) {
1794 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): Bad command packet virtual address.\n");
1795 return 1;
1796 }
1797
1798 if (srb->cmnd[0] == READ_6 || srb->cmnd[0] == READ_10) {
1799 command_packet->opcode__sgloffset = TW_OPSGL_IN(3, TW_OP_READ);
1800 } else {
1801 command_packet->opcode__sgloffset = TW_OPSGL_IN(3, TW_OP_WRITE);
1802 }
1803
1804 command_packet->size = 3;
1805 command_packet->request_id = request_id;
1806 command_packet->unit__hostid = TW_UNITHOST_IN(0, srb->device->id);
1807 command_packet->status = 0;
1808 command_packet->flags = 0;
1809
1810 if (srb->cmnd[0] == WRITE_10) {
1811 if ((srb->cmnd[1] & 0x8) || (srb->cmnd[1] & 0x10))
1812 command_packet->flags = 1;
1813 }
1814
1815 if (srb->cmnd[0] == READ_6 || srb->cmnd[0] == WRITE_6) {
1816 lba = ((u32)srb->cmnd[1] << 16) | ((u32)srb->cmnd[2] << 8) | (u32)srb->cmnd[3];
1817 num_sectors = (u32)srb->cmnd[4];
1818 } else {
1819 lba = ((u32)srb->cmnd[2] << 24) | ((u32)srb->cmnd[3] << 16) | ((u32)srb->cmnd[4] << 8) | (u32)srb->cmnd[5];
1820 num_sectors = (u32)srb->cmnd[8] | ((u32)srb->cmnd[7] << 8);
1821 }
1822
1823 /* Update sector statistic */
1824 tw_dev->sector_count = num_sectors;
1825 if (tw_dev->sector_count > tw_dev->max_sector_count)
1826 tw_dev->max_sector_count = tw_dev->sector_count;
1827
1828 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): lba = 0x%x num_sectors = 0x%x\n", lba, num_sectors);
1829 command_packet->byte8.io.lba = lba;
1830 command_packet->byte6.block_count = num_sectors;
1831
1832 /* Do this if there are no sg list entries */
1833 if (tw_dev->srb[request_id]->use_sg == 0) {
1834 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): SG = 0\n");
1835 buffaddr = tw_map_scsi_single_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
1836 if (buffaddr == 0)
1837 return 1;
1838
1839 command_packet->byte8.io.sgl[0].address = buffaddr;
1840 command_packet->byte8.io.sgl[0].length = tw_dev->srb[request_id]->request_bufflen;
1841 command_packet->size+=2;
1842 }
1843
1844 /* Do this if we have multiple sg list entries */
1845 if (tw_dev->srb[request_id]->use_sg > 0) {
1846 use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
1847 if (use_sg == 0)
1848 return 1;
1849
1850 for (i=0;i<use_sg; i++) {
1851 command_packet->byte8.io.sgl[i].address = sg_dma_address(&sglist[i]);
1852 command_packet->byte8.io.sgl[i].length = sg_dma_len(&sglist[i]);
1853 command_packet->size+=2;
1854 }
1855 }
1856
1857 /* Update SG statistics */
1858 tw_dev->sgl_entries = tw_dev->srb[request_id]->use_sg;
1859 if (tw_dev->sgl_entries > tw_dev->max_sgl_entries)
1860 tw_dev->max_sgl_entries = tw_dev->sgl_entries;
1861
1862 command_que_value = tw_dev->command_packet_physical_address[request_id];
1863 if (command_que_value == 0) {
1864 dprintk(KERN_WARNING "3w-xxxx: tw_scsiop_read_write(): Bad command packet physical address.\n");
1865 return 1;
1866 }
1867
1868 /* Now try to post the command to the board */
1869 tw_post_command_packet(tw_dev, request_id);
1870
1871 return 0;
1872} /* End tw_scsiop_read_write() */
1873
1874/* This function will handle the request sense scsi command */
1875static int tw_scsiop_request_sense(TW_Device_Extension *tw_dev, int request_id)
1876{
1877 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_request_sense()\n");
1878
1879 /* For now we just zero the request buffer */
1880 memset(tw_dev->srb[request_id]->request_buffer, 0, tw_dev->srb[request_id]->request_bufflen);
1881 tw_dev->state[request_id] = TW_S_COMPLETED;
1882 tw_state_request_finish(tw_dev, request_id);
1883
1884 /* If we got a request_sense, we probably want a reset, return error */
1885 tw_dev->srb[request_id]->result = (DID_ERROR << 16);
1886 tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
1887
1888 return 0;
1889} /* End tw_scsiop_request_sense() */
1890
1891/* This function will handle synchronize cache scsi command */
1892static int tw_scsiop_synchronize_cache(TW_Device_Extension *tw_dev, int request_id)
1893{
1894 TW_Command *command_packet;
1895 unsigned long command_que_value;
1896
1897 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_synchronize_cache()\n");
1898
1899 /* Send firmware flush command for this unit */
1900 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
1901 if (command_packet == NULL) {
1902 printk(KERN_WARNING "3w-xxxx: tw_scsiop_synchronize_cache(): Bad command packet virtual address.\n");
1903 return 1;
1904 }
1905
1906 /* Setup the command packet */
1907 memset(command_packet, 0, sizeof(TW_Sector));
1908 command_packet->opcode__sgloffset = TW_OPSGL_IN(0, TW_OP_FLUSH_CACHE);
1909 command_packet->size = 2;
1910 command_packet->request_id = request_id;
1911 command_packet->unit__hostid = TW_UNITHOST_IN(0, tw_dev->srb[request_id]->device->id);
1912 command_packet->status = 0;
1913 command_packet->flags = 0;
1914 command_packet->byte6.parameter_count = 1;
1915 command_que_value = tw_dev->command_packet_physical_address[request_id];
1916 if (command_que_value == 0) {
1917 printk(KERN_WARNING "3w-xxxx: tw_scsiop_synchronize_cache(): Bad command packet physical address.\n");
1918 return 1;
1919 }
1920
1921 /* Now try to post the command packet */
1922 tw_post_command_packet(tw_dev, request_id);
1923
1924 return 0;
1925} /* End tw_scsiop_synchronize_cache() */
1926
1927/* This function will handle test unit ready scsi command */
1928static int tw_scsiop_test_unit_ready(TW_Device_Extension *tw_dev, int request_id)
1929{
1930 TW_Param *param;
1931 TW_Command *command_packet;
1932 unsigned long command_que_value;
1933 unsigned long param_value;
1934
1935 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_test_unit_ready()\n");
1936
1937 /* Initialize command packet */
1938 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
1939 if (command_packet == NULL) {
1940 printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad command packet virtual address.\n");
1941 return 1;
1942 }
1943 memset(command_packet, 0, sizeof(TW_Sector));
1944 command_packet->opcode__sgloffset = TW_OPSGL_IN(2, TW_OP_GET_PARAM);
1945 command_packet->size = 4;
1946 command_packet->request_id = request_id;
1947 command_packet->status = 0;
1948 command_packet->flags = 0;
1949 command_packet->byte6.parameter_count = 1;
1950
1951 /* Now setup the param */
1952 if (tw_dev->alignment_virtual_address[request_id] == NULL) {
1953 printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad alignment virtual address.\n");
1954 return 1;
1955 }
1956 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
1957 memset(param, 0, sizeof(TW_Sector));
1958 param->table_id = 3; /* unit summary table */
1959 param->parameter_id = 3; /* unitsstatus parameter */
1960 param->parameter_size_bytes = TW_MAX_UNITS;
1961 param_value = tw_dev->alignment_physical_address[request_id];
1962 if (param_value == 0) {
1963 printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad alignment physical address.\n");
1964 return 1;
1965 }
1966
1967 command_packet->byte8.param.sgl[0].address = param_value;
1968 command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
1969 command_que_value = tw_dev->command_packet_physical_address[request_id];
1970 if (command_que_value == 0) {
1971 printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad command packet physical address.\n");
1972 return 1;
1973 }
1974
1975 /* Now try to post the command packet */
1976 tw_post_command_packet(tw_dev, request_id);
1977
1978 return 0;
1979} /* End tw_scsiop_test_unit_ready() */
1980
1981/* This function is called by the isr to complete a testunitready command */
1982static int tw_scsiop_test_unit_ready_complete(TW_Device_Extension *tw_dev, int request_id)
1983{
1984 unsigned char *is_unit_present;
1985 TW_Param *param;
1986
1987 dprintk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready_complete()\n");
1988
1989 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
1990 if (param == NULL) {
1991 printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready_complete(): Bad alignment virtual address.\n");
1992 return 1;
1993 }
1994 is_unit_present = &(param->data[0]);
1995
1996 if (is_unit_present[tw_dev->srb[request_id]->device->id] & TW_UNIT_ONLINE) {
1997 tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = 1;
1998 } else {
1999 tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = 0;
2000 tw_dev->srb[request_id]->result = (DID_BAD_TARGET << 16);
2001 return TW_ISR_DONT_RESULT;
2002 }
2003
2004 return 0;
2005} /* End tw_scsiop_test_unit_ready_complete() */
2006
2007/* This is the main scsi queue function to handle scsi opcodes */
2008static int tw_scsi_queue(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
2009{
2010 unsigned char *command = SCpnt->cmnd;
2011 int request_id = 0;
2012 int retval = 1;
2013 TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
2014
2015 /* Save done function into Scsi_Cmnd struct */
2016 SCpnt->scsi_done = done;
2017
2018 /* Queue the command and get a request id */
2019 tw_state_request_start(tw_dev, &request_id);
2020
2021 /* Save the scsi command for use by the ISR */
2022 tw_dev->srb[request_id] = SCpnt;
2023
2024 /* Initialize phase to zero */
2025 SCpnt->SCp.phase = TW_PHASE_INITIAL;
2026
2027 switch (*command) {
2028 case READ_10:
2029 case READ_6:
2030 case WRITE_10:
2031 case WRITE_6:
2032 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ/WRITE.\n");
2033 retval = tw_scsiop_read_write(tw_dev, request_id);
2034 break;
2035 case TEST_UNIT_READY:
2036 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught TEST_UNIT_READY.\n");
2037 retval = tw_scsiop_test_unit_ready(tw_dev, request_id);
2038 break;
2039 case INQUIRY:
2040 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught INQUIRY.\n");
2041 retval = tw_scsiop_inquiry(tw_dev, request_id);
2042 break;
2043 case READ_CAPACITY:
2044 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ_CAPACITY.\n");
2045 retval = tw_scsiop_read_capacity(tw_dev, request_id);
2046 break;
2047 case REQUEST_SENSE:
2048 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught REQUEST_SENSE.\n");
2049 retval = tw_scsiop_request_sense(tw_dev, request_id);
2050 break;
2051 case MODE_SENSE:
2052 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught MODE_SENSE.\n");
2053 retval = tw_scsiop_mode_sense(tw_dev, request_id);
2054 break;
2055 case SYNCHRONIZE_CACHE:
2056 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught SYNCHRONIZE_CACHE.\n");
2057 retval = tw_scsiop_synchronize_cache(tw_dev, request_id);
2058 break;
2059 case TW_IOCTL:
2060 printk(KERN_WARNING "3w-xxxx: SCSI_IOCTL_SEND_COMMAND deprecated, please update your 3ware tools.\n");
2061 break;
2062 default:
2063 printk(KERN_NOTICE "3w-xxxx: scsi%d: Unknown scsi opcode: 0x%x\n", tw_dev->host->host_no, *command);
2064 tw_dev->state[request_id] = TW_S_COMPLETED;
2065 tw_state_request_finish(tw_dev, request_id);
2066 SCpnt->result = (DID_BAD_TARGET << 16);
2067 done(SCpnt);
2068 retval = 0;
2069 }
2070 if (retval) {
2071 tw_dev->state[request_id] = TW_S_COMPLETED;
2072 tw_state_request_finish(tw_dev, request_id);
2073 SCpnt->result = (DID_ERROR << 16);
2074 done(SCpnt);
2075 retval = 0;
2076 }
2077 return retval;
2078} /* End tw_scsi_queue() */
2079
2080/* This function is the interrupt service routine */
David Howells7d12e782006-10-05 14:55:46 +01002081static irqreturn_t tw_interrupt(int irq, void *dev_instance)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082{
2083 int request_id;
2084 u32 status_reg_value;
2085 TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance;
2086 TW_Response_Queue response_que;
2087 int error = 0, retval = 0;
2088 TW_Command *command_packet;
2089 int handled = 0;
2090
2091 /* Get the host lock for io completions */
2092 spin_lock(tw_dev->host->host_lock);
2093
2094 /* Read the registers */
2095 status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
2096
2097 /* Check if this is our interrupt, otherwise bail */
2098 if (!(status_reg_value & TW_STATUS_VALID_INTERRUPT))
2099 goto tw_interrupt_bail;
2100
2101 handled = 1;
2102
2103 /* Check controller for errors */
2104 if (tw_check_bits(status_reg_value)) {
2105 dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
2106 if (tw_decode_bits(tw_dev, status_reg_value, 1)) {
2107 TW_CLEAR_ALL_INTERRUPTS(tw_dev);
2108 goto tw_interrupt_bail;
2109 }
2110 }
2111
2112 /* Handle host interrupt */
2113 if (status_reg_value & TW_STATUS_HOST_INTERRUPT) {
2114 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received host interrupt.\n");
2115 TW_CLEAR_HOST_INTERRUPT(tw_dev);
2116 }
2117
2118 /* Handle attention interrupt */
2119 if (status_reg_value & TW_STATUS_ATTENTION_INTERRUPT) {
2120 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received attention interrupt.\n");
2121 TW_CLEAR_ATTENTION_INTERRUPT(tw_dev);
2122 tw_state_request_start(tw_dev, &request_id);
2123 error = tw_aen_read_queue(tw_dev, request_id);
2124 if (error) {
2125 printk(KERN_WARNING "3w-xxxx: scsi%d: Error reading aen queue.\n", tw_dev->host->host_no);
2126 tw_dev->state[request_id] = TW_S_COMPLETED;
2127 tw_state_request_finish(tw_dev, request_id);
2128 }
2129 }
2130
2131 /* Handle command interrupt */
2132 if (status_reg_value & TW_STATUS_COMMAND_INTERRUPT) {
2133 /* Drain as many pending commands as we can */
2134 while (tw_dev->pending_request_count > 0) {
2135 request_id = tw_dev->pending_queue[tw_dev->pending_head];
2136 if (tw_dev->state[request_id] != TW_S_PENDING) {
2137 printk(KERN_WARNING "3w-xxxx: scsi%d: Found request id that wasn't pending.\n", tw_dev->host->host_no);
2138 break;
2139 }
2140 if (tw_post_command_packet(tw_dev, request_id)==0) {
2141 if (tw_dev->pending_head == TW_Q_LENGTH-1) {
2142 tw_dev->pending_head = TW_Q_START;
2143 } else {
2144 tw_dev->pending_head = tw_dev->pending_head + 1;
2145 }
2146 tw_dev->pending_request_count--;
2147 } else {
2148 /* If we get here, we will continue re-posting on the next command interrupt */
2149 break;
2150 }
2151 }
2152 /* If there are no more pending requests, we mask command interrupt */
2153 if (tw_dev->pending_request_count == 0)
2154 TW_MASK_COMMAND_INTERRUPT(tw_dev);
2155 }
2156
2157 /* Handle response interrupt */
2158 if (status_reg_value & TW_STATUS_RESPONSE_INTERRUPT) {
2159 /* Drain the response queue from the board */
2160 while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
2161 /* Read response queue register */
2162 response_que.value = inl(TW_RESPONSE_QUEUE_REG_ADDR(tw_dev));
2163 request_id = TW_RESID_OUT(response_que.response_id);
2164 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
2165 error = 0;
2166
2167 /* Check for bad response */
2168 if (command_packet->status != 0) {
2169 /* If internal command, don't error, don't fill sense */
2170 if (tw_dev->srb[request_id] == NULL) {
2171 tw_decode_sense(tw_dev, request_id, 0);
2172 } else {
2173 error = tw_decode_sense(tw_dev, request_id, 1);
2174 }
2175 }
2176
2177 /* Check for correct state */
2178 if (tw_dev->state[request_id] != TW_S_POSTED) {
2179 if (tw_dev->srb[request_id] != NULL) {
2180 printk(KERN_WARNING "3w-xxxx: scsi%d: Received a request id that wasn't posted.\n", tw_dev->host->host_no);
2181 error = 1;
2182 }
2183 }
2184
2185 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Response queue request id: %d.\n", request_id);
2186
2187 /* Check for internal command completion */
2188 if (tw_dev->srb[request_id] == NULL) {
2189 dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found internally posted command.\n");
2190 /* Check for chrdev ioctl completion */
2191 if (request_id != tw_dev->chrdev_request_id) {
2192 retval = tw_aen_complete(tw_dev, request_id);
2193 if (retval) {
2194 printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing aen.\n", tw_dev->host->host_no);
2195 }
2196 } else {
2197 tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
2198 wake_up(&tw_dev->ioctl_wqueue);
2199 }
2200 } else {
2201 switch (tw_dev->srb[request_id]->cmnd[0]) {
2202 case READ_10:
2203 case READ_6:
2204 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_10/READ_6\n");
2205 break;
2206 case WRITE_10:
2207 case WRITE_6:
2208 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_10/WRITE_6\n");
2209 break;
2210 case TEST_UNIT_READY:
2211 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught TEST_UNIT_READY\n");
2212 error = tw_scsiop_test_unit_ready_complete(tw_dev, request_id);
2213 break;
2214 case INQUIRY:
2215 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught INQUIRY\n");
2216 error = tw_scsiop_inquiry_complete(tw_dev, request_id);
2217 break;
2218 case READ_CAPACITY:
2219 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_CAPACITY\n");
2220 error = tw_scsiop_read_capacity_complete(tw_dev, request_id);
2221 break;
2222 case MODE_SENSE:
2223 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught MODE_SENSE\n");
2224 error = tw_scsiop_mode_sense_complete(tw_dev, request_id);
2225 break;
2226 case SYNCHRONIZE_CACHE:
2227 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught SYNCHRONIZE_CACHE\n");
2228 break;
2229 default:
2230 printk(KERN_WARNING "3w-xxxx: case slip in tw_interrupt()\n");
2231 error = 1;
2232 }
2233
2234 /* If no error command was a success */
2235 if (error == 0) {
2236 tw_dev->srb[request_id]->result = (DID_OK << 16);
2237 }
2238
2239 /* If error, command failed */
2240 if (error == 1) {
2241 /* Ask for a host reset */
2242 tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
2243 }
2244
2245 /* Now complete the io */
2246 if ((error != TW_ISR_DONT_COMPLETE)) {
2247 tw_dev->state[request_id] = TW_S_COMPLETED;
2248 tw_state_request_finish(tw_dev, request_id);
2249 tw_dev->posted_request_count--;
2250 tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
2251
2252 tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
2253 }
2254 }
2255
2256 /* Check for valid status after each drain */
2257 status_reg_value = inl(TW_STATUS_REG_ADDR(tw_dev));
2258 if (tw_check_bits(status_reg_value)) {
2259 dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
2260 if (tw_decode_bits(tw_dev, status_reg_value, 1)) {
2261 TW_CLEAR_ALL_INTERRUPTS(tw_dev);
2262 goto tw_interrupt_bail;
2263 }
2264 }
2265 }
2266 }
2267
2268tw_interrupt_bail:
2269 spin_unlock(tw_dev->host->host_lock);
2270 return IRQ_RETVAL(handled);
2271} /* End tw_interrupt() */
2272
2273/* This function tells the controller to shut down */
2274static void __tw_shutdown(TW_Device_Extension *tw_dev)
2275{
2276 /* Disable interrupts */
2277 TW_DISABLE_INTERRUPTS(tw_dev);
2278
2279 printk(KERN_WARNING "3w-xxxx: Shutting down host %d.\n", tw_dev->host->host_no);
2280
2281 /* Tell the card we are shutting down */
2282 if (tw_initconnection(tw_dev, 1)) {
2283 printk(KERN_WARNING "3w-xxxx: Connection shutdown failed.\n");
2284 } else {
2285 printk(KERN_WARNING "3w-xxxx: Shutdown complete.\n");
2286 }
2287
2288 /* Clear all interrupts just before exit */
2289 TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);
2290} /* End __tw_shutdown() */
2291
2292/* Wrapper for __tw_shutdown */
Greg Kroah-Hartmand18c3db2005-06-23 17:35:56 -07002293static void tw_shutdown(struct pci_dev *pdev)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294{
Greg Kroah-Hartmand18c3db2005-06-23 17:35:56 -07002295 struct Scsi_Host *host = pci_get_drvdata(pdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296 TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
2297
2298 __tw_shutdown(tw_dev);
2299} /* End tw_shutdown() */
2300
2301static struct scsi_host_template driver_template = {
2302 .module = THIS_MODULE,
2303 .name = "3ware Storage Controller",
2304 .queuecommand = tw_scsi_queue,
2305 .eh_host_reset_handler = tw_scsi_eh_reset,
2306 .bios_param = tw_scsi_biosparam,
2307 .change_queue_depth = tw_change_queue_depth,
2308 .can_queue = TW_Q_LENGTH-2,
2309 .this_id = -1,
2310 .sg_tablesize = TW_MAX_SGL_LENGTH,
2311 .max_sectors = TW_MAX_SECTORS,
2312 .cmd_per_lun = TW_MAX_CMDS_PER_LUN,
2313 .use_clustering = ENABLE_CLUSTERING,
2314 .shost_attrs = tw_host_attrs,
2315 .emulated = 1
2316};
2317
2318/* This function will probe and initialize a card */
2319static int __devinit tw_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
2320{
2321 struct Scsi_Host *host = NULL;
2322 TW_Device_Extension *tw_dev;
2323 int retval = -ENODEV;
2324
2325 retval = pci_enable_device(pdev);
2326 if (retval) {
2327 printk(KERN_WARNING "3w-xxxx: Failed to enable pci device.");
2328 goto out_disable_device;
2329 }
2330
2331 pci_set_master(pdev);
2332
2333 retval = pci_set_dma_mask(pdev, TW_DMA_MASK);
2334 if (retval) {
2335 printk(KERN_WARNING "3w-xxxx: Failed to set dma mask.");
2336 goto out_disable_device;
2337 }
2338
2339 host = scsi_host_alloc(&driver_template, sizeof(TW_Device_Extension));
2340 if (!host) {
2341 printk(KERN_WARNING "3w-xxxx: Failed to allocate memory for device extension.");
2342 retval = -ENOMEM;
2343 goto out_disable_device;
2344 }
2345 tw_dev = (TW_Device_Extension *)host->hostdata;
2346
2347 memset(tw_dev, 0, sizeof(TW_Device_Extension));
2348
2349 /* Save values to device extension */
2350 tw_dev->host = host;
2351 tw_dev->tw_pci_dev = pdev;
2352
2353 if (tw_initialize_device_extension(tw_dev)) {
2354 printk(KERN_WARNING "3w-xxxx: Failed to initialize device extension.");
2355 goto out_free_device_extension;
2356 }
2357
2358 /* Request IO regions */
2359 retval = pci_request_regions(pdev, "3w-xxxx");
2360 if (retval) {
2361 printk(KERN_WARNING "3w-xxxx: Failed to get mem region.");
2362 goto out_free_device_extension;
2363 }
2364
2365 /* Save base address */
2366 tw_dev->base_addr = pci_resource_start(pdev, 0);
2367 if (!tw_dev->base_addr) {
2368 printk(KERN_WARNING "3w-xxxx: Failed to get io address.");
2369 goto out_release_mem_region;
2370 }
2371
2372 /* Disable interrupts on the card */
2373 TW_DISABLE_INTERRUPTS(tw_dev);
2374
2375 /* Initialize the card */
2376 if (tw_reset_sequence(tw_dev))
2377 goto out_release_mem_region;
2378
2379 /* Set host specific parameters */
2380 host->max_id = TW_MAX_UNITS;
2381 host->max_cmd_len = TW_MAX_CDB_LEN;
2382
2383 /* Luns and channels aren't supported by adapter */
2384 host->max_lun = 0;
2385 host->max_channel = 0;
2386
2387 /* Register the card with the kernel SCSI layer */
2388 retval = scsi_add_host(host, &pdev->dev);
2389 if (retval) {
2390 printk(KERN_WARNING "3w-xxxx: scsi add host failed");
2391 goto out_release_mem_region;
2392 }
2393
2394 pci_set_drvdata(pdev, host);
2395
2396 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);
2397
2398 /* Now setup the interrupt handler */
Thomas Gleixner1d6f3592006-07-01 19:29:42 -07002399 retval = request_irq(pdev->irq, tw_interrupt, IRQF_SHARED, "3w-xxxx", tw_dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400 if (retval) {
2401 printk(KERN_WARNING "3w-xxxx: Error requesting IRQ.");
2402 goto out_remove_host;
2403 }
2404
2405 tw_device_extension_list[tw_device_extension_count] = tw_dev;
2406 tw_device_extension_count++;
2407
2408 /* Re-enable interrupts on the card */
2409 TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);
2410
2411 /* Finally, scan the host */
2412 scsi_scan_host(host);
2413
2414 if (twe_major == -1) {
2415 if ((twe_major = register_chrdev (0, "twe", &tw_fops)) < 0)
2416 printk(KERN_WARNING "3w-xxxx: Failed to register character device.");
2417 }
2418 return 0;
2419
2420out_remove_host:
2421 scsi_remove_host(host);
2422out_release_mem_region:
2423 pci_release_regions(pdev);
2424out_free_device_extension:
2425 tw_free_device_extension(tw_dev);
2426 scsi_host_put(host);
2427out_disable_device:
2428 pci_disable_device(pdev);
2429
2430 return retval;
2431} /* End tw_probe() */
2432
2433/* This function is called to remove a device */
2434static void tw_remove(struct pci_dev *pdev)
2435{
2436 struct Scsi_Host *host = pci_get_drvdata(pdev);
2437 TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
2438
2439 scsi_remove_host(tw_dev->host);
2440
2441 /* Unregister character device */
2442 if (twe_major >= 0) {
2443 unregister_chrdev(twe_major, "twe");
2444 twe_major = -1;
2445 }
2446
2447 /* Free up the IRQ */
2448 free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
2449
2450 /* Shutdown the card */
2451 __tw_shutdown(tw_dev);
2452
2453 /* Free up the mem region */
2454 pci_release_regions(pdev);
2455
2456 /* Free up device extension resources */
2457 tw_free_device_extension(tw_dev);
2458
2459 scsi_host_put(tw_dev->host);
2460 pci_disable_device(pdev);
2461 tw_device_extension_count--;
2462} /* End tw_remove() */
2463
2464/* PCI Devices supported by this driver */
2465static struct pci_device_id tw_pci_tbl[] __devinitdata = {
2466 { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_1000,
2467 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2468 { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_7000,
2469 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
2470 { }
2471};
2472MODULE_DEVICE_TABLE(pci, tw_pci_tbl);
2473
2474/* pci_driver initializer */
2475static struct pci_driver tw_driver = {
2476 .name = "3w-xxxx",
2477 .id_table = tw_pci_tbl,
2478 .probe = tw_probe,
2479 .remove = tw_remove,
Greg Kroah-Hartmand18c3db2005-06-23 17:35:56 -07002480 .shutdown = tw_shutdown,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481};
2482
2483/* This function is called on driver initialization */
2484static int __init tw_init(void)
2485{
2486 printk(KERN_WARNING "3ware Storage Controller device driver for Linux v%s.\n", TW_DRIVER_VERSION);
2487
Henrik Kretzschmardcbccbde2006-09-25 16:58:58 -07002488 return pci_register_driver(&tw_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489} /* End tw_init() */
2490
2491/* This function is called on driver exit */
2492static void __exit tw_exit(void)
2493{
2494 pci_unregister_driver(&tw_driver);
2495} /* End tw_exit() */
2496
2497module_init(tw_init);
2498module_exit(tw_exit);
2499