Squash another dozen warnings.
[linux-2.6/linux-mips.git] / drivers / scsi / 3w-xxxx.c
blobf4d5371d0ecde8d00eae26586c250e230e98f05d
1 /*
2 3w-xxxx.c -- 3ware Storage Controller device driver for Linux.
4 Written By: Adam Radford <linux@3ware.com>
5 Modifications By: Joel Jacobson <linux@3ware.com>
6 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
7 Brad Strand <linux@3ware.com>
9 Copyright (C) 1999-2003 3ware Inc.
11 Kernel compatiblity By: Andre Hedrick <andre@suse.com>
12 Non-Copyright (C) 2000 Andre Hedrick <andre@suse.com>
14 Further tiny build fixes and trivial hoovering Alan Cox
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.
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.
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.
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
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
49 Bugs/Comments/Suggestions should be mailed to:
50 linux@3ware.com
52 For more information, goto:
53 http://www.3ware.com
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.
174 #include <linux/module.h>
176 MODULE_AUTHOR ("3ware Inc.");
177 #ifdef __SMP__
178 MODULE_DESCRIPTION ("3ware Storage Controller Linux Driver (SMP)");
179 #else
180 MODULE_DESCRIPTION ("3ware Storage Controller Linux Driver");
181 #endif
182 MODULE_LICENSE("GPL");
184 #include <linux/kernel.h>
185 #include <linux/pci.h>
186 #include <linux/time.h>
187 #include <linux/proc_fs.h>
188 #include <linux/sched.h>
189 #include <linux/ioport.h>
190 #include <linux/blk.h>
191 #include <linux/hdreg.h>
192 #include <linux/string.h>
193 #include <linux/delay.h>
194 #include <linux/smp.h>
195 #include <linux/reboot.h>
196 #include <linux/spinlock.h>
197 #include <linux/interrupt.h>
199 #include <asm/errno.h>
200 #include <asm/io.h>
201 #include <asm/irq.h>
202 #include <asm/uaccess.h>
204 #define __3W_C /* let 3w-xxxx.h know it is use */
206 #include "scsi.h"
207 #include "hosts.h"
209 #include "3w-xxxx.h"
211 static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
212 static int tw_chrdev_open(struct inode *inode, struct file *file);
213 static int tw_chrdev_release(struct inode *inode, struct file *file);
214 static int tw_copy_info(TW_Info *info, char *fmt, ...);
215 static void tw_copy_mem_info(TW_Info *info, char *data, int len);
216 static int tw_halt(struct notifier_block *nb, ulong event, void *buf);
217 static int tw_map_scsi_sg_data(struct pci_dev *pdev, Scsi_Cmnd *cmd);
218 static u32 tw_map_scsi_single_data(struct pci_dev *pdev, Scsi_Cmnd *cmd);
219 static void tw_unmap_scsi_data(struct pci_dev *pdev, Scsi_Cmnd *cmd);
221 /* Notifier block to get a notify on system shutdown/halt/reboot */
222 static struct notifier_block tw_notifier = {
223 tw_halt, NULL, 0
226 /* File operations struct for character device */
227 static struct file_operations tw_fops = {
228 .owner = THIS_MODULE,
229 .ioctl = tw_chrdev_ioctl,
230 .open = tw_chrdev_open,
231 .release = tw_chrdev_release
234 /* Globals */
235 char *tw_driver_version="1.02.00.032";
236 TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
237 int tw_device_extension_count = 0;
238 static int twe_major = -1;
240 /* Functions */
242 /* This function will complete an aen request from the isr */
243 int tw_aen_complete(TW_Device_Extension *tw_dev, int request_id)
245 TW_Param *param;
246 unsigned short aen;
247 int error = 0, table_max = 0;
249 dprintk(KERN_WARNING "3w-xxxx: tw_aen_complete()\n");
250 if (tw_dev->alignment_virtual_address[request_id] == NULL) {
251 printk(KERN_WARNING "3w-xxxx: tw_aen_complete(): Bad alignment virtual address.\n");
252 return 1;
254 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
255 aen = *(unsigned short *)(param->data);
256 dprintk(KERN_NOTICE "3w-xxxx: tw_aen_complete(): Queue'd code 0x%x\n", aen);
258 /* Print some useful info when certain aen codes come out */
259 if (aen == 0x0ff) {
260 printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: INFO: AEN queue overflow.\n", tw_dev->host->host_no);
261 } else {
262 table_max = sizeof(tw_aen_string)/sizeof(char *);
263 if ((aen & 0x0ff) < table_max) {
264 if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') {
265 printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: %s%d.\n", tw_dev->host->host_no, tw_aen_string[aen & 0xff], aen >> 8);
266 } else {
267 if (aen != 0x0)
268 printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: %s.\n", tw_dev->host->host_no, tw_aen_string[aen & 0xff]);
270 } else {
271 printk(KERN_WARNING "3w-xxxx: scsi%d: Received AEN %d.\n", tw_dev->host->host_no, aen);
274 if (aen != 0x0)
275 tw_dev->aen_count++;
277 /* Now queue the code */
278 tw_dev->aen_queue[tw_dev->aen_tail] = aen;
279 if (tw_dev->aen_tail == TW_Q_LENGTH - 1) {
280 tw_dev->aen_tail = TW_Q_START;
281 } else {
282 tw_dev->aen_tail = tw_dev->aen_tail + 1;
284 if (tw_dev->aen_head == tw_dev->aen_tail) {
285 if (tw_dev->aen_head == TW_Q_LENGTH - 1) {
286 tw_dev->aen_head = TW_Q_START;
287 } else {
288 tw_dev->aen_head = tw_dev->aen_head + 1;
292 if (aen != TW_AEN_QUEUE_EMPTY) {
293 error = tw_aen_read_queue(tw_dev, request_id);
294 if (error) {
295 printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing AEN.\n", tw_dev->host->host_no);
296 tw_dev->state[request_id] = TW_S_COMPLETED;
297 tw_state_request_finish(tw_dev, request_id);
299 } else {
300 tw_dev->state[request_id] = TW_S_COMPLETED;
301 tw_state_request_finish(tw_dev, request_id);
304 return 0;
305 } /* End tw_aen_complete() */
307 /* This function will drain the aen queue after a soft reset */
308 int tw_aen_drain_queue(TW_Device_Extension *tw_dev)
310 TW_Command *command_packet;
311 TW_Param *param;
312 int request_id = 0;
313 u32 command_que_addr;
314 unsigned long command_que_value;
315 unsigned long param_value;
316 TW_Response_Queue response_queue;
317 u32 response_que_addr;
318 unsigned short aen;
319 unsigned short aen_code;
320 int finished = 0;
321 int first_reset = 0;
322 int queue = 0;
323 int found = 0, table_max = 0;
325 dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue()\n");
327 command_que_addr = tw_dev->registers.command_que_addr;
328 response_que_addr = tw_dev->registers.response_que_addr;
330 if (tw_poll_status(tw_dev, TW_STATUS_ATTENTION_INTERRUPT | TW_STATUS_MICROCONTROLLER_READY, 30)) {
331 dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): No attention interrupt for card %d.\n", tw_device_extension_count);
332 return 1;
334 tw_clear_attention_interrupt(tw_dev);
336 /* Empty response queue */
337 tw_empty_response_que(tw_dev);
339 /* Initialize command packet */
340 if (tw_dev->command_packet_virtual_address[request_id] == NULL) {
341 printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad command packet virtual address.\n");
342 return 1;
344 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
345 memset(command_packet, 0, sizeof(TW_Sector));
346 command_packet->byte0.opcode = TW_OP_GET_PARAM;
347 command_packet->byte0.sgl_offset = 2;
348 command_packet->size = 4;
349 command_packet->request_id = request_id;
350 command_packet->byte3.unit = 0;
351 command_packet->byte3.host_id = 0;
352 command_packet->status = 0;
353 command_packet->flags = 0;
354 command_packet->byte6.parameter_count = 1;
355 command_que_value = tw_dev->command_packet_physical_address[request_id];
356 if (command_que_value == 0) {
357 printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad command packet physical address.\n");
358 return 1;
361 /* Now setup the param */
362 if (tw_dev->alignment_virtual_address[request_id] == NULL) {
363 printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad alignment virtual address.\n");
364 return 1;
366 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
367 memset(param, 0, sizeof(TW_Sector));
368 param->table_id = 0x401; /* AEN table */
369 param->parameter_id = 2; /* Unit code */
370 param->parameter_size_bytes = 2;
371 param_value = tw_dev->alignment_physical_address[request_id];
372 if (param_value == 0) {
373 printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad alignment physical address.\n");
374 return 1;
376 command_packet->byte8.param.sgl[0].address = param_value;
377 command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
379 /* Now drain the controller's aen queue */
380 do {
381 /* Post command packet */
382 outl(command_que_value, command_que_addr);
384 /* Now poll for completion */
385 if (tw_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, 30) == 0) {
386 response_queue.value = inl(response_que_addr);
387 request_id = (unsigned char)response_queue.u.response_id;
389 if (request_id != 0) {
390 /* Unexpected request id */
391 printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Unexpected request id.\n");
392 return 1;
395 if (command_packet->status != 0) {
396 if (command_packet->flags != TW_AEN_TABLE_UNDEFINED) {
397 /* Bad response */
398 tw_decode_sense(tw_dev, request_id, 0);
399 return 1;
400 } else {
401 /* We know this is a 3w-1x00, and doesn't support aen's */
402 return 0;
406 /* Now check the aen */
407 aen = *(unsigned short *)(param->data);
408 aen_code = (aen & 0x0ff);
409 queue = 0;
410 switch (aen_code) {
411 case TW_AEN_QUEUE_EMPTY:
412 dprintk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]);
413 if (first_reset != 1) {
414 return 1;
415 } else {
416 finished = 1;
418 break;
419 case TW_AEN_SOFT_RESET:
420 if (first_reset == 0) {
421 first_reset = 1;
422 } else {
423 printk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]);
424 tw_dev->aen_count++;
425 queue = 1;
427 break;
428 default:
429 if (aen == 0x0ff) {
430 printk(KERN_WARNING "3w-xxxx: AEN: INFO: AEN queue overflow.\n");
431 } else {
432 table_max = sizeof(tw_aen_string)/sizeof(char *);
433 if ((aen & 0x0ff) < table_max) {
434 if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') {
435 printk(KERN_WARNING "3w-xxxx: AEN: %s%d.\n", tw_aen_string[aen & 0xff], aen >> 8);
436 } else {
437 printk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]);
439 } else
440 printk(KERN_WARNING "3w-xxxx: Received AEN %d.\n", aen);
442 tw_dev->aen_count++;
443 queue = 1;
446 /* Now put the aen on the aen_queue */
447 if (queue == 1) {
448 tw_dev->aen_queue[tw_dev->aen_tail] = aen;
449 if (tw_dev->aen_tail == TW_Q_LENGTH - 1) {
450 tw_dev->aen_tail = TW_Q_START;
451 } else {
452 tw_dev->aen_tail = tw_dev->aen_tail + 1;
454 if (tw_dev->aen_head == tw_dev->aen_tail) {
455 if (tw_dev->aen_head == TW_Q_LENGTH - 1) {
456 tw_dev->aen_head = TW_Q_START;
457 } else {
458 tw_dev->aen_head = tw_dev->aen_head + 1;
462 found = 1;
464 if (found == 0) {
465 printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Response never received.\n");
466 return 1;
468 } while (finished == 0);
470 return 0;
471 } /* End tw_aen_drain_queue() */
473 /* This function will read the aen queue from the isr */
474 int tw_aen_read_queue(TW_Device_Extension *tw_dev, int request_id)
476 TW_Command *command_packet;
477 TW_Param *param;
478 u32 command_que_addr;
479 unsigned long command_que_value;
480 u32 status_reg_value = 0, status_reg_addr;
481 unsigned long param_value = 0;
483 dprintk(KERN_NOTICE "3w-xxxx: tw_aen_read_queue()\n");
484 command_que_addr = tw_dev->registers.command_que_addr;
485 status_reg_addr = tw_dev->registers.status_reg_addr;
487 status_reg_value = inl(status_reg_addr);
488 if (tw_check_bits(status_reg_value)) {
489 dprintk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Unexpected bits.\n");
490 tw_decode_bits(tw_dev, status_reg_value, 1);
491 return 1;
493 if (tw_dev->command_packet_virtual_address[request_id] == NULL) {
494 printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Bad command packet virtual address.\n");
495 return 1;
497 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
498 memset(command_packet, 0, sizeof(TW_Sector));
499 command_packet->byte0.opcode = TW_OP_GET_PARAM;
500 command_packet->byte0.sgl_offset = 2;
501 command_packet->size = 4;
502 command_packet->request_id = request_id;
503 command_packet->byte3.unit = 0;
504 command_packet->byte3.host_id = 0;
505 command_packet->status = 0;
506 command_packet->flags = 0;
507 command_packet->byte6.parameter_count = 1;
508 command_que_value = tw_dev->command_packet_physical_address[request_id];
509 if (command_que_value == 0) {
510 printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Bad command packet physical address.\n");
511 return 1;
513 /* Now setup the param */
514 if (tw_dev->alignment_virtual_address[request_id] == NULL) {
515 printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Bad alignment virtual address.\n");
516 return 1;
518 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
519 memset(param, 0, sizeof(TW_Sector));
520 param->table_id = 0x401; /* AEN table */
521 param->parameter_id = 2; /* Unit code */
522 param->parameter_size_bytes = 2;
523 param_value = tw_dev->alignment_physical_address[request_id];
524 if (param_value == 0) {
525 printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Bad alignment physical address.\n");
526 return 1;
528 command_packet->byte8.param.sgl[0].address = param_value;
529 command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
531 /* Now post the command packet */
532 if ((status_reg_value & TW_STATUS_COMMAND_QUEUE_FULL) == 0) {
533 dprintk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Post succeeded.\n");
534 tw_dev->srb[request_id] = 0; /* Flag internal command */
535 tw_dev->state[request_id] = TW_S_POSTED;
536 outl(command_que_value, command_que_addr);
537 } else {
538 printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Post failed, will retry.\n");
539 return 1;
542 return 0;
543 } /* End tw_aen_read_queue() */
545 /* This function will allocate memory */
546 int tw_allocate_memory(TW_Device_Extension *tw_dev, int size, int which)
548 int i;
549 dma_addr_t dma_handle;
550 unsigned long *cpu_addr = NULL;
552 dprintk(KERN_NOTICE "3w-xxxx: tw_allocate_memory()\n");
554 for (i=0;i<TW_Q_LENGTH;i++) {
555 cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, size, &dma_handle);
556 if (cpu_addr == NULL) {
557 printk(KERN_WARNING "3w-xxxx: pci_alloc_consistent() failed.\n");
558 return 1;
561 if ((unsigned long)cpu_addr % (tw_dev->tw_pci_dev->device == TW_DEVICE_ID ? TW_ALIGNMENT_6000 : TW_ALIGNMENT_7000)) {
562 printk(KERN_WARNING "3w-xxxx: Couldn't allocate correctly aligned memory.\n");
563 pci_free_consistent(tw_dev->tw_pci_dev, size, cpu_addr, dma_handle);
564 return 1;
567 switch(which) {
568 case 0:
569 tw_dev->command_packet_virtual_address[i] = cpu_addr;
570 tw_dev->command_packet_physical_address[i] = dma_handle;
571 memset(tw_dev->command_packet_virtual_address[i], 0, size);
572 break;
573 case 1:
574 tw_dev->alignment_virtual_address[i] = cpu_addr;
575 tw_dev->alignment_physical_address[i] = dma_handle;
576 memset(tw_dev->alignment_virtual_address[i], 0, size);
577 break;
578 default:
579 printk(KERN_WARNING "3w-xxxx: tw_allocate_memory(): case slip in tw_allocate_memory()\n");
580 return 1;
584 return 0;
585 } /* End tw_allocate_memory() */
587 /* This function will check the status register for unexpected bits */
588 int tw_check_bits(u32 status_reg_value)
590 if ((status_reg_value & TW_STATUS_EXPECTED_BITS) != TW_STATUS_EXPECTED_BITS) {
591 dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): No expected bits (0x%x).\n", status_reg_value);
592 return 1;
594 if ((status_reg_value & TW_STATUS_UNEXPECTED_BITS) != 0) {
595 dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): Found unexpected bits (0x%x).\n", status_reg_value);
596 return 1;
599 return 0;
600 } /* End tw_check_bits() */
602 /* This function will report controller error status */
603 int tw_check_errors(TW_Device_Extension *tw_dev)
605 u32 status_reg_addr, status_reg_value;
607 status_reg_addr = tw_dev->registers.status_reg_addr;
608 status_reg_value = inl(status_reg_addr);
610 if (TW_STATUS_ERRORS(status_reg_value) || tw_check_bits(status_reg_value)) {
611 tw_decode_bits(tw_dev, status_reg_value, 0);
612 return 1;
615 return 0;
616 } /* End tw_check_errors() */
618 /* This function handles ioctl for the character device */
619 static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
621 int error, request_id;
622 dma_addr_t dma_handle;
623 unsigned short tw_aen_code;
624 unsigned long before;
625 unsigned long flags;
626 unsigned int data_buffer_length = 0;
627 unsigned long data_buffer_length_adjusted = 0;
628 unsigned long *cpu_addr;
629 TW_New_Ioctl *tw_ioctl;
630 TW_Passthru *passthru;
631 TW_Device_Extension *tw_dev = tw_device_extension_list[minor(inode->i_rdev)];
632 int retval = -EFAULT;
634 dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl()\n");
636 /* Only let one of these through at a time */
637 if (down_interruptible(&tw_dev->ioctl_sem))
638 return -EINTR;
640 /* First copy down the buffer length */
641 error = copy_from_user(&data_buffer_length, (void *)arg, sizeof(unsigned int));
642 if (error)
643 goto out;
645 /* Check size */
646 if (data_buffer_length > TW_MAX_SECTORS * 512) {
647 retval = -EINVAL;
648 goto out;
651 /* Hardware can only do multiple of 512 byte transfers */
652 data_buffer_length_adjusted = (data_buffer_length + 511) & ~511;
654 /* Now allocate ioctl buf memory */
655 cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, &dma_handle);
656 if (cpu_addr == NULL) {
657 retval = -ENOMEM;
658 goto out;
661 tw_ioctl = (TW_New_Ioctl *)cpu_addr;
663 /* Now copy down the entire ioctl */
664 error = copy_from_user(tw_ioctl, (void *)arg, data_buffer_length + sizeof(TW_New_Ioctl) - 1);
665 if (error)
666 goto out2;
668 passthru = (TW_Passthru *)&tw_ioctl->firmware_command;
670 /* See which ioctl we are doing */
671 switch (cmd) {
672 case TW_OP_NOP:
673 dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): caught TW_OP_NOP.\n");
674 break;
675 case TW_OP_AEN_LISTEN:
676 dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): caught TW_AEN_LISTEN.\n");
677 memset(tw_ioctl->data_buffer, 0, tw_ioctl->data_buffer_length);
679 spin_lock_irqsave(tw_dev->host->host_lock, flags);
680 if (tw_dev->aen_head == tw_dev->aen_tail) {
681 tw_aen_code = TW_AEN_QUEUE_EMPTY;
682 } else {
683 tw_aen_code = tw_dev->aen_queue[tw_dev->aen_head];
684 if (tw_dev->aen_head == TW_Q_LENGTH - 1) {
685 tw_dev->aen_head = TW_Q_START;
686 } else {
687 tw_dev->aen_head = tw_dev->aen_head + 1;
690 spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
691 memcpy(tw_ioctl->data_buffer, &tw_aen_code, sizeof(tw_aen_code));
692 break;
693 case TW_CMD_PACKET_WITH_DATA:
694 dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): caught TW_CMD_PACKET_WITH_DATA.\n");
695 spin_lock_irqsave(&tw_dev->tw_lock, flags);
697 tw_state_request_start(tw_dev, &request_id);
699 /* Flag internal command */
700 tw_dev->srb[request_id] = 0;
702 /* Flag chrdev ioctl */
703 tw_dev->chrdev_request_id = request_id;
705 tw_ioctl->firmware_command.request_id = request_id;
707 /* Load the sg list */
708 switch (tw_ioctl->firmware_command.byte0.sgl_offset) {
709 case 2:
710 tw_ioctl->firmware_command.byte8.param.sgl[0].address = dma_handle + sizeof(TW_New_Ioctl) - 1;
711 tw_ioctl->firmware_command.byte8.param.sgl[0].length = data_buffer_length_adjusted;
712 break;
713 case 3:
714 tw_ioctl->firmware_command.byte8.io.sgl[0].address = dma_handle + sizeof(TW_New_Ioctl) - 1;
715 tw_ioctl->firmware_command.byte8.io.sgl[0].length = data_buffer_length_adjusted;
716 break;
717 case 5:
718 passthru->sg_list[0].address = dma_handle + sizeof(TW_New_Ioctl) - 1;
719 passthru->sg_list[0].length = data_buffer_length_adjusted;
720 break;
723 memcpy(tw_dev->command_packet_virtual_address[request_id], &(tw_ioctl->firmware_command), sizeof(TW_Command));
725 /* Now post the command packet to the controller */
726 tw_post_command_packet(tw_dev, request_id);
727 spin_unlock_irqrestore(&tw_dev->tw_lock, flags);
729 /* Now wait for the command to complete */
730 before = jiffies;
732 while (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE)
734 /* FIXME: race condition on the wait*/
735 interruptible_sleep_on_timeout(&tw_dev->ioctl_wqueue, 1);
736 if (time_after(jiffies, before + HZ *TW_IOCTL_CHRDEV_TIMEOUT)) {
737 /* Now we need to reset the board */
738 printk(KERN_WARNING "3w-xxxx: scsi%d: Character ioctl (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, cmd);
739 spin_lock_irqsave(&tw_dev->tw_lock, flags);
740 tw_dev->state[request_id] = TW_S_COMPLETED;
741 tw_state_request_finish(tw_dev, request_id);
742 tw_dev->posted_request_count--;
743 if (tw_reset_device_extension(tw_dev)) {
744 printk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): Reset failed for card %d.\n", tw_dev->host->host_no);
746 spin_unlock_irqrestore(&tw_dev->tw_lock, flags);
747 if (signal_pending(current))
748 retval = -EINTR;
749 else
750 retval = -EIO;
751 goto out2;
755 /* Now copy in the command packet response */
756 memcpy(&(tw_ioctl->firmware_command), tw_dev->command_packet_virtual_address[request_id], sizeof(TW_Command));
758 /* Now complete the io */
759 spin_lock_irqsave(&tw_dev->tw_lock, flags);
760 tw_dev->posted_request_count--;
761 tw_dev->state[request_id] = TW_S_COMPLETED;
762 tw_state_request_finish(tw_dev, request_id);
763 spin_unlock_irqrestore(&tw_dev->tw_lock, flags);
764 break;
765 default:
766 retval = -ENOTTY;
767 goto out2;
770 /* Now copy the response to userspace */
771 error = copy_to_user((void *)arg, tw_ioctl, sizeof(TW_New_Ioctl) + tw_ioctl->data_buffer_length - 1);
772 if (error == 0)
773 retval = 0;
774 out2:
775 /* Now free ioctl buf memory */
776 pci_free_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle);
777 out:
778 up(&tw_dev->ioctl_sem);
779 return retval;
780 } /* End tw_chrdev_ioctl() */
782 /* This function handles open for the character device */
783 static int tw_chrdev_open(struct inode *inode, struct file *file)
785 unsigned int minor_number;
787 dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_open()\n");
789 minor_number = minor(inode->i_rdev);
790 if (minor_number >= tw_device_extension_count)
791 return -ENODEV;
793 return 0;
794 } /* End tw_chrdev_open() */
796 /* This function handles close for the character device */
797 static int tw_chrdev_release(struct inode *inode, struct file *file)
799 dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_release()\n");
801 return 0;
802 } /* End tw_chrdev_release() */
804 /* This function will clear all interrupts on the controller */
805 void tw_clear_all_interrupts(TW_Device_Extension *tw_dev)
807 u32 control_reg_addr, control_reg_value;
809 control_reg_addr = tw_dev->registers.control_reg_addr;
810 control_reg_value = TW_STATUS_VALID_INTERRUPT;
811 outl(control_reg_value, control_reg_addr);
812 } /* End tw_clear_all_interrupts() */
814 /* This function will clear the attention interrupt */
815 void tw_clear_attention_interrupt(TW_Device_Extension *tw_dev)
817 u32 control_reg_addr, control_reg_value;
819 control_reg_addr = tw_dev->registers.control_reg_addr;
820 control_reg_value = TW_CONTROL_CLEAR_ATTENTION_INTERRUPT;
821 outl(control_reg_value, control_reg_addr);
822 } /* End tw_clear_attention_interrupt() */
824 /* This function will clear the host interrupt */
825 void tw_clear_host_interrupt(TW_Device_Extension *tw_dev)
827 u32 control_reg_addr, control_reg_value;
829 control_reg_addr = tw_dev->registers.control_reg_addr;
830 control_reg_value = TW_CONTROL_CLEAR_HOST_INTERRUPT;
831 outl(control_reg_value, control_reg_addr);
832 } /* End tw_clear_host_interrupt() */
834 /* This function is called by tw_scsi_proc_info */
835 static int tw_copy_info(TW_Info *info, char *fmt, ...)
837 va_list args;
838 char buf[81];
839 int len;
841 va_start(args, fmt);
842 len = vsprintf(buf, fmt, args);
843 va_end(args);
844 tw_copy_mem_info(info, buf, len);
845 return len;
846 } /* End tw_copy_info() */
848 /* This function is called by tw_scsi_proc_info */
849 static void tw_copy_mem_info(TW_Info *info, char *data, int len)
851 if (info->position + len > info->length)
852 len = info->length - info->position;
854 if (info->position + len < info->offset) {
855 info->position += len;
856 return;
858 if (info->position < info->offset) {
859 data += (info->offset - info->position);
860 len -= (info->offset - info->position);
862 if (len > 0) {
863 memcpy(info->buffer + info->position, data, len);
864 info->position += len;
866 } /* End tw_copy_mem_info() */
868 /* This function will print readable messages from status register errors */
869 int tw_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value, int print_host)
871 char host[16];
873 dprintk(KERN_WARNING "3w-xxxx: tw_decode_bits()\n");
875 if (print_host)
876 sprintf(host, " scsi%d:", tw_dev->host->host_no);
877 else
878 host[0] = '\0';
880 switch (status_reg_value & TW_STATUS_UNEXPECTED_BITS) {
881 case TW_STATUS_PCI_PARITY_ERROR:
882 printk(KERN_WARNING "3w-xxxx:%s PCI Parity Error: clearing.\n", host);
883 outl(TW_CONTROL_CLEAR_PARITY_ERROR, tw_dev->registers.control_reg_addr);
884 break;
885 case TW_STATUS_MICROCONTROLLER_ERROR:
886 if (tw_dev->reset_print == 0) {
887 printk(KERN_WARNING "3w-xxxx:%s Microcontroller Error: clearing.\n", host);
888 tw_dev->reset_print = 1;
890 return 1;
891 case TW_STATUS_PCI_ABORT:
892 printk(KERN_WARNING "3w-xxxx:%s PCI Abort: clearing.\n", host);
893 outl(TW_CONTROL_CLEAR_PCI_ABORT, tw_dev->registers.control_reg_addr);
894 pci_write_config_word(tw_dev->tw_pci_dev, PCI_STATUS, TW_PCI_CLEAR_PCI_ABORT);
895 break;
896 case TW_STATUS_QUEUE_ERROR:
897 printk(KERN_WARNING "3w-xxxx:%s Controller Queue Error: clearing.\n", host);
898 outl(TW_CONTROL_CLEAR_QUEUE_ERROR, tw_dev->registers.control_reg_addr);
899 break;
900 case TW_STATUS_SBUF_WRITE_ERROR:
901 printk(KERN_WARNING "3w-xxxx:%s SBUF Write Error: clearing.\n", host);
902 outl(TW_CONTROL_CLEAR_SBUF_WRITE_ERROR, tw_dev->registers.control_reg_addr);
903 break;
906 return 0;
907 } /* End tw_decode_bits() */
909 /* This function will return valid sense buffer information for failed cmds */
910 int tw_decode_sense(TW_Device_Extension *tw_dev, int request_id, int fill_sense)
912 int i;
913 TW_Command *command;
915 dprintk(KERN_WARNING "3w-xxxx: tw_decode_sense()\n");
916 command = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
918 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, command->byte3.unit);
920 /* Attempt to return intelligent sense information */
921 if (fill_sense) {
922 if ((command->status == 0xc7) || (command->status == 0xcb)) {
923 for (i=0;i<(sizeof(tw_sense_table)/sizeof(tw_sense_table[0]));i++) {
924 if (command->flags == tw_sense_table[i][0]) {
926 /* Valid bit and 'current errors' */
927 tw_dev->srb[request_id]->sense_buffer[0] = (0x1 << 7 | 0x70);
929 /* Sense key */
930 tw_dev->srb[request_id]->sense_buffer[2] = tw_sense_table[i][1];
932 /* Additional sense length */
933 tw_dev->srb[request_id]->sense_buffer[7] = 0xa; /* 10 bytes */
935 /* Additional sense code */
936 tw_dev->srb[request_id]->sense_buffer[12] = tw_sense_table[i][2];
938 /* Additional sense code qualifier */
939 tw_dev->srb[request_id]->sense_buffer[13] = tw_sense_table[i][3];
941 tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
942 return TW_ISR_DONT_RESULT; /* Special case for isr to not over-write result */
947 /* If no table match, error so we get a reset */
948 return 1;
951 return 0;
952 } /* End tw_decode_sense() */
954 /* This function will disable interrupts on the controller */
955 void tw_disable_interrupts(TW_Device_Extension *tw_dev)
957 u32 control_reg_value, control_reg_addr;
959 control_reg_addr = tw_dev->registers.control_reg_addr;
960 control_reg_value = TW_CONTROL_DISABLE_INTERRUPTS;
961 outl(control_reg_value, control_reg_addr);
962 } /* End tw_disable_interrupts() */
964 /* This function will empty the response que */
965 void tw_empty_response_que(TW_Device_Extension *tw_dev)
967 u32 status_reg_addr, status_reg_value;
968 u32 response_que_addr, response_que_value;
970 status_reg_addr = tw_dev->registers.status_reg_addr;
971 response_que_addr = tw_dev->registers.response_que_addr;
973 status_reg_value = inl(status_reg_addr);
975 while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
976 response_que_value = inl(response_que_addr);
977 status_reg_value = inl(status_reg_addr);
979 } /* End tw_empty_response_que() */
981 /* This function will enable interrupts on the controller */
982 void tw_enable_interrupts(TW_Device_Extension *tw_dev)
984 u32 control_reg_value, control_reg_addr;
986 control_reg_addr = tw_dev->registers.control_reg_addr;
987 control_reg_value = (TW_CONTROL_ENABLE_INTERRUPTS |
988 TW_CONTROL_UNMASK_RESPONSE_INTERRUPT);
989 outl(control_reg_value, control_reg_addr);
990 } /* End tw_enable_interrupts() */
992 /* This function will enable interrupts on the controller */
993 void tw_enable_and_clear_interrupts(TW_Device_Extension *tw_dev)
995 u32 control_reg_value, control_reg_addr;
997 control_reg_addr = tw_dev->registers.control_reg_addr;
998 control_reg_value = (TW_CONTROL_CLEAR_ATTENTION_INTERRUPT |
999 TW_CONTROL_UNMASK_RESPONSE_INTERRUPT |
1000 TW_CONTROL_ENABLE_INTERRUPTS);
1001 outl(control_reg_value, control_reg_addr);
1002 } /* End tw_enable_and_clear_interrupts() */
1004 /* This function will find and initialize all cards */
1005 int tw_findcards(Scsi_Host_Template *tw_host)
1007 int numcards = 0, tries = 0, error = 0;
1008 struct Scsi_Host *host;
1009 TW_Device_Extension *tw_dev;
1010 TW_Device_Extension *tw_dev2;
1011 struct pci_dev *tw_pci_dev = NULL;
1012 u32 status_reg_value;
1013 unsigned char c = 1;
1014 int i, j = -1;
1015 u16 device[TW_NUMDEVICES] = { TW_DEVICE_ID, TW_DEVICE_ID2 };
1017 dprintk(KERN_NOTICE "3w-xxxx: tw_findcards()\n");
1019 for (i=0;i<TW_NUMDEVICES;i++) {
1020 while ((tw_pci_dev = pci_find_device(TW_VENDOR_ID, device[i], tw_pci_dev))) {
1021 j++;
1022 if (pci_enable_device(tw_pci_dev))
1023 continue;
1025 /* We only need 32-bit addressing for 5,6,7xxx cards */
1026 if (pci_set_dma_mask(tw_pci_dev, 0xffffffff)) {
1027 printk(KERN_WARNING "3w-xxxx: No suitable DMA available.\n");
1028 continue;
1031 /* Prepare temporary device extension */
1032 tw_dev=(TW_Device_Extension *)kmalloc(sizeof(TW_Device_Extension), GFP_ATOMIC);
1033 if (tw_dev == NULL) {
1034 printk(KERN_WARNING "3w-xxxx: tw_findcards(): kmalloc() failed for card %d.\n", j);
1035 continue;
1037 memset(tw_dev, 0, sizeof(TW_Device_Extension));
1039 init_MUTEX(&tw_dev->ioctl_sem);
1041 /* Save pci_dev struct to device extension */
1042 tw_dev->tw_pci_dev = tw_pci_dev;
1044 error = tw_initialize_device_extension(tw_dev);
1045 if (error) {
1046 printk(KERN_WARNING "3w-xxxx: tw_findcards(): Couldn't initialize device extension for card %d.\n", j);
1047 tw_free_device_extension(tw_dev);
1048 kfree(tw_dev);
1049 continue;
1052 /* Calculate the cards register addresses */
1053 tw_dev->registers.base_addr = pci_resource_start(tw_pci_dev, 0);
1054 tw_dev->registers.control_reg_addr = pci_resource_start(tw_pci_dev, 0);
1055 tw_dev->registers.status_reg_addr = pci_resource_start(tw_pci_dev, 0) + 0x4;
1056 tw_dev->registers.command_que_addr = pci_resource_start(tw_pci_dev, 0) + 0x8;
1057 tw_dev->registers.response_que_addr = pci_resource_start(tw_pci_dev, 0) + 0xC;
1059 /* Check for errors and clear them */
1060 status_reg_value = inl(tw_dev->registers.status_reg_addr);
1061 if (TW_STATUS_ERRORS(status_reg_value))
1062 tw_decode_bits(tw_dev, status_reg_value, 0);
1064 /* Poll status register for 60 secs for 'Controller Ready' flag */
1065 if (tw_poll_status(tw_dev, TW_STATUS_MICROCONTROLLER_READY, 60)) {
1066 printk(KERN_WARNING "3w-xxxx: tw_findcards(): Microcontroller not ready for card %d.\n", j);
1067 tw_free_device_extension(tw_dev);
1068 kfree(tw_dev);
1069 continue;
1072 /* Disable interrupts on the card */
1073 tw_disable_interrupts(tw_dev);
1075 tries = 0;
1077 while (tries < TW_MAX_RESET_TRIES) {
1078 /* Do soft reset */
1079 tw_soft_reset(tw_dev);
1081 error = tw_aen_drain_queue(tw_dev);
1082 if (error) {
1083 printk(KERN_WARNING "3w-xxxx: AEN drain failed for card %d.\n", j);
1084 tries++;
1085 continue;
1088 /* Check for controller errors */
1089 if (tw_check_errors(tw_dev)) {
1090 printk(KERN_WARNING "3w-xxxx: Controller errors found, retrying for card %d.\n", j);
1091 tries++;
1092 continue;
1095 /* Now the controller is in a good state */
1096 break;
1099 if (tries >= TW_MAX_RESET_TRIES) {
1100 printk(KERN_WARNING "3w-xxxx: Controller errors, card not responding, check all cabling for card %d.\n", j);
1101 tw_free_device_extension(tw_dev);
1102 kfree(tw_dev);
1103 continue;
1106 /* Reserve the io address space */
1107 if (!request_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE, TW_DEVICE_NAME)) {
1108 printk(KERN_WARNING "3w-xxxx: tw_findcards(): Couldn't get io range 0x%lx-0x%lx for card %d.\n",
1109 (tw_dev->tw_pci_dev->resource[0].start),
1110 (tw_dev->tw_pci_dev->resource[0].start) +
1111 TW_IO_ADDRESS_RANGE, j);
1112 tw_free_device_extension(tw_dev);
1113 kfree(tw_dev);
1114 continue;
1117 error = tw_initialize_units(tw_dev);
1118 if (error) {
1119 printk(KERN_WARNING "3w-xxxx: No valid units for for card %d.\n", j);
1122 error = tw_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS);
1123 if (error) {
1124 printk(KERN_WARNING "3w-xxxx: Connection initialization failed for card %d.\n", j);
1125 release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE);
1126 tw_free_device_extension(tw_dev);
1127 kfree(tw_dev);
1128 continue;
1131 /* Set card status as online */
1132 tw_dev->online = 1;
1134 /* Calculate max cmds per lun, and setup queues */
1135 if (tw_dev->num_units > 0) {
1136 /* Use SHT cmd_per_lun here */
1137 tw_dev->free_head = TW_Q_START;
1138 tw_dev->free_tail = TW_Q_START;
1139 tw_dev->free_wrap = TW_Q_LENGTH - 1;
1142 /* Register the card with the kernel SCSI layer */
1143 host = scsi_register(tw_host, sizeof(TW_Device_Extension));
1144 if (host == NULL) {
1145 printk(KERN_WARNING "3w-xxxx: tw_findcards(): scsi_register() failed for card %d.\n", j);
1146 release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE);
1147 tw_free_device_extension(tw_dev);
1148 kfree(tw_dev);
1149 continue;
1152 /* Set max target id's */
1153 host->max_id = TW_MAX_UNITS;
1155 /* Set max cdb size in bytes */
1156 host->max_cmd_len = 16;
1158 /* Set max sectors per io */
1159 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
1160 host->max_sectors = TW_MAX_SECTORS;
1161 #endif
1163 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
1164 scsi_set_device(host, &tw_pci_dev->dev);
1165 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4)
1166 scsi_set_pci_device(host, tw_pci_dev);
1167 #endif
1169 status_reg_value = inl(tw_dev->registers.status_reg_addr);
1171 printk(KERN_NOTICE "scsi%d : Found a 3ware Storage Controller at 0x%x, IRQ: %d, P-chip: %d.%d\n", host->host_no,
1172 (u32)(tw_pci_dev->resource[0].start), tw_pci_dev->irq,
1173 (status_reg_value & TW_STATUS_MAJOR_VERSION_MASK) >> 28,
1174 (status_reg_value & TW_STATUS_MINOR_VERSION_MASK) >> 24);
1176 if (host->hostdata) {
1177 tw_dev2 = (TW_Device_Extension *)host->hostdata;
1178 memcpy(tw_dev2, tw_dev, sizeof(TW_Device_Extension));
1179 tw_device_extension_list[tw_device_extension_count] = tw_dev2;
1180 numcards++;
1181 tw_device_extension_count = numcards;
1182 tw_dev2->host = host;
1183 } else {
1184 printk(KERN_WARNING "3w-xxxx: tw_findcards(): Bad scsi host data for card %d.\n", j);
1185 scsi_unregister(host);
1186 release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE);
1187 tw_free_device_extension(tw_dev);
1188 kfree(tw_dev);
1189 continue;
1192 /* Tell the firmware we support shutdown notification*/
1193 error = tw_setfeature(tw_dev2, 2, 1, &c);
1194 if (error) {
1195 printk(KERN_WARNING "3w-xxxx: Unable to set features for card %d, old firmware or card.\n", j);
1198 /* Now setup the interrupt handler */
1199 error = tw_setup_irq(tw_dev2);
1200 if (error) {
1201 printk(KERN_WARNING "3w-xxxx: tw_findcards(): Error requesting irq for card %d.\n", j);
1202 scsi_unregister(host);
1203 release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE);
1205 tw_free_device_extension(tw_dev);
1206 kfree(tw_dev);
1207 numcards--;
1208 continue;
1211 /* Re-enable interrupts on the card */
1212 tw_enable_interrupts(tw_dev2);
1214 /* Free the temporary device extension */
1215 if (tw_dev)
1216 kfree(tw_dev);
1220 if (numcards == 0) {
1221 printk(KERN_WARNING "3w-xxxx: No cards found.\n");
1222 } else {
1223 register_reboot_notifier(&tw_notifier);
1224 if ((twe_major = register_chrdev (0, "twe", &tw_fops)) < 0) {
1225 printk(KERN_WARNING "3w-xxxx: Unable to register \"twe\" character device, error = %d.\n", twe_major);
1229 return numcards;
1230 } /* End tw_findcards() */
1232 /* This function will free up device extension resources */
1233 void tw_free_device_extension(TW_Device_Extension *tw_dev)
1235 int i;
1237 dprintk(KERN_NOTICE "3w-xxxx: tw_free_device_extension()\n");
1238 /* Free command packet and generic buffer memory */
1239 for (i=0;i<TW_Q_LENGTH;i++) {
1240 if (tw_dev->command_packet_virtual_address[i])
1241 pci_free_consistent(tw_dev->tw_pci_dev, sizeof(TW_Sector), tw_dev->command_packet_virtual_address[i], tw_dev->command_packet_physical_address[i]);
1243 if (tw_dev->alignment_virtual_address[i])
1244 pci_free_consistent(tw_dev->tw_pci_dev, sizeof(TW_Sector), tw_dev->alignment_virtual_address[i], tw_dev->alignment_physical_address[i]);
1246 } /* End tw_free_device_extension() */
1248 /* Clean shutdown routine */
1249 static int tw_halt(struct notifier_block *nb, ulong event, void *buf)
1251 int i;
1253 for (i=0;i<tw_device_extension_count;i++) {
1254 if (tw_device_extension_list[i]->online == 1) {
1255 printk(KERN_NOTICE "3w-xxxx: Shutting down card %d.\n", i);
1256 tw_shutdown_device(tw_device_extension_list[i]);
1257 tw_device_extension_list[i]->online = 0;
1260 unregister_reboot_notifier(&tw_notifier);
1262 return NOTIFY_OK;
1263 } /* End tw_halt() */
1265 /* This function will send an initconnection command to controller */
1266 int tw_initconnection(TW_Device_Extension *tw_dev, int message_credits)
1268 unsigned long command_que_value;
1269 u32 command_que_addr;
1270 u32 response_que_addr;
1271 TW_Command *command_packet;
1272 TW_Response_Queue response_queue;
1273 int request_id = 0;
1275 dprintk(KERN_NOTICE "3w-xxxx: tw_initconnection()\n");
1276 command_que_addr = tw_dev->registers.command_que_addr;
1277 response_que_addr = tw_dev->registers.response_que_addr;
1279 /* Initialize InitConnection command packet */
1280 if (tw_dev->command_packet_virtual_address[request_id] == NULL) {
1281 printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad command packet virtual address.\n");
1282 return 1;
1285 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
1286 memset(command_packet, 0, sizeof(TW_Sector));
1287 command_packet->byte0.opcode = TW_OP_INIT_CONNECTION;
1288 command_packet->byte0.sgl_offset = 0x0;
1289 command_packet->size = TW_INIT_COMMAND_PACKET_SIZE;
1290 command_packet->request_id = request_id;
1291 command_packet->byte3.unit = 0x0;
1292 command_packet->byte3.host_id = 0x0;
1293 command_packet->status = 0x0;
1294 command_packet->flags = 0x0;
1295 command_packet->byte6.message_credits = message_credits;
1296 command_packet->byte8.init_connection.response_queue_pointer = 0x0;
1297 command_que_value = tw_dev->command_packet_physical_address[request_id];
1299 if (command_que_value == 0) {
1300 printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad command packet physical address.\n");
1301 return 1;
1304 /* Send command packet to the board */
1305 outl(command_que_value, command_que_addr);
1307 /* Poll for completion */
1308 if (tw_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, 30) == 0) {
1309 response_queue.value = inl(response_que_addr);
1310 request_id = (unsigned char)response_queue.u.response_id;
1311 if (request_id != 0) {
1312 /* unexpected request id */
1313 printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Unexpected request id.\n");
1314 return 1;
1316 if (command_packet->status != 0) {
1317 /* bad response */
1318 tw_decode_sense(tw_dev, request_id, 0);
1319 return 1;
1322 return 0;
1323 } /* End tw_initconnection() */
1325 /* This function will initialize the fields of a device extension */
1326 int tw_initialize_device_extension(TW_Device_Extension *tw_dev)
1328 int i, error=0;
1330 dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_device_extension()\n");
1332 /* Initialize command packet buffers */
1333 error = tw_allocate_memory(tw_dev, sizeof(TW_Command), 0);
1334 if (error) {
1335 printk(KERN_WARNING "3w-xxxx: Command packet memory allocation failed.\n");
1336 return 1;
1339 /* Initialize generic buffer */
1340 error = tw_allocate_memory(tw_dev, sizeof(TW_Sector), 1);
1341 if (error) {
1342 printk(KERN_WARNING "3w-xxxx: Generic memory allocation failed.\n");
1343 return 1;
1346 for (i=0;i<TW_Q_LENGTH;i++) {
1347 tw_dev->free_queue[i] = i;
1348 tw_dev->state[i] = TW_S_INITIAL;
1351 tw_dev->pending_head = TW_Q_START;
1352 tw_dev->pending_tail = TW_Q_START;
1353 spin_lock_init(&tw_dev->tw_lock);
1354 tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
1355 init_waitqueue_head(&tw_dev->ioctl_wqueue);
1357 return 0;
1358 } /* End tw_initialize_device_extension() */
1360 /* This function will get unit info from the controller */
1361 int tw_initialize_units(TW_Device_Extension *tw_dev)
1363 int found = 0;
1364 unsigned char request_id = 0;
1365 TW_Command *command_packet;
1366 TW_Param *param;
1367 int i, imax, num_units = 0;
1368 unsigned long command_que_value;
1369 u32 command_que_addr;
1370 u32 response_que_addr;
1371 TW_Response_Queue response_queue;
1372 unsigned long param_value;
1373 unsigned char *is_unit_present;
1375 dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_units()\n");
1377 command_que_addr = tw_dev->registers.command_que_addr;
1378 response_que_addr = tw_dev->registers.response_que_addr;
1380 /* Setup the command packet */
1381 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
1382 if (command_packet == NULL) {
1383 printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad command packet virtual address.\n");
1384 return 1;
1386 memset(command_packet, 0, sizeof(TW_Sector));
1387 command_packet->byte0.opcode = TW_OP_GET_PARAM;
1388 command_packet->byte0.sgl_offset = 2;
1389 command_packet->size = 4;
1390 command_packet->request_id = request_id;
1391 command_packet->byte3.unit = 0;
1392 command_packet->byte3.host_id = 0;
1393 command_packet->status = 0;
1394 command_packet->flags = 0;
1395 command_packet->byte6.block_count = 1;
1397 /* Now setup the param */
1398 if (tw_dev->alignment_virtual_address[request_id] == NULL) {
1399 printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad alignment virtual address.\n");
1400 return 1;
1402 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
1403 memset(param, 0, sizeof(TW_Sector));
1404 param->table_id = 3; /* unit summary table */
1405 param->parameter_id = 3; /* unitstatus parameter */
1406 param->parameter_size_bytes = TW_MAX_UNITS;
1407 param_value = tw_dev->alignment_physical_address[request_id];
1408 if (param_value == 0) {
1409 printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad alignment physical address.\n");
1410 return 1;
1413 command_packet->byte8.param.sgl[0].address = param_value;
1414 command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
1416 /* Post the command packet to the board */
1417 command_que_value = tw_dev->command_packet_physical_address[request_id];
1418 if (command_que_value == 0) {
1419 printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad command packet physical address.\n");
1420 return 1;
1422 outl(command_que_value, command_que_addr);
1424 /* Poll for completion */
1425 if (tw_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, 30) == 0) {
1426 response_queue.value = inl(response_que_addr);
1427 request_id = (unsigned char)response_queue.u.response_id;
1428 if (request_id != 0) {
1429 /* unexpected request id */
1430 printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected request id.\n");
1431 return 1;
1433 if (command_packet->status != 0) {
1434 /* bad response */
1435 tw_decode_sense(tw_dev, request_id, 0);
1436 return 1;
1438 found = 1;
1440 if (found == 0) {
1441 /* response never received */
1442 printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): No response.\n");
1443 return 1;
1446 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
1447 is_unit_present = (unsigned char *)&(param->data[0]);
1449 /* Show all units present */
1450 imax = TW_MAX_UNITS;
1451 for(i=0; i<imax; i++) {
1452 if (is_unit_present[i] == 0) {
1453 tw_dev->is_unit_present[i] = FALSE;
1454 } else {
1455 if (is_unit_present[i] & TW_UNIT_ONLINE) {
1456 dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_units(): Unit %d found.\n", i);
1457 tw_dev->is_unit_present[i] = TRUE;
1458 num_units++;
1462 tw_dev->num_units = num_units;
1464 if (num_units == 0) {
1465 dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_units(): No units found.\n");
1466 return 1;
1469 return 0;
1470 } /* End tw_initialize_units() */
1472 /* This function is the interrupt service routine */
1473 static irqreturn_t tw_interrupt(int irq, void *dev_instance,
1474 struct pt_regs *regs)
1476 int request_id;
1477 u32 status_reg_addr, status_reg_value;
1478 u32 response_que_addr;
1479 TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance;
1480 TW_Response_Queue response_que;
1481 int error = 0, retval = 0;
1482 unsigned long flags = 0;
1483 TW_Command *command_packet;
1484 int handled = 0;
1486 dprintk(KERN_WARNING "3w-xxxx: tw_interrupt()\n");
1488 /* See if we are already running on another processor */
1489 if (test_and_set_bit(TW_IN_INTR, &tw_dev->flags))
1490 return IRQ_NONE;
1492 /* Get the host lock for io completions */
1493 spin_lock_irqsave(tw_dev->host->host_lock, flags);
1495 /* See if the interrupt matches this instance */
1496 if (tw_dev->tw_pci_dev->irq == irq) {
1498 handled = 1;
1499 /* Make sure io isn't queueing */
1500 spin_lock(&tw_dev->tw_lock);
1502 /* Read the registers */
1503 status_reg_addr = tw_dev->registers.status_reg_addr;
1504 response_que_addr = tw_dev->registers.response_que_addr;
1505 status_reg_value = inl(status_reg_addr);
1507 /* Check if this is our interrupt, otherwise bail */
1508 if (!(status_reg_value & TW_STATUS_VALID_INTERRUPT))
1509 goto tw_interrupt_bail;
1511 /* Check controller for errors */
1512 if (tw_check_bits(status_reg_value)) {
1513 dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
1514 if (tw_decode_bits(tw_dev, status_reg_value, 1)) {
1515 tw_clear_all_interrupts(tw_dev);
1516 goto tw_interrupt_bail;
1520 /* Handle host interrupt */
1521 if (status_reg_value & TW_STATUS_HOST_INTERRUPT) {
1522 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received host interrupt.\n");
1523 tw_clear_host_interrupt(tw_dev);
1526 /* Handle attention interrupt */
1527 if (status_reg_value & TW_STATUS_ATTENTION_INTERRUPT) {
1528 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received attention interrupt.\n");
1529 tw_clear_attention_interrupt(tw_dev);
1530 tw_state_request_start(tw_dev, &request_id);
1531 error = tw_aen_read_queue(tw_dev, request_id);
1532 if (error) {
1533 printk(KERN_WARNING "3w-xxxx: scsi%d: Error reading aen queue.\n", tw_dev->host->host_no);
1534 tw_dev->state[request_id] = TW_S_COMPLETED;
1535 tw_state_request_finish(tw_dev, request_id);
1539 /* Handle command interrupt */
1540 if (status_reg_value & TW_STATUS_COMMAND_INTERRUPT) {
1541 /* Drain as many pending commands as we can */
1542 while (tw_dev->pending_request_count > 0) {
1543 request_id = tw_dev->pending_queue[tw_dev->pending_head];
1544 if (tw_dev->state[request_id] != TW_S_PENDING) {
1545 printk(KERN_WARNING "3w-xxxx: scsi%d: Found request id that wasn't pending.\n", tw_dev->host->host_no);
1546 break;
1548 if (tw_post_command_packet(tw_dev, request_id)==0) {
1549 if (tw_dev->pending_head == TW_Q_LENGTH-1) {
1550 tw_dev->pending_head = TW_Q_START;
1551 } else {
1552 tw_dev->pending_head = tw_dev->pending_head + 1;
1554 tw_dev->pending_request_count--;
1555 } else {
1556 /* If we get here, we will continue re-posting on the next command interrupt */
1557 break;
1560 /* If there are no more pending requests, we mask command interrupt */
1561 if (tw_dev->pending_request_count == 0)
1562 tw_mask_command_interrupt(tw_dev);
1565 /* Handle response interrupt */
1566 if (status_reg_value & TW_STATUS_RESPONSE_INTERRUPT) {
1567 /* Drain the response queue from the board */
1568 while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
1569 /* Read response queue register */
1570 response_que.value = inl(response_que_addr);
1571 request_id = response_que.u.response_id;
1572 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
1573 error = 0;
1575 /* Check for bad response */
1576 if (command_packet->status != 0) {
1577 /* If internal command, don't error, don't fill sense */
1578 if (tw_dev->srb[request_id] == 0) {
1579 tw_decode_sense(tw_dev, request_id, 0);
1580 } else {
1581 error = tw_decode_sense(tw_dev, request_id, 1);
1585 /* Check for correct state */
1586 if (tw_dev->state[request_id] != TW_S_POSTED) {
1587 /* Handle timed out ioctl's */
1588 if (tw_dev->srb[request_id] != 0) {
1589 if (tw_dev->srb[request_id]->cmnd[0] != TW_IOCTL) {
1590 printk(KERN_WARNING "3w-xxxx: scsi%d: Received a request id (%d) (opcode = 0x%x) that wasn't posted.\n", tw_dev->host->host_no, request_id, command_packet->byte0.opcode);
1591 error = 1;
1596 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Response queue request id: %d.\n", request_id);
1598 /* Check for internal command completion */
1599 if (tw_dev->srb[request_id] == 0) {
1600 dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found internally posted command.\n");
1601 /* Check for chrdev ioctl completion */
1602 if (request_id != tw_dev->chrdev_request_id) {
1603 retval = tw_aen_complete(tw_dev, request_id);
1604 if (retval) {
1605 printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing aen.\n", tw_dev->host->host_no);
1607 } else {
1608 tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
1610 } else {
1611 switch (tw_dev->srb[request_id]->cmnd[0]) {
1612 case READ_10:
1613 case READ_6:
1614 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_10/READ_6\n");
1615 break;
1616 case WRITE_10:
1617 case WRITE_6:
1618 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_10/WRITE_6\n");
1619 break;
1620 case TEST_UNIT_READY:
1621 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught TEST_UNIT_READY\n");
1622 error = tw_scsiop_test_unit_ready_complete(tw_dev, request_id);
1623 break;
1624 case INQUIRY:
1625 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught INQUIRY\n");
1626 error = tw_scsiop_inquiry_complete(tw_dev, request_id);
1627 break;
1628 case READ_CAPACITY:
1629 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_CAPACITY\n");
1630 error = tw_scsiop_read_capacity_complete(tw_dev, request_id);
1631 break;
1632 case MODE_SENSE:
1633 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught MODE_SENSE\n");
1634 error = tw_scsiop_mode_sense_complete(tw_dev, request_id);
1635 break;
1636 case SYNCHRONIZE_CACHE:
1637 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught SYNCHRONIZE_CACHE\n");
1638 break;
1639 case TW_IOCTL:
1640 dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught TW_IOCTL\n");
1641 error = tw_ioctl_complete(tw_dev, request_id);
1642 break;
1643 default:
1644 printk(KERN_WARNING "3w-xxxx: case slip in tw_interrupt()\n");
1645 error = 1;
1648 /* If no error command was a success */
1649 if (error == 0) {
1650 tw_dev->srb[request_id]->result = (DID_OK << 16);
1653 /* If error, command failed */
1654 if (error == 1) {
1655 /* Ask for a host reset */
1656 tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
1659 /* Now complete the io */
1660 if ((error != TW_ISR_DONT_COMPLETE)) {
1661 tw_dev->state[request_id] = TW_S_COMPLETED;
1662 tw_state_request_finish(tw_dev, request_id);
1663 tw_dev->posted_request_count--;
1664 tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
1666 tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
1670 /* Check for valid status after each drain */
1671 status_reg_value = inl(status_reg_addr);
1672 if (tw_check_bits(status_reg_value)) {
1673 dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
1674 if (tw_decode_bits(tw_dev, status_reg_value, 1)) {
1675 tw_clear_all_interrupts(tw_dev);
1676 goto tw_interrupt_bail;
1681 tw_interrupt_bail:
1682 spin_unlock(&tw_dev->tw_lock);
1683 } else
1684 dprintk(KERN_WARNING "3w-xxxx: tw_interrupt() called for wrong instance.\n");
1686 spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
1687 clear_bit(TW_IN_INTR, &tw_dev->flags);
1688 return IRQ_RETVAL(handled);
1689 } /* End tw_interrupt() */
1691 /* This function handles ioctls from userspace to the driver */
1692 int tw_ioctl(TW_Device_Extension *tw_dev, int request_id)
1694 unsigned char opcode;
1695 int bufflen, error = 0;
1696 TW_Param *param;
1697 TW_Command *command_packet, *command_save;
1698 unsigned long param_value;
1699 TW_Ioctl *ioctl = NULL;
1700 TW_Passthru *passthru = NULL;
1701 int tw_aen_code, i, use_sg;
1702 unsigned long *data_ptr;
1703 int total_bytes = 0, posted = 0;
1704 dma_addr_t dma_handle;
1705 struct timeval before, timeout;
1707 ioctl = (TW_Ioctl *)tw_dev->srb[request_id]->request_buffer;
1708 if (ioctl == NULL) {
1709 printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Request buffer NULL.\n");
1710 tw_dev->state[request_id] = TW_S_COMPLETED;
1711 tw_state_request_finish(tw_dev, request_id);
1712 tw_dev->srb[request_id]->result = (DID_OK << 16);
1713 tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
1714 return 0;
1716 bufflen = tw_dev->srb[request_id]->request_bufflen;
1718 /* Initialize command packet */
1719 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
1720 if (command_packet == NULL) {
1721 printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Bad command packet virtual address.\n");
1722 tw_dev->state[request_id] = TW_S_COMPLETED;
1723 tw_state_request_finish(tw_dev, request_id);
1724 tw_dev->srb[request_id]->result = (DID_OK << 16);
1725 tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
1726 return 0;
1728 memset(command_packet, 0, sizeof(TW_Sector));
1730 /* Initialize param */
1731 if (tw_dev->alignment_virtual_address[request_id] == NULL) {
1732 printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Bad alignment virtual address.\n");
1733 tw_dev->state[request_id] = TW_S_COMPLETED;
1734 tw_state_request_finish(tw_dev, request_id);
1735 tw_dev->srb[request_id]->result = (DID_OK << 16);
1736 tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
1737 return 0;
1739 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
1740 memset(param, 0, sizeof(TW_Sector));
1742 dprintk(KERN_NOTICE "opcode = %d table_id = %d parameter_id = %d parameter_size_bytes = %d\n", ioctl->opcode, ioctl->table_id, ioctl->parameter_id, ioctl->parameter_size_bytes);
1743 opcode = ioctl->opcode;
1745 switch (opcode) {
1746 case TW_OP_NOP:
1747 dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_NOP.\n");
1748 command_packet->byte0.opcode = TW_OP_NOP;
1749 break;
1750 case TW_OP_GET_PARAM:
1751 dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_GET_PARAM.\n");
1752 command_packet->byte0.opcode = TW_OP_GET_PARAM;
1753 command_packet->byte3.unit = ioctl->unit_index;
1754 param->table_id = ioctl->table_id;
1755 param->parameter_id = ioctl->parameter_id;
1756 param->parameter_size_bytes = ioctl->parameter_size_bytes;
1757 tw_dev->ioctl_size[request_id] = ioctl->parameter_size_bytes;
1758 dprintk(KERN_NOTICE "table_id = %d parameter_id = %d parameter_size_bytes %d\n", param->table_id, param->parameter_id, param->parameter_size_bytes);
1759 break;
1760 case TW_OP_SET_PARAM:
1761 dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_SET_PARAM: table_id = %d, parameter_id = %d, parameter_size_bytes = %d.\n",
1762 ioctl->table_id, ioctl->parameter_id, ioctl->parameter_size_bytes);
1763 if (ioctl->data != NULL) {
1764 command_packet->byte0.opcode = TW_OP_SET_PARAM;
1765 param->table_id = ioctl->table_id;
1766 param->parameter_id = ioctl->parameter_id;
1767 param->parameter_size_bytes = ioctl->parameter_size_bytes;
1768 memcpy(param->data, ioctl->data, ioctl->parameter_size_bytes);
1769 break;
1770 } else {
1771 printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n");
1772 return 1;
1774 case TW_OP_AEN_LISTEN:
1775 dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_AEN_LISTEN.\n");
1776 if (tw_dev->aen_head == tw_dev->aen_tail) {
1777 /* aen queue empty */
1778 dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): Aen queue empty.\n");
1779 tw_aen_code = TW_AEN_QUEUE_EMPTY;
1780 memcpy(tw_dev->srb[request_id]->request_buffer, &tw_aen_code, ioctl->parameter_size_bytes);
1781 } else {
1782 /* Copy aen queue entry to request buffer */
1783 dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): Returning aen 0x%x\n", tw_dev->aen_queue[tw_dev->aen_head]);
1784 tw_aen_code = tw_dev->aen_queue[tw_dev->aen_head];
1785 memcpy(tw_dev->srb[request_id]->request_buffer, &tw_aen_code, ioctl->parameter_size_bytes);
1786 if (tw_dev->aen_head == TW_Q_LENGTH - 1) {
1787 tw_dev->aen_head = TW_Q_START;
1788 } else {
1789 tw_dev->aen_head = tw_dev->aen_head + 1;
1792 tw_dev->state[request_id] = TW_S_COMPLETED;
1793 tw_state_request_finish(tw_dev, request_id);
1794 tw_dev->srb[request_id]->result = (DID_OK << 16);
1795 tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
1796 return 0;
1797 case TW_ATA_PASSTHRU:
1798 if (ioctl->data != NULL) {
1799 memcpy(command_packet, ioctl->data, sizeof(TW_Command));
1800 command_packet->request_id = request_id;
1801 } else {
1802 printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n");
1803 return 1;
1806 passthru = (TW_Passthru *)tw_dev->command_packet_virtual_address[request_id];
1807 passthru->sg_list[0].length = passthru->sector_count*512;
1808 if (passthru->sg_list[0].length > TW_MAX_PASSTHRU_BYTES) {
1809 printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Passthru size (%d) too big.\n", passthru->sg_list[0].length);
1810 return 1;
1812 passthru->sg_list[0].address = tw_dev->alignment_physical_address[request_id];
1813 tw_post_command_packet(tw_dev, request_id);
1814 return 0;
1815 case TW_CMD_PACKET:
1816 dprintk(KERN_WARNING "3w-xxxx: tw_ioctl(): caught TW_CMD_PACKET.\n");
1817 if (ioctl->data != NULL) {
1818 memcpy(command_packet, ioctl->data, sizeof(TW_Command));
1819 command_packet->request_id = request_id;
1820 tw_post_command_packet(tw_dev, request_id);
1821 return 0;
1822 } else {
1823 printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n");
1824 return 1;
1826 case TW_CMD_PACKET_WITH_DATA:
1827 dprintk(KERN_WARNING "3w-xxxx: tw_ioctl(): caught TW_CMD_PACKET_WITH_DATA.\n");
1828 command_save = (TW_Command *)tw_dev->alignment_virtual_address[request_id];
1829 if (command_save == NULL) {
1830 printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad alignment virtual address.\n", tw_dev->host->host_no);
1831 return 1;
1833 if (ioctl->data != NULL) {
1834 /* Copy down the command packet */
1835 memcpy(command_packet, ioctl->data, sizeof(TW_Command));
1836 memcpy(command_save, ioctl->data, sizeof(TW_Command));
1837 command_packet->request_id = request_id;
1839 /* Now deal with the two possible sglists */
1840 if (command_packet->byte0.sgl_offset == 2) {
1841 use_sg = command_packet->size - 3;
1842 for (i=0;i<use_sg;i++)
1843 total_bytes+=command_packet->byte8.param.sgl[i].length;
1844 tw_dev->ioctl_data[request_id] = pci_alloc_consistent(tw_dev->tw_pci_dev, total_bytes, &dma_handle);
1846 if (!tw_dev->ioctl_data[request_id]) {
1847 printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): pci_alloc_consistent() failed for request_id %d.\n", tw_dev->host->host_no, request_id);
1848 return 1;
1851 /* Copy param sglist into the kernel */
1852 data_ptr = tw_dev->ioctl_data[request_id];
1853 for (i=0;i<use_sg;i++) {
1854 if (command_packet->byte8.param.sgl[i].address != 0) {
1855 error = copy_from_user(data_ptr, (void *)(unsigned long)command_packet->byte8.param.sgl[i].address, command_packet->byte8.param.sgl[i].length);
1856 if (error) {
1857 dprintk(KERN_WARNING "3w-xxxx: scsi%d: Error copying param sglist from userspace.\n", tw_dev->host->host_no);
1858 goto tw_ioctl_bail;
1860 } else {
1861 printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad param sgl address.\n", tw_dev->host->host_no);
1862 tw_dev->srb[request_id]->result = (DID_RESET << 16);
1863 goto tw_ioctl_bail;
1865 data_ptr+=command_packet->byte8.param.sgl[i].length;
1867 command_packet->size = 4;
1868 command_packet->byte8.param.sgl[0].address = dma_handle;
1869 command_packet->byte8.param.sgl[0].length = total_bytes;
1871 if (command_packet->byte0.sgl_offset == 3) {
1872 use_sg = command_packet->size - 4;
1873 for (i=0;i<use_sg;i++)
1874 total_bytes+=command_packet->byte8.io.sgl[i].length;
1875 tw_dev->ioctl_data[request_id] = pci_alloc_consistent(tw_dev->tw_pci_dev, total_bytes, &dma_handle);
1877 if (!tw_dev->ioctl_data[request_id]) {
1878 printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): pci_alloc_consistent() failed for request_id %d.\n", tw_dev->host->host_no, request_id);
1879 return 1;
1881 if (command_packet->byte0.opcode == TW_OP_WRITE) {
1882 /* Copy io sglist into the kernel */
1883 data_ptr = tw_dev->ioctl_data[request_id];
1884 for (i=0;i<use_sg;i++) {
1885 if (command_packet->byte8.io.sgl[i].address != 0) {
1886 error = copy_from_user(data_ptr, (void *)(unsigned long)command_packet->byte8.io.sgl[i].address, command_packet->byte8.io.sgl[i].length);
1887 if (error) {
1888 dprintk(KERN_WARNING "3w-xxxx: scsi%d: Error copying io sglist from userspace.\n", tw_dev->host->host_no);
1889 goto tw_ioctl_bail;
1891 } else {
1892 printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad io sgl address.\n", tw_dev->host->host_no);
1893 tw_dev->srb[request_id]->result = (DID_RESET << 16);
1894 goto tw_ioctl_bail;
1896 data_ptr+=command_packet->byte8.io.sgl[i].length;
1899 command_packet->size = 5;
1900 command_packet->byte8.io.sgl[0].address = dma_handle;
1901 command_packet->byte8.io.sgl[0].length = total_bytes;
1904 spin_unlock(&tw_dev->tw_lock);
1905 spin_unlock_irq(tw_dev->host->host_lock);
1907 set_bit(TW_IN_IOCTL, &tw_dev->flags);
1909 /* Finally post the command packet */
1910 tw_post_command_packet(tw_dev, request_id);
1911 posted = 1;
1912 do_gettimeofday(&before);
1914 tw_ioctl_retry:
1915 mdelay(TW_IOCTL_WAIT_TIME);
1916 if (test_bit(TW_IN_IOCTL, &tw_dev->flags)) {
1917 do_gettimeofday(&timeout);
1918 if (before.tv_sec + TW_IOCTL_TIMEOUT < timeout.tv_sec) {
1919 spin_lock_irq(tw_dev->host->host_lock);
1920 spin_lock(&tw_dev->tw_lock);
1921 goto tw_ioctl_bail;
1922 } else {
1923 goto tw_ioctl_retry;
1927 spin_lock_irq(tw_dev->host->host_lock);
1928 spin_lock(&tw_dev->tw_lock);
1930 if (signal_pending(current)) {
1931 dprintk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Signal pending, aborting ioctl().\n", tw_dev->host->host_no);
1932 tw_dev->srb[request_id]->result = (DID_OK << 16);
1933 goto tw_ioctl_bail;
1936 tw_dev->srb[request_id]->result = (DID_OK << 16);
1937 /* Now copy up the param or io sglist to userspace */
1938 if (command_packet->byte0.sgl_offset == 2) {
1939 use_sg = command_save->size - 3;
1940 data_ptr = tw_dev->ioctl_data[request_id];
1941 for (i=0;i<use_sg;i++) {
1942 if (command_save->byte8.param.sgl[i].address != 0) {
1943 error = copy_to_user((void *)(unsigned long)command_save->byte8.param.sgl[i].address, data_ptr, command_save->byte8.param.sgl[i].length);
1944 if (error) {
1945 dprintk(KERN_WARNING "3w-xxxx: scsi%d: Error copying param sglist to userspace.\n", tw_dev->host->host_no);
1946 goto tw_ioctl_bail;
1948 dprintk(KERN_WARNING "3w-xxxx: scsi%d: Copied %ld bytes to pid %d.\n", tw_dev->host->host_no, command_save->byte8.param.sgl[i].length, current->pid);
1949 data_ptr+=command_save->byte8.param.sgl[i].length;
1950 } else {
1951 printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad param sgl address.\n", tw_dev->host->host_no);
1952 tw_dev->srb[request_id]->result = (DID_RESET << 16);
1953 goto tw_ioctl_bail;
1957 if (command_packet->byte0.sgl_offset == 3) {
1958 use_sg = command_save->size - 4;
1959 if (command_packet->byte0.opcode == TW_OP_READ) {
1960 data_ptr = tw_dev->ioctl_data[request_id];
1961 for(i=0;i<use_sg;i++) {
1962 if (command_save->byte8.io.sgl[i].address != 0) {
1963 error = copy_to_user((void *)(unsigned long)command_save->byte8.io.sgl[i].address, data_ptr, command_save->byte8.io.sgl[i].length);
1964 if (error) {
1965 dprintk(KERN_WARNING "3w-xxxx: scsi%d: Error copying io sglist to userspace.\n", tw_dev->host->host_no);
1966 goto tw_ioctl_bail;
1968 dprintk(KERN_WARNING "3w-xxxx: scsi%d: Copied %ld bytes to pid %d.\n", tw_dev->host->host_no, command_save->byte8.io.sgl[i].length, current->pid);
1969 data_ptr+=command_save->byte8.io.sgl[i].length;
1970 } else {
1971 printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad io sgl address.\n", tw_dev->host->host_no);
1972 tw_dev->srb[request_id]->result = (DID_RESET << 16);
1973 goto tw_ioctl_bail;
1979 tw_ioctl_bail:
1981 /* Free up sglist memory */
1982 if (tw_dev->ioctl_data[request_id])
1983 pci_free_consistent(tw_dev->tw_pci_dev, total_bytes, tw_dev->ioctl_data[request_id], dma_handle);
1984 else
1985 printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Error freeing ioctl data.\n", tw_dev->host->host_no);
1987 /* Now complete the io */
1988 tw_dev->state[request_id] = TW_S_COMPLETED;
1989 tw_state_request_finish(tw_dev, request_id);
1990 if (posted)
1991 tw_dev->posted_request_count--;
1992 tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
1993 return 0;
1994 } else {
1995 printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n");
1996 return 1;
1998 default:
1999 dprintk(KERN_WARNING "3w-xxxx: Unknown ioctl 0x%x.\n", opcode);
2000 tw_dev->state[request_id] = TW_S_COMPLETED;
2001 tw_state_request_finish(tw_dev, request_id);
2002 tw_dev->srb[request_id]->result = (DID_OK << 16);
2003 tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
2004 return 0;
2007 param_value = tw_dev->alignment_physical_address[request_id];
2008 if (param_value == 0) {
2009 printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Bad alignment physical address.\n");
2010 tw_dev->state[request_id] = TW_S_COMPLETED;
2011 tw_state_request_finish(tw_dev, request_id);
2012 tw_dev->srb[request_id]->result = (DID_OK << 16);
2013 tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
2016 command_packet->byte8.param.sgl[0].address = param_value;
2017 command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
2019 command_packet->byte0.sgl_offset = 2;
2020 command_packet->size = 4;
2021 command_packet->request_id = request_id;
2022 command_packet->byte3.host_id = 0;
2023 command_packet->status = 0;
2024 command_packet->flags = 0;
2025 command_packet->byte6.parameter_count = 1;
2027 /* Now try to post the command to the board */
2028 tw_post_command_packet(tw_dev, request_id);
2030 return 0;
2031 } /* End tw_ioctl() */
2033 /* This function is called by the isr to complete ioctl requests */
2034 int tw_ioctl_complete(TW_Device_Extension *tw_dev, int request_id)
2036 unsigned char *param_data;
2037 unsigned char *buff;
2038 TW_Param *param;
2039 TW_Ioctl *ioctl = NULL;
2040 TW_Passthru *passthru = NULL;
2041 TW_Command *command_packet;
2043 ioctl = (TW_Ioctl *)tw_dev->srb[request_id]->request_buffer;
2044 dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl_complete()\n");
2045 buff = tw_dev->srb[request_id]->request_buffer;
2046 if (buff == NULL) {
2047 printk(KERN_WARNING "3w-xxxx: tw_ioctl_complete(): Request buffer NULL.\n");
2048 return 1;
2051 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
2052 if (command_packet == NULL) {
2053 printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl_complete(): Bad command packet virtual address.\n", tw_dev->host->host_no);
2054 return 1;
2057 dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl_complete(): Request_bufflen = %d\n", tw_dev->srb[request_id]->request_bufflen);
2059 ioctl = (TW_Ioctl *)buff;
2060 switch (ioctl->opcode) {
2061 case TW_ATA_PASSTHRU:
2062 passthru = (TW_Passthru *)ioctl->data;
2063 memcpy(buff, tw_dev->alignment_virtual_address[request_id], passthru->sector_count * 512);
2064 break;
2065 case TW_CMD_PACKET_WITH_DATA:
2066 dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_complete(): caught TW_CMD_PACKET_WITH_DATA.\n");
2067 clear_bit(TW_IN_IOCTL, &tw_dev->flags);
2068 return TW_ISR_DONT_COMPLETE; /* Special case for isr to not complete io */
2069 default:
2070 memset(buff, 0, tw_dev->srb[request_id]->request_bufflen);
2071 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
2072 if (param == NULL) {
2073 printk(KERN_WARNING "3w-xxxx: tw_ioctl_complete(): Bad alignment virtual address.\n");
2074 return 1;
2076 param_data = &(param->data[0]);
2077 memcpy(buff, param_data, tw_dev->ioctl_size[request_id]);
2079 return 0;
2080 } /* End tw_ioctl_complete() */
2082 static int tw_map_scsi_sg_data(struct pci_dev *pdev, Scsi_Cmnd *cmd)
2084 int use_sg;
2085 int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
2087 dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data()\n");
2089 if (cmd->use_sg == 0)
2090 return 0;
2092 use_sg = pci_map_sg(pdev, cmd->buffer, cmd->use_sg, dma_dir);
2094 if (use_sg == 0) {
2095 printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n");
2096 return 0;
2099 cmd->SCp.phase = 2;
2100 cmd->SCp.have_data_in = use_sg;
2102 return use_sg;
2103 } /* End tw_map_scsi_sg_data() */
2105 static u32 tw_map_scsi_single_data(struct pci_dev *pdev, Scsi_Cmnd *cmd)
2107 dma_addr_t mapping;
2108 int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
2110 dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_single_data()\n");
2112 if (cmd->request_bufflen == 0)
2113 return 0;
2115 mapping = pci_map_page(pdev, virt_to_page(cmd->request_buffer), ((unsigned long)cmd->request_buffer & ~PAGE_MASK), cmd->request_bufflen, dma_dir);
2117 if (mapping == 0) {
2118 printk(KERN_WARNING "3w-xxxx: tw_map_scsi_single_data(): pci_map_page() failed.\n");
2119 return 0;
2122 cmd->SCp.phase = 1;
2123 cmd->SCp.have_data_in = mapping;
2125 return mapping;
2126 } /* End tw_map_scsi_single_data() */
2128 /* This function will mask the command interrupt */
2129 void tw_mask_command_interrupt(TW_Device_Extension *tw_dev)
2131 u32 control_reg_addr, control_reg_value;
2133 control_reg_addr = tw_dev->registers.control_reg_addr;
2134 control_reg_value = TW_CONTROL_MASK_COMMAND_INTERRUPT;
2135 outl(control_reg_value, control_reg_addr);
2136 } /* End tw_mask_command_interrupt() */
2138 /* This function will poll the status register for a flag */
2139 int tw_poll_status(TW_Device_Extension *tw_dev, u32 flag, int seconds)
2141 u32 status_reg_addr, status_reg_value;
2142 struct timeval before, timeout;
2144 status_reg_addr = tw_dev->registers.status_reg_addr;
2145 do_gettimeofday(&before);
2146 status_reg_value = inl(status_reg_addr);
2148 if (tw_check_bits(status_reg_value)) {
2149 dprintk(KERN_WARNING "3w-xxxx: tw_poll_status(): Unexpected bits.\n");
2150 tw_decode_bits(tw_dev, status_reg_value, 0);
2153 while ((status_reg_value & flag) != flag) {
2154 status_reg_value = inl(status_reg_addr);
2156 if (tw_check_bits(status_reg_value)) {
2157 dprintk(KERN_WARNING "3w-xxxx: tw_poll_status(): Unexpected bits.\n");
2158 tw_decode_bits(tw_dev, status_reg_value, 0);
2161 do_gettimeofday(&timeout);
2162 if (before.tv_sec + seconds < timeout.tv_sec) {
2163 dprintk(KERN_WARNING "3w-xxxx: tw_poll_status(): Flag 0x%x not found.\n", flag);
2164 return 1;
2166 mdelay(5);
2168 return 0;
2169 } /* End tw_poll_status() */
2171 /* This function will poll the status register for disappearance of a flag */
2172 int tw_poll_status_gone(TW_Device_Extension *tw_dev, u32 flag, int seconds)
2174 u32 status_reg_addr, status_reg_value;
2175 struct timeval before, timeout;
2177 status_reg_addr = tw_dev->registers.status_reg_addr;
2178 do_gettimeofday(&before);
2179 status_reg_value = inl(status_reg_addr);
2181 if (tw_check_bits(status_reg_value)) {
2182 dprintk(KERN_WARNING "3w-xxxx: tw_poll_status_gone(): Unexpected bits.\n");
2183 tw_decode_bits(tw_dev, status_reg_value, 0);
2186 while ((status_reg_value & flag) != 0) {
2187 status_reg_value = inl(status_reg_addr);
2189 if (tw_check_bits(status_reg_value)) {
2190 dprintk(KERN_WARNING "3w-xxxx: tw_poll_status_gone(): Unexpected bits.\n");
2191 tw_decode_bits(tw_dev, status_reg_value, 0);
2194 do_gettimeofday(&timeout);
2195 if (before.tv_sec + seconds < timeout.tv_sec) {
2196 dprintk(KERN_WARNING "3w-xxxx: tw_poll_status_gone(): Flag 0x%x never disappeared.\n", flag);
2197 return 1;
2199 mdelay(5);
2201 return 0;
2202 } /* End tw_poll_status_gone() */
2204 /* This function will attempt to post a command packet to the board */
2205 int tw_post_command_packet(TW_Device_Extension *tw_dev, int request_id)
2207 u32 status_reg_addr, status_reg_value;
2208 unsigned long command_que_value;
2209 u32 command_que_addr;
2211 dprintk(KERN_NOTICE "3w-xxxx: tw_post_command_packet()\n");
2212 command_que_addr = tw_dev->registers.command_que_addr;
2213 command_que_value = tw_dev->command_packet_physical_address[request_id];
2214 status_reg_addr = tw_dev->registers.status_reg_addr;
2215 status_reg_value = inl(status_reg_addr);
2217 if (tw_check_bits(status_reg_value)) {
2218 dprintk(KERN_WARNING "3w-xxxx: tw_post_command_packet(): Unexpected bits.\n");
2219 tw_decode_bits(tw_dev, status_reg_value, 1);
2222 if ((status_reg_value & TW_STATUS_COMMAND_QUEUE_FULL) == 0) {
2223 /* We successfully posted the command packet */
2224 outl(command_que_value, command_que_addr);
2225 tw_dev->state[request_id] = TW_S_POSTED;
2226 tw_dev->posted_request_count++;
2227 if (tw_dev->posted_request_count > tw_dev->max_posted_request_count) {
2228 tw_dev->max_posted_request_count = tw_dev->posted_request_count;
2230 } else {
2231 /* Couldn't post the command packet, so we do it in the isr */
2232 if (tw_dev->state[request_id] != TW_S_PENDING) {
2233 tw_dev->state[request_id] = TW_S_PENDING;
2234 tw_dev->pending_request_count++;
2235 if (tw_dev->pending_request_count > tw_dev->max_pending_request_count) {
2236 tw_dev->max_pending_request_count = tw_dev->pending_request_count;
2238 tw_dev->pending_queue[tw_dev->pending_tail] = request_id;
2239 if (tw_dev->pending_tail == TW_Q_LENGTH-1) {
2240 tw_dev->pending_tail = TW_Q_START;
2241 } else {
2242 tw_dev->pending_tail = tw_dev->pending_tail + 1;
2245 tw_unmask_command_interrupt(tw_dev);
2246 return 1;
2248 return 0;
2249 } /* End tw_post_command_packet() */
2251 /* This function will reset a device extension */
2252 int tw_reset_device_extension(TW_Device_Extension *tw_dev)
2254 int imax = 0;
2255 int i = 0;
2256 Scsi_Cmnd *srb;
2258 dprintk(KERN_NOTICE "3w-xxxx: tw_reset_device_extension()\n");
2259 imax = TW_Q_LENGTH;
2261 if (tw_reset_sequence(tw_dev)) {
2262 printk(KERN_WARNING "3w-xxxx: scsi%d: Reset sequence failed.\n", tw_dev->host->host_no);
2263 return 1;
2266 /* Abort all requests that are in progress */
2267 for (i=0;i<imax;i++) {
2268 if ((tw_dev->state[i] != TW_S_FINISHED) &&
2269 (tw_dev->state[i] != TW_S_INITIAL) &&
2270 (tw_dev->state[i] != TW_S_COMPLETED)) {
2271 srb = tw_dev->srb[i];
2272 if (srb != NULL) {
2273 srb->result = (DID_RESET << 16);
2274 tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);
2275 tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[i]);
2280 /* Reset queues and counts */
2281 for (i=0;i<imax;i++) {
2282 tw_dev->free_queue[i] = i;
2283 tw_dev->state[i] = TW_S_INITIAL;
2285 tw_dev->free_head = TW_Q_START;
2286 tw_dev->free_tail = TW_Q_START;
2287 tw_dev->posted_request_count = 0;
2288 tw_dev->pending_request_count = 0;
2289 tw_dev->pending_head = TW_Q_START;
2290 tw_dev->pending_tail = TW_Q_START;
2291 tw_dev->reset_print = 0;
2292 tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
2294 return 0;
2295 } /* End tw_reset_device_extension() */
2297 /* This function will reset a controller */
2298 int tw_reset_sequence(TW_Device_Extension *tw_dev)
2300 int error = 0;
2301 int tries = 0;
2303 /* Disable interrupts */
2304 tw_disable_interrupts(tw_dev);
2306 /* Reset the board */
2307 while (tries < TW_MAX_RESET_TRIES) {
2308 tw_soft_reset(tw_dev);
2310 error = tw_aen_drain_queue(tw_dev);
2311 if (error) {
2312 printk(KERN_WARNING "3w-xxxx: scsi%d: AEN drain failed, retrying.\n", tw_dev->host->host_no);
2313 tries++;
2314 continue;
2317 /* Check for controller errors */
2318 if (tw_check_errors(tw_dev)) {
2319 printk(KERN_WARNING "3w-xxxx: scsi%d: Controller errors found, retrying.\n", tw_dev->host->host_no);
2320 tries++;
2321 continue;
2324 /* Now the controller is in a good state */
2325 break;
2328 if (tries >= TW_MAX_RESET_TRIES) {
2329 printk(KERN_WARNING "3w-xxxx: scsi%d: Controller errors, card not responding, check all cabling.\n", tw_dev->host->host_no);
2330 return 1;
2333 error = tw_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS);
2334 if (error) {
2335 printk(KERN_WARNING "3w-xxxx: scsi%d: Connection initialization failed.\n", tw_dev->host->host_no);
2336 return 1;
2339 /* Re-enable interrupts */
2340 tw_enable_and_clear_interrupts(tw_dev);
2342 return 0;
2343 } /* End tw_reset_sequence() */
2345 /* This funciton returns unit geometry in cylinders/heads/sectors */
2346 int tw_scsi_biosparam(struct scsi_device *sdev, struct block_device *bdev,
2347 sector_t capacity, int geom[])
2349 int heads, sectors, cylinders;
2350 TW_Device_Extension *tw_dev;
2352 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_biosparam()\n");
2353 tw_dev = (TW_Device_Extension *)sdev->host->hostdata;
2355 heads = 64;
2356 sectors = 32;
2357 cylinders = (unsigned long)capacity / (heads * sectors);
2359 if (capacity >= 0x200000) {
2360 heads = 255;
2361 sectors = 63;
2362 cylinders = (unsigned long)capacity / (heads * sectors);
2365 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_biosparam(): heads = %d, sectors = %d, cylinders = %d\n", heads, sectors, cylinders);
2366 geom[0] = heads;
2367 geom[1] = sectors;
2368 geom[2] = cylinders;
2370 return 0;
2371 } /* End tw_scsi_biosparam() */
2373 /* This function will find and initialize any cards */
2374 int tw_scsi_detect(Scsi_Host_Template *tw_host)
2376 int ret;
2378 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_detect()\n");
2380 printk(KERN_WARNING "3ware Storage Controller device driver for Linux v%s.\n", tw_driver_version);
2382 ret = tw_findcards(tw_host);
2384 return ret;
2385 } /* End tw_scsi_detect() */
2387 /* This is the new scsi eh abort function */
2388 int tw_scsi_eh_abort(Scsi_Cmnd *SCpnt)
2390 TW_Device_Extension *tw_dev=NULL;
2391 int i = 0;
2393 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_eh_abort()\n");
2395 if (!SCpnt) {
2396 printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Invalid Scsi_Cmnd.\n");
2397 return (FAILED);
2400 tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
2401 if (tw_dev == NULL) {
2402 printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Invalid device extension.\n");
2403 return (FAILED);
2406 spin_lock(&tw_dev->tw_lock);
2407 tw_dev->num_aborts++;
2409 /* If the command hasn't been posted yet, we can do the abort */
2410 for (i=0;i<TW_Q_LENGTH;i++) {
2411 if (tw_dev->srb[i] == SCpnt) {
2412 if (tw_dev->state[i] == TW_S_STARTED) {
2413 printk(KERN_WARNING "3w-xxxx: scsi%d: Unit #%d: Command (%p) timed out.\n", tw_dev->host->host_no, tw_dev->srb[i]==0 ? 0 : tw_dev->srb[i]->device->id, SCpnt);
2414 tw_dev->state[i] = TW_S_COMPLETED;
2415 tw_state_request_finish(tw_dev, i);
2416 spin_unlock(&tw_dev->tw_lock);
2417 return (SUCCESS);
2419 if (tw_dev->state[i] == TW_S_PENDING) {
2420 printk(KERN_WARNING "3w-xxxx: scsi%d: Unit #%d: Command (%p) timed out.\n", tw_dev->host->host_no, tw_dev->srb[i]==0 ? 0 : tw_dev->srb[i]->device->id, SCpnt);
2421 if (tw_dev->pending_head == TW_Q_LENGTH-1) {
2422 tw_dev->pending_head = TW_Q_START;
2423 } else {
2424 tw_dev->pending_head = tw_dev->pending_head + 1;
2426 tw_dev->pending_request_count--;
2427 tw_dev->state[i] = TW_S_COMPLETED;
2428 tw_state_request_finish(tw_dev, i);
2429 spin_unlock(&tw_dev->tw_lock);
2430 return (SUCCESS);
2432 if (tw_dev->state[i] == TW_S_POSTED) {
2433 /* If the command has already been posted, we have to reset the card */
2434 printk(KERN_WARNING "3w-xxxx: scsi%d: Unit #%d: Command (%p) timed out, resetting card.\n", tw_dev->host->host_no, tw_dev->srb[i]==0 ? 0 : tw_dev->srb[i]->device->id, SCpnt);
2435 /* We have to let AEN requests through before the reset */
2436 spin_unlock(&tw_dev->tw_lock);
2437 spin_unlock_irq(tw_dev->host->host_lock);
2438 mdelay(TW_AEN_WAIT_TIME);
2439 spin_lock_irq(tw_dev->host->host_lock);
2440 spin_lock(&tw_dev->tw_lock);
2442 if (tw_reset_device_extension(tw_dev)) {
2443 dprintk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Reset failed for card %d.\n", tw_dev->host->host_no);
2444 spin_unlock(&tw_dev->tw_lock);
2445 return (FAILED);
2451 spin_unlock(&tw_dev->tw_lock);
2452 return (SUCCESS);
2453 } /* End tw_scsi_eh_abort() */
2455 /* This is the new scsi eh reset function */
2456 int tw_scsi_eh_reset(Scsi_Cmnd *SCpnt)
2458 TW_Device_Extension *tw_dev=NULL;
2460 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_eh_reset()\n");
2462 if (!SCpnt) {
2463 printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_reset(): Invalid Scsi_Cmnd.\n");
2464 return (FAILED);
2467 tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
2468 if (tw_dev == NULL) {
2469 printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_reset(): Invalid device extension.\n");
2470 return (FAILED);
2473 /* We have to let AEN requests through before the reset */
2474 spin_unlock_irq(tw_dev->host->host_lock);
2475 mdelay(TW_AEN_WAIT_TIME);
2476 spin_lock_irq(tw_dev->host->host_lock);
2478 spin_lock(&tw_dev->tw_lock);
2479 tw_dev->num_resets++;
2481 /* Now reset the card and some of the device extension data */
2482 if (tw_reset_device_extension(tw_dev)) {
2483 printk(KERN_WARNING "3w-xxxx: scsi%d: Reset failed.\n", tw_dev->host->host_no);
2484 spin_unlock(&tw_dev->tw_lock);
2485 return (FAILED);
2487 printk(KERN_WARNING "3w-xxxx: scsi%d: Reset succeeded.\n", tw_dev->host->host_no);
2488 spin_unlock(&tw_dev->tw_lock);
2490 return (SUCCESS);
2491 } /* End tw_scsi_eh_reset() */
2493 /* This function handles input and output from /proc/scsi/3w-xxxx/x */
2494 int tw_scsi_proc_info(struct Scsi_Host *shost, char *buffer, char **start,
2495 off_t offset, int length, int inout)
2497 TW_Device_Extension *tw_dev = NULL;
2498 TW_Info info;
2499 int i;
2500 int j;
2502 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_proc_info()\n");
2504 /* Find the correct device extension */
2505 for (i=0;i<tw_device_extension_count;i++)
2506 if (tw_device_extension_list[i]->host->host_no == shost->host_no)
2507 tw_dev = tw_device_extension_list[i];
2508 if (tw_dev == NULL) {
2509 printk(KERN_WARNING "3w-xxxx: tw_scsi_proc_info(): Couldn't locate device extension.\n");
2510 return (-EINVAL);
2513 info.buffer = buffer;
2514 info.length = length;
2515 info.offset = offset;
2516 info.position = 0;
2518 if (inout) {
2519 /* Write */
2520 if (strncmp(buffer, "debug", 5) == 0) {
2521 printk(KERN_INFO "3w-xxxx: Posted commands:\n");
2522 for (j=0;j<TW_Q_LENGTH;j++) {
2523 if (tw_dev->state[j] == TW_S_POSTED) {
2524 TW_Command *command = (TW_Command *)tw_dev->command_packet_virtual_address[j];
2525 printk(KERN_INFO "3w-xxxx: Request_id: %d\n", j);
2526 printk(KERN_INFO "Opcode: 0x%x\n", command->byte0.opcode);
2527 printk(KERN_INFO "Block_count: 0x%x\n", command->byte6.block_count);
2528 printk(KERN_INFO "LBA: 0x%x\n", command->byte8.io.lba);
2529 printk(KERN_INFO "Physical command packet addr: 0x%lx\n", tw_dev->command_packet_physical_address[j]);
2530 printk(KERN_INFO "Scsi_Cmnd: %p\n", tw_dev->srb[j]);
2533 printk(KERN_INFO "3w-xxxx: Free_head: %3d\n", tw_dev->free_head);
2534 printk(KERN_INFO "3w-xxxx: Free_tail: %3d\n", tw_dev->free_tail);
2536 return length;
2537 } else {
2538 /* Read */
2539 if (start) {
2540 *start = buffer;
2542 tw_copy_info(&info, "scsi%d: 3ware Storage Controller\n", shost->host_no);
2543 tw_copy_info(&info, "Driver version: %s\n", tw_driver_version);
2544 tw_copy_info(&info, "Current commands posted: %3d\n", tw_dev->posted_request_count);
2545 tw_copy_info(&info, "Max commands posted: %3d\n", tw_dev->max_posted_request_count);
2546 tw_copy_info(&info, "Current pending commands: %3d\n", tw_dev->pending_request_count);
2547 tw_copy_info(&info, "Max pending commands: %3d\n", tw_dev->max_pending_request_count);
2548 tw_copy_info(&info, "Last sgl length: %3d\n", tw_dev->sgl_entries);
2549 tw_copy_info(&info, "Max sgl length: %3d\n", tw_dev->max_sgl_entries);
2550 tw_copy_info(&info, "Last sector count: %3d\n", tw_dev->sector_count);
2551 tw_copy_info(&info, "Max sector count: %3d\n", tw_dev->max_sector_count);
2552 tw_copy_info(&info, "Resets: %3d\n", tw_dev->num_resets);
2553 tw_copy_info(&info, "Aborts: %3d\n", tw_dev->num_aborts);
2554 tw_copy_info(&info, "AEN's: %3d\n", tw_dev->aen_count);
2556 if (info.position > info.offset) {
2557 return (info.position - info.offset);
2558 } else {
2559 return 0;
2561 } /* End tw_scsi_proc_info() */
2563 /* This is the main scsi queue function to handle scsi opcodes */
2564 int tw_scsi_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
2566 unsigned char *command = SCpnt->cmnd;
2567 int request_id = 0;
2568 int error = 0;
2569 TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
2571 if (tw_dev == NULL) {
2572 printk(KERN_WARNING "3w-xxxx: tw_scsi_queue(): Invalid device extension.\n");
2573 SCpnt->result = (DID_ERROR << 16);
2574 done(SCpnt);
2575 return 0;
2578 spin_lock(&tw_dev->tw_lock);
2579 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue()\n");
2581 /* Skip scsi command if it isn't for us */
2582 if ((SCpnt->device->channel != 0) || (SCpnt->device->lun != 0)) {
2583 SCpnt->result = (DID_BAD_TARGET << 16);
2584 done(SCpnt);
2585 spin_unlock(&tw_dev->tw_lock);
2586 return 0;
2589 /* Save done function into Scsi_Cmnd struct */
2590 SCpnt->scsi_done = done;
2592 /* Queue the command and get a request id */
2593 tw_state_request_start(tw_dev, &request_id);
2595 /* Save the scsi command for use by the ISR */
2596 tw_dev->srb[request_id] = SCpnt;
2598 /* Initialize phase to zero */
2599 SCpnt->SCp.phase = 0;
2601 switch (*command) {
2602 case READ_10:
2603 case READ_6:
2604 case WRITE_10:
2605 case WRITE_6:
2606 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ/WRITE.\n");
2607 error = tw_scsiop_read_write(tw_dev, request_id);
2608 break;
2609 case TEST_UNIT_READY:
2610 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught TEST_UNIT_READY.\n");
2611 error = tw_scsiop_test_unit_ready(tw_dev, request_id);
2612 break;
2613 case INQUIRY:
2614 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught INQUIRY.\n");
2615 error = tw_scsiop_inquiry(tw_dev, request_id);
2616 break;
2617 case READ_CAPACITY:
2618 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ_CAPACITY.\n");
2619 error = tw_scsiop_read_capacity(tw_dev, request_id);
2620 break;
2621 case REQUEST_SENSE:
2622 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught REQUEST_SENSE.\n");
2623 error = tw_scsiop_request_sense(tw_dev, request_id);
2624 break;
2625 case MODE_SENSE:
2626 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught MODE_SENSE.\n");
2627 error = tw_scsiop_mode_sense(tw_dev, request_id);
2628 break;
2629 case SYNCHRONIZE_CACHE:
2630 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught SYNCHRONIZE_CACHE.\n");
2631 error = tw_scsiop_synchronize_cache(tw_dev, request_id);
2632 break;
2633 case TW_IOCTL:
2634 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught TW_SCSI_IOCTL.\n");
2635 error = tw_ioctl(tw_dev, request_id);
2636 break;
2637 default:
2638 printk(KERN_NOTICE "3w-xxxx: scsi%d: Unknown scsi opcode: 0x%x\n", tw_dev->host->host_no, *command);
2639 tw_dev->state[request_id] = TW_S_COMPLETED;
2640 tw_state_request_finish(tw_dev, request_id);
2641 SCpnt->result = (DID_BAD_TARGET << 16);
2642 done(SCpnt);
2644 if (error) {
2645 tw_dev->state[request_id] = TW_S_COMPLETED;
2646 tw_state_request_finish(tw_dev, request_id);
2647 SCpnt->result = (DID_ERROR << 16);
2648 done(SCpnt);
2650 spin_unlock(&tw_dev->tw_lock);
2652 return 0;
2653 } /* End tw_scsi_queue() */
2655 /* This function will release the resources on an rmmod call */
2656 int tw_scsi_release(struct Scsi_Host *tw_host)
2658 TW_Device_Extension *tw_dev;
2659 tw_dev = (TW_Device_Extension *)tw_host->hostdata;
2661 dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_release()\n");
2663 /* Fake like we just shut down, so notify the card that
2664 * we "shut down cleanly".
2666 tw_halt(0, 0, 0); // parameters aren't actually used
2668 /* Free up the IO region */
2669 release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE);
2671 /* Free up the IRQ */
2672 free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
2674 /* Unregister character device */
2675 if (twe_major >= 0) {
2676 unregister_chrdev(twe_major, "twe");
2677 twe_major = -1;
2680 /* Free up device extension resources */
2681 tw_free_device_extension(tw_dev);
2683 /* Tell kernel scsi-layer we are gone */
2684 scsi_unregister(tw_host);
2686 return 0;
2687 } /* End tw_scsi_release() */
2689 /* This function handles scsi inquiry commands */
2690 int tw_scsiop_inquiry(TW_Device_Extension *tw_dev, int request_id)
2692 TW_Param *param;
2693 TW_Command *command_packet;
2694 unsigned long command_que_value;
2695 u32 command_que_addr;
2696 unsigned long param_value;
2698 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry()\n");
2700 /* Initialize command packet */
2701 command_que_addr = tw_dev->registers.command_que_addr;
2702 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
2703 if (command_packet == NULL) {
2704 printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad command packet virtual address.\n");
2705 return 1;
2707 memset(command_packet, 0, sizeof(TW_Sector));
2708 command_packet->byte0.opcode = TW_OP_GET_PARAM;
2709 command_packet->byte0.sgl_offset = 2;
2710 command_packet->size = 4;
2711 command_packet->request_id = request_id;
2712 command_packet->byte3.unit = 0;
2713 command_packet->byte3.host_id = 0;
2714 command_packet->status = 0;
2715 command_packet->flags = 0;
2716 command_packet->byte6.parameter_count = 1;
2718 /* Now setup the param */
2719 if (tw_dev->alignment_virtual_address[request_id] == NULL) {
2720 printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad alignment virtual address.\n");
2721 return 1;
2723 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
2724 memset(param, 0, sizeof(TW_Sector));
2725 param->table_id = 3; /* unit summary table */
2726 param->parameter_id = 3; /* unitsstatus parameter */
2727 param->parameter_size_bytes = TW_MAX_UNITS;
2728 param_value = tw_dev->alignment_physical_address[request_id];
2729 if (param_value == 0) {
2730 printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad alignment physical address.\n");
2731 return 1;
2734 command_packet->byte8.param.sgl[0].address = param_value;
2735 command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
2736 command_que_value = tw_dev->command_packet_physical_address[request_id];
2737 if (command_que_value == 0) {
2738 printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad command packet physical address.\n");
2739 return 1;
2742 /* Now try to post the command packet */
2743 tw_post_command_packet(tw_dev, request_id);
2745 return 0;
2746 } /* End tw_scsiop_inquiry() */
2748 /* This function is called by the isr to complete an inquiry command */
2749 int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_id)
2751 unsigned char *is_unit_present;
2752 unsigned char *request_buffer;
2753 TW_Param *param;
2755 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry_complete()\n");
2757 /* Fill request buffer */
2758 if (tw_dev->srb[request_id]->request_buffer == NULL) {
2759 printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry_complete(): Request buffer NULL.\n");
2760 return 1;
2762 request_buffer = tw_dev->srb[request_id]->request_buffer;
2763 memset(request_buffer, 0, tw_dev->srb[request_id]->request_bufflen);
2764 request_buffer[0] = TYPE_DISK; /* Peripheral device type */
2765 request_buffer[1] = 0; /* Device type modifier */
2766 request_buffer[2] = 0; /* No ansi/iso compliance */
2767 request_buffer[4] = 31; /* Additional length */
2768 memcpy(&request_buffer[8], "3ware ", 8); /* Vendor ID */
2769 sprintf(&request_buffer[16], "Logical Disk %-2d ", tw_dev->srb[request_id]->device->id);
2770 memcpy(&request_buffer[32], tw_driver_version, 3);
2772 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
2773 if (param == NULL) {
2774 printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry_complete(): Bad alignment virtual address.\n");
2775 return 1;
2777 is_unit_present = &(param->data[0]);
2779 if (is_unit_present[tw_dev->srb[request_id]->device->id] & TW_UNIT_ONLINE) {
2780 tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = TRUE;
2781 } else {
2782 tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = FALSE;
2783 tw_dev->srb[request_id]->result = (DID_BAD_TARGET << 16);
2784 return TW_ISR_DONT_RESULT;
2787 return 0;
2788 } /* End tw_scsiop_inquiry_complete() */
2790 /* This function handles scsi mode_sense commands */
2791 int tw_scsiop_mode_sense(TW_Device_Extension *tw_dev, int request_id)
2793 TW_Param *param;
2794 TW_Command *command_packet;
2795 unsigned long command_que_value;
2796 unsigned long param_value;
2798 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_mode_sense()\n");
2800 /* Only page control = 0, page code = 0x8 (cache page) supported */
2801 if (tw_dev->srb[request_id]->cmnd[2] != 0x8) {
2802 tw_dev->state[request_id] = TW_S_COMPLETED;
2803 tw_state_request_finish(tw_dev, request_id);
2804 tw_dev->srb[request_id]->result = (DID_OK << 16);
2805 tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
2806 return 0;
2809 /* Now read firmware cache setting for this unit */
2810 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
2811 if (command_packet == NULL) {
2812 printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad command packet virtual address.\n");
2813 return 1;
2816 /* Setup the command packet */
2817 memset(command_packet, 0, sizeof(TW_Sector));
2818 command_packet->byte0.opcode = TW_OP_GET_PARAM;
2819 command_packet->byte0.sgl_offset = 2;
2820 command_packet->size = 4;
2821 command_packet->request_id = request_id;
2822 command_packet->byte3.unit = 0;
2823 command_packet->byte3.host_id = 0;
2824 command_packet->status = 0;
2825 command_packet->flags = 0;
2826 command_packet->byte6.parameter_count = 1;
2828 /* Setup the param */
2829 if (tw_dev->alignment_virtual_address[request_id] == NULL) {
2830 printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad alignment virtual address.\n");
2831 return 1;
2834 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
2835 memset(param, 0, sizeof(TW_Sector));
2836 param->table_id = TW_UNIT_INFORMATION_TABLE_BASE + tw_dev->srb[request_id]->device->id;
2837 param->parameter_id = 7; /* unit flags */
2838 param->parameter_size_bytes = 1;
2839 param_value = tw_dev->alignment_physical_address[request_id];
2840 if (param_value == 0) {
2841 printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad alignment physical address.\n");
2842 return 1;
2845 command_packet->byte8.param.sgl[0].address = param_value;
2846 command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
2847 command_que_value = tw_dev->command_packet_physical_address[request_id];
2848 if (command_que_value == 0) {
2849 printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad command packet physical address.\n");
2850 return 1;
2853 /* Now try to post the command packet */
2854 tw_post_command_packet(tw_dev, request_id);
2856 return 0;
2857 } /* End tw_scsiop_mode_sense() */
2859 /* This function is called by the isr to complete a mode sense command */
2860 int tw_scsiop_mode_sense_complete(TW_Device_Extension *tw_dev, int request_id)
2862 TW_Param *param;
2863 unsigned char *flags;
2864 unsigned char *request_buffer;
2866 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_mode_sense_complete()\n");
2868 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
2869 if (param == NULL) {
2870 printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense_complete(): Bad alignment virtual address.\n");
2871 return 1;
2873 flags = (char *)&(param->data[0]);
2874 request_buffer = tw_dev->srb[request_id]->buffer;
2875 memset(request_buffer, 0, tw_dev->srb[request_id]->request_bufflen);
2877 request_buffer[0] = 0xf; /* mode data length */
2878 request_buffer[1] = 0; /* default medium type */
2879 request_buffer[2] = 0x10; /* dpo/fua support on */
2880 request_buffer[3] = 0; /* no block descriptors */
2881 request_buffer[4] = 0x8; /* caching page */
2882 request_buffer[5] = 0xa; /* page length */
2883 if (*flags & 0x1)
2884 request_buffer[6] = 0x4; /* WCE on */
2885 else
2886 request_buffer[6] = 0x0; /* WCE off */
2888 return 0;
2889 } /* End tw_scsiop_mode_sense_complete() */
2891 /* This function handles scsi read_capacity commands */
2892 int tw_scsiop_read_capacity(TW_Device_Extension *tw_dev, int request_id)
2894 TW_Param *param;
2895 TW_Command *command_packet;
2896 unsigned long command_que_value;
2897 u32 command_que_addr;
2898 unsigned long param_value;
2900 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity()\n");
2902 /* Initialize command packet */
2903 command_que_addr = tw_dev->registers.command_que_addr;
2904 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
2906 if (command_packet == NULL) {
2907 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad command packet virtual address.\n");
2908 return 1;
2910 memset(command_packet, 0, sizeof(TW_Sector));
2911 command_packet->byte0.opcode = TW_OP_GET_PARAM;
2912 command_packet->byte0.sgl_offset = 2;
2913 command_packet->size = 4;
2914 command_packet->request_id = request_id;
2915 command_packet->byte3.unit = tw_dev->srb[request_id]->device->id;
2916 command_packet->byte3.host_id = 0;
2917 command_packet->status = 0;
2918 command_packet->flags = 0;
2919 command_packet->byte6.block_count = 1;
2921 /* Now setup the param */
2922 if (tw_dev->alignment_virtual_address[request_id] == NULL) {
2923 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad alignment virtual address.\n");
2924 return 1;
2926 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
2927 memset(param, 0, sizeof(TW_Sector));
2928 param->table_id = TW_UNIT_INFORMATION_TABLE_BASE +
2929 tw_dev->srb[request_id]->device->id;
2930 param->parameter_id = 4; /* unitcapacity parameter */
2931 param->parameter_size_bytes = 4;
2932 param_value = tw_dev->alignment_physical_address[request_id];
2933 if (param_value == 0) {
2934 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad alignment physical address.\n");
2935 return 1;
2938 command_packet->byte8.param.sgl[0].address = param_value;
2939 command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
2940 command_que_value = tw_dev->command_packet_physical_address[request_id];
2941 if (command_que_value == 0) {
2942 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad command packet physical address.\n");
2943 return 1;
2946 /* Now try to post the command to the board */
2947 tw_post_command_packet(tw_dev, request_id);
2949 return 0;
2950 } /* End tw_scsiop_read_capacity() */
2952 /* This function is called by the isr to complete a readcapacity command */
2953 int tw_scsiop_read_capacity_complete(TW_Device_Extension *tw_dev, int request_id)
2955 unsigned char *param_data;
2956 u32 capacity;
2957 char *buff;
2958 TW_Param *param;
2960 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete()\n");
2962 buff = tw_dev->srb[request_id]->request_buffer;
2963 if (buff == NULL) {
2964 printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Request buffer NULL.\n");
2965 return 1;
2967 memset(buff, 0, tw_dev->srb[request_id]->request_bufflen);
2968 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
2969 if (param == NULL) {
2970 printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Bad alignment virtual address.\n");
2971 return 1;
2973 param_data = &(param->data[0]);
2975 capacity = (param_data[3] << 24) | (param_data[2] << 16) |
2976 (param_data[1] << 8) | param_data[0];
2978 /* Subtract one sector to fix get last sector ioctl */
2979 capacity -= 1;
2981 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete(): Capacity = 0x%x.\n", capacity);
2983 /* Number of LBA's */
2984 buff[0] = (capacity >> 24);
2985 buff[1] = (capacity >> 16) & 0xff;
2986 buff[2] = (capacity >> 8) & 0xff;
2987 buff[3] = capacity & 0xff;
2989 /* Block size in bytes (512) */
2990 buff[4] = (TW_BLOCK_SIZE >> 24);
2991 buff[5] = (TW_BLOCK_SIZE >> 16) & 0xff;
2992 buff[6] = (TW_BLOCK_SIZE >> 8) & 0xff;
2993 buff[7] = TW_BLOCK_SIZE & 0xff;
2995 return 0;
2996 } /* End tw_scsiop_read_capacity_complete() */
2998 /* This function handles scsi read or write commands */
2999 int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id)
3001 TW_Command *command_packet;
3002 unsigned long command_que_value;
3003 u32 command_que_addr = 0x0;
3004 u32 lba = 0x0, num_sectors = 0x0, buffaddr = 0x0;
3005 int i, use_sg;
3006 Scsi_Cmnd *srb;
3007 struct scatterlist *sglist;
3009 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write()\n");
3011 if (tw_dev->srb[request_id]->request_buffer == NULL) {
3012 printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_write(): Request buffer NULL.\n");
3013 return 1;
3015 sglist = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
3016 srb = tw_dev->srb[request_id];
3018 /* Initialize command packet */
3019 command_que_addr = tw_dev->registers.command_que_addr;
3020 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
3021 if (command_packet == NULL) {
3022 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): Bad command packet virtual address.\n");
3023 return 1;
3026 if (srb->cmnd[0] == READ_6 || srb->cmnd[0] == READ_10) {
3027 command_packet->byte0.opcode = TW_OP_READ;
3028 } else {
3029 command_packet->byte0.opcode = TW_OP_WRITE;
3032 command_packet->byte0.sgl_offset = 3;
3033 command_packet->size = 3;
3034 command_packet->request_id = request_id;
3035 command_packet->byte3.unit = srb->device->id;
3036 command_packet->byte3.host_id = 0;
3037 command_packet->status = 0;
3038 command_packet->flags = 0;
3040 if (srb->cmnd[0] == WRITE_10) {
3041 if ((srb->cmnd[1] & 0x8) || (srb->cmnd[1] & 0x10))
3042 command_packet->flags = 1;
3045 if (srb->cmnd[0] == READ_6 || srb->cmnd[0] == WRITE_6) {
3046 lba = ((u32)srb->cmnd[1] << 16) | ((u32)srb->cmnd[2] << 8) | (u32)srb->cmnd[3];
3047 num_sectors = (u32)srb->cmnd[4];
3048 } else {
3049 lba = ((u32)srb->cmnd[2] << 24) | ((u32)srb->cmnd[3] << 16) | ((u32)srb->cmnd[4] << 8) | (u32)srb->cmnd[5];
3050 num_sectors = (u32)srb->cmnd[8] | ((u32)srb->cmnd[7] << 8);
3053 /* Update sector statistic */
3054 tw_dev->sector_count = num_sectors;
3055 if (tw_dev->sector_count > tw_dev->max_sector_count)
3056 tw_dev->max_sector_count = tw_dev->sector_count;
3058 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): lba = 0x%x num_sectors = 0x%x\n", lba, num_sectors);
3059 command_packet->byte8.io.lba = lba;
3060 command_packet->byte6.block_count = num_sectors;
3062 /* Do this if there are no sg list entries */
3063 if (tw_dev->srb[request_id]->use_sg == 0) {
3064 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): SG = 0\n");
3065 buffaddr = tw_map_scsi_single_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
3066 if (buffaddr == 0)
3067 return 1;
3069 command_packet->byte8.io.sgl[0].address = buffaddr;
3070 command_packet->byte8.io.sgl[0].length = tw_dev->srb[request_id]->request_bufflen;
3071 command_packet->size+=2;
3074 /* Do this if we have multiple sg list entries */
3075 if (tw_dev->srb[request_id]->use_sg > 0) {
3076 use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
3077 if (use_sg == 0)
3078 return 1;
3080 for (i=0;i<use_sg; i++) {
3081 command_packet->byte8.io.sgl[i].address = sg_dma_address(&sglist[i]);
3082 command_packet->byte8.io.sgl[i].length = sg_dma_len(&sglist[i]);
3083 command_packet->size+=2;
3087 /* Update SG statistics */
3088 tw_dev->sgl_entries = tw_dev->srb[request_id]->use_sg;
3089 if (tw_dev->sgl_entries > tw_dev->max_sgl_entries)
3090 tw_dev->max_sgl_entries = tw_dev->sgl_entries;
3092 command_que_value = tw_dev->command_packet_physical_address[request_id];
3093 if (command_que_value == 0) {
3094 dprintk(KERN_WARNING "3w-xxxx: tw_scsiop_read_write(): Bad command packet physical address.\n");
3095 return 1;
3098 /* Now try to post the command to the board */
3099 tw_post_command_packet(tw_dev, request_id);
3101 return 0;
3102 } /* End tw_scsiop_read_write() */
3104 /* This function will handle the request sense scsi command */
3105 int tw_scsiop_request_sense(TW_Device_Extension *tw_dev, int request_id)
3107 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_request_sense()\n");
3109 /* For now we just zero the request buffer */
3110 memset(tw_dev->srb[request_id]->request_buffer, 0, tw_dev->srb[request_id]->request_bufflen);
3111 tw_dev->state[request_id] = TW_S_COMPLETED;
3112 tw_state_request_finish(tw_dev, request_id);
3114 /* If we got a request_sense, we probably want a reset, return error */
3115 tw_dev->srb[request_id]->result = (DID_ERROR << 16);
3116 tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
3118 return 0;
3119 } /* End tw_scsiop_request_sense() */
3121 /* This function will handle synchronize cache scsi command */
3122 int tw_scsiop_synchronize_cache(TW_Device_Extension *tw_dev, int request_id)
3124 TW_Command *command_packet;
3125 unsigned long command_que_value;
3127 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_synchronize_cache()\n");
3129 /* Send firmware flush command for this unit */
3130 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
3131 if (command_packet == NULL) {
3132 printk(KERN_WARNING "3w-xxxx: tw_scsiop_synchronize_cache(): Bad command packet virtual address.\n");
3133 return 1;
3136 /* Setup the command packet */
3137 memset(command_packet, 0, sizeof(TW_Sector));
3138 command_packet->byte0.opcode = TW_OP_FLUSH_CACHE;
3139 command_packet->byte0.sgl_offset = 0;
3140 command_packet->size = 2;
3141 command_packet->request_id = request_id;
3142 command_packet->byte3.unit = tw_dev->srb[request_id]->device->id;
3143 command_packet->byte3.host_id = 0;
3144 command_packet->status = 0;
3145 command_packet->flags = 0;
3146 command_packet->byte6.parameter_count = 1;
3147 command_que_value = tw_dev->command_packet_physical_address[request_id];
3148 if (command_que_value == 0) {
3149 printk(KERN_WARNING "3w-xxxx: tw_scsiop_synchronize_cache(): Bad command packet physical address.\n");
3150 return 1;
3153 /* Now try to post the command packet */
3154 tw_post_command_packet(tw_dev, request_id);
3156 return 0;
3157 } /* End tw_scsiop_synchronize_cache() */
3159 /* This function will handle test unit ready scsi command */
3160 int tw_scsiop_test_unit_ready(TW_Device_Extension *tw_dev, int request_id)
3162 TW_Param *param;
3163 TW_Command *command_packet;
3164 unsigned long command_que_value;
3165 u32 command_que_addr;
3166 unsigned long param_value;
3168 dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_test_unit_ready()\n");
3170 /* Initialize command packet */
3171 command_que_addr = tw_dev->registers.command_que_addr;
3172 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
3173 if (command_packet == NULL) {
3174 printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad command packet virtual address.\n");
3175 return 1;
3177 memset(command_packet, 0, sizeof(TW_Sector));
3178 command_packet->byte0.opcode = TW_OP_GET_PARAM;
3179 command_packet->byte0.sgl_offset = 2;
3180 command_packet->size = 4;
3181 command_packet->request_id = request_id;
3182 command_packet->byte3.unit = 0;
3183 command_packet->byte3.host_id = 0;
3184 command_packet->status = 0;
3185 command_packet->flags = 0;
3186 command_packet->byte6.parameter_count = 1;
3188 /* Now setup the param */
3189 if (tw_dev->alignment_virtual_address[request_id] == NULL) {
3190 printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad alignment virtual address.\n");
3191 return 1;
3193 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
3194 memset(param, 0, sizeof(TW_Sector));
3195 param->table_id = 3; /* unit summary table */
3196 param->parameter_id = 3; /* unitsstatus parameter */
3197 param->parameter_size_bytes = TW_MAX_UNITS;
3198 param_value = tw_dev->alignment_physical_address[request_id];
3199 if (param_value == 0) {
3200 printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad alignment physical address.\n");
3201 return 1;
3204 command_packet->byte8.param.sgl[0].address = param_value;
3205 command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
3206 command_que_value = tw_dev->command_packet_physical_address[request_id];
3207 if (command_que_value == 0) {
3208 printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad command packet physical address.\n");
3209 return 1;
3212 /* Now try to post the command packet */
3213 tw_post_command_packet(tw_dev, request_id);
3215 return 0;
3216 } /* End tw_scsiop_test_unit_ready() */
3218 /* This function is called by the isr to complete a testunitready command */
3219 int tw_scsiop_test_unit_ready_complete(TW_Device_Extension *tw_dev, int request_id)
3221 unsigned char *is_unit_present;
3222 TW_Param *param;
3224 dprintk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready_complete()\n");
3226 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
3227 if (param == NULL) {
3228 printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready_complete(): Bad alignment virtual address.\n");
3229 return 1;
3231 is_unit_present = &(param->data[0]);
3233 if (is_unit_present[tw_dev->srb[request_id]->device->id] & TW_UNIT_ONLINE) {
3234 tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = TRUE;
3235 } else {
3236 tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = FALSE;
3237 tw_dev->srb[request_id]->result = (DID_BAD_TARGET << 16);
3238 return TW_ISR_DONT_RESULT;
3241 return 0;
3242 } /* End tw_scsiop_test_unit_ready_complete() */
3244 /* Set a value in the features table */
3245 int tw_setfeature(TW_Device_Extension *tw_dev, int parm, int param_size,
3246 unsigned char *val)
3248 TW_Param *param;
3249 TW_Command *command_packet;
3250 TW_Response_Queue response_queue;
3251 int request_id = 0;
3252 unsigned long command_que_value;
3253 u32 command_que_addr;
3254 u32 response_que_addr;
3255 unsigned long param_value;
3257 /* Initialize SetParam command packet */
3258 if (tw_dev->command_packet_virtual_address[request_id] == NULL) {
3259 printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad command packet virtual address.\n");
3260 return 1;
3262 command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
3263 memset(command_packet, 0, sizeof(TW_Sector));
3264 param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
3266 command_packet->byte0.opcode = TW_OP_SET_PARAM;
3267 command_packet->byte0.sgl_offset = 2;
3268 param->table_id = 0x404; /* Features table */
3269 param->parameter_id = parm;
3270 param->parameter_size_bytes = param_size;
3271 memcpy(param->data, val, param_size);
3273 param_value = tw_dev->alignment_physical_address[request_id];
3274 if (param_value == 0) {
3275 printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Bad alignment physical address.\n");
3276 tw_dev->state[request_id] = TW_S_COMPLETED;
3277 tw_state_request_finish(tw_dev, request_id);
3278 tw_dev->srb[request_id]->result = (DID_OK << 16);
3279 tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
3281 command_packet->byte8.param.sgl[0].address = param_value;
3282 command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
3284 command_packet->size = 4;
3285 command_packet->request_id = request_id;
3286 command_packet->byte6.parameter_count = 1;
3288 command_que_value = tw_dev->command_packet_physical_address[request_id];
3289 if (command_que_value == 0) {
3290 printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad command packet physical address.\n");
3291 return 1;
3293 command_que_addr = tw_dev->registers.command_que_addr;
3294 response_que_addr = tw_dev->registers.response_que_addr;
3296 /* Send command packet to the board */
3297 outl(command_que_value, command_que_addr);
3299 /* Poll for completion */
3300 if (tw_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, 30) == 0) {
3301 response_queue.value = inl(response_que_addr);
3302 request_id = (unsigned char)response_queue.u.response_id;
3303 if (request_id != 0) {
3304 /* unexpected request id */
3305 printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Unexpected request id.\n");
3306 return 1;
3308 if (command_packet->status != 0) {
3309 /* bad response */
3310 tw_decode_sense(tw_dev, request_id, 0);
3311 return 1;
3315 return 0;
3316 } /* End tw_setfeature() */
3318 /* This function will setup the interrupt handler */
3319 int tw_setup_irq(TW_Device_Extension *tw_dev)
3321 char *device = TW_DEVICE_NAME;
3322 int error;
3324 dprintk(KERN_NOTICE "3w-xxxx: tw_setup_irq()\n");
3325 error = request_irq(tw_dev->tw_pci_dev->irq, tw_interrupt, SA_SHIRQ, device, tw_dev);
3327 if (error < 0) {
3328 printk(KERN_WARNING "3w-xxxx: scsi%d: Error requesting IRQ: %d.\n", tw_dev->host->host_no, tw_dev->tw_pci_dev->irq);
3329 return 1;
3331 return 0;
3332 } /* End tw_setup_irq() */
3334 /* This function will tell the controller we're shutting down by sending
3335 initconnection with a 1 */
3336 int tw_shutdown_device(TW_Device_Extension *tw_dev)
3338 int error;
3340 /* Disable interrupts */
3341 tw_disable_interrupts(tw_dev);
3343 /* poke the board */
3344 error = tw_initconnection(tw_dev, 1);
3345 if (error) {
3346 printk(KERN_WARNING "3w-xxxx: scsi%d: Connection shutdown failed.\n", tw_dev->host->host_no);
3347 } else {
3348 printk(KERN_NOTICE "3w-xxxx: Shutdown complete.\n");
3351 /* Re-enable interrupts */
3352 tw_enable_and_clear_interrupts(tw_dev);
3354 return 0;
3355 } /* End tw_shutdown_device() */
3357 /* This function will soft reset the controller */
3358 void tw_soft_reset(TW_Device_Extension *tw_dev)
3360 u32 control_reg_addr, control_reg_value;
3362 control_reg_addr = tw_dev->registers.control_reg_addr;
3363 control_reg_value = ( TW_CONTROL_ISSUE_SOFT_RESET |
3364 TW_CONTROL_CLEAR_HOST_INTERRUPT |
3365 TW_CONTROL_CLEAR_ATTENTION_INTERRUPT |
3366 TW_CONTROL_MASK_COMMAND_INTERRUPT |
3367 TW_CONTROL_MASK_RESPONSE_INTERRUPT |
3368 TW_CONTROL_CLEAR_ERROR_STATUS |
3369 TW_CONTROL_DISABLE_INTERRUPTS);
3370 outl(control_reg_value, control_reg_addr);
3371 } /* End tw_soft_reset() */
3373 /* This function will free a request_id */
3374 int tw_state_request_finish(TW_Device_Extension *tw_dev, int request_id)
3376 dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_finish()\n");
3378 tw_dev->free_queue[tw_dev->free_tail] = request_id;
3379 tw_dev->state[request_id] = TW_S_FINISHED;
3380 if (tw_dev->free_tail == tw_dev->free_wrap)
3381 tw_dev->free_tail = TW_Q_START;
3382 else
3383 tw_dev->free_tail++;
3385 dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_finish(): Freeing request_id %d\n", request_id);
3387 return 0;
3388 } /* End tw_state_request_finish() */
3390 /* This function will assign an available request_id */
3391 int tw_state_request_start(TW_Device_Extension *tw_dev, int *request_id)
3393 int id = 0;
3395 dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_start()\n");
3397 /* Obtain next free request_id */
3398 id = tw_dev->free_queue[tw_dev->free_head];
3399 if (tw_dev->free_head == tw_dev->free_wrap)
3400 tw_dev->free_head = TW_Q_START;
3401 else
3402 tw_dev->free_head++;
3404 *request_id = id;
3405 tw_dev->state[id] = TW_S_STARTED;
3407 dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_start(): id = %d.\n", id);
3408 return 0;
3409 } /* End tw_state_request_start() */
3411 static void tw_unmap_scsi_data(struct pci_dev *pdev, Scsi_Cmnd *cmd)
3413 int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
3415 dprintk(KERN_WARNING "3w-xxxx: tw_unmap_scsi_data()\n");
3417 switch(cmd->SCp.phase) {
3418 case 1:
3419 pci_unmap_page(pdev, cmd->SCp.have_data_in, cmd->request_bufflen, dma_dir);
3420 break;
3421 case 2:
3422 pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, dma_dir);
3423 break;
3425 } /* End tw_unmap_scsi_data() */
3427 /* This function will unmask the command interrupt on the controller */
3428 void tw_unmask_command_interrupt(TW_Device_Extension *tw_dev)
3430 u32 control_reg_addr, control_reg_value;
3432 control_reg_addr = tw_dev->registers.control_reg_addr;
3433 control_reg_value = TW_CONTROL_UNMASK_COMMAND_INTERRUPT;
3434 outl(control_reg_value, control_reg_addr);
3435 } /* End tw_unmask_command_interrupt() */
3437 static Scsi_Host_Template driver_template = {
3438 .proc_name = "3w-xxxx",
3439 .proc_info = tw_scsi_proc_info,
3440 .name = "3ware Storage Controller",
3441 .detect = tw_scsi_detect,
3442 .release = tw_scsi_release,
3443 .queuecommand = tw_scsi_queue,
3444 .eh_abort_handler = tw_scsi_eh_abort,
3445 .eh_host_reset_handler = tw_scsi_eh_reset,
3446 .bios_param = tw_scsi_biosparam,
3447 .can_queue = TW_Q_LENGTH-2,
3448 .this_id = -1,
3449 .sg_tablesize = TW_MAX_SGL_LENGTH,
3450 .max_sectors = TW_MAX_SECTORS,
3451 .cmd_per_lun = TW_MAX_CMDS_PER_LUN,
3452 .use_clustering = ENABLE_CLUSTERING,
3453 .emulated = 1,
3454 .highmem_io = 1,
3456 #include "scsi_module.c"