OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [scsi/] [3w-xxxx.c] - Blame information for rev 1774

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
   3w-xxxx.c -- 3ware Storage Controller device driver for Linux.
3
 
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>
8
 
9
   Copyright (C) 1999-2003 3ware Inc.
10
 
11
   Kernel compatablity By:      Andre Hedrick <andre@suse.com>
12
   Non-Copyright (C) 2000       Andre Hedrick <andre@suse.com>
13
 
14
   Further tiny build fixes and trivial hoovering    Alan Cox
15
 
16
   This program is free software; you can redistribute it and/or modify
17
   it under the terms of the GNU General Public License as published by
18
   the Free Software Foundation; version 2 of the License.
19
 
20
   This program is distributed in the hope that it will be useful,
21
   but WITHOUT ANY WARRANTY; without even the implied warranty of
22
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
   GNU General Public License for more details.
24
 
25
   NO WARRANTY
26
   THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
27
   CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
28
   LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
29
   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
30
   solely responsible for determining the appropriateness of using and
31
   distributing the Program and assumes all risks associated with its
32
   exercise of rights under this Agreement, including but not limited to
33
   the risks and costs of program errors, damage to or loss of data,
34
   programs or equipment, and unavailability or interruption of operations.
35
 
36
   DISCLAIMER OF LIABILITY
37
   NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
38
   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39
   DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
40
   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
41
   TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
42
   USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
43
   HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
44
 
45
   You should have received a copy of the GNU General Public License
46
   along with this program; if not, write to the Free Software
47
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
48
 
49
   Bugs/Comments/Suggestions should be mailed to:
50
   linux@3ware.com
51
 
52
   For more information, goto:
53
   http://www.3ware.com
54
 
55
   History
56
   -------
57
   0.1.000 -     Initial release.
58
   0.4.000 -     Added support for Asynchronous Event Notification through
59
                 ioctls for 3DM.
60
   1.0.000 -     Added DPO & FUA bit support for WRITE_10 & WRITE_6 cdb
61
                 to disable drive write-cache before writes.
62
   1.1.000 -     Fixed performance bug with DPO & FUA not existing for WRITE_6.
63
   1.2.000 -     Added support for clean shutdown notification/feature table.
64
   1.02.00.001 - Added support for full command packet posts through ioctls
65
                 for 3DM.
66
                 Bug fix so hot spare drives don't show up.
67
   1.02.00.002 - Fix bug with tw_setfeature() call that caused oops on some
68
                 systems.
69
   08/21/00    - release previously allocated resources on failure at
70
                 tw_allocate_memory (acme)
71
   1.02.00.003 - Fix tw_interrupt() to report error to scsi layer when
72
                 controller status is non-zero.
73
                 Added handling of request_sense opcode.
74
                 Fix possible null pointer dereference in
75
                 tw_reset_device_extension()
76
   1.02.00.004 - Add support for device id of 3ware 7000 series controllers.
77
                 Make tw_setfeature() call with interrupts disabled.
78
                 Register interrupt handler before enabling interrupts.
79
                 Clear attention interrupt before draining aen queue.
80
   1.02.00.005 - Allocate bounce buffers and custom queue depth for raid5 for
81
                 6000 and 5000 series controllers.
82
                 Reduce polling mdelays causing problems on some systems.
83
                 Fix use_sg = 1 calculation bug.
84
                 Check for scsi_register returning NULL.
85
                 Add aen count to /proc/scsi/3w-xxxx.
86
                 Remove aen code unit masking in tw_aen_complete().
87
   1.02.00.006 - Remove unit from printk in tw_scsi_eh_abort(), causing
88
                 possible oops.
89
                 Fix possible null pointer dereference in tw_scsi_queue()
90
                 if done function pointer was invalid.
91
   1.02.00.007 - Fix possible null pointer dereferences in tw_ioctl().
92
                 Remove check for invalid done function pointer from
93
                 tw_scsi_queue().
94
   1.02.00.008 - Set max sectors per io to TW_MAX_SECTORS in tw_findcards().
95
                 Add tw_decode_error() for printing readable error messages.
96
                 Print some useful information on certain aen codes.
97
                 Add tw_decode_bits() for interpreting status register output.
98
                 Make scsi_set_pci_device() for kernels >= 2.4.4
99
                 Fix bug where aen's could be lost before a reset.
100
                 Re-add spinlocks in tw_scsi_detect().
101
                 Fix possible null pointer dereference in tw_aen_drain_queue()
102
                 during initialization.
103
                 Clear pci parity errors during initialization and during io.
104
   1.02.00.009 - Remove redundant increment in tw_state_request_start().
105
                 Add ioctl support for direct ATA command passthru.
106
                 Add entire aen code string list.
107
   1.02.00.010 - Cleanup queueing code, fix jbod thoughput.
108
                 Fix get_param for specific units.
109
   1.02.00.011 - Fix bug in tw_aen_complete() where aen's could be lost.
110
                 Fix tw_aen_drain_queue() to display useful info at init.
111
                 Set tw_host->max_id for 12 port cards.
112
                 Add ioctl support for raw command packet post from userspace
113
                 with sglist fragments (parameter and io).
114
   1.02.00.012 - Fix read capacity to under report by 1 sector to fix get
115
                 last sector ioctl.
116
   1.02.00.013 - Fix bug where more AEN codes weren't coming out during
117
                 driver initialization.
118
                 Improved handling of PCI aborts.
119
   1.02.00.014 - Fix bug in tw_findcards() where AEN code could be lost.
120
                 Increase timeout in tw_aen_drain_queue() to 30 seconds.
121
   1.02.00.015 - Re-write raw command post with data ioctl method.
122
   1.02.00.016 - Set max_cmd_len for 3dm.
123
                 Set max sectors to 256 for non raid5 & 6XXX.
124
   1.02.00.017 - Modified pci parity error handling/clearing from config space
125
                 during initialization.
126
   1.02.00.018 - Better handling of request sense opcode and sense information
127
                 for failed commands.  Add tw_decode_sense().
128
                 Replace all mdelay()'s with scsi_sleep().
129
   1.02.00.019 - Revert mdelay's and scsi_sleep's, this caused problems on
130
                 some SMP systems.
131
   1.02.00.020 - Bump cmd_per_lun in SHT to 255 for better jbod performance.
132
                 Make module license ifdef'd for backward compatibility.
133
                 Improve handling of errors in tw_interrupt().
134
                 Add handling/clearing of controller queue error.
135
                 Better alignment checking in tw_allocate_memory().
136
                 Cleanup tw_initialize_device_extension().
137
                 Empty stale responses before draining aen queue.
138
                 Fix tw_scsi_eh_abort() to not reset on every io abort.
139
                 Set can_queue in SHT to 255 to prevent hang from AEN.
140
   1.02.00.021 - Fix possible null pointer dereference in tw_scsi_release().
141
   1.02.00.022 - Fix bug in tw_aen_drain_queue() where unit # was always zero.
142
   1.02.00.023 - Add severity levels to AEN strings.
143
   1.02.00.024 - Fix command interrupt spurious error messages.
144
                 Fix bug in raw command post with data ioctl method.
145
                 Fix bug where rollcall sometimes failed with cable errors.
146
   1.02.00.025 - Print unit # on all command timeouts.
147
   1.02.00.026 - Fix possible infinite retry bug with power glitch induced
148
                 drive timeouts.
149
                 Cleanup some AEN severity levels.
150
   1.02.00.027 - Add drive not supported AEN code for SATA controllers.
151
                 Remove spurious unknown ioctl error message.
152
   1.02.00.028 - Fix bug where multiple controllers with no units were the
153
                 same card number.
154
                 Fix bug where cards were being shut down more than once.
155
   1.02.00.029 - Add new pci dma mapping for kernel 2.4 for highmem support.
156
                 Replace pci_map_single() with pci_map_page() for highmem.
157
                 Check for tw_setfeature() failure.
158
   1.02.00.030 - Make driver 64-bit clean.
159
   1.02.00.031 - Cleanup polling timeouts/routines in several places.
160
                 Add support for mode sense opcode.
161
                 Add support for cache mode page.
162
                 Add support for synchronize cache opcode.
163
   1.02.00.032 - Fix small multicard rollcall bug.
164
                 Make driver stay loaded with no units for hot add/swap.
165
                 Add support for "twe" character device for ioctls.
166
                 Clean up request_id queueing code.
167
                 Fix tw_scsi_queue() spinlocks.
168
   1.02.00.033 - Fix tw_aen_complete() to not queue 'queue empty' AEN's.
169
                 Initialize queues correctly when loading with no valid units.
170
   1.02.00.034 - Fix tw_decode_bits() to handle multiple errors.
171
                 Add support for user configurable cmd_per_lun.
172
                 Add support for sht->select_queue_depths.
173
   1.02.00.035 - Improve tw_allocate_memory() memory allocation.
174
                 Fix tw_chrdev_ioctl() to sleep correctly.
175
   1.02.00.036 - Increase character ioctl timeout to 60 seconds.
176
   1.02.00.037 - Fix tw_ioctl() to handle all non-data ATA passthru cmds
177
                 for 'smartmontools' support.
178
*/
179
 
180
#include <linux/module.h>
181
 
182
MODULE_AUTHOR ("3ware Inc.");
183
#ifdef CONFIG_SMP
184
MODULE_DESCRIPTION ("3ware Storage Controller Linux Driver (SMP)");
185
#else
186
MODULE_DESCRIPTION ("3ware Storage Controller Linux Driver");
187
#endif
188
 
189
#include <linux/kernel.h>
190
#include <linux/pci.h>
191
#include <linux/time.h>
192
#include <linux/proc_fs.h>
193
#include <linux/sched.h>
194
#include <linux/ioport.h>
195
#include <linux/blk.h>
196
#include <linux/hdreg.h>
197
#include <linux/string.h>
198
#include <linux/delay.h>
199
#include <linux/smp.h>
200
#include <linux/reboot.h>
201
#include <linux/spinlock.h>
202
 
203
#include <asm/errno.h>
204
#include <asm/io.h>
205
#include <asm/irq.h>
206
#include <asm/uaccess.h>
207
 
208
#define __3W_C                  /* let 3w-xxxx.h know it is use */
209
 
210
#include "sd.h"
211
#include "scsi.h"
212
#include "hosts.h"
213
 
214
#include "3w-xxxx.h"
215
 
216
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,10)
217
MODULE_LICENSE("GPL");
218
#endif
219
 
220
static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
221
static int tw_chrdev_open(struct inode *inode, struct file *file);
222
static int tw_chrdev_release(struct inode *inode, struct file *file);
223
static int tw_copy_info(TW_Info *info, char *fmt, ...);
224
static void tw_copy_mem_info(TW_Info *info, char *data, int len);
225
static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
226
static int tw_halt(struct notifier_block *nb, ulong event, void *buf);
227
static int tw_map_scsi_sg_data(struct pci_dev *pdev, Scsi_Cmnd *cmd);
228
static u32 tw_map_scsi_single_data(struct pci_dev *pdev, Scsi_Cmnd *cmd);
229
static void tw_unmap_scsi_data(struct pci_dev *pdev, Scsi_Cmnd *cmd);
230
 
231
/* Notifier block to get a notify on system shutdown/halt/reboot */
232
static struct notifier_block tw_notifier = {
233
        tw_halt, NULL, 0
234
};
235
 
236
/* File operations struct for character device */
237
static struct file_operations tw_fops = {
238
        owner: THIS_MODULE,
239
        ioctl: tw_chrdev_ioctl,
240
        open: tw_chrdev_open,
241
        release: tw_chrdev_release
242
};
243
 
244
/* Globals */
245
char *tw_driver_version="1.02.00.037";
246
TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
247
int tw_device_extension_count = 0;
248
static int twe_major = -1;
249
 
250
/* Functions */
251
 
252
/* This function will complete an aen request from the isr */
253
int tw_aen_complete(TW_Device_Extension *tw_dev, int request_id)
254
{
255
        TW_Param *param;
256
        unsigned short aen;
257
        int error = 0, table_max = 0;
258
 
259
        dprintk(KERN_WARNING "3w-xxxx: tw_aen_complete()\n");
260
        if (tw_dev->alignment_virtual_address[request_id] == NULL) {
261
                printk(KERN_WARNING "3w-xxxx: tw_aen_complete(): Bad alignment virtual address.\n");
262
                return 1;
263
        }
264
        param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
265
        aen = *(unsigned short *)(param->data);
266
        dprintk(KERN_NOTICE "3w-xxxx: tw_aen_complete(): Queue'd code 0x%x\n", aen);
267
 
268
        /* Print some useful info when certain aen codes come out */
269
        if (aen == 0x0ff) {
270
                printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: INFO: AEN queue overflow.\n", tw_dev->host->host_no);
271
        } else {
272
                table_max = sizeof(tw_aen_string)/sizeof(char *);
273
                if ((aen & 0x0ff) < table_max) {
274
                        if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') {
275
                                printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: %s%d.\n", tw_dev->host->host_no, tw_aen_string[aen & 0xff], aen >> 8);
276
                        } else {
277
                                if (aen != 0x0)
278
                                        printk(KERN_WARNING "3w-xxxx: scsi%d: AEN: %s.\n", tw_dev->host->host_no, tw_aen_string[aen & 0xff]);
279
                        }
280
                } else {
281
                        printk(KERN_WARNING "3w-xxxx: scsi%d: Received AEN %d.\n", tw_dev->host->host_no, aen);
282
                }
283
        }
284
        if (aen != TW_AEN_QUEUE_EMPTY) {
285
                tw_dev->aen_count++;
286
 
287
                /* Now queue the code */
288
                tw_dev->aen_queue[tw_dev->aen_tail] = aen;
289
                if (tw_dev->aen_tail == TW_Q_LENGTH - 1) {
290
                        tw_dev->aen_tail = TW_Q_START;
291
                } else {
292
                        tw_dev->aen_tail = tw_dev->aen_tail + 1;
293
                }
294
                if (tw_dev->aen_head == tw_dev->aen_tail) {
295
                        if (tw_dev->aen_head == TW_Q_LENGTH - 1) {
296
                                tw_dev->aen_head = TW_Q_START;
297
                        } else {
298
                                tw_dev->aen_head = tw_dev->aen_head + 1;
299
                        }
300
                }
301
 
302
                error = tw_aen_read_queue(tw_dev, request_id);
303
                if (error) {
304
                        printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing AEN.\n", tw_dev->host->host_no);
305
                        tw_dev->state[request_id] = TW_S_COMPLETED;
306
                        tw_state_request_finish(tw_dev, request_id);
307
                }
308
        } else {
309
                tw_dev->state[request_id] = TW_S_COMPLETED;
310
                tw_state_request_finish(tw_dev, request_id);
311
        }
312
 
313
        return 0;
314
} /* End tw_aen_complete() */
315
 
316
/* This function will drain the aen queue after a soft reset */
317
int tw_aen_drain_queue(TW_Device_Extension *tw_dev)
318
{
319
        TW_Command *command_packet;
320
        TW_Param *param;
321
        int request_id = 0;
322
        u32 command_que_addr;
323
        unsigned long command_que_value;
324
        unsigned long param_value;
325
        TW_Response_Queue response_queue;
326
        u32 response_que_addr;
327
        unsigned short aen;
328
        unsigned short aen_code;
329
        int finished = 0;
330
        int first_reset = 0;
331
        int queue = 0;
332
        int found = 0, table_max = 0;
333
 
334
        dprintk(KERN_NOTICE "3w-xxxx: tw_aen_drain_queue()\n");
335
 
336
        command_que_addr = tw_dev->registers.command_que_addr;
337
        response_que_addr = tw_dev->registers.response_que_addr;
338
 
339
        if (tw_poll_status(tw_dev, TW_STATUS_ATTENTION_INTERRUPT | TW_STATUS_MICROCONTROLLER_READY, 30)) {
340
                dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): No attention interrupt for card %d.\n", tw_device_extension_count);
341
                return 1;
342
        }
343
        tw_clear_attention_interrupt(tw_dev);
344
 
345
        /* Empty response queue */
346
        tw_empty_response_que(tw_dev);
347
 
348
        /* Initialize command packet */
349
        if (tw_dev->command_packet_virtual_address[request_id] == NULL) {
350
                printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad command packet virtual address.\n");
351
                return 1;
352
        }
353
        command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
354
        memset(command_packet, 0, sizeof(TW_Sector));
355
        command_packet->byte0.opcode = TW_OP_GET_PARAM;
356
        command_packet->byte0.sgl_offset = 2;
357
        command_packet->size = 4;
358
        command_packet->request_id = request_id;
359
        command_packet->byte3.unit = 0;
360
        command_packet->byte3.host_id = 0;
361
        command_packet->status = 0;
362
        command_packet->flags = 0;
363
        command_packet->byte6.parameter_count = 1;
364
        command_que_value = tw_dev->command_packet_physical_address[request_id];
365
        if (command_que_value == 0) {
366
                printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad command packet physical address.\n");
367
                return 1;
368
        }
369
 
370
        /* Now setup the param */
371
        if (tw_dev->alignment_virtual_address[request_id] == NULL) {
372
                printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad alignment virtual address.\n");
373
                return 1;
374
        }
375
        param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
376
        memset(param, 0, sizeof(TW_Sector));
377
        param->table_id = 0x401; /* AEN table */
378
        param->parameter_id = 2; /* Unit code */
379
        param->parameter_size_bytes = 2;
380
        param_value = tw_dev->alignment_physical_address[request_id];
381
        if (param_value == 0) {
382
                printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad alignment physical address.\n");
383
                return 1;
384
        }
385
        command_packet->byte8.param.sgl[0].address = param_value;
386
        command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
387
 
388
        /* Now drain the controller's aen queue */
389
        do {
390
                /* Post command packet */
391
                outl(command_que_value, command_que_addr);
392
 
393
                /* Now poll for completion */
394
                if (tw_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, 30) == 0) {
395
                        response_queue.value = inl(response_que_addr);
396
                        request_id = (unsigned char)response_queue.u.response_id;
397
                        if (request_id != 0) {
398
                                /* Unexpected request id */
399
                                printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Unexpected request id.\n");
400
                                return 1;
401
                        }
402
 
403
                        if (command_packet->status != 0) {
404
                                if (command_packet->flags != TW_AEN_TABLE_UNDEFINED) {
405
                                        /* Bad response */
406
                                        tw_decode_sense(tw_dev, request_id, 0);
407
                                        return 1;
408
                                } else {
409
                                        /* We know this is a 3w-1x00, and doesn't support aen's */
410
                                        return 0;
411
                                }
412
                        }
413
 
414
                        /* Now check the aen */
415
                        aen = *(unsigned short *)(param->data);
416
                        aen_code = (aen & 0x0ff);
417
                        queue = 0;
418
                        switch (aen_code) {
419
                                case TW_AEN_QUEUE_EMPTY:
420
                                        dprintk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]);
421
                                        if (first_reset != 1) {
422
                                                return 1;
423
                                        } else {
424
                                                finished = 1;
425
                                        }
426
                                        break;
427
                                case TW_AEN_SOFT_RESET:
428
                                        if (first_reset == 0) {
429
                                                first_reset = 1;
430
                                        } else {
431
                                                printk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]);
432
                                                tw_dev->aen_count++;
433
                                                queue = 1;
434
                                        }
435
                                        break;
436
                                default:
437
                                        if (aen == 0x0ff) {
438
                                                printk(KERN_WARNING "3w-xxxx: AEN: INFO: AEN queue overflow.\n");
439
                                        } else {
440
                                                table_max = sizeof(tw_aen_string)/sizeof(char *);
441
                                                if ((aen & 0x0ff) < table_max) {
442
                                                        if ((tw_aen_string[aen & 0xff][strlen(tw_aen_string[aen & 0xff])-1]) == '#') {
443
                                                                printk(KERN_WARNING "3w-xxxx: AEN: %s%d.\n", tw_aen_string[aen & 0xff], aen >> 8);
444
                                                        } else {
445
                                                                printk(KERN_WARNING "3w-xxxx: AEN: %s.\n", tw_aen_string[aen & 0xff]);
446
                                                        }
447
                                                } else
448
                                                        printk(KERN_WARNING "3w-xxxx: Received AEN %d.\n", aen);
449
                                        }
450
                                        tw_dev->aen_count++;
451
                                        queue = 1;
452
                        }
453
 
454
                        /* Now put the aen on the aen_queue */
455
                        if (queue == 1) {
456
                                tw_dev->aen_queue[tw_dev->aen_tail] = aen;
457
                                if (tw_dev->aen_tail == TW_Q_LENGTH - 1) {
458
                                        tw_dev->aen_tail = TW_Q_START;
459
                                } else {
460
                                        tw_dev->aen_tail = tw_dev->aen_tail + 1;
461
                                }
462
                                if (tw_dev->aen_head == tw_dev->aen_tail) {
463
                                        if (tw_dev->aen_head == TW_Q_LENGTH - 1) {
464
                                                tw_dev->aen_head = TW_Q_START;
465
                                        } else {
466
                                                tw_dev->aen_head = tw_dev->aen_head + 1;
467
                                        }
468
                                }
469
                        }
470
                        found = 1;
471
                }
472
                if (found == 0) {
473
                        printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Response never received.\n");
474
                        return 1;
475
                }
476
        } while (finished == 0);
477
 
478
        return 0;
479
} /* End tw_aen_drain_queue() */
480
 
481
/* This function will read the aen queue from the isr */
482
int tw_aen_read_queue(TW_Device_Extension *tw_dev, int request_id)
483
{
484
        TW_Command *command_packet;
485
        TW_Param *param;
486
        u32 command_que_addr;
487
        unsigned long command_que_value;
488
        u32 status_reg_value = 0, status_reg_addr;
489
        unsigned long param_value = 0;
490
 
491
        dprintk(KERN_NOTICE "3w-xxxx: tw_aen_read_queue()\n");
492
        command_que_addr = tw_dev->registers.command_que_addr;
493
        status_reg_addr = tw_dev->registers.status_reg_addr;
494
 
495
        status_reg_value = inl(status_reg_addr);
496
        if (tw_check_bits(status_reg_value)) {
497
                dprintk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Unexpected bits.\n");
498
                tw_decode_bits(tw_dev, status_reg_value, 1);
499
                return 1;
500
        }
501
        if (tw_dev->command_packet_virtual_address[request_id] == NULL) {
502
                printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Bad command packet virtual address.\n");
503
                return 1;
504
        }
505
        command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
506
        memset(command_packet, 0, sizeof(TW_Sector));
507
        command_packet->byte0.opcode = TW_OP_GET_PARAM;
508
        command_packet->byte0.sgl_offset = 2;
509
        command_packet->size = 4;
510
        command_packet->request_id = request_id;
511
        command_packet->byte3.unit = 0;
512
        command_packet->byte3.host_id = 0;
513
        command_packet->status = 0;
514
        command_packet->flags = 0;
515
        command_packet->byte6.parameter_count = 1;
516
        command_que_value = tw_dev->command_packet_physical_address[request_id];
517
        if (command_que_value == 0) {
518
                printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Bad command packet physical address.\n");
519
                return 1;
520
        }
521
        /* Now setup the param */
522
        if (tw_dev->alignment_virtual_address[request_id] == NULL) {
523
                printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Bad alignment virtual address.\n");
524
                return 1;
525
        }
526
        param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
527
        memset(param, 0, sizeof(TW_Sector));
528
        param->table_id = 0x401; /* AEN table */
529
        param->parameter_id = 2; /* Unit code */
530
        param->parameter_size_bytes = 2;
531
        param_value = tw_dev->alignment_physical_address[request_id];
532
        if (param_value == 0) {
533
                printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Bad alignment physical address.\n");
534
                return 1;
535
        }
536
        command_packet->byte8.param.sgl[0].address = param_value;
537
        command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
538
 
539
        /* Now post the command packet */
540
        if ((status_reg_value & TW_STATUS_COMMAND_QUEUE_FULL) == 0) {
541
                dprintk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Post succeeded.\n");
542
                tw_dev->srb[request_id] = 0; /* Flag internal command */
543
                tw_dev->state[request_id] = TW_S_POSTED;
544
                outl(command_que_value, command_que_addr);
545
        } else {
546
                printk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Post failed, will retry.\n");
547
                return 1;
548
        }
549
 
550
        return 0;
551
} /* End tw_aen_read_queue() */
552
 
553
/* This function will allocate memory and check if it is 16 d-word aligned */
554
int tw_allocate_memory(TW_Device_Extension *tw_dev, int size, int which)
555
{
556
        int i, imax;
557
        dma_addr_t dma_handle;
558
        unsigned long *cpu_addr = NULL;
559
 
560
        dprintk(KERN_NOTICE "3w-xxxx: tw_allocate_memory()\n");
561
 
562
 
563
        if (which == 2)
564
                imax = TW_MAX_BOUNCEBUF;
565
        else
566
                imax = TW_Q_LENGTH;
567
 
568
        cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, size*imax, &dma_handle);
569
        if (cpu_addr == NULL) {
570
                printk(KERN_WARNING "3w-xxxx: pci_alloc_consistent() failed.\n");
571
                return 1;
572
        }
573
 
574
        if ((unsigned long)cpu_addr % (tw_dev->tw_pci_dev->device == TW_DEVICE_ID ? TW_ALIGNMENT_6000 : TW_ALIGNMENT_7000)) {
575
                printk(KERN_WARNING "3w-xxxx: Couldn't allocate correctly aligned memory.\n");
576
                pci_free_consistent(tw_dev->tw_pci_dev, size*imax, cpu_addr, dma_handle);
577
                return 1;
578
        }
579
 
580
        memset(cpu_addr, 0, size*imax);
581
 
582
        for (i=0;i<imax;i++) {
583
                switch(which) {
584
                case 0:
585
                        tw_dev->command_packet_physical_address[i] = dma_handle+(i*size);
586
                        tw_dev->command_packet_virtual_address[i] = (unsigned long *)((unsigned char *)cpu_addr + (i*size));
587
                        break;
588
                case 1:
589
                        tw_dev->alignment_physical_address[i] = dma_handle+(i*size);
590
                        tw_dev->alignment_virtual_address[i] = (unsigned long *)((unsigned char *)cpu_addr + (i*size));
591
                        break;
592
                case 2:
593
                        tw_dev->bounce_buffer_phys[i] = dma_handle+(i*size);
594
                        tw_dev->bounce_buffer[i] = (unsigned long *)((unsigned char *)cpu_addr + (i*size));
595
                        break;
596
                default:
597
                        printk(KERN_WARNING "3w-xxxx: tw_allocate_memory(): case slip in tw_allocate_memory()\n");
598
                        return 1;
599
                }
600
        }
601
 
602
        return 0;
603
} /* End tw_allocate_memory() */
604
 
605
/* This function will check the status register for unexpected bits */
606
int tw_check_bits(u32 status_reg_value)
607
{
608
        if ((status_reg_value & TW_STATUS_EXPECTED_BITS) != TW_STATUS_EXPECTED_BITS) {
609
                dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): No expected bits (0x%x).\n", status_reg_value);
610
                return 1;
611
        }
612
        if ((status_reg_value & TW_STATUS_UNEXPECTED_BITS) != 0) {
613
                dprintk(KERN_WARNING "3w-xxxx: tw_check_bits(): Found unexpected bits (0x%x).\n", status_reg_value);
614
                return 1;
615
        }
616
 
617
        return 0;
618
} /* End tw_check_bits() */
619
 
620
/* This function will report controller error status */
621
int tw_check_errors(TW_Device_Extension *tw_dev)
622
{
623
        u32 status_reg_addr, status_reg_value;
624
 
625
        status_reg_addr = tw_dev->registers.status_reg_addr;
626
        status_reg_value = inl(status_reg_addr);
627
 
628
        if (TW_STATUS_ERRORS(status_reg_value) || tw_check_bits(status_reg_value)) {
629
                tw_decode_bits(tw_dev, status_reg_value, 0);
630
                return 1;
631
        }
632
 
633
        return 0;
634
} /* End tw_check_errors() */
635
 
636
/* This function handles ioctl for the character device */
637
static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
638
{
639
        int error, request_id;
640
        dma_addr_t dma_handle;
641
        unsigned short tw_aen_code;
642
        unsigned long flags;
643
        unsigned int data_buffer_length = 0;
644
        unsigned long data_buffer_length_adjusted = 0;
645
        unsigned long *cpu_addr;
646
        long timeout;
647
        TW_New_Ioctl *tw_ioctl;
648
        TW_Passthru *passthru;
649
        TW_Device_Extension *tw_dev = tw_device_extension_list[MINOR(inode->i_rdev)];
650
        int retval = -EFAULT;
651
 
652
        dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl()\n");
653
 
654
        /* Only let one of these through at a time */
655
        if (down_interruptible(&tw_dev->ioctl_sem))
656
                return -EINTR;
657
 
658
        /* First copy down the buffer length */
659
        error = copy_from_user(&data_buffer_length, (void *)arg, sizeof(unsigned int));
660
        if (error)
661
                goto out;
662
 
663
        /* Check size */
664
        if (data_buffer_length > TW_MAX_SECTORS * 512) {
665
                retval = -EINVAL;
666
                goto out;
667
        }
668
 
669
        /* Hardware can only do multiple of 512 byte transfers */
670
        data_buffer_length_adjusted = (data_buffer_length + 511) & ~511;
671
 
672
        /* Now allocate ioctl buf memory */
673
        cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, &dma_handle);
674
        if (cpu_addr == NULL) {
675
                retval = -ENOMEM;
676
                goto out;
677
        }
678
 
679
        tw_ioctl = (TW_New_Ioctl *)cpu_addr;
680
 
681
        /* Now copy down the entire ioctl */
682
        error = copy_from_user(tw_ioctl, (void *)arg, data_buffer_length + sizeof(TW_New_Ioctl) - 1);
683
        if (error)
684
                goto out2;
685
 
686
        passthru = (TW_Passthru *)&tw_ioctl->firmware_command;
687
 
688
        /* See which ioctl we are doing */
689
        switch (cmd) {
690
                case TW_OP_NOP:
691
                        dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): caught TW_OP_NOP.\n");
692
                        break;
693
                case TW_OP_AEN_LISTEN:
694
                        dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): caught TW_AEN_LISTEN.\n");
695
                        memset(tw_ioctl->data_buffer, 0, tw_ioctl->data_buffer_length);
696
                        spin_lock_irqsave(&tw_dev->tw_lock, flags);
697
                        if (tw_dev->aen_head == tw_dev->aen_tail) {
698
                                tw_aen_code = TW_AEN_QUEUE_EMPTY;
699
                        } else {
700
                                tw_aen_code = tw_dev->aen_queue[tw_dev->aen_head];
701
                                if (tw_dev->aen_head == TW_Q_LENGTH - 1) {
702
                                        tw_dev->aen_head = TW_Q_START;
703
                                } else {
704
                                        tw_dev->aen_head = tw_dev->aen_head + 1;
705
                                }
706
                        }
707
                        spin_unlock_irqrestore(&tw_dev->tw_lock, flags);
708
                        memcpy(tw_ioctl->data_buffer, &tw_aen_code, sizeof(tw_aen_code));
709
                        break;
710
                case TW_CMD_PACKET_WITH_DATA:
711
                        dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): caught TW_CMD_PACKET_WITH_DATA.\n");
712
                        spin_lock_irqsave(&tw_dev->tw_lock, flags);
713
 
714
                        tw_state_request_start(tw_dev, &request_id);
715
 
716
                        /* Flag internal command */
717
                        tw_dev->srb[request_id] = 0;
718
 
719
                        /* Flag chrdev ioctl */
720
                        tw_dev->chrdev_request_id = request_id;
721
 
722
                        tw_ioctl->firmware_command.request_id = request_id;
723
 
724
                        /* Load the sg list */
725
                        switch (tw_ioctl->firmware_command.byte0.sgl_offset) {
726
                        case 2:
727
                                tw_ioctl->firmware_command.byte8.param.sgl[0].address = dma_handle + sizeof(TW_New_Ioctl) - 1;
728
                                tw_ioctl->firmware_command.byte8.param.sgl[0].length = data_buffer_length_adjusted;
729
                                break;
730
                        case 3:
731
                                tw_ioctl->firmware_command.byte8.io.sgl[0].address = dma_handle + sizeof(TW_New_Ioctl) - 1;
732
                                tw_ioctl->firmware_command.byte8.io.sgl[0].length = data_buffer_length_adjusted;
733
                                break;
734
                        case 5:
735
                                passthru->sg_list[0].address = dma_handle + sizeof(TW_New_Ioctl) - 1;
736
                                passthru->sg_list[0].length = data_buffer_length_adjusted;
737
                                break;
738
                        }
739
 
740
                        memcpy(tw_dev->command_packet_virtual_address[request_id], &(tw_ioctl->firmware_command), sizeof(TW_Command));
741
 
742
                        /* Now post the command packet to the controller */
743
                        tw_post_command_packet(tw_dev, request_id);
744
                        spin_unlock_irqrestore(&tw_dev->tw_lock, flags);
745
 
746
                        timeout = TW_IOCTL_CHRDEV_TIMEOUT*HZ;
747
 
748
                        /* Now wait for the command to complete */
749
                        tw_wait_event_interruptible_timeout(tw_dev->ioctl_wqueue, tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout);
750
 
751
                        /* Check if we timed out, got a signal, or didn't get
752
                           an interrupt */
753
                        if ((timeout <= 0) && (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE)) {
754
                                /* Now we need to reset the board */
755
                                if (timeout == -ERESTARTSYS) {
756
                                        retval = timeout;
757
                                } else {
758
                                        printk(KERN_WARNING "3w-xxxx: scsi%d: Character ioctl (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, cmd);
759
                                        retval = -EIO;
760
                                }
761
                                spin_lock_irqsave(&tw_dev->tw_lock, flags);
762
                                tw_dev->state[request_id] = TW_S_COMPLETED;
763
                                tw_state_request_finish(tw_dev, request_id);
764
                                tw_dev->posted_request_count--;
765
                                if (tw_reset_device_extension(tw_dev)) {
766
                                        printk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): Reset failed for card %d.\n", tw_dev->host->host_no);
767
                                }
768
                                spin_unlock_irqrestore(&tw_dev->tw_lock, flags);
769
                                goto out2;
770
                        }
771
 
772
                        /* Now copy in the command packet response */
773
                        memcpy(&(tw_ioctl->firmware_command), tw_dev->command_packet_virtual_address[request_id], sizeof(TW_Command));
774
 
775
                        /* Now complete the io */
776
                        spin_lock_irqsave(&tw_dev->tw_lock, flags);
777
                        tw_dev->posted_request_count--;
778
                        tw_dev->state[request_id] = TW_S_COMPLETED;
779
                        tw_state_request_finish(tw_dev, request_id);
780
                        spin_unlock_irqrestore(&tw_dev->tw_lock, flags);
781
                        break;
782
                default:
783
                        retval = -ENOTTY;
784
                        goto out2;
785
        }
786
 
787
        /* Now copy the entire response to userspace */
788
        error = copy_to_user((void *)arg, tw_ioctl, sizeof(TW_New_Ioctl) + tw_ioctl->data_buffer_length - 1);
789
        if (error == 0)
790
                retval = 0;
791
out2:
792
        /* Now free ioctl buf memory */
793
        pci_free_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle);
794
out:
795
        up(&tw_dev->ioctl_sem);
796
        return retval;
797
} /* End tw_chrdev_ioctl() */
798
 
799
/* This function handles open for the character device */
800
static int tw_chrdev_open(struct inode *inode, struct file *file)
801
{
802
        unsigned int minor_number;
803
 
804
        dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_open()\n");
805
 
806
        minor_number = MINOR(inode->i_rdev);
807
        if (minor_number >= tw_device_extension_count)
808
                return -ENODEV;
809
 
810
        return 0;
811
} /* End tw_chrdev_open() */
812
 
813
/* This function handles close for the character device */
814
static int tw_chrdev_release(struct inode *inode, struct file *file)
815
{
816
        dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_release()\n");
817
 
818
        return 0;
819
} /* End tw_chrdev_release() */
820
 
821
/* This function will clear all interrupts on the controller */
822
void tw_clear_all_interrupts(TW_Device_Extension *tw_dev)
823
{
824
        u32 control_reg_addr, control_reg_value;
825
 
826
        control_reg_addr = tw_dev->registers.control_reg_addr;
827
        control_reg_value = TW_STATUS_VALID_INTERRUPT;
828
        outl(control_reg_value, control_reg_addr);
829
} /* End tw_clear_all_interrupts() */
830
 
831
/* This function will clear the attention interrupt */
832
void tw_clear_attention_interrupt(TW_Device_Extension *tw_dev)
833
{
834
        u32 control_reg_addr, control_reg_value;
835
 
836
        control_reg_addr = tw_dev->registers.control_reg_addr;
837
        control_reg_value = TW_CONTROL_CLEAR_ATTENTION_INTERRUPT;
838
        outl(control_reg_value, control_reg_addr);
839
} /* End tw_clear_attention_interrupt() */
840
 
841
/* This function will clear the host interrupt */
842
void tw_clear_host_interrupt(TW_Device_Extension *tw_dev)
843
{
844
        u32 control_reg_addr, control_reg_value;
845
 
846
        control_reg_addr = tw_dev->registers.control_reg_addr;
847
        control_reg_value = TW_CONTROL_CLEAR_HOST_INTERRUPT;
848
        outl(control_reg_value, control_reg_addr);
849
} /* End tw_clear_host_interrupt() */
850
 
851
/* This function is called by tw_scsi_proc_info */
852
static int tw_copy_info(TW_Info *info, char *fmt, ...)
853
{
854
        va_list args;
855
        char buf[81];
856
        int len;
857
 
858
        va_start(args, fmt);
859
        len = vsprintf(buf, fmt, args);
860
        va_end(args);
861
        tw_copy_mem_info(info, buf, len);
862
        return len;
863
} /* End tw_copy_info() */
864
 
865
/* This function is called by tw_scsi_proc_info */
866
static void tw_copy_mem_info(TW_Info *info, char *data, int len)
867
{
868
        if (info->position + len > info->length)
869
                len = info->length - info->position;
870
 
871
        if (info->position + len < info->offset) {
872
                info->position += len;
873
                return;
874
        }
875
        if (info->position < info->offset) {
876
                data += (info->offset - info->position);
877
                len  -= (info->offset - info->position);
878
        }
879
        if (len > 0) {
880
                memcpy(info->buffer + info->position, data, len);
881
                info->position += len;
882
        }
883
} /* End tw_copy_mem_info() */
884
 
885
/* This function will print readable messages from status register errors */
886
int tw_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value, int print_host)
887
{
888
        char host[16];
889
 
890
        dprintk(KERN_WARNING "3w-xxxx: tw_decode_bits()\n");
891
 
892
        if (print_host)
893
                sprintf(host, " scsi%d:", tw_dev->host->host_no);
894
        else
895
                host[0] = '\0';
896
 
897
        if (status_reg_value & TW_STATUS_PCI_PARITY_ERROR) {
898
                printk(KERN_WARNING "3w-xxxx:%s PCI Parity Error: clearing.\n", host);
899
                outl(TW_CONTROL_CLEAR_PARITY_ERROR, tw_dev->registers.control_reg_addr);
900
        }
901
 
902
        if (status_reg_value & TW_STATUS_PCI_ABORT) {
903
                printk(KERN_WARNING "3w-xxxx:%s PCI Abort: clearing.\n", host);
904
                outl(TW_CONTROL_CLEAR_PCI_ABORT, tw_dev->registers.control_reg_addr);
905
                pci_write_config_word(tw_dev->tw_pci_dev, PCI_STATUS, TW_PCI_CLEAR_PCI_ABORT);
906
        }
907
 
908
        if (status_reg_value & TW_STATUS_QUEUE_ERROR) {
909
                printk(KERN_WARNING "3w-xxxx:%s Controller Queue Error: clearing.\n", host);
910
                outl(TW_CONTROL_CLEAR_QUEUE_ERROR, tw_dev->registers.control_reg_addr);
911
        }
912
 
913
        if (status_reg_value & TW_STATUS_SBUF_WRITE_ERROR) {
914
                printk(KERN_WARNING "3w-xxxx:%s SBUF Write Error: clearing.\n", host);
915
                outl(TW_CONTROL_CLEAR_SBUF_WRITE_ERROR, tw_dev->registers.control_reg_addr);
916
        }
917
 
918
        if (status_reg_value & TW_STATUS_MICROCONTROLLER_ERROR) {
919
                if (tw_dev->reset_print == 0) {
920
                        printk(KERN_WARNING "3w-xxxx:%s Microcontroller Error: clearing.\n", host);
921
                        tw_dev->reset_print = 1;
922
                }
923
                return 1;
924
        }
925
 
926
        return 0;
927
} /* End tw_decode_bits() */
928
 
929
/* This function will return valid sense buffer information for failed cmds */
930
int tw_decode_sense(TW_Device_Extension *tw_dev, int request_id, int fill_sense)
931
{
932
        int i;
933
        TW_Command *command;
934
 
935
        dprintk(KERN_WARNING "3w-xxxx: tw_decode_sense()\n");
936
        command = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
937
 
938
        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);
939
 
940
        /* Attempt to return intelligent sense information */
941
        if (fill_sense) {
942
                if ((command->status == 0xc7) || (command->status == 0xcb)) {
943
                        for (i=0;i<(sizeof(tw_sense_table)/sizeof(tw_sense_table[0]));i++) {
944
                                if (command->flags == tw_sense_table[i][0]) {
945
 
946
                                        /* Valid bit and 'current errors' */
947
                                        tw_dev->srb[request_id]->sense_buffer[0] = (0x1 << 7 | 0x70);
948
 
949
                                        /* Sense key */
950
                                        tw_dev->srb[request_id]->sense_buffer[2] = tw_sense_table[i][1];
951
 
952
                                        /* Additional sense length */
953
                                        tw_dev->srb[request_id]->sense_buffer[7] = 0xa; /* 10 bytes */
954
 
955
                                        /* Additional sense code */
956
                                        tw_dev->srb[request_id]->sense_buffer[12] = tw_sense_table[i][2];
957
 
958
                                        /* Additional sense code qualifier */
959
                                        tw_dev->srb[request_id]->sense_buffer[13] = tw_sense_table[i][3];
960
 
961
                                        tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
962
                                        return TW_ISR_DONT_RESULT; /* Special case for isr to not over-write result */
963
                                }
964
                        }
965
                }
966
 
967
                /* If no table match, error so we get a reset */
968
                return 1;
969
        }
970
 
971
        return 0;
972
} /* End tw_decode_sense() */
973
 
974
/* This function will disable interrupts on the controller */
975
void tw_disable_interrupts(TW_Device_Extension *tw_dev)
976
{
977
        u32 control_reg_value, control_reg_addr;
978
 
979
        control_reg_addr = tw_dev->registers.control_reg_addr;
980
        control_reg_value = TW_CONTROL_DISABLE_INTERRUPTS;
981
        outl(control_reg_value, control_reg_addr);
982
} /* End tw_disable_interrupts() */
983
 
984
/* This function will empty the response que */
985
void tw_empty_response_que(TW_Device_Extension *tw_dev)
986
{
987
        u32 status_reg_addr, status_reg_value;
988
        u32 response_que_addr, response_que_value;
989
 
990
        status_reg_addr = tw_dev->registers.status_reg_addr;
991
        response_que_addr = tw_dev->registers.response_que_addr;
992
 
993
        status_reg_value = inl(status_reg_addr);
994
 
995
        while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
996
                response_que_value = inl(response_que_addr);
997
                status_reg_value = inl(status_reg_addr);
998
        }
999
} /* End tw_empty_response_que() */
1000
 
1001
/* This function will enable interrupts on the controller */
1002
void tw_enable_interrupts(TW_Device_Extension *tw_dev)
1003
{
1004
        u32 control_reg_value, control_reg_addr;
1005
 
1006
        control_reg_addr = tw_dev->registers.control_reg_addr;
1007
        control_reg_value = (TW_CONTROL_ENABLE_INTERRUPTS |
1008
                             TW_CONTROL_UNMASK_RESPONSE_INTERRUPT);
1009
        outl(control_reg_value, control_reg_addr);
1010
} /* End tw_enable_interrupts() */
1011
 
1012
/* This function will enable interrupts on the controller */
1013
void tw_enable_and_clear_interrupts(TW_Device_Extension *tw_dev)
1014
{
1015
        u32 control_reg_value, control_reg_addr;
1016
 
1017
        control_reg_addr = tw_dev->registers.control_reg_addr;
1018
        control_reg_value = (TW_CONTROL_CLEAR_ATTENTION_INTERRUPT |
1019
                             TW_CONTROL_UNMASK_RESPONSE_INTERRUPT |
1020
                             TW_CONTROL_ENABLE_INTERRUPTS);
1021
        outl(control_reg_value, control_reg_addr);
1022
} /* End tw_enable_and_clear_interrupts() */
1023
 
1024
/* This function will find and initialize all cards */
1025
int tw_findcards(Scsi_Host_Template *tw_host)
1026
{
1027
        int numcards = 0, tries = 0, error = 0;
1028
        struct Scsi_Host *host;
1029
        TW_Device_Extension *tw_dev;
1030
        TW_Device_Extension *tw_dev2;
1031
        struct pci_dev *tw_pci_dev = NULL;
1032
        u32 status_reg_value;
1033
        unsigned char c = 1;
1034
        int i, j = -1;
1035
        u16 device[TW_NUMDEVICES] = { TW_DEVICE_ID, TW_DEVICE_ID2 };
1036
 
1037
        dprintk(KERN_NOTICE "3w-xxxx: tw_findcards()\n");
1038
 
1039
        for (i=0;i<TW_NUMDEVICES;i++) {
1040
                while ((tw_pci_dev = pci_find_device(TW_VENDOR_ID, device[i], tw_pci_dev))) {
1041
                        j++;
1042
                        if (pci_enable_device(tw_pci_dev))
1043
                                continue;
1044
 
1045
                        /* We only need 32-bit addressing for 5,6,7xxx cards */
1046
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4)
1047
                        if (pci_set_dma_mask(tw_pci_dev, 0xffffffff)) {
1048
                                printk(KERN_WARNING "3w-xxxx: No suitable DMA available.\n");
1049
                                continue;
1050
                        }
1051
#endif
1052
 
1053
                        /* Prepare temporary device extension */
1054
                        tw_dev=(TW_Device_Extension *)kmalloc(sizeof(TW_Device_Extension), GFP_ATOMIC);
1055
                        if (tw_dev == NULL) {
1056
                                printk(KERN_WARNING "3w-xxxx: tw_findcards(): kmalloc() failed for card %d.\n", j);
1057
                                continue;
1058
                        }
1059
                        memset(tw_dev, 0, sizeof(TW_Device_Extension));
1060
 
1061
                        /* Save pci_dev struct to device extension */
1062
                        tw_dev->tw_pci_dev = tw_pci_dev;
1063
 
1064
                        error = tw_initialize_device_extension(tw_dev);
1065
                        if (error) {
1066
                                printk(KERN_WARNING "3w-xxxx: tw_findcards(): Couldn't initialize device extension for card %d.\n", j);
1067
                                tw_free_device_extension(tw_dev);
1068
                                kfree(tw_dev);
1069
                                continue;
1070
                        }
1071
 
1072
                        /* Calculate the cards register addresses */
1073
                        tw_dev->registers.base_addr = pci_resource_start(tw_pci_dev, 0);
1074
                        tw_dev->registers.control_reg_addr = pci_resource_start(tw_pci_dev, 0);
1075
                        tw_dev->registers.status_reg_addr = pci_resource_start(tw_pci_dev, 0) + 0x4;
1076
                        tw_dev->registers.command_que_addr = pci_resource_start(tw_pci_dev, 0) + 0x8;
1077
                        tw_dev->registers.response_que_addr = pci_resource_start(tw_pci_dev, 0) + 0xC;
1078
 
1079
                        /* Check for errors and clear them */
1080
                        status_reg_value = inl(tw_dev->registers.status_reg_addr);
1081
                        if (TW_STATUS_ERRORS(status_reg_value))
1082
                                tw_decode_bits(tw_dev, status_reg_value, 0);
1083
 
1084
                        /* Poll status register for 60 secs for 'Controller Ready' flag */
1085
                        if (tw_poll_status(tw_dev, TW_STATUS_MICROCONTROLLER_READY, 60)) {
1086
                                printk(KERN_WARNING "3w-xxxx: tw_findcards(): Microcontroller not ready for card %d.\n", j);
1087
                                tw_free_device_extension(tw_dev);
1088
                                kfree(tw_dev);
1089
                                continue;
1090
                        }
1091
 
1092
                        /* Disable interrupts on the card */
1093
                        tw_disable_interrupts(tw_dev);
1094
 
1095
                        tries = 0;
1096
 
1097
                        while (tries < TW_MAX_RESET_TRIES) {
1098
                                /* Do soft reset */
1099
                                tw_soft_reset(tw_dev);
1100
 
1101
                                error = tw_aen_drain_queue(tw_dev);
1102
                                if (error) {
1103
                                        printk(KERN_WARNING "3w-xxxx: AEN drain failed for card %d.\n", j);
1104
                                        tries++;
1105
                                        continue;
1106
                                }
1107
 
1108
                                /* Check for controller errors */
1109
                                if (tw_check_errors(tw_dev)) {
1110
                                        printk(KERN_WARNING "3w-xxxx: Controller errors found, retrying for card %d.\n", j);
1111
                                        tries++;
1112
                                        continue;
1113
                                }
1114
 
1115
                                /* Now the controller is in a good state */
1116
                                break;
1117
                        }
1118
 
1119
                        if (tries >= TW_MAX_RESET_TRIES) {
1120
                                printk(KERN_WARNING "3w-xxxx: Controller errors, card not responding, check all cabling for card %d.\n", j);
1121
                                tw_free_device_extension(tw_dev);
1122
                                kfree(tw_dev);
1123
                                continue;
1124
                        }
1125
 
1126
                        /* Make sure that io region isn't already taken */
1127
                        if (check_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE)) {
1128
                                printk(KERN_WARNING "3w-xxxx: tw_findcards(): Couldn't get io range 0x%lx-0x%lx for card %d.\n",
1129
                                       (tw_dev->tw_pci_dev->resource[0].start),
1130
                                       (tw_dev->tw_pci_dev->resource[0].start) +
1131
                                       TW_IO_ADDRESS_RANGE, j);
1132
                                tw_free_device_extension(tw_dev);
1133
                                kfree(tw_dev);
1134
                                continue;
1135
                        }
1136
 
1137
                        /* Reserve the io address space */
1138
                        request_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE, TW_DEVICE_NAME);
1139
                        error = tw_initialize_units(tw_dev);
1140
                        if (error) {
1141
                                printk(KERN_WARNING "3w-xxxx: No valid units for card %d.\n", j);
1142
                        }
1143
 
1144
                        error = tw_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS);
1145
                        if (error) {
1146
                                printk(KERN_WARNING "3w-xxxx: Connection initialization failed for card %d.\n", j);
1147
                                release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE);
1148
                                tw_free_device_extension(tw_dev);
1149
                                kfree(tw_dev);
1150
                                continue;
1151
                        }
1152
 
1153
                        /* Set card status as online */
1154
                        tw_dev->online = 1;
1155
 
1156
                        /* Calculate max cmds per lun, and setup queues */
1157
                        if ((tw_dev->num_raid_five > 0) && (tw_dev->tw_pci_dev->device == TW_DEVICE_ID)) {
1158
                                tw_host->cmd_per_lun = (TW_MAX_BOUNCEBUF-2)/tw_dev->num_units;
1159
                                tw_dev->free_head = TW_Q_START;
1160
                                tw_dev->free_tail = TW_Q_START;
1161
                                tw_dev->free_wrap = TW_MAX_BOUNCEBUF - 1;
1162
                        } else {
1163
                                /* Check for user configured cmd_per_lun */
1164
#ifdef CONFIG_3W_XXXX_CMD_PER_LUN
1165
                                tw_host->cmd_per_lun = CONFIG_3W_XXXX_CMD_PER_LUN;
1166
                                if (tw_host->cmd_per_lun > TW_MAX_CMDS_PER_LUN)
1167
                                        tw_host->cmd_per_lun = TW_MAX_CMDS_PER_LUN;
1168
#else
1169
                                /* Use SHT cmd_per_lun default */
1170
                                tw_host->cmd_per_lun = TW_MAX_CMDS_PER_LUN;
1171
#endif
1172
                                tw_dev->free_head = TW_Q_START;
1173
                                tw_dev->free_tail = TW_Q_START;
1174
                                tw_dev->free_wrap = TW_Q_LENGTH - 1;
1175
                        }
1176
 
1177
                /* Register the card with the kernel SCSI layer */
1178
                        host = scsi_register(tw_host, sizeof(TW_Device_Extension));
1179
                        if (host == NULL) {
1180
                                printk(KERN_WARNING "3w-xxxx: tw_findcards(): scsi_register() failed for card %d.\n", j);
1181
                                release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE);
1182
                                tw_free_device_extension(tw_dev);
1183
                                kfree(tw_dev);
1184
                                continue;
1185
                        }
1186
 
1187
                        /* Set max target id's */
1188
                        host->max_id = TW_MAX_UNITS;
1189
 
1190
                        /* Set max cdb size in bytes */
1191
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,15)                        
1192
                        host->max_cmd_len = TW_MAX_CDB_LEN;
1193
#endif
1194
 
1195
                        /* Set max sectors per io */
1196
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
1197
                        if ((tw_dev->num_raid_five > 0) && (tw_dev->tw_pci_dev->device == TW_DEVICE_ID))
1198
                                host->max_sectors = TW_MAX_BOUNCE_SECTORS;
1199
                        else
1200
                                host->max_sectors = TW_MAX_SECTORS;
1201
#endif
1202
 
1203
                        host->select_queue_depths = tw_select_queue_depths;
1204
 
1205
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4)
1206
                        scsi_set_pci_device(host, tw_pci_dev);
1207
#endif
1208
 
1209
                        status_reg_value = inl(tw_dev->registers.status_reg_addr);
1210
 
1211
                        printk(KERN_NOTICE "scsi%d : Found a 3ware Storage Controller at 0x%x, IRQ: %d, P-chip: %d.%d\n", host->host_no,
1212
                                (u32)(tw_pci_dev->resource[0].start), tw_pci_dev->irq,
1213
                                (status_reg_value & TW_STATUS_MAJOR_VERSION_MASK) >> 28,
1214
                                (status_reg_value & TW_STATUS_MINOR_VERSION_MASK) >> 24);
1215
 
1216
                        if (host->hostdata) {
1217
                                tw_dev2 = (TW_Device_Extension *)host->hostdata;
1218
                                memcpy(tw_dev2, tw_dev, sizeof(TW_Device_Extension));
1219
                                /* Need to init the sem/wqueue after the copy */
1220
                                init_MUTEX(&tw_dev2->ioctl_sem);
1221
                                init_waitqueue_head(&tw_dev2->ioctl_wqueue);
1222
 
1223
                                tw_device_extension_list[tw_device_extension_count] = tw_dev2;
1224
                                numcards++;
1225
                                tw_device_extension_count = numcards;
1226
                                tw_dev2->host = host;
1227
                        } else {
1228
                                printk(KERN_WARNING "3w-xxxx: tw_findcards(): Bad scsi host data for card %d.\n", j);
1229
                                scsi_unregister(host);
1230
                                release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE);
1231
                                tw_free_device_extension(tw_dev);
1232
                                kfree(tw_dev);
1233
                                continue;
1234
                        }
1235
 
1236
                        /* Tell the firmware we support shutdown notification*/
1237
                        error = tw_setfeature(tw_dev2, 2, 1, &c);
1238
                        if (error) {
1239
                                printk(KERN_WARNING "3w-xxxx: Unable to set features for card %d, old firmware or card.\n", j);
1240
                        }
1241
 
1242
                        /* Now setup the interrupt handler */
1243
                        error = tw_setup_irq(tw_dev2);
1244
                        if (error) {
1245
                                printk(KERN_WARNING "3w-xxxx: tw_findcards(): Error requesting irq for card %d.\n", j);
1246
                                scsi_unregister(host);
1247
                                release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE);
1248
 
1249
                                tw_free_device_extension(tw_dev);
1250
                                kfree(tw_dev);
1251
                                numcards--;
1252
                                continue;
1253
                        }
1254
 
1255
                        /* Re-enable interrupts on the card */
1256
                        tw_enable_interrupts(tw_dev2);
1257
 
1258
                        /* Free the temporary device extension */
1259
                        if (tw_dev)
1260
                                kfree(tw_dev);
1261
                }
1262
        }
1263
 
1264
        if (numcards == 0) {
1265
                printk(KERN_WARNING "3w-xxxx: No cards found.\n");
1266
        } else {
1267
                register_reboot_notifier(&tw_notifier);
1268
                if ((twe_major = register_chrdev (0, "twe", &tw_fops)) < 0) {
1269
                        printk(KERN_WARNING "3w-xxxx: Unable to register \"twe\" character device, error = %d.\n", twe_major);
1270
                }
1271
        }
1272
 
1273
        return numcards;
1274
} /* End tw_findcards() */
1275
 
1276
/* This function will free up device extension resources */
1277
void tw_free_device_extension(TW_Device_Extension *tw_dev)
1278
{
1279
        dprintk(KERN_NOTICE "3w-xxxx: tw_free_device_extension()\n");
1280
 
1281
        /* Free command packet and generic buffer memory */
1282
        if (tw_dev->command_packet_physical_address[0])
1283
                pci_free_consistent(tw_dev->tw_pci_dev, sizeof(TW_Command)*TW_Q_LENGTH, tw_dev->command_packet_virtual_address[0], tw_dev->command_packet_physical_address[0]);
1284
 
1285
        if (tw_dev->alignment_physical_address[0])
1286
                pci_free_consistent(tw_dev->tw_pci_dev, sizeof(TW_Sector)*TW_Q_LENGTH, tw_dev->alignment_virtual_address[0], tw_dev->alignment_physical_address[0]);
1287
 
1288
        if (tw_dev->bounce_buffer[0])
1289
                pci_free_consistent(tw_dev->tw_pci_dev, sizeof(TW_Sector)*TW_MAX_BOUNCE_SECTORS*TW_MAX_BOUNCEBUF, tw_dev->bounce_buffer[0], tw_dev->bounce_buffer_phys[0]);
1290
} /* End tw_free_device_extension() */
1291
 
1292
/* Clean shutdown routine */
1293
static int tw_halt(struct notifier_block *nb, ulong event, void *buf)
1294
{
1295
        int i;
1296
 
1297
        for (i=0;i<tw_device_extension_count;i++) {
1298
                if (tw_device_extension_list[i]->online == 1) {
1299
                        printk(KERN_NOTICE "3w-xxxx: Shutting down card %d.\n", i);
1300
                        tw_shutdown_device(tw_device_extension_list[i]);
1301
                        tw_device_extension_list[i]->online = 0;
1302
                }
1303
        }
1304
        unregister_reboot_notifier(&tw_notifier);
1305
 
1306
        return NOTIFY_OK;
1307
} /* End tw_halt() */
1308
 
1309
/* This function will send an initconnection command to controller */
1310
int tw_initconnection(TW_Device_Extension *tw_dev, int message_credits)
1311
{
1312
        unsigned long command_que_value;
1313
        u32 command_que_addr;
1314
        u32 response_que_addr;
1315
        TW_Command  *command_packet;
1316
        TW_Response_Queue response_queue;
1317
        int request_id = 0;
1318
 
1319
        dprintk(KERN_NOTICE "3w-xxxx: tw_initconnection()\n");
1320
        command_que_addr = tw_dev->registers.command_que_addr;
1321
        response_que_addr = tw_dev->registers.response_que_addr;
1322
 
1323
        /* Initialize InitConnection command packet */
1324
        if (tw_dev->command_packet_virtual_address[request_id] == NULL) {
1325
                printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad command packet virtual address.\n");
1326
                return 1;
1327
        }
1328
 
1329
        command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
1330
        memset(command_packet, 0, sizeof(TW_Sector));
1331
        command_packet->byte0.opcode = TW_OP_INIT_CONNECTION;
1332
        command_packet->byte0.sgl_offset = 0x0;
1333
        command_packet->size = TW_INIT_COMMAND_PACKET_SIZE;
1334
        command_packet->request_id = request_id;
1335
        command_packet->byte3.unit = 0x0;
1336
        command_packet->byte3.host_id = 0x0;
1337
        command_packet->status = 0x0;
1338
        command_packet->flags = 0x0;
1339
        command_packet->byte6.message_credits = message_credits;
1340
        command_packet->byte8.init_connection.response_queue_pointer = 0x0;
1341
        command_que_value = tw_dev->command_packet_physical_address[request_id];
1342
 
1343
        if (command_que_value == 0) {
1344
                printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Bad command packet physical address.\n");
1345
                return 1;
1346
        }
1347
 
1348
        /* Send command packet to the board */
1349
        outl(command_que_value, command_que_addr);
1350
 
1351
        /* Poll for completion */
1352
        if (tw_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, 30) == 0) {
1353
                response_queue.value = inl(response_que_addr);
1354
                request_id = (unsigned char)response_queue.u.response_id;
1355
                if (request_id != 0) {
1356
                        /* unexpected request id */
1357
                        printk(KERN_WARNING "3w-xxxx: tw_initconnection(): Unexpected request id.\n");
1358
                        return 1;
1359
                }
1360
                if (command_packet->status != 0) {
1361
                        /* bad response */
1362
                        tw_decode_sense(tw_dev, request_id, 0);
1363
                        return 1;
1364
                }
1365
        }
1366
        return 0;
1367
} /* End tw_initconnection() */
1368
 
1369
/* This function will initialize the fields of a device extension */
1370
int tw_initialize_device_extension(TW_Device_Extension *tw_dev)
1371
{
1372
        int i, error = 0;
1373
 
1374
        dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_device_extension()\n");
1375
 
1376
        /* Initialize command packet buffers */
1377
        error = tw_allocate_memory(tw_dev, sizeof(TW_Command), 0);
1378
        if (error) {
1379
                printk(KERN_WARNING "3w-xxxx: Command packet memory allocation failed.\n");
1380
                return 1;
1381
        }
1382
 
1383
        /* Initialize generic buffer */
1384
        error = tw_allocate_memory(tw_dev, sizeof(TW_Sector), 1);
1385
        if (error) {
1386
                printk(KERN_WARNING "3w-xxxx: Generic memory allocation failed.\n");
1387
                return 1;
1388
        }
1389
 
1390
        for (i=0;i<TW_Q_LENGTH;i++) {
1391
                tw_dev->free_queue[i] = i;
1392
                tw_dev->state[i] = TW_S_INITIAL;
1393
        }
1394
 
1395
        tw_dev->pending_head = TW_Q_START;
1396
        tw_dev->pending_tail = TW_Q_START;
1397
        spin_lock_init(&tw_dev->tw_lock);
1398
        tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
1399
 
1400
        return 0;
1401
} /* End tw_initialize_device_extension() */
1402
 
1403
/* This function will get unit info from the controller */
1404
int tw_initialize_units(TW_Device_Extension *tw_dev)
1405
{
1406
        int found = 0, error = 0;
1407
        unsigned char request_id = 0;
1408
        TW_Command *command_packet;
1409
        TW_Param *param;
1410
        int i, j, imax, num_units = 0, num_raid_five = 0;
1411
        unsigned long command_que_value;
1412
        u32 command_que_addr;
1413
        u32 response_que_addr;
1414
        TW_Response_Queue response_queue;
1415
        unsigned long param_value;
1416
        unsigned char *is_unit_present;
1417
        unsigned char *raid_level;
1418
 
1419
        dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_units()\n");
1420
 
1421
        command_que_addr = tw_dev->registers.command_que_addr;
1422
        response_que_addr = tw_dev->registers.response_que_addr;
1423
 
1424
        /* Setup the command packet */
1425
        command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
1426
        if (command_packet == NULL) {
1427
                printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad command packet virtual address.\n");
1428
                return 1;
1429
        }
1430
        memset(command_packet, 0, sizeof(TW_Sector));
1431
        command_packet->byte0.opcode      = TW_OP_GET_PARAM;
1432
        command_packet->byte0.sgl_offset  = 2;
1433
        command_packet->size              = 4;
1434
        command_packet->request_id        = request_id;
1435
        command_packet->byte3.unit        = 0;
1436
        command_packet->byte3.host_id     = 0;
1437
        command_packet->status            = 0;
1438
        command_packet->flags             = 0;
1439
        command_packet->byte6.block_count = 1;
1440
 
1441
        /* Now setup the param */
1442
        if (tw_dev->alignment_virtual_address[request_id] == NULL) {
1443
                printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad alignment virtual address.\n");
1444
                return 1;
1445
        }
1446
        param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
1447
        memset(param, 0, sizeof(TW_Sector));
1448
        param->table_id = 3;       /* unit summary table */
1449
        param->parameter_id = 3;   /* unitstatus parameter */
1450
        param->parameter_size_bytes = TW_MAX_UNITS;
1451
        param_value = tw_dev->alignment_physical_address[request_id];
1452
        if (param_value == 0) {
1453
                printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad alignment physical address.\n");
1454
                return 1;
1455
        }
1456
 
1457
        command_packet->byte8.param.sgl[0].address = param_value;
1458
        command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
1459
 
1460
        /* Post the command packet to the board */
1461
        command_que_value = tw_dev->command_packet_physical_address[request_id];
1462
        if (command_que_value == 0) {
1463
                printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad command packet physical address.\n");
1464
                return 1;
1465
        }
1466
        outl(command_que_value, command_que_addr);
1467
 
1468
        /* Poll for completion */
1469
        if (tw_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, 30) == 0) {
1470
                response_queue.value = inl(response_que_addr);
1471
                request_id = (unsigned char)response_queue.u.response_id;
1472
                if (request_id != 0) {
1473
                        /* unexpected request id */
1474
                        printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected request id.\n");
1475
                        return 1;
1476
                }
1477
                if (command_packet->status != 0) {
1478
                        /* bad response */
1479
                        tw_decode_sense(tw_dev, request_id, 0);
1480
                        return 1;
1481
                }
1482
                found = 1;
1483
        }
1484
        if (found == 0) {
1485
                /* response never received */
1486
                printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): No response.\n");
1487
                return 1;
1488
        }
1489
 
1490
        param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
1491
        is_unit_present = (unsigned char *)&(param->data[0]);
1492
 
1493
        /* Show all units present */
1494
        imax = TW_MAX_UNITS;
1495
        for(i=0; i<imax; i++) {
1496
                if (is_unit_present[i] == 0) {
1497
                        tw_dev->is_unit_present[i] = FALSE;
1498
                } else {
1499
                  if (is_unit_present[i] & TW_UNIT_ONLINE) {
1500
                        dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_units(): Unit %d found.\n", i);
1501
                        tw_dev->is_unit_present[i] = TRUE;
1502
                        num_units++;
1503
                  }
1504
                }
1505
        }
1506
        tw_dev->num_units = num_units;
1507
 
1508
        if (num_units == 0) {
1509
                dprintk(KERN_NOTICE "3w-xxxx: tw_initialize_units(): No units found.\n");
1510
                return 1;
1511
        }
1512
 
1513
        /* Find raid 5 arrays */
1514
        for (j=0;j<TW_MAX_UNITS;j++) {
1515
                if (tw_dev->is_unit_present[j] == 0)
1516
                        continue;
1517
                command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
1518
                if (command_packet == NULL) {
1519
                        printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad command packet virtual address.\n");
1520
                        return 1;
1521
                }
1522
                memset(command_packet, 0, sizeof(TW_Sector));
1523
                command_packet->byte0.opcode      = TW_OP_GET_PARAM;
1524
                command_packet->byte0.sgl_offset  = 2;
1525
                command_packet->size              = 4;
1526
                command_packet->request_id        = request_id;
1527
                command_packet->byte3.unit        = 0;
1528
                command_packet->byte3.host_id     = 0;
1529
                command_packet->status            = 0;
1530
                command_packet->flags             = 0;
1531
                command_packet->byte6.block_count = 1;
1532
 
1533
                /* Now setup the param */
1534
                if (tw_dev->alignment_virtual_address[request_id] == NULL) {
1535
                        printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad alignment virtual address.\n");
1536
                        return 1;
1537
                }
1538
                param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
1539
                memset(param, 0, sizeof(TW_Sector));
1540
                param->table_id = 0x300+j; /* unit summary table */
1541
                param->parameter_id = 0x6; /* unit descriptor */
1542
                param->parameter_size_bytes = 0xc;
1543
                param_value = tw_dev->alignment_physical_address[request_id];
1544
                if (param_value == 0) {
1545
                        printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad alignment physical address.\n");
1546
                        return 1;
1547
                }
1548
 
1549
                command_packet->byte8.param.sgl[0].address = param_value;
1550
                command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
1551
 
1552
                /* Post the command packet to the board */
1553
                command_que_value = tw_dev->command_packet_physical_address[request_id];
1554
                if (command_que_value == 0) {
1555
                        printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Bad command packet physical address.\n");
1556
                        return 1;
1557
                }
1558
                outl(command_que_value, command_que_addr);
1559
 
1560
                /* Poll for completion */
1561
                if (tw_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, 30) == 0) {
1562
                        response_queue.value = inl(response_que_addr);
1563
                        request_id = (unsigned char)response_queue.u.response_id;
1564
                        if (request_id != 0) {
1565
                                /* unexpected request id */
1566
                                printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected request id.\n");
1567
                                return 1;
1568
                        }
1569
                        if (command_packet->status != 0) {
1570
                                /* bad response */
1571
                                tw_decode_sense(tw_dev, request_id, 0);
1572
                                return 1;
1573
                        }
1574
                        found = 1;
1575
                }
1576
                if (found == 0) {
1577
                        /* response never received */
1578
                        printk(KERN_WARNING "3w-xxxx: tw_initialize_units(): No response.\n");
1579
                        return 1;
1580
                }
1581
 
1582
                param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
1583
                raid_level = (unsigned char *)&(param->data[1]);
1584
                if (*raid_level == 5) {
1585
                        dprintk(KERN_WARNING "3w-xxxx: Found unit %d to be a raid5 unit.\n", j);
1586
                        tw_dev->is_raid_five[j] = 1;
1587
                        num_raid_five++;
1588
                }
1589
        }
1590
        tw_dev->num_raid_five = num_raid_five;
1591
 
1592
        /* Now allocate raid5 bounce buffers */
1593
        if ((num_raid_five != 0) && (tw_dev->tw_pci_dev->device == TW_DEVICE_ID)) {
1594
                error = tw_allocate_memory(tw_dev, sizeof(TW_Sector)*TW_MAX_BOUNCE_SECTORS, 2);
1595
                if (error) {
1596
                        printk(KERN_WARNING "3w-xxxx: Bounce buffer allocation failed.\n");
1597
                        return 1;
1598
                }
1599
        }
1600
 
1601
        return 0;
1602
} /* End tw_initialize_units() */
1603
 
1604
/* This function is the interrupt service routine */
1605
static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
1606
{
1607
        int request_id;
1608
        u32 status_reg_addr, status_reg_value;
1609
        u32 response_que_addr;
1610
        TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance;
1611
        TW_Response_Queue response_que;
1612
        int error = 0, retval = 0;
1613
        unsigned long flags = 0;
1614
        TW_Command *command_packet;
1615
 
1616
        dprintk(KERN_WARNING "3w-xxxx: tw_interrupt()\n");
1617
 
1618
        /* See if we are already running on another processor */
1619
        if (test_and_set_bit(TW_IN_INTR, &tw_dev->flags))
1620
                return;
1621
 
1622
        /* Get the block layer lock for io completions */
1623
        spin_lock_irqsave(&io_request_lock, flags);
1624
 
1625
        /* See if the interrupt matches this instance */
1626
        if (tw_dev->tw_pci_dev->irq == irq) {
1627
 
1628
                /* Make sure io isn't queueing */
1629
                spin_lock(&tw_dev->tw_lock);
1630
 
1631
                /* Read the registers */
1632
                status_reg_addr = tw_dev->registers.status_reg_addr;
1633
                response_que_addr = tw_dev->registers.response_que_addr;
1634
                status_reg_value = inl(status_reg_addr);
1635
 
1636
                /* Check if this is our interrupt, otherwise bail */
1637
                if (!(status_reg_value & TW_STATUS_VALID_INTERRUPT))
1638
                        goto tw_interrupt_bail;
1639
 
1640
                /* Check controller for errors */
1641
                if (tw_check_bits(status_reg_value)) {
1642
                        dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
1643
                        if (tw_decode_bits(tw_dev, status_reg_value, 1)) {
1644
                                tw_clear_all_interrupts(tw_dev);
1645
                                goto tw_interrupt_bail;
1646
                        }
1647
                }
1648
 
1649
                /* Handle host interrupt */
1650
                if (status_reg_value & TW_STATUS_HOST_INTERRUPT) {
1651
                        dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received host interrupt.\n");
1652
                        tw_clear_host_interrupt(tw_dev);
1653
                }
1654
 
1655
                /* Handle attention interrupt */
1656
                if (status_reg_value & TW_STATUS_ATTENTION_INTERRUPT) {
1657
                        dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received attention interrupt.\n");
1658
                        tw_clear_attention_interrupt(tw_dev);
1659
                        tw_state_request_start(tw_dev, &request_id);
1660
                        error = tw_aen_read_queue(tw_dev, request_id);
1661
                        if (error) {
1662
                                printk(KERN_WARNING "3w-xxxx: scsi%d: Error reading aen queue.\n", tw_dev->host->host_no);
1663
                                tw_dev->state[request_id] = TW_S_COMPLETED;
1664
                                tw_state_request_finish(tw_dev, request_id);
1665
                        }
1666
                }
1667
 
1668
                /* Handle command interrupt */
1669
                if (status_reg_value & TW_STATUS_COMMAND_INTERRUPT) {
1670
                        /* Drain as many pending commands as we can */
1671
                        while (tw_dev->pending_request_count > 0) {
1672
                                request_id = tw_dev->pending_queue[tw_dev->pending_head];
1673
                                if (tw_dev->state[request_id] != TW_S_PENDING) {
1674
                                        printk(KERN_WARNING "3w-xxxx: scsi%d: Found request id that wasn't pending.\n", tw_dev->host->host_no);
1675
                                        break;
1676
                                }
1677
                                if (tw_post_command_packet(tw_dev, request_id)==0) {
1678
                                        if (tw_dev->pending_head == TW_Q_LENGTH-1) {
1679
                                                tw_dev->pending_head = TW_Q_START;
1680
                                        } else {
1681
                                                tw_dev->pending_head = tw_dev->pending_head + 1;
1682
                                        }
1683
                                        tw_dev->pending_request_count--;
1684
                                } else {
1685
                                        /* If we get here, we will continue re-posting on the next command interrupt */
1686
                                        break;
1687
                                }
1688
                        }
1689
                        /* If there are no more pending requests, we mask command interrupt */
1690
                        if (tw_dev->pending_request_count == 0)
1691
                                tw_mask_command_interrupt(tw_dev);
1692
                }
1693
 
1694
                /* Handle response interrupt */
1695
                if (status_reg_value & TW_STATUS_RESPONSE_INTERRUPT) {
1696
                        /* Drain the response queue from the board */
1697
                        while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
1698
                                /* Read response queue register */
1699
                                response_que.value = inl(response_que_addr);
1700
                                request_id = response_que.u.response_id;
1701
                                command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
1702
                                error = 0;
1703
 
1704
                                /* Check for bad response */
1705
                                if (command_packet->status != 0) {
1706
                                        /* If internal command, don't error, don't fill sense */
1707
                                        if (tw_dev->srb[request_id] == 0) {
1708
                                                tw_decode_sense(tw_dev, request_id, 0);
1709
                                        } else {
1710
                                                error = tw_decode_sense(tw_dev, request_id, 1);
1711
                                        }
1712
                                }
1713
 
1714
                                /* Check for correct state */
1715
                                if (tw_dev->state[request_id] != TW_S_POSTED) {
1716
                                        /* Handle timed out ioctl's */
1717
                                        if (tw_dev->srb[request_id] != 0) {
1718
                                                if (tw_dev->srb[request_id]->cmnd[0] != TW_IOCTL) {
1719
                                                        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);
1720
                                                        error = 1;
1721
                                                }
1722
                                        }
1723
                                }
1724
 
1725
                                dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Response queue request id: %d.\n", request_id);
1726
 
1727
                                /* Check for internal command completion */
1728
                                if (tw_dev->srb[request_id] == 0) {
1729
                                        dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found internally posted command.\n");
1730
                                        /* Check for chrdev ioctl completion */
1731
                                        if (request_id != tw_dev->chrdev_request_id) {
1732
                                                retval = tw_aen_complete(tw_dev, request_id);
1733
                                                if (retval) {
1734
                                                        printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing aen.\n", tw_dev->host->host_no);
1735
                                                }
1736
                                        } else {
1737
                                                tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
1738
                                                wake_up(&tw_dev->ioctl_wqueue);
1739
                                        }
1740
                                } else {
1741
                                switch (tw_dev->srb[request_id]->cmnd[0]) {
1742
                                        case READ_10:
1743
                                        case READ_6:
1744
                                                dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_10/READ_6\n");
1745
                                                break;
1746
                                        case WRITE_10:
1747
                                        case WRITE_6:
1748
                                                dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_10/WRITE_6\n");
1749
                                                break;
1750
                                        case TEST_UNIT_READY:
1751
                                                dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught TEST_UNIT_READY\n");
1752
                                                error = tw_scsiop_test_unit_ready_complete(tw_dev, request_id);
1753
                                                break;
1754
                                        case INQUIRY:
1755
                                                dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught INQUIRY\n");
1756
                                                error = tw_scsiop_inquiry_complete(tw_dev, request_id);
1757
                                                break;
1758
                                        case READ_CAPACITY:
1759
                                                dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught READ_CAPACITY\n");
1760
                                                error = tw_scsiop_read_capacity_complete(tw_dev, request_id);
1761
                                                break;
1762
                                        case MODE_SENSE:
1763
                                                dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught MODE_SENSE\n");
1764
                                                error = tw_scsiop_mode_sense_complete(tw_dev, request_id);
1765
                                                break;
1766
                                        case SYNCHRONIZE_CACHE:
1767
                                                dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught SYNCHRONIZE_CACHE\n");
1768
                                                break;
1769
                                        case TW_IOCTL:
1770
                                                dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught TW_IOCTL\n");
1771
                                                error = tw_ioctl_complete(tw_dev, request_id);
1772
                                                break;
1773
                                        default:
1774
                                                printk(KERN_WARNING "3w-xxxx: case slip in tw_interrupt()\n");
1775
                                                error = 1;
1776
                                        }
1777
 
1778
                                        /* If no error command was a success */
1779
                                        if (error == 0) {
1780
                                                tw_dev->srb[request_id]->result = (DID_OK << 16);
1781
                                        }
1782
 
1783
                                        /* If error, command failed */
1784
                                        if (error == 1) {
1785
                                                /* Ask for a host reset */
1786
                                                tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
1787
                                        }
1788
 
1789
                                        /* Now complete the io */
1790
                                        if ((error != TW_ISR_DONT_COMPLETE)) {
1791
                                                tw_dev->state[request_id] = TW_S_COMPLETED;
1792
                                                tw_state_request_finish(tw_dev, request_id);
1793
                                                tw_dev->posted_request_count--;
1794
                                                tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
1795
                                                tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
1796
                                        }
1797
                                }
1798
 
1799
                                /* Check for valid status after each drain */
1800
                                status_reg_value = inl(status_reg_addr);
1801
                                if (tw_check_bits(status_reg_value)) {
1802
                                        dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
1803
                                        if (tw_decode_bits(tw_dev, status_reg_value, 1)) {
1804
                                                tw_clear_all_interrupts(tw_dev);
1805
                                                goto tw_interrupt_bail;
1806
                                        }
1807
                                }
1808
                        }
1809
                }
1810
tw_interrupt_bail:
1811
                spin_unlock(&tw_dev->tw_lock);
1812
        } else
1813
                dprintk(KERN_WARNING "3w-xxxx: tw_interrupt() called for wrong instance.\n");
1814
 
1815
        spin_unlock_irqrestore(&io_request_lock, flags);
1816
        clear_bit(TW_IN_INTR, &tw_dev->flags);
1817
} /* End tw_interrupt() */
1818
 
1819
/* This function handles ioctls from userspace to the driver */
1820
int tw_ioctl(TW_Device_Extension *tw_dev, int request_id)
1821
{
1822
        unsigned char opcode;
1823
        int bufflen, error = 0;
1824
        TW_Param *param;
1825
        TW_Command *command_packet, *command_save;
1826
        unsigned long param_value;
1827
        TW_Ioctl *ioctl = NULL;
1828
        TW_Passthru *passthru = NULL;
1829
        int tw_aen_code, i, use_sg;
1830
        unsigned long *data_ptr;
1831
        int total_bytes = 0, posted = 0;
1832
        dma_addr_t dma_handle;
1833
        struct timeval before, timeout;
1834
 
1835
        ioctl = (TW_Ioctl *)tw_dev->srb[request_id]->request_buffer;
1836
        if (ioctl == NULL) {
1837
                printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Request buffer NULL.\n");
1838
                tw_dev->state[request_id] = TW_S_COMPLETED;
1839
                tw_state_request_finish(tw_dev, request_id);
1840
                tw_dev->srb[request_id]->result = (DID_OK << 16);
1841
                tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
1842
                return 0;
1843
        }
1844
        bufflen = tw_dev->srb[request_id]->request_bufflen;
1845
 
1846
        /* Initialize command packet */
1847
        command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
1848
        if (command_packet == NULL) {
1849
                printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Bad command packet virtual address.\n");
1850
                tw_dev->state[request_id] = TW_S_COMPLETED;
1851
                tw_state_request_finish(tw_dev, request_id);
1852
                tw_dev->srb[request_id]->result = (DID_OK << 16);
1853
                tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
1854
                return 0;
1855
        }
1856
        memset(command_packet, 0, sizeof(TW_Sector));
1857
 
1858
        /* Initialize param */
1859
        if (tw_dev->alignment_virtual_address[request_id] == NULL) {
1860
                printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Bad alignment virtual address.\n");
1861
                tw_dev->state[request_id] = TW_S_COMPLETED;
1862
                tw_state_request_finish(tw_dev, request_id);
1863
                tw_dev->srb[request_id]->result = (DID_OK << 16);
1864
                tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
1865
                return 0;
1866
        }
1867
        param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
1868
        memset(param, 0, sizeof(TW_Sector));
1869
 
1870
        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);
1871
        opcode = ioctl->opcode;
1872
 
1873
        switch (opcode) {
1874
                case TW_OP_NOP:
1875
                        dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_NOP.\n");
1876
                        command_packet->byte0.opcode = TW_OP_NOP;
1877
                        break;
1878
                case TW_OP_GET_PARAM:
1879
                        dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_GET_PARAM.\n");
1880
                        command_packet->byte0.opcode = TW_OP_GET_PARAM;
1881
                        command_packet->byte3.unit = ioctl->unit_index;
1882
                        param->table_id = ioctl->table_id;
1883
                        param->parameter_id = ioctl->parameter_id;
1884
                        param->parameter_size_bytes = ioctl->parameter_size_bytes;
1885
                        tw_dev->ioctl_size[request_id] = ioctl->parameter_size_bytes;
1886
                        dprintk(KERN_NOTICE "table_id = %d parameter_id = %d parameter_size_bytes %d\n", param->table_id, param->parameter_id, param->parameter_size_bytes);
1887
                        break;
1888
                case TW_OP_SET_PARAM:
1889
                        dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_SET_PARAM: table_id = %d, parameter_id = %d, parameter_size_bytes = %d.\n",
1890
                        ioctl->table_id, ioctl->parameter_id, ioctl->parameter_size_bytes);
1891
                        if (ioctl->data != NULL) {
1892
                                command_packet->byte0.opcode = TW_OP_SET_PARAM;
1893
                                param->table_id = ioctl->table_id;
1894
                                param->parameter_id = ioctl->parameter_id;
1895
                                param->parameter_size_bytes = ioctl->parameter_size_bytes;
1896
                                memcpy(param->data, ioctl->data, ioctl->parameter_size_bytes);
1897
                                break;
1898
                        } else {
1899
                                printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n");
1900
                                return 1;
1901
                        }
1902
                case TW_OP_AEN_LISTEN:
1903
                        dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): caught TW_OP_AEN_LISTEN.\n");
1904
                        if (tw_dev->aen_head == tw_dev->aen_tail) {
1905
                                /* aen queue empty */
1906
                                dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): Aen queue empty.\n");
1907
                                tw_aen_code = TW_AEN_QUEUE_EMPTY;
1908
                                memcpy(tw_dev->srb[request_id]->request_buffer, &tw_aen_code, ioctl->parameter_size_bytes);
1909
                        } else {
1910
                                /* Copy aen queue entry to request buffer */
1911
                                dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl(): Returning aen 0x%x\n", tw_dev->aen_queue[tw_dev->aen_head]);
1912
                                tw_aen_code = tw_dev->aen_queue[tw_dev->aen_head];
1913
                                memcpy(tw_dev->srb[request_id]->request_buffer, &tw_aen_code, ioctl->parameter_size_bytes);
1914
                                if (tw_dev->aen_head == TW_Q_LENGTH - 1) {
1915
                                        tw_dev->aen_head = TW_Q_START;
1916
                                } else {
1917
                                        tw_dev->aen_head = tw_dev->aen_head + 1;
1918
                                }
1919
                        }
1920
                        tw_dev->state[request_id] = TW_S_COMPLETED;
1921
                        tw_state_request_finish(tw_dev, request_id);
1922
                        tw_dev->srb[request_id]->result = (DID_OK << 16);
1923
                        tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
1924
                        return 0;
1925
                case TW_ATA_PASSTHRU:
1926
                        if (ioctl->data != NULL) {
1927
                                memcpy(command_packet, ioctl->data, sizeof(TW_Command));
1928
                                command_packet->request_id = request_id;
1929
                        } else {
1930
                                printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n");
1931
                                return 1;
1932
                        }
1933
 
1934
                        passthru = (TW_Passthru *)tw_dev->command_packet_virtual_address[request_id];
1935
                        /* Don't load sg_list for non-data ATA cmds */
1936
                        if ((passthru->param != 0) && (passthru->param != 0x8)) {
1937
                                passthru->sg_list[0].length = passthru->sector_count*512;
1938
                                if (passthru->sg_list[0].length > TW_MAX_PASSTHRU_BYTES) {
1939
                                        printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Passthru size (%d) too big.\n", passthru->sg_list[0].length);
1940
                                        return 1;
1941
                                }
1942
                                passthru->sg_list[0].address = tw_dev->alignment_physical_address[request_id];
1943
                        }
1944
                        tw_post_command_packet(tw_dev, request_id);
1945
                        return 0;
1946
                case TW_CMD_PACKET:
1947
                        dprintk(KERN_WARNING "3w-xxxx: tw_ioctl(): caught TW_CMD_PACKET.\n");
1948
                        if (ioctl->data != NULL) {
1949
                                memcpy(command_packet, ioctl->data, sizeof(TW_Command));
1950
                                command_packet->request_id = request_id;
1951
                                tw_post_command_packet(tw_dev, request_id);
1952
                                return 0;
1953
                        } else {
1954
                                printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n");
1955
                                return 1;
1956
                        }
1957
                case TW_CMD_PACKET_WITH_DATA:
1958
                        dprintk(KERN_WARNING "3w-xxxx: tw_ioctl(): caught TW_CMD_PACKET_WITH_DATA.\n");
1959
                        command_save = (TW_Command *)tw_dev->alignment_virtual_address[request_id];
1960
                        if (command_save == NULL) {
1961
                                printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad alignment virtual address.\n", tw_dev->host->host_no);
1962
                                return 1;
1963
                        }
1964
                        if (ioctl->data != NULL) {
1965
                                /* Copy down the command packet */
1966
                                memcpy(command_packet, ioctl->data, sizeof(TW_Command));
1967
                                memcpy(command_save, ioctl->data, sizeof(TW_Command));
1968
                                command_packet->request_id = request_id;
1969
 
1970
                                /* Now deal with the two possible sglists */
1971
                                if (command_packet->byte0.sgl_offset == 2) {
1972
                                        use_sg = command_packet->size - 3;
1973
                                        for (i=0;i<use_sg;i++)
1974
                                                total_bytes+=command_packet->byte8.param.sgl[i].length;
1975
                                        tw_dev->ioctl_data[request_id] = pci_alloc_consistent(tw_dev->tw_pci_dev, total_bytes, &dma_handle);
1976
 
1977
                                        if (!tw_dev->ioctl_data[request_id]) {
1978
                                                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);
1979
                                                return 1;
1980
                                        }
1981
 
1982
                                        /* Copy param sglist into the kernel */
1983
                                        data_ptr = tw_dev->ioctl_data[request_id];
1984
                                        for (i=0;i<use_sg;i++) {
1985
                                                if (command_packet->byte8.param.sgl[i].address != 0) {
1986
                                                        error = copy_from_user(data_ptr, (void *)(unsigned long)command_packet->byte8.param.sgl[i].address, command_packet->byte8.param.sgl[i].length);
1987
                                                        if (error) {
1988
                                                                dprintk(KERN_WARNING "3w-xxxx: scsi%d: Error copying param sglist from userspace.\n", tw_dev->host->host_no);
1989
                                                                goto tw_ioctl_bail;
1990
                                                        }
1991
                                                } else {
1992
                                                        printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad param sgl address.\n", tw_dev->host->host_no);
1993
                                                        tw_dev->srb[request_id]->result = (DID_RESET << 16);
1994
                                                        goto tw_ioctl_bail;
1995
                                                }
1996
                                                data_ptr+=command_packet->byte8.param.sgl[i].length;
1997
                                        }
1998
                                        command_packet->size = 4;
1999
                                        command_packet->byte8.param.sgl[0].address = dma_handle;
2000
                                        command_packet->byte8.param.sgl[0].length = total_bytes;
2001
                                }
2002
                                if (command_packet->byte0.sgl_offset == 3) {
2003
                                        use_sg = command_packet->size - 4;
2004
                                        for (i=0;i<use_sg;i++)
2005
                                                total_bytes+=command_packet->byte8.io.sgl[i].length;
2006
                                        tw_dev->ioctl_data[request_id] = pci_alloc_consistent(tw_dev->tw_pci_dev, total_bytes, &dma_handle);
2007
 
2008
                                        if (!tw_dev->ioctl_data[request_id]) {
2009
                                                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);
2010
                                                return 1;
2011
                                        }
2012
                                        if (command_packet->byte0.opcode == TW_OP_WRITE) {
2013
                                                /* Copy io sglist into the kernel */
2014
                                                data_ptr = tw_dev->ioctl_data[request_id];
2015
                                                for (i=0;i<use_sg;i++) {
2016
                                                        if (command_packet->byte8.io.sgl[i].address != 0) {
2017
                                                                error = copy_from_user(data_ptr, (void *)(unsigned long)command_packet->byte8.io.sgl[i].address, command_packet->byte8.io.sgl[i].length);
2018
                                                                if (error) {
2019
                                                                        dprintk(KERN_WARNING "3w-xxxx: scsi%d: Error copying io sglist from userspace.\n", tw_dev->host->host_no);
2020
                                                                        goto tw_ioctl_bail;
2021
                                                                }
2022
                                                        } else {
2023
                                                                printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad io sgl address.\n", tw_dev->host->host_no);
2024
                                                                tw_dev->srb[request_id]->result = (DID_RESET << 16);
2025
                                                                goto tw_ioctl_bail;
2026
                                                        }
2027
                                                        data_ptr+=command_packet->byte8.io.sgl[i].length;
2028
                                                }
2029
                                        }
2030
                                        command_packet->size = 5;
2031
                                        command_packet->byte8.io.sgl[0].address = dma_handle;
2032
                                        command_packet->byte8.io.sgl[0].length = total_bytes;
2033
                                }
2034
 
2035
                                spin_unlock(&tw_dev->tw_lock);
2036
                                spin_unlock_irq(&io_request_lock);
2037
 
2038
                                set_bit(TW_IN_IOCTL, &tw_dev->flags);
2039
 
2040
                                /* Finally post the command packet */
2041
                                tw_post_command_packet(tw_dev, request_id);
2042
                                posted = 1;
2043
                                do_gettimeofday(&before);
2044
 
2045
                        tw_ioctl_retry:
2046
                                mdelay(TW_IOCTL_WAIT_TIME);
2047
                                if (test_bit(TW_IN_IOCTL, &tw_dev->flags)) {
2048
                                        do_gettimeofday(&timeout);
2049
                                        if (before.tv_sec + TW_IOCTL_TIMEOUT < timeout.tv_sec) {
2050
                                                spin_lock_irq(&io_request_lock);
2051
                                                spin_lock(&tw_dev->tw_lock);
2052
                                                goto tw_ioctl_bail;
2053
                                        } else {
2054
                                                goto tw_ioctl_retry;
2055
                                        }
2056
                                }
2057
 
2058
                                spin_lock_irq(&io_request_lock);
2059
                                spin_lock(&tw_dev->tw_lock);
2060
 
2061
                                if (signal_pending(current)) {
2062
                                        dprintk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Signal pending, aborting ioctl().\n", tw_dev->host->host_no);
2063
                                        tw_dev->srb[request_id]->result = (DID_OK << 16);
2064
                                        goto tw_ioctl_bail;
2065
                                }
2066
 
2067
                                tw_dev->srb[request_id]->result = (DID_OK << 16);
2068
                                /* Now copy up the param or io sglist to userspace */
2069
                                if (command_packet->byte0.sgl_offset == 2) {
2070
                                        use_sg = command_save->size - 3;
2071
                                        data_ptr = tw_dev->ioctl_data[request_id];
2072
                                        for (i=0;i<use_sg;i++) {
2073
                                                if (command_save->byte8.param.sgl[i].address != 0) {
2074
                                                        error = copy_to_user((void *)(unsigned long)command_save->byte8.param.sgl[i].address, data_ptr, command_save->byte8.param.sgl[i].length);
2075
                                                        if (error) {
2076
                                                                dprintk(KERN_WARNING "3w-xxxx: scsi%d: Error copying param sglist to userspace.\n", tw_dev->host->host_no);
2077
                                                                goto tw_ioctl_bail;
2078
                                                        }
2079
                                                        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);
2080
                                                        data_ptr+=command_save->byte8.param.sgl[i].length;
2081
                                                } else {
2082
                                                        printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad param sgl address.\n", tw_dev->host->host_no);
2083
                                                        tw_dev->srb[request_id]->result = (DID_RESET << 16);
2084
                                                        goto tw_ioctl_bail;
2085
                                                }
2086
                                        }
2087
                                }
2088
                                if (command_packet->byte0.sgl_offset == 3) {
2089
                                        use_sg = command_save->size - 4;
2090
                                        if (command_packet->byte0.opcode == TW_OP_READ) {
2091
                                                data_ptr = tw_dev->ioctl_data[request_id];
2092
                                                for(i=0;i<use_sg;i++) {
2093
                                                        if (command_save->byte8.io.sgl[i].address != 0) {
2094
                                                                error = copy_to_user((void *)(unsigned long)command_save->byte8.io.sgl[i].address, data_ptr, command_save->byte8.io.sgl[i].length);
2095
                                                                if (error) {
2096
                                                                        dprintk(KERN_WARNING "3w-xxxx: scsi%d: Error copying io sglist to userspace.\n", tw_dev->host->host_no);
2097
                                                                        goto tw_ioctl_bail;
2098
                                                                }
2099
                                                                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);
2100
                                                                data_ptr+=command_save->byte8.io.sgl[i].length;
2101
                                                        } else {
2102
                                                                printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Bad io sgl address.\n", tw_dev->host->host_no);
2103
                                                                tw_dev->srb[request_id]->result = (DID_RESET << 16);
2104
                                                                goto tw_ioctl_bail;
2105
                                                        }
2106
                                                }
2107
                                        }
2108
                                }
2109
 
2110
                        tw_ioctl_bail:
2111
 
2112
                                /* Free up sglist memory */
2113
                                if (tw_dev->ioctl_data[request_id])
2114
                                        pci_free_consistent(tw_dev->tw_pci_dev, total_bytes, tw_dev->ioctl_data[request_id], dma_handle);
2115
                                else
2116
                                        printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl(): Error freeing ioctl data.\n", tw_dev->host->host_no);
2117
 
2118
                                /* Now complete the io */
2119
                                tw_dev->state[request_id] = TW_S_COMPLETED;
2120
                                tw_state_request_finish(tw_dev, request_id);
2121
                                if (posted)
2122
                                        tw_dev->posted_request_count--;
2123
                                tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
2124
                                return 0;
2125
                        } else {
2126
                                printk(KERN_WARNING "3w-xxxx: tw_ioctl(): ioctl->data NULL.\n");
2127
                                return 1;
2128
                        }
2129
                default:
2130
                        dprintk(KERN_WARNING "3w-xxxx: Unknown ioctl 0x%x.\n", opcode);
2131
                        tw_dev->state[request_id] = TW_S_COMPLETED;
2132
                        tw_state_request_finish(tw_dev, request_id);
2133
                        tw_dev->srb[request_id]->result = (DID_OK << 16);
2134
                        tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
2135
                        return 0;
2136
        }
2137
 
2138
        param_value = tw_dev->alignment_physical_address[request_id];
2139
        if (param_value == 0) {
2140
                printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Bad alignment physical address.\n");
2141
                tw_dev->state[request_id] = TW_S_COMPLETED;
2142
                tw_state_request_finish(tw_dev, request_id);
2143
                tw_dev->srb[request_id]->result = (DID_OK << 16);
2144
                tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
2145
        }
2146
 
2147
        command_packet->byte8.param.sgl[0].address = param_value;
2148
        command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
2149
 
2150
        command_packet->byte0.sgl_offset = 2;
2151
        command_packet->size = 4;
2152
        command_packet->request_id = request_id;
2153
        command_packet->byte3.host_id = 0;
2154
        command_packet->status = 0;
2155
        command_packet->flags = 0;
2156
        command_packet->byte6.parameter_count = 1;
2157
 
2158
        /* Now try to post the command to the board */
2159
        tw_post_command_packet(tw_dev, request_id);
2160
 
2161
        return 0;
2162
} /* End tw_ioctl() */
2163
 
2164
/* This function is called by the isr to complete ioctl requests */
2165
int tw_ioctl_complete(TW_Device_Extension *tw_dev, int request_id)
2166
{
2167
        unsigned char *param_data;
2168
        unsigned char *buff;
2169
        TW_Param *param;
2170
        TW_Ioctl *ioctl = NULL;
2171
        TW_Passthru *passthru = NULL;
2172
        TW_Command *command_packet;
2173
 
2174
        ioctl = (TW_Ioctl *)tw_dev->srb[request_id]->request_buffer;
2175
        dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl_complete()\n");
2176
        buff = tw_dev->srb[request_id]->request_buffer;
2177
        if (buff == NULL) {
2178
                printk(KERN_WARNING "3w-xxxx: tw_ioctl_complete(): Request buffer NULL.\n");
2179
                return 1;
2180
        }
2181
 
2182
        command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
2183
        if (command_packet == NULL) {
2184
                printk(KERN_WARNING "3w-xxxx: scsi%d: tw_ioctl_complete(): Bad command packet virtual address.\n", tw_dev->host->host_no);
2185
                return 1;
2186
        }
2187
 
2188
        dprintk(KERN_NOTICE "3w-xxxx: tw_ioctl_complete(): Request_bufflen = %d\n", tw_dev->srb[request_id]->request_bufflen);
2189
 
2190
        ioctl = (TW_Ioctl *)buff;
2191
        switch (ioctl->opcode) {
2192
                case TW_ATA_PASSTHRU:
2193
                        passthru = (TW_Passthru *)ioctl->data;
2194
                        /* Don't return data for non-data ATA cmds */
2195
                        if ((passthru->param != 0) && (passthru->param != 0x8))
2196
                                memcpy(buff, tw_dev->alignment_virtual_address[request_id], passthru->sector_count * 512);
2197
                        else {
2198
                                /* For non-data cmds, return cmd pkt */
2199
                                if (tw_dev->srb[request_id]->request_bufflen >= sizeof(TW_Command))
2200
                                        memcpy(buff, tw_dev->command_packet_virtual_address[request_id], sizeof(TW_Command));
2201
                        }
2202
                        break;
2203
                case TW_CMD_PACKET_WITH_DATA:
2204
                        dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_complete(): caught TW_CMD_PACKET_WITH_DATA.\n");
2205
                        clear_bit(TW_IN_IOCTL, &tw_dev->flags);
2206
                        return TW_ISR_DONT_COMPLETE; /* Special case for isr to not complete io */
2207
                default:
2208
                        memset(buff, 0, tw_dev->srb[request_id]->request_bufflen);
2209
                        param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
2210
                        if (param == NULL) {
2211
                                printk(KERN_WARNING "3w-xxxx: tw_ioctl_complete(): Bad alignment virtual address.\n");
2212
                                return 1;
2213
                        }
2214
                        param_data = &(param->data[0]);
2215
                        memcpy(buff, param_data, tw_dev->ioctl_size[request_id]);
2216
        }
2217
        return 0;
2218
} /* End tw_ioctl_complete() */
2219
 
2220
static int tw_map_scsi_sg_data(struct pci_dev *pdev, Scsi_Cmnd *cmd)
2221
{
2222
        int use_sg;
2223
        int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
2224
 
2225
        dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data()\n");
2226
 
2227
        if (cmd->use_sg == 0)
2228
                return 0;
2229
 
2230
        use_sg = pci_map_sg(pdev, cmd->buffer, cmd->use_sg, dma_dir);
2231
 
2232
        if (use_sg == 0) {
2233
                printk(KERN_WARNING "3w-xxxx: tw_map_scsi_sg_data(): pci_map_sg() failed.\n");
2234
                return 0;
2235
        }
2236
 
2237
        cmd->SCp.phase = 2;
2238
        cmd->SCp.have_data_in = use_sg;
2239
 
2240
        return use_sg;
2241
} /* End tw_map_scsi_sg_data() */
2242
 
2243
static u32 tw_map_scsi_single_data(struct pci_dev *pdev, Scsi_Cmnd *cmd)
2244
{
2245
        dma_addr_t mapping;
2246
        int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
2247
 
2248
        dprintk(KERN_WARNING "3w-xxxx: tw_map_scsi_single_data()\n");
2249
 
2250
        if (cmd->request_bufflen == 0)
2251
                return 0;
2252
#ifdef BLK_BOUNCE_HIGH
2253
        mapping = pci_map_page(pdev, virt_to_page(cmd->request_buffer), ((unsigned long)cmd->request_buffer & ~PAGE_MASK), cmd->request_bufflen, dma_dir);
2254
#else
2255
        mapping = pci_map_single(pdev, cmd->request_buffer, cmd->request_bufflen, dma_dir);
2256
#endif
2257
 
2258
        if (mapping == 0) {
2259
                printk(KERN_WARNING "3w-xxxx: tw_map_scsi_single_data(): pci_map_page() failed.\n");
2260
                return 0;
2261
        }
2262
 
2263
        cmd->SCp.phase = 1;
2264
        cmd->SCp.have_data_in = mapping;
2265
 
2266
        return mapping;
2267
} /* End tw_map_scsi_single_data() */
2268
 
2269
/* This function will mask the command interrupt */
2270
void tw_mask_command_interrupt(TW_Device_Extension *tw_dev)
2271
{
2272
        u32 control_reg_addr, control_reg_value;
2273
 
2274
        control_reg_addr = tw_dev->registers.control_reg_addr;
2275
        control_reg_value = TW_CONTROL_MASK_COMMAND_INTERRUPT;
2276
        outl(control_reg_value, control_reg_addr);
2277
} /* End tw_mask_command_interrupt() */
2278
 
2279
/* This function will poll the status register for a flag */
2280
int tw_poll_status(TW_Device_Extension *tw_dev, u32 flag, int seconds)
2281
{
2282
        u32 status_reg_addr, status_reg_value;
2283
        struct timeval before, timeout;
2284
 
2285
        status_reg_addr = tw_dev->registers.status_reg_addr;
2286
        do_gettimeofday(&before);
2287
        status_reg_value = inl(status_reg_addr);
2288
 
2289
        if (tw_check_bits(status_reg_value)) {
2290
                dprintk(KERN_WARNING "3w-xxxx: tw_poll_status(): Unexpected bits.\n");
2291
                tw_decode_bits(tw_dev, status_reg_value, 0);
2292
        }
2293
 
2294
        while ((status_reg_value & flag) != flag) {
2295
                status_reg_value = inl(status_reg_addr);
2296
 
2297
                if (tw_check_bits(status_reg_value)) {
2298
                        dprintk(KERN_WARNING "3w-xxxx: tw_poll_status(): Unexpected bits.\n");
2299
                        tw_decode_bits(tw_dev, status_reg_value, 0);
2300
                }
2301
 
2302
                do_gettimeofday(&timeout);
2303
                if (before.tv_sec + seconds < timeout.tv_sec) {
2304
                        dprintk(KERN_WARNING "3w-xxxx: tw_poll_status(): Flag 0x%x not found.\n", flag);
2305
                        return 1;
2306
                }
2307
                mdelay(5);
2308
        }
2309
        return 0;
2310
} /* End tw_poll_status() */
2311
 
2312
/* This function will poll the status register for disappearance of a flag */
2313
int tw_poll_status_gone(TW_Device_Extension *tw_dev, u32 flag, int seconds)
2314
{
2315
        u32 status_reg_addr, status_reg_value;
2316
        struct timeval before, timeout;
2317
 
2318
        status_reg_addr = tw_dev->registers.status_reg_addr;
2319
        do_gettimeofday(&before);
2320
        status_reg_value = inl(status_reg_addr);
2321
 
2322
        if (tw_check_bits(status_reg_value)) {
2323
                dprintk(KERN_WARNING "3w-xxxx: tw_poll_status_gone(): Unexpected bits.\n");
2324
                tw_decode_bits(tw_dev, status_reg_value, 0);
2325
        }
2326
 
2327
        while ((status_reg_value & flag) != 0) {
2328
                status_reg_value = inl(status_reg_addr);
2329
 
2330
                if (tw_check_bits(status_reg_value)) {
2331
                        dprintk(KERN_WARNING "3w-xxxx: tw_poll_status_gone(): Unexpected bits.\n");
2332
                        tw_decode_bits(tw_dev, status_reg_value, 0);
2333
                }
2334
 
2335
                do_gettimeofday(&timeout);
2336
                if (before.tv_sec + seconds < timeout.tv_sec) {
2337
                        dprintk(KERN_WARNING "3w-xxxx: tw_poll_status_gone(): Flag 0x%x never disappeared.\n", flag);
2338
                        return 1;
2339
                }
2340
                mdelay(5);
2341
        }
2342
        return 0;
2343
} /* End tw_poll_status_gone() */
2344
 
2345
/* This function will attempt to post a command packet to the board */
2346
int tw_post_command_packet(TW_Device_Extension *tw_dev, int request_id)
2347
{
2348
        u32 status_reg_addr, status_reg_value;
2349
        unsigned long command_que_value;
2350
        u32 command_que_addr;
2351
 
2352
        dprintk(KERN_NOTICE "3w-xxxx: tw_post_command_packet()\n");
2353
        command_que_addr = tw_dev->registers.command_que_addr;
2354
        command_que_value = tw_dev->command_packet_physical_address[request_id];
2355
        status_reg_addr = tw_dev->registers.status_reg_addr;
2356
        status_reg_value = inl(status_reg_addr);
2357
 
2358
        if (tw_check_bits(status_reg_value)) {
2359
                dprintk(KERN_WARNING "3w-xxxx: tw_post_command_packet(): Unexpected bits.\n");
2360
                tw_decode_bits(tw_dev, status_reg_value, 1);
2361
        }
2362
 
2363
        if ((status_reg_value & TW_STATUS_COMMAND_QUEUE_FULL) == 0) {
2364
                /* We successfully posted the command packet */
2365
                outl(command_que_value, command_que_addr);
2366
                tw_dev->state[request_id] = TW_S_POSTED;
2367
                tw_dev->posted_request_count++;
2368
                if (tw_dev->posted_request_count > tw_dev->max_posted_request_count) {
2369
                        tw_dev->max_posted_request_count = tw_dev->posted_request_count;
2370
                }
2371
        } else {
2372
                /* Couldn't post the command packet, so we do it in the isr */
2373
                if (tw_dev->state[request_id] != TW_S_PENDING) {
2374
                        tw_dev->state[request_id] = TW_S_PENDING;
2375
                        tw_dev->pending_request_count++;
2376
                        if (tw_dev->pending_request_count > tw_dev->max_pending_request_count) {
2377
                                tw_dev->max_pending_request_count = tw_dev->pending_request_count;
2378
                        }
2379
                        tw_dev->pending_queue[tw_dev->pending_tail] = request_id;
2380
                        if (tw_dev->pending_tail == TW_Q_LENGTH-1) {
2381
                                tw_dev->pending_tail = TW_Q_START;
2382
                        } else {
2383
                                tw_dev->pending_tail = tw_dev->pending_tail + 1;
2384
                        }
2385
                }
2386
                tw_unmask_command_interrupt(tw_dev);
2387
                return 1;
2388
        }
2389
        return 0;
2390
} /* End tw_post_command_packet() */
2391
 
2392
/* This function will reset a device extension */
2393
int tw_reset_device_extension(TW_Device_Extension *tw_dev)
2394
{
2395
        int imax = 0;
2396
        int i = 0;
2397
        Scsi_Cmnd *srb;
2398
 
2399
        dprintk(KERN_NOTICE "3w-xxxx: tw_reset_device_extension()\n");
2400
        imax = TW_Q_LENGTH;
2401
 
2402
        if (tw_reset_sequence(tw_dev)) {
2403
                printk(KERN_WARNING "3w-xxxx: scsi%d: Reset sequence failed.\n", tw_dev->host->host_no);
2404
                return 1;
2405
        }
2406
 
2407
        /* Abort all requests that are in progress */
2408
        for (i=0;i<imax;i++) {
2409
                if ((tw_dev->state[i] != TW_S_FINISHED) &&
2410
                    (tw_dev->state[i] != TW_S_INITIAL) &&
2411
                    (tw_dev->state[i] != TW_S_COMPLETED)) {
2412
                        srb = tw_dev->srb[i];
2413
                        if (srb != NULL) {
2414
                                srb->result = (DID_RESET << 16);
2415
                                tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);
2416
                                tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[i]);
2417
                        }
2418
                }
2419
        }
2420
 
2421
        /* Reset queues and counts */
2422
        for (i=0;i<imax;i++) {
2423
                tw_dev->free_queue[i] = i;
2424
                tw_dev->state[i] = TW_S_INITIAL;
2425
        }
2426
        tw_dev->free_head = TW_Q_START;
2427
        tw_dev->free_tail = TW_Q_START;
2428
        tw_dev->posted_request_count = 0;
2429
        tw_dev->pending_request_count = 0;
2430
        tw_dev->pending_head = TW_Q_START;
2431
        tw_dev->pending_tail = TW_Q_START;
2432
        tw_dev->reset_print = 0;
2433
        tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
2434
 
2435
        return 0;
2436
} /* End tw_reset_device_extension() */
2437
 
2438
/* This function will reset a controller */
2439
int tw_reset_sequence(TW_Device_Extension *tw_dev)
2440
{
2441
        int error = 0;
2442
        int tries = 0;
2443
 
2444
        /* Disable interrupts */
2445
        tw_disable_interrupts(tw_dev);
2446
 
2447
        /* Reset the board */
2448
        while (tries < TW_MAX_RESET_TRIES) {
2449
                tw_soft_reset(tw_dev);
2450
 
2451
                error = tw_aen_drain_queue(tw_dev);
2452
                if (error) {
2453
                        printk(KERN_WARNING "3w-xxxx: scsi%d: AEN drain failed, retrying.\n", tw_dev->host->host_no);
2454
                        tries++;
2455
                        continue;
2456
                }
2457
 
2458
                /* Check for controller errors */
2459
                if (tw_check_errors(tw_dev)) {
2460
                        printk(KERN_WARNING "3w-xxxx: scsi%d: Controller errors found, retrying.\n", tw_dev->host->host_no);
2461
                        tries++;
2462
                        continue;
2463
                }
2464
 
2465
                /* Now the controller is in a good state */
2466
                break;
2467
        }
2468
 
2469
        if (tries >= TW_MAX_RESET_TRIES) {
2470
                printk(KERN_WARNING "3w-xxxx: scsi%d: Controller errors, card not responding, check all cabling.\n", tw_dev->host->host_no);
2471
                return 1;
2472
        }
2473
 
2474
        error = tw_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS);
2475
        if (error) {
2476
                printk(KERN_WARNING "3w-xxxx: scsi%d: Connection initialization failed.\n", tw_dev->host->host_no);
2477
                return 1;
2478
        }
2479
 
2480
        /* Re-enable interrupts */
2481
        tw_enable_and_clear_interrupts(tw_dev);
2482
 
2483
        return 0;
2484
} /* End tw_reset_sequence() */
2485
 
2486
/* This funciton returns unit geometry in cylinders/heads/sectors */
2487
int tw_scsi_biosparam(Disk *disk, kdev_t dev, int geom[])
2488
{
2489
        int heads, sectors, cylinders;
2490
        TW_Device_Extension *tw_dev;
2491
 
2492
        dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_biosparam()\n");
2493
        tw_dev = (TW_Device_Extension *)disk->device->host->hostdata;
2494
 
2495
        heads = 64;
2496
        sectors = 32;
2497
        cylinders = disk->capacity / (heads * sectors);
2498
 
2499
        if (disk->capacity >= 0x200000) {
2500
                heads = 255;
2501
                sectors = 63;
2502
                cylinders = disk->capacity / (heads * sectors);
2503
        }
2504
 
2505
        dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_biosparam(): heads = %d, sectors = %d, cylinders = %d\n", heads, sectors, cylinders);
2506
        geom[0] = heads;
2507
        geom[1] = sectors;
2508
        geom[2] = cylinders;
2509
 
2510
        return 0;
2511
} /* End tw_scsi_biosparam() */
2512
 
2513
/* This function will find and initialize any cards */
2514
int tw_scsi_detect(Scsi_Host_Template *tw_host)
2515
{
2516
        int ret;
2517
 
2518
        dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_detect()\n");
2519
 
2520
        printk(KERN_WARNING "3ware Storage Controller device driver for Linux v%s.\n", tw_driver_version);
2521
 
2522
        /* Check if the kernel has PCI interface compiled in */
2523
        if (!pci_present()) {
2524
                printk(KERN_WARNING "3w-xxxx: tw_scsi_detect(): No pci interface present.\n");
2525
                return 0;
2526
        }
2527
 
2528
        spin_unlock_irq(&io_request_lock);
2529
        ret = tw_findcards(tw_host);
2530
        spin_lock_irq(&io_request_lock);
2531
 
2532
        return ret;
2533
} /* End tw_scsi_detect() */
2534
 
2535
/* This is the new scsi eh abort function */
2536
int tw_scsi_eh_abort(Scsi_Cmnd *SCpnt)
2537
{
2538
        TW_Device_Extension *tw_dev=NULL;
2539
        int i = 0;
2540
 
2541
        dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_eh_abort()\n");
2542
 
2543
        if (!SCpnt) {
2544
                printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Invalid Scsi_Cmnd.\n");
2545
                return (FAILED);
2546
        }
2547
 
2548
        tw_dev = (TW_Device_Extension *)SCpnt->host->hostdata;
2549
        if (tw_dev == NULL) {
2550
                printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Invalid device extension.\n");
2551
                return (FAILED);
2552
        }
2553
 
2554
        spin_lock(&tw_dev->tw_lock);
2555
        tw_dev->num_aborts++;
2556
 
2557
        /* If the command hasn't been posted yet, we can do the abort */
2558
        for (i=0;i<TW_Q_LENGTH;i++) {
2559
                if (tw_dev->srb[i] == SCpnt) {
2560
                        if (tw_dev->state[i] == TW_S_STARTED) {
2561
                                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]->target, SCpnt);
2562
                                tw_dev->state[i] = TW_S_COMPLETED;
2563
                                tw_state_request_finish(tw_dev, i);
2564
                                spin_unlock(&tw_dev->tw_lock);
2565
                                return (SUCCESS);
2566
                        }
2567
                        if (tw_dev->state[i] == TW_S_PENDING) {
2568
                                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]->target, SCpnt);
2569
                                if (tw_dev->pending_head == TW_Q_LENGTH-1) {
2570
                                        tw_dev->pending_head = TW_Q_START;
2571
                                } else {
2572
                                        tw_dev->pending_head = tw_dev->pending_head + 1;
2573
                                }
2574
                                tw_dev->pending_request_count--;
2575
                                tw_dev->state[i] = TW_S_COMPLETED;
2576
                                tw_state_request_finish(tw_dev, i);
2577
                                spin_unlock(&tw_dev->tw_lock);
2578
                                return (SUCCESS);
2579
                        }
2580
                        if (tw_dev->state[i] == TW_S_POSTED) {
2581
                                /* If the command has already been posted, we have to reset the card */
2582
                                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]->target, SCpnt);
2583
                                /* We have to let AEN requests through before the reset */
2584
                                spin_unlock(&tw_dev->tw_lock);
2585
                                spin_unlock_irq(&io_request_lock);
2586
                                mdelay(TW_AEN_WAIT_TIME);
2587
                                spin_lock_irq(&io_request_lock);
2588
                                spin_lock(&tw_dev->tw_lock);
2589
 
2590
                                if (tw_reset_device_extension(tw_dev)) {
2591
                                        dprintk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Reset failed for card %d.\n", tw_dev->host->host_no);
2592
                                        spin_unlock(&tw_dev->tw_lock);
2593
                                        return (FAILED);
2594
                                }
2595
                        }
2596
                }
2597
        }
2598
 
2599
        spin_unlock(&tw_dev->tw_lock);
2600
        return (SUCCESS);
2601
} /* End tw_scsi_eh_abort() */
2602
 
2603
/* This is the new scsi eh reset function */
2604
int tw_scsi_eh_reset(Scsi_Cmnd *SCpnt)
2605
{
2606
        TW_Device_Extension *tw_dev=NULL;
2607
 
2608
        dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_eh_reset()\n");
2609
 
2610
        if (!SCpnt) {
2611
                printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_reset(): Invalid Scsi_Cmnd.\n");
2612
                return (FAILED);
2613
        }
2614
 
2615
        tw_dev = (TW_Device_Extension *)SCpnt->host->hostdata;
2616
        if (tw_dev == NULL) {
2617
                printk(KERN_WARNING "3w-xxxx: tw_scsi_eh_reset(): Invalid device extension.\n");
2618
                return (FAILED);
2619
        }
2620
 
2621
        /* We have to let AEN requests through before the reset */
2622
        spin_unlock_irq(&io_request_lock);
2623
        mdelay(TW_AEN_WAIT_TIME);
2624
        spin_lock_irq(&io_request_lock);
2625
 
2626
        spin_lock(&tw_dev->tw_lock);
2627
        tw_dev->num_resets++;
2628
 
2629
        /* Now reset the card and some of the device extension data */
2630
        if (tw_reset_device_extension(tw_dev)) {
2631
                printk(KERN_WARNING "3w-xxxx: scsi%d: Reset failed.\n", tw_dev->host->host_no);
2632
                spin_unlock(&tw_dev->tw_lock);
2633
                return (FAILED);
2634
        }
2635
        printk(KERN_WARNING "3w-xxxx: scsi%d: Reset succeeded.\n", tw_dev->host->host_no);
2636
        spin_unlock(&tw_dev->tw_lock);
2637
 
2638
        return (SUCCESS);
2639
} /* End tw_scsi_eh_reset() */
2640
 
2641
/* This function handles input and output from /proc/scsi/3w-xxxx/x */
2642
int tw_scsi_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout)
2643
{
2644
        TW_Device_Extension *tw_dev = NULL;
2645
        TW_Info info;
2646
        int i;
2647
        int j;
2648
 
2649
        dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_proc_info()\n");
2650
 
2651
        /* Find the correct device extension */
2652
        for (i=0;i<tw_device_extension_count;i++)
2653
                if (tw_device_extension_list[i]->host->host_no == hostno)
2654
                        tw_dev = tw_device_extension_list[i];
2655
        if (tw_dev == NULL) {
2656
                printk(KERN_WARNING "3w-xxxx: tw_scsi_proc_info(): Couldn't locate device extension.\n");
2657
                return (-EINVAL);
2658
        }
2659
 
2660
        info.buffer = buffer;
2661
        info.length = length;
2662
        info.offset = offset;
2663
        info.position = 0;
2664
 
2665
        if (inout) {
2666
                /* Write */
2667
                if (strncmp(buffer, "debug", 5) == 0) {
2668
                        printk(KERN_INFO "3w-xxxx: Posted commands:\n");
2669
                        for (j=0;j<TW_Q_LENGTH;j++) {
2670
                                if (tw_dev->state[j] == TW_S_POSTED) {
2671
                                        TW_Command *command = (TW_Command *)tw_dev->command_packet_virtual_address[j];
2672
                                        printk(KERN_INFO "3w-xxxx: Request_id: %d\n", j);
2673
                                        printk(KERN_INFO "Opcode: 0x%x\n", command->byte0.opcode);
2674
                                        printk(KERN_INFO "Block_count: 0x%x\n", command->byte6.block_count);
2675
                                        printk(KERN_INFO "LBA: 0x%x\n", command->byte8.io.lba);
2676
                                        printk(KERN_INFO "Physical command packet addr: 0x%lx\n", tw_dev->command_packet_physical_address[j]);
2677
                                        printk(KERN_INFO "Scsi_Cmnd: %p\n", tw_dev->srb[j]);
2678
                                }
2679
                        }
2680
                        printk(KERN_INFO "3w-xxxx: Free_head: %3d\n", tw_dev->free_head);
2681
                        printk(KERN_INFO "3w-xxxx: Free_tail: %3d\n", tw_dev->free_tail);
2682
                }
2683
                return length;
2684
        } else {
2685
                /* Read */
2686
                if (start) {
2687
                        *start = buffer;
2688
                }
2689
                tw_copy_info(&info, "scsi%d: 3ware Storage Controller\n", hostno);
2690
                tw_copy_info(&info, "Driver version: %s\n", tw_driver_version);
2691
                tw_copy_info(&info, "Current commands posted:       %3d\n", tw_dev->posted_request_count);
2692
                tw_copy_info(&info, "Max commands posted:           %3d\n", tw_dev->max_posted_request_count);
2693
                tw_copy_info(&info, "Current pending commands:      %3d\n", tw_dev->pending_request_count);
2694
                tw_copy_info(&info, "Max pending commands:          %3d\n", tw_dev->max_pending_request_count);
2695
                tw_copy_info(&info, "Last sgl length:               %3d\n", tw_dev->sgl_entries);
2696
                tw_copy_info(&info, "Max sgl length:                %3d\n", tw_dev->max_sgl_entries);
2697
                tw_copy_info(&info, "Last sector count:             %3d\n", tw_dev->sector_count);
2698
                tw_copy_info(&info, "Max sector count:              %3d\n", tw_dev->max_sector_count);
2699
                tw_copy_info(&info, "Resets:                        %3d\n", tw_dev->num_resets);
2700
                tw_copy_info(&info, "Aborts:                        %3d\n", tw_dev->num_aborts);
2701
                tw_copy_info(&info, "AEN's:                         %3d\n", tw_dev->aen_count);
2702
        }
2703
        if (info.position > info.offset) {
2704
                return (info.position - info.offset);
2705
        } else {
2706
                return 0;
2707
        }
2708
} /* End tw_scsi_proc_info() */
2709
 
2710
/* This is the main scsi queue function to handle scsi opcodes */
2711
int tw_scsi_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
2712
{
2713
        unsigned char *command = SCpnt->cmnd;
2714
        int request_id = 0;
2715
        int error = 0;
2716
        TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->host->hostdata;
2717
 
2718
        if (tw_dev == NULL) {
2719
                printk(KERN_WARNING "3w-xxxx: tw_scsi_queue(): Invalid device extension.\n");
2720
                SCpnt->result = (DID_ERROR << 16);
2721
                done(SCpnt);
2722
                return 0;
2723
        }
2724
 
2725
        spin_lock(&tw_dev->tw_lock);
2726
        dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue()\n");
2727
 
2728
        /* Skip scsi command if it isn't for us */
2729
        if ((SCpnt->channel != 0) || (SCpnt->lun != 0)) {
2730
                SCpnt->result = (DID_BAD_TARGET << 16);
2731
                done(SCpnt);
2732
                spin_unlock(&tw_dev->tw_lock);
2733
                return 0;
2734
        }
2735
 
2736
        /* Save done function into Scsi_Cmnd struct */
2737
        SCpnt->scsi_done = done;
2738
 
2739
        /* Queue the command and get a request id */
2740
        tw_state_request_start(tw_dev, &request_id);
2741
 
2742
        /* Save the scsi command for use by the ISR */
2743
        tw_dev->srb[request_id] = SCpnt;
2744
 
2745
        /* Initialize phase to zero */
2746
        SCpnt->SCp.phase = 0;
2747
 
2748
        switch (*command) {
2749
                case READ_10:
2750
                case READ_6:
2751
                case WRITE_10:
2752
                case WRITE_6:
2753
                        dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ/WRITE.\n");
2754
                        error = tw_scsiop_read_write(tw_dev, request_id);
2755
                        break;
2756
                case TEST_UNIT_READY:
2757
                        dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught TEST_UNIT_READY.\n");
2758
                        error = tw_scsiop_test_unit_ready(tw_dev, request_id);
2759
                        break;
2760
                case INQUIRY:
2761
                        dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught INQUIRY.\n");
2762
                        error = tw_scsiop_inquiry(tw_dev, request_id);
2763
                        break;
2764
                case READ_CAPACITY:
2765
                        dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught READ_CAPACITY.\n");
2766
                        error = tw_scsiop_read_capacity(tw_dev, request_id);
2767
                        break;
2768
                case REQUEST_SENSE:
2769
                        dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught REQUEST_SENSE.\n");
2770
                        error = tw_scsiop_request_sense(tw_dev, request_id);
2771
                        break;
2772
                case MODE_SENSE:
2773
                        dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught MODE_SENSE.\n");
2774
                        error = tw_scsiop_mode_sense(tw_dev, request_id);
2775
                        break;
2776
                case SYNCHRONIZE_CACHE:
2777
                        dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught SYNCHRONIZE_CACHE.\n");
2778
                        error = tw_scsiop_synchronize_cache(tw_dev, request_id);
2779
                        break;
2780
                case TW_IOCTL:
2781
                        dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue(): caught TW_SCSI_IOCTL.\n");
2782
                        error = tw_ioctl(tw_dev, request_id);
2783
                        break;
2784
                default:
2785
                        printk(KERN_NOTICE "3w-xxxx: scsi%d: Unknown scsi opcode: 0x%x\n", tw_dev->host->host_no, *command);
2786
                        tw_dev->state[request_id] = TW_S_COMPLETED;
2787
                        tw_state_request_finish(tw_dev, request_id);
2788
                        SCpnt->result = (DID_BAD_TARGET << 16);
2789
                        done(SCpnt);
2790
        }
2791
        if (error) {
2792
                tw_dev->state[request_id] = TW_S_COMPLETED;
2793
                tw_state_request_finish(tw_dev, request_id);
2794
                SCpnt->result = (DID_ERROR << 16);
2795
                done(SCpnt);
2796
        }
2797
        spin_unlock(&tw_dev->tw_lock);
2798
 
2799
        return 0;
2800
} /* End tw_scsi_queue() */
2801
 
2802
/* This function will release the resources on an rmmod call */
2803
int tw_scsi_release(struct Scsi_Host *tw_host)
2804
{
2805
        TW_Device_Extension *tw_dev;
2806
        tw_dev = (TW_Device_Extension *)tw_host->hostdata;
2807
 
2808
        dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_release()\n");
2809
 
2810
        /* Fake like we just shut down, so notify the card that
2811
         * we "shut down cleanly".
2812
         */
2813
        tw_halt(0, 0, 0);  // parameters aren't actually used
2814
 
2815
        /* Free up the IO region */
2816
        release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE);
2817
 
2818
        /* Free up the IRQ */
2819
        free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
2820
 
2821
        /* Unregister character device */
2822
        if (twe_major >= 0) {
2823
                unregister_chrdev(twe_major, "twe");
2824
                twe_major = -1;
2825
        }
2826
 
2827
        /* Free up device extension resources */
2828
        tw_free_device_extension(tw_dev);
2829
 
2830
        /* Tell kernel scsi-layer we are gone */
2831
        scsi_unregister(tw_host);
2832
 
2833
        return 0;
2834
} /* End tw_scsi_release() */
2835
 
2836
/* This function handles scsi inquiry commands */
2837
int tw_scsiop_inquiry(TW_Device_Extension *tw_dev, int request_id)
2838
{
2839
        TW_Param *param;
2840
        TW_Command *command_packet;
2841
        unsigned long command_que_value;
2842
        u32 command_que_addr;
2843
        unsigned long param_value;
2844
 
2845
        dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry()\n");
2846
 
2847
        /* Initialize command packet */
2848
        command_que_addr = tw_dev->registers.command_que_addr;
2849
        command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
2850
        if (command_packet == NULL) {
2851
                printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad command packet virtual address.\n");
2852
                return 1;
2853
        }
2854
        memset(command_packet, 0, sizeof(TW_Sector));
2855
        command_packet->byte0.opcode = TW_OP_GET_PARAM;
2856
        command_packet->byte0.sgl_offset = 2;
2857
        command_packet->size = 4;
2858
        command_packet->request_id = request_id;
2859
        command_packet->byte3.unit = 0;
2860
        command_packet->byte3.host_id = 0;
2861
        command_packet->status = 0;
2862
        command_packet->flags = 0;
2863
        command_packet->byte6.parameter_count = 1;
2864
 
2865
        /* Now setup the param */
2866
        if (tw_dev->alignment_virtual_address[request_id] == NULL) {
2867
                printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad alignment virtual address.\n");
2868
                return 1;
2869
        }
2870
        param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
2871
        memset(param, 0, sizeof(TW_Sector));
2872
        param->table_id = 3;     /* unit summary table */
2873
        param->parameter_id = 3; /* unitsstatus parameter */
2874
        param->parameter_size_bytes = TW_MAX_UNITS;
2875
        param_value = tw_dev->alignment_physical_address[request_id];
2876
        if (param_value == 0) {
2877
                printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad alignment physical address.\n");
2878
                return 1;
2879
        }
2880
 
2881
        command_packet->byte8.param.sgl[0].address = param_value;
2882
        command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
2883
        command_que_value = tw_dev->command_packet_physical_address[request_id];
2884
        if (command_que_value == 0) {
2885
                printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry(): Bad command packet physical address.\n");
2886
                return 1;
2887
        }
2888
 
2889
        /* Now try to post the command packet */
2890
        tw_post_command_packet(tw_dev, request_id);
2891
 
2892
        return 0;
2893
} /* End tw_scsiop_inquiry() */
2894
 
2895
/* This function is called by the isr to complete an inquiry command */
2896
int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_id)
2897
{
2898
        unsigned char *is_unit_present;
2899
        unsigned char *request_buffer;
2900
        TW_Param *param;
2901
 
2902
        dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry_complete()\n");
2903
 
2904
        /* Fill request buffer */
2905
        if (tw_dev->srb[request_id]->request_buffer == NULL) {
2906
                printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry_complete(): Request buffer NULL.\n");
2907
                return 1;
2908
        }
2909
        request_buffer = tw_dev->srb[request_id]->request_buffer;
2910
        memset(request_buffer, 0, tw_dev->srb[request_id]->request_bufflen);
2911
        request_buffer[0] = TYPE_DISK; /* Peripheral device type */
2912
        request_buffer[1] = 0;          /* Device type modifier */
2913
        request_buffer[2] = 0;          /* No ansi/iso compliance */
2914
        request_buffer[4] = 31;        /* Additional length */
2915
        memcpy(&request_buffer[8], "3ware   ", 8);       /* Vendor ID */
2916
        sprintf(&request_buffer[16], "Logical Disk %-2d ", tw_dev->srb[request_id]->target);
2917
        memcpy(&request_buffer[32], tw_driver_version, 3);
2918
 
2919
        param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
2920
        if (param == NULL) {
2921
                printk(KERN_WARNING "3w-xxxx: tw_scsiop_inquiry_complete(): Bad alignment virtual address.\n");
2922
                return 1;
2923
        }
2924
        is_unit_present = &(param->data[0]);
2925
 
2926
        if (is_unit_present[tw_dev->srb[request_id]->target] & TW_UNIT_ONLINE) {
2927
                tw_dev->is_unit_present[tw_dev->srb[request_id]->target] = TRUE;
2928
        } else {
2929
                tw_dev->is_unit_present[tw_dev->srb[request_id]->target] = FALSE;
2930
                tw_dev->srb[request_id]->result = (DID_BAD_TARGET << 16);
2931
                return TW_ISR_DONT_RESULT;
2932
        }
2933
 
2934
        return 0;
2935
} /* End tw_scsiop_inquiry_complete() */
2936
 
2937
/* This function handles scsi mode_sense commands */
2938
int tw_scsiop_mode_sense(TW_Device_Extension *tw_dev, int request_id)
2939
{
2940
        TW_Param *param;
2941
        TW_Command *command_packet;
2942
        unsigned long command_que_value;
2943
        unsigned long param_value;
2944
 
2945
        dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_mode_sense()\n");
2946
 
2947
        /* Only page control = 0, page code = 0x8 (cache page) supported */
2948
        if (tw_dev->srb[request_id]->cmnd[2] != 0x8) {
2949
                tw_dev->state[request_id] = TW_S_COMPLETED;
2950
                tw_state_request_finish(tw_dev, request_id);
2951
                tw_dev->srb[request_id]->result = (DID_OK << 16);
2952
                tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
2953
                return 0;
2954
        }
2955
 
2956
        /* Now read firmware cache setting for this unit */
2957
        command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
2958
        if (command_packet == NULL) {
2959
                printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad command packet virtual address.\n");
2960
                return 1;
2961
        }
2962
 
2963
        /* Setup the command packet */
2964
        memset(command_packet, 0, sizeof(TW_Sector));
2965
        command_packet->byte0.opcode = TW_OP_GET_PARAM;
2966
        command_packet->byte0.sgl_offset = 2;
2967
        command_packet->size = 4;
2968
        command_packet->request_id = request_id;
2969
        command_packet->byte3.unit = 0;
2970
        command_packet->byte3.host_id = 0;
2971
        command_packet->status = 0;
2972
        command_packet->flags = 0;
2973
        command_packet->byte6.parameter_count = 1;
2974
 
2975
        /* Setup the param */
2976
        if (tw_dev->alignment_virtual_address[request_id] == NULL) {
2977
                printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad alignment virtual address.\n");
2978
                return 1;
2979
        }
2980
 
2981
        param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
2982
        memset(param, 0, sizeof(TW_Sector));
2983
        param->table_id = TW_UNIT_INFORMATION_TABLE_BASE + tw_dev->srb[request_id]->target;
2984
        param->parameter_id = 7; /* unit flags */
2985
        param->parameter_size_bytes = 1;
2986
        param_value = tw_dev->alignment_physical_address[request_id];
2987
        if (param_value == 0) {
2988
                printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad alignment physical address.\n");
2989
                return 1;
2990
        }
2991
 
2992
        command_packet->byte8.param.sgl[0].address = param_value;
2993
        command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
2994
        command_que_value = tw_dev->command_packet_physical_address[request_id];
2995
        if (command_que_value == 0) {
2996
                printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense(): Bad command packet physical address.\n");
2997
                return 1;
2998
        }
2999
 
3000
        /* Now try to post the command packet */
3001
        tw_post_command_packet(tw_dev, request_id);
3002
 
3003
        return 0;
3004
} /* End tw_scsiop_mode_sense() */
3005
 
3006
/* This function is called by the isr to complete a mode sense command */
3007
int tw_scsiop_mode_sense_complete(TW_Device_Extension *tw_dev, int request_id)
3008
{
3009
        TW_Param *param;
3010
        unsigned char *flags;
3011
        unsigned char *request_buffer;
3012
 
3013
        dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_mode_sense_complete()\n");
3014
 
3015
        param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
3016
        if (param == NULL) {
3017
                printk(KERN_WARNING "3w-xxxx: tw_scsiop_mode_sense_complete(): Bad alignment virtual address.\n");
3018
                return 1;
3019
        }
3020
        flags = (char *)&(param->data[0]);
3021
        request_buffer = tw_dev->srb[request_id]->buffer;
3022
        memset(request_buffer, 0, tw_dev->srb[request_id]->request_bufflen);
3023
 
3024
        request_buffer[0] = 0xf;        /* mode data length */
3025
        request_buffer[1] = 0;          /* default medium type */
3026
        request_buffer[2] = 0x10;       /* dpo/fua support on */
3027
        request_buffer[3] = 0;          /* no block descriptors */
3028
        request_buffer[4] = 0x8;        /* caching page */
3029
        request_buffer[5] = 0xa;        /* page length */
3030
        if (*flags & 0x1)
3031
                request_buffer[6] = 0x4;        /* WCE on */
3032
        else
3033
                request_buffer[6] = 0x0;        /* WCE off */
3034
 
3035
        return 0;
3036
} /* End tw_scsiop_mode_sense_complete() */
3037
 
3038
/* This function handles scsi read_capacity commands */
3039
int tw_scsiop_read_capacity(TW_Device_Extension *tw_dev, int request_id)
3040
{
3041
        TW_Param *param;
3042
        TW_Command *command_packet;
3043
        unsigned long command_que_value;
3044
        u32 command_que_addr;
3045
        unsigned long param_value;
3046
 
3047
        dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity()\n");
3048
 
3049
        /* Initialize command packet */
3050
        command_que_addr = tw_dev->registers.command_que_addr;
3051
        command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
3052
 
3053
        if (command_packet == NULL) {
3054
                dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad command packet virtual address.\n");
3055
                return 1;
3056
        }
3057
        memset(command_packet, 0, sizeof(TW_Sector));
3058
        command_packet->byte0.opcode = TW_OP_GET_PARAM;
3059
        command_packet->byte0.sgl_offset = 2;
3060
        command_packet->size = 4;
3061
        command_packet->request_id = request_id;
3062
        command_packet->byte3.unit = tw_dev->srb[request_id]->target;
3063
        command_packet->byte3.host_id = 0;
3064
        command_packet->status = 0;
3065
        command_packet->flags = 0;
3066
        command_packet->byte6.block_count = 1;
3067
 
3068
        /* Now setup the param */
3069
        if (tw_dev->alignment_virtual_address[request_id] == NULL) {
3070
                dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad alignment virtual address.\n");
3071
                return 1;
3072
        }
3073
        param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
3074
        memset(param, 0, sizeof(TW_Sector));
3075
        param->table_id = TW_UNIT_INFORMATION_TABLE_BASE +
3076
        tw_dev->srb[request_id]->target;
3077
        param->parameter_id = 4;        /* unitcapacity parameter */
3078
        param->parameter_size_bytes = 4;
3079
        param_value = tw_dev->alignment_physical_address[request_id];
3080
        if (param_value == 0) {
3081
                dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad alignment physical address.\n");
3082
                return 1;
3083
        }
3084
 
3085
        command_packet->byte8.param.sgl[0].address = param_value;
3086
        command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
3087
        command_que_value = tw_dev->command_packet_physical_address[request_id];
3088
        if (command_que_value == 0) {
3089
                dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity(): Bad command packet physical address.\n");
3090
                return 1;
3091
        }
3092
 
3093
        /* Now try to post the command to the board */
3094
        tw_post_command_packet(tw_dev, request_id);
3095
 
3096
        return 0;
3097
} /* End tw_scsiop_read_capacity() */
3098
 
3099
/* This function is called by the isr to complete a readcapacity command */
3100
int tw_scsiop_read_capacity_complete(TW_Device_Extension *tw_dev, int request_id)
3101
{
3102
        unsigned char *param_data;
3103
        u32 capacity;
3104
        char *buff;
3105
        TW_Param *param;
3106
 
3107
        dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete()\n");
3108
 
3109
        buff = tw_dev->srb[request_id]->request_buffer;
3110
        if (buff == NULL) {
3111
                printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Request buffer NULL.\n");
3112
                return 1;
3113
        }
3114
        memset(buff, 0, tw_dev->srb[request_id]->request_bufflen);
3115
        param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
3116
        if (param == NULL) {
3117
                printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_capacity_complete(): Bad alignment virtual address.\n");
3118
                return 1;
3119
        }
3120
        param_data = &(param->data[0]);
3121
 
3122
        capacity = (param_data[3] << 24) | (param_data[2] << 16) |
3123
                   (param_data[1] << 8) | param_data[0];
3124
 
3125
        /* Subtract one sector to fix get last sector ioctl */
3126
        capacity -= 1;
3127
 
3128
        dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_capacity_complete(): Capacity = 0x%x.\n", capacity);
3129
 
3130
        /* Number of LBA's */
3131
        buff[0] = (capacity >> 24);
3132
        buff[1] = (capacity >> 16) & 0xff;
3133
        buff[2] = (capacity >> 8) & 0xff;
3134
        buff[3] = capacity & 0xff;
3135
 
3136
        /* Block size in bytes (512) */
3137
        buff[4] = (TW_BLOCK_SIZE >> 24);
3138
        buff[5] = (TW_BLOCK_SIZE >> 16) & 0xff;
3139
        buff[6] = (TW_BLOCK_SIZE >> 8) & 0xff;
3140
        buff[7] = TW_BLOCK_SIZE & 0xff;
3141
 
3142
        return 0;
3143
} /* End tw_scsiop_read_capacity_complete() */
3144
 
3145
/* This function handles scsi read or write commands */
3146
int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id)
3147
{
3148
        TW_Command *command_packet;
3149
        unsigned long command_que_value;
3150
        u32 command_que_addr = 0x0;
3151
        u32 lba = 0x0, num_sectors = 0x0, buffaddr = 0x0;
3152
        int i, use_sg, count = 0;
3153
        Scsi_Cmnd *srb;
3154
        struct scatterlist *sglist;
3155
 
3156
        dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write()\n");
3157
 
3158
        if (tw_dev->srb[request_id]->request_buffer == NULL) {
3159
                printk(KERN_WARNING "3w-xxxx: tw_scsiop_read_write(): Request buffer NULL.\n");
3160
                return 1;
3161
        }
3162
        sglist = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;
3163
        srb = tw_dev->srb[request_id];
3164
 
3165
        /* Initialize command packet */
3166
        command_que_addr = tw_dev->registers.command_que_addr;
3167
        command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
3168
        if (command_packet == NULL) {
3169
                dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): Bad command packet virtual address.\n");
3170
                return 1;
3171
        }
3172
 
3173
        if (srb->cmnd[0] == READ_6 || srb->cmnd[0] == READ_10) {
3174
                command_packet->byte0.opcode = TW_OP_READ;
3175
        } else {
3176
                command_packet->byte0.opcode = TW_OP_WRITE;
3177
        }
3178
 
3179
        command_packet->byte0.sgl_offset = 3;
3180
        command_packet->size = 3;
3181
        command_packet->request_id = request_id;
3182
        command_packet->byte3.unit = srb->target;
3183
        command_packet->byte3.host_id = 0;
3184
        command_packet->status = 0;
3185
        command_packet->flags = 0;
3186
 
3187
        if (srb->cmnd[0] == WRITE_10) {
3188
                if ((srb->cmnd[1] & 0x8) || (srb->cmnd[1] & 0x10))
3189
                        command_packet->flags = 1;
3190
        }
3191
 
3192
        if (srb->cmnd[0] == READ_6 || srb->cmnd[0] == WRITE_6) {
3193
                lba = ((u32)srb->cmnd[1] << 16) | ((u32)srb->cmnd[2] << 8) | (u32)srb->cmnd[3];
3194
                num_sectors = (u32)srb->cmnd[4];
3195
        } else {
3196
                lba = ((u32)srb->cmnd[2] << 24) | ((u32)srb->cmnd[3] << 16) | ((u32)srb->cmnd[4] << 8) | (u32)srb->cmnd[5];
3197
                num_sectors = (u32)srb->cmnd[8] | ((u32)srb->cmnd[7] << 8);
3198
        }
3199
 
3200
        /* Update sector statistic */
3201
        tw_dev->sector_count = num_sectors;
3202
        if (tw_dev->sector_count > tw_dev->max_sector_count)
3203
                tw_dev->max_sector_count = tw_dev->sector_count;
3204
 
3205
        dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): lba = 0x%x num_sectors = 0x%x\n", lba, num_sectors);
3206
        command_packet->byte8.io.lba = lba;
3207
        command_packet->byte6.block_count = num_sectors;
3208
 
3209
        if ((tw_dev->is_raid_five[tw_dev->srb[request_id]->target] == 0) || (srb->cmnd[0] == READ_6) || (srb->cmnd[0] == READ_10) || (tw_dev->tw_pci_dev->device == TW_DEVICE_ID2)) {
3210
                /* Do this if there are no sg list entries */
3211
                if (tw_dev->srb[request_id]->use_sg == 0) {
3212
                        dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_read_write(): SG = 0\n");
3213
                        buffaddr = tw_map_scsi_single_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
3214
                        if (buffaddr == 0)
3215
                                return 1;
3216
 
3217
                        command_packet->byte8.io.sgl[0].address = buffaddr;
3218
                        command_packet->byte8.io.sgl[0].length = tw_dev->srb[request_id]->request_bufflen;
3219
                        command_packet->size+=2;
3220
                }
3221
 
3222
                /* Do this if we have multiple sg list entries */
3223
                if (tw_dev->srb[request_id]->use_sg > 0) {
3224
                        use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
3225
                        if (use_sg == 0)
3226
                                return 1;
3227
 
3228
                        for (i=0;i<use_sg; i++) {
3229
                                command_packet->byte8.io.sgl[i].address = sg_dma_address(&sglist[i]);
3230
                                command_packet->byte8.io.sgl[i].length = sg_dma_len(&sglist[i]);
3231
                                command_packet->size+=2;
3232
                        }
3233
                }
3234
        } else {
3235
                /* Do this if there are no sg list entries for raid 5 */
3236
                if (tw_dev->srb[request_id]->use_sg == 0) {
3237
                        dprintk(KERN_WARNING "doing raid 5 write use_sg = 0, bounce_buffer[%d] = 0x%p\n", request_id, tw_dev->bounce_buffer[request_id]);
3238
                        buffaddr = tw_map_scsi_single_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
3239
                        if (buffaddr == 0)
3240
                                return 1;
3241
 
3242
                        memcpy(tw_dev->bounce_buffer[request_id], bus_to_virt(buffaddr), tw_dev->srb[request_id]->request_bufflen);
3243
                        command_packet->byte8.io.sgl[0].address = tw_dev->bounce_buffer_phys[request_id];
3244
                        command_packet->byte8.io.sgl[0].length = tw_dev->srb[request_id]->request_bufflen;
3245
                        command_packet->size+=2;
3246
                }
3247
 
3248
                /* Do this if we have multiple sg list entries for raid 5 */
3249
                if (tw_dev->srb[request_id]->use_sg > 0) {
3250
                        dprintk(KERN_WARNING "doing raid 5 write use_sg = %d, sglist[0].length = %d\n", tw_dev->srb[request_id]->use_sg, sglist[0].length);
3251
                        use_sg = tw_map_scsi_sg_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
3252
                        if (use_sg == 0)
3253
                                return 1;
3254
 
3255
                        for (i=0;i<use_sg; i++) {
3256
                                memcpy((char *)tw_dev->bounce_buffer[request_id]+count, bus_to_virt(sg_dma_address(&sglist[i])), sg_dma_len(&sglist[i]));
3257
                                count+=sg_dma_len(&sglist[i]);
3258
                        }
3259
                        command_packet->byte8.io.sgl[0].address = tw_dev->bounce_buffer_phys[request_id];
3260
                        command_packet->byte8.io.sgl[0].length = count;
3261
                        command_packet->size = 5; /* single sgl */
3262
                }
3263
        }
3264
 
3265
        /* Update SG statistics */
3266
        tw_dev->sgl_entries = tw_dev->srb[request_id]->use_sg;
3267
        if (tw_dev->sgl_entries > tw_dev->max_sgl_entries)
3268
                tw_dev->max_sgl_entries = tw_dev->sgl_entries;
3269
 
3270
        command_que_value = tw_dev->command_packet_physical_address[request_id];
3271
        if (command_que_value == 0) {
3272
                dprintk(KERN_WARNING "3w-xxxx: tw_scsiop_read_write(): Bad command packet physical address.\n");
3273
                return 1;
3274
        }
3275
 
3276
        /* Now try to post the command to the board */
3277
        tw_post_command_packet(tw_dev, request_id);
3278
 
3279
        return 0;
3280
} /* End tw_scsiop_read_write() */
3281
 
3282
/* This function will handle the request sense scsi command */
3283
int tw_scsiop_request_sense(TW_Device_Extension *tw_dev, int request_id)
3284
{
3285
        dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_request_sense()\n");
3286
 
3287
        /* For now we just zero the request buffer */
3288
        memset(tw_dev->srb[request_id]->request_buffer, 0, tw_dev->srb[request_id]->request_bufflen);
3289
 
3290
        tw_dev->state[request_id] = TW_S_COMPLETED;
3291
        tw_state_request_finish(tw_dev, request_id);
3292
 
3293
        /* If we got a request_sense, we probably want a reset, return error */
3294
        tw_dev->srb[request_id]->result = (DID_ERROR << 16);
3295
        tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
3296
 
3297
        return 0;
3298
} /* End tw_scsiop_request_sense() */
3299
 
3300
/* This function will handle synchronize cache scsi command */
3301
int tw_scsiop_synchronize_cache(TW_Device_Extension *tw_dev, int request_id)
3302
{
3303
        TW_Command *command_packet;
3304
        unsigned long command_que_value;
3305
 
3306
        dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_synchronize_cache()\n");
3307
 
3308
        /* Send firmware flush command for this unit */
3309
        command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
3310
        if (command_packet == NULL) {
3311
                printk(KERN_WARNING "3w-xxxx: tw_scsiop_synchronize_cache(): Bad command packet virtual address.\n");
3312
                return 1;
3313
        }
3314
 
3315
        /* Setup the command packet */
3316
        memset(command_packet, 0, sizeof(TW_Sector));
3317
        command_packet->byte0.opcode = TW_OP_FLUSH_CACHE;
3318
        command_packet->byte0.sgl_offset = 0;
3319
        command_packet->size = 2;
3320
        command_packet->request_id = request_id;
3321
        command_packet->byte3.unit = tw_dev->srb[request_id]->target;
3322
        command_packet->byte3.host_id = 0;
3323
        command_packet->status = 0;
3324
        command_packet->flags = 0;
3325
        command_packet->byte6.parameter_count = 1;
3326
        command_que_value = tw_dev->command_packet_physical_address[request_id];
3327
        if (command_que_value == 0) {
3328
                printk(KERN_WARNING "3w-xxxx: tw_scsiop_synchronize_cache(): Bad command packet physical address.\n");
3329
                return 1;
3330
        }
3331
 
3332
        /* Now try to post the command packet */
3333
        tw_post_command_packet(tw_dev, request_id);
3334
 
3335
        return 0;
3336
} /* End tw_scsiop_synchronize_cache() */
3337
 
3338
/* This function will handle test unit ready scsi command */
3339
int tw_scsiop_test_unit_ready(TW_Device_Extension *tw_dev, int request_id)
3340
{
3341
 
3342
        TW_Param *param;
3343
        TW_Command *command_packet;
3344
        unsigned long command_que_value;
3345
        u32 command_que_addr;
3346
        unsigned long param_value;
3347
 
3348
        dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_test_unit_ready()\n");
3349
 
3350
        /* Initialize command packet */
3351
        command_que_addr = tw_dev->registers.command_que_addr;
3352
        command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
3353
        if (command_packet == NULL) {
3354
                printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad command packet virtual address.\n");
3355
                return 1;
3356
        }
3357
        memset(command_packet, 0, sizeof(TW_Sector));
3358
        command_packet->byte0.opcode = TW_OP_GET_PARAM;
3359
        command_packet->byte0.sgl_offset = 2;
3360
        command_packet->size = 4;
3361
        command_packet->request_id = request_id;
3362
        command_packet->byte3.unit = 0;
3363
        command_packet->byte3.host_id = 0;
3364
        command_packet->status = 0;
3365
        command_packet->flags = 0;
3366
        command_packet->byte6.parameter_count = 1;
3367
 
3368
        /* Now setup the param */
3369
        if (tw_dev->alignment_virtual_address[request_id] == NULL) {
3370
                printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad alignment virtual address.\n");
3371
                return 1;
3372
        }
3373
        param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
3374
        memset(param, 0, sizeof(TW_Sector));
3375
        param->table_id = 3;     /* unit summary table */
3376
        param->parameter_id = 3; /* unitsstatus parameter */
3377
        param->parameter_size_bytes = TW_MAX_UNITS;
3378
        param_value = tw_dev->alignment_physical_address[request_id];
3379
        if (param_value == 0) {
3380
                printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad alignment physical address.\n");
3381
                return 1;
3382
        }
3383
 
3384
        command_packet->byte8.param.sgl[0].address = param_value;
3385
        command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
3386
        command_que_value = tw_dev->command_packet_physical_address[request_id];
3387
        if (command_que_value == 0) {
3388
                printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad command packet physical address.\n");
3389
                return 1;
3390
        }
3391
 
3392
        /* Now try to post the command packet */
3393
        tw_post_command_packet(tw_dev, request_id);
3394
 
3395
        return 0;
3396
} /* End tw_scsiop_test_unit_ready() */
3397
 
3398
/* This function is called by the isr to complete a testunitready command */
3399
int tw_scsiop_test_unit_ready_complete(TW_Device_Extension *tw_dev, int request_id)
3400
{
3401
        unsigned char *is_unit_present;
3402
        TW_Param *param;
3403
 
3404
        dprintk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready_complete()\n");
3405
 
3406
        param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
3407
        if (param == NULL) {
3408
                printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready_complete(): Bad alignment virtual address.\n");
3409
                return 1;
3410
        }
3411
        is_unit_present = &(param->data[0]);
3412
 
3413
        if (is_unit_present[tw_dev->srb[request_id]->target] & TW_UNIT_ONLINE) {
3414
                tw_dev->is_unit_present[tw_dev->srb[request_id]->target] = TRUE;
3415
        } else {
3416
                tw_dev->is_unit_present[tw_dev->srb[request_id]->target] = FALSE;
3417
                tw_dev->srb[request_id]->result = (DID_BAD_TARGET << 16);
3418
                return TW_ISR_DONT_RESULT;
3419
        }
3420
 
3421
        return 0;
3422
} /* End tw_scsiop_test_unit_ready_complete() */
3423
 
3424
/* This function will select queue depths for a target */
3425
void tw_select_queue_depths(struct Scsi_Host *host, Scsi_Device *dev)
3426
{
3427
        Scsi_Device *ptr;
3428
        TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
3429
 
3430
        dprintk(KERN_WARNING "3w-xxxx: tw_select_queue_depths()\n");
3431
 
3432
        for (ptr = dev; ptr != NULL; ptr = ptr->next) {
3433
                if (ptr->host == host) {
3434
                        if ((tw_dev->num_raid_five > 0) && (tw_dev->tw_pci_dev->device == TW_DEVICE_ID)) {
3435
                                ptr->queue_depth = (TW_MAX_BOUNCEBUF-2)/tw_dev->num_units;
3436
                        } else {
3437
#ifdef CONFIG_3W_XXXX_CMD_PER_LUN
3438
                                ptr->queue_depth = CONFIG_3W_XXXX_CMD_PER_LUN;
3439
                                if (ptr->queue_depth > TW_MAX_CMDS_PER_LUN)
3440
                                        ptr->queue_depth = TW_MAX_CMDS_PER_LUN;
3441
#else
3442
                                ptr->queue_depth = TW_MAX_CMDS_PER_LUN;
3443
#endif
3444
                        }
3445
                }
3446
        }
3447
} /* End tw_select_queue_depths() */
3448
 
3449
/* Set a value in the features table */
3450
int tw_setfeature(TW_Device_Extension *tw_dev, int parm, int param_size,
3451
                  unsigned char *val)
3452
{
3453
        TW_Param *param;
3454
        TW_Command  *command_packet;
3455
        TW_Response_Queue response_queue;
3456
        int request_id = 0;
3457
        unsigned long command_que_value;
3458
        u32 command_que_addr;
3459
        u32 response_que_addr;
3460
        unsigned long param_value;
3461
 
3462
        /* Initialize SetParam command packet */
3463
        if (tw_dev->command_packet_virtual_address[request_id] == NULL) {
3464
                printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad command packet virtual address.\n");
3465
                return 1;
3466
        }
3467
        command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
3468
        memset(command_packet, 0, sizeof(TW_Sector));
3469
        param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
3470
 
3471
        command_packet->byte0.opcode = TW_OP_SET_PARAM;
3472
        command_packet->byte0.sgl_offset  = 2;
3473
        param->table_id = 0x404;  /* Features table */
3474
        param->parameter_id = parm;
3475
        param->parameter_size_bytes = param_size;
3476
        memcpy(param->data, val, param_size);
3477
 
3478
        param_value = tw_dev->alignment_physical_address[request_id];
3479
        if (param_value == 0) {
3480
                printk(KERN_WARNING "3w-xxxx: tw_ioctl(): Bad alignment physical address.\n");
3481
                tw_dev->state[request_id] = TW_S_COMPLETED;
3482
                tw_state_request_finish(tw_dev, request_id);
3483
                tw_dev->srb[request_id]->result = (DID_OK << 16);
3484
                tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
3485
        }
3486
        command_packet->byte8.param.sgl[0].address = param_value;
3487
        command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector);
3488
 
3489
        command_packet->size = 4;
3490
        command_packet->request_id = request_id;
3491
        command_packet->byte6.parameter_count = 1;
3492
 
3493
        command_que_value = tw_dev->command_packet_physical_address[request_id];
3494
        if (command_que_value == 0) {
3495
                printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Bad command packet physical address.\n");
3496
        return 1;
3497
        }
3498
        command_que_addr = tw_dev->registers.command_que_addr;
3499
        response_que_addr = tw_dev->registers.response_que_addr;
3500
 
3501
        /* Send command packet to the board */
3502
        outl(command_que_value, command_que_addr);
3503
 
3504
        /* Poll for completion */
3505
        if (tw_poll_status_gone(tw_dev, TW_STATUS_RESPONSE_QUEUE_EMPTY, 30) == 0) {
3506
                response_queue.value = inl(response_que_addr);
3507
                request_id = (unsigned char)response_queue.u.response_id;
3508
                if (request_id != 0) {
3509
                        /* unexpected request id */
3510
                        printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Unexpected request id.\n");
3511
                        return 1;
3512
                }
3513
                if (command_packet->status != 0) {
3514
                        /* bad response */
3515
                        tw_decode_sense(tw_dev, request_id, 0);
3516
                        return 1;
3517
                }
3518
        }
3519
 
3520
        return 0;
3521
} /* End tw_setfeature() */
3522
 
3523
/* This function will setup the interrupt handler */
3524
int tw_setup_irq(TW_Device_Extension *tw_dev)
3525
{
3526
        char *device = TW_DEVICE_NAME;
3527
        int error;
3528
 
3529
        dprintk(KERN_NOTICE "3w-xxxx: tw_setup_irq()\n");
3530
        error = request_irq(tw_dev->tw_pci_dev->irq, tw_interrupt, SA_SHIRQ, device, tw_dev);
3531
 
3532
        if (error < 0) {
3533
                printk(KERN_WARNING "3w-xxxx: scsi%d: Error requesting IRQ: %d.\n", tw_dev->host->host_no, tw_dev->tw_pci_dev->irq);
3534
                return 1;
3535
        }
3536
        return 0;
3537
} /* End tw_setup_irq() */
3538
 
3539
/* This function will tell the controller we're shutting down by sending
3540
   initconnection with a 1 */
3541
int tw_shutdown_device(TW_Device_Extension *tw_dev)
3542
{
3543
        int error;
3544
 
3545
        /* Disable interrupts */
3546
        tw_disable_interrupts(tw_dev);
3547
 
3548
        /* poke the board */
3549
        error = tw_initconnection(tw_dev, 1);
3550
        if (error) {
3551
                printk(KERN_WARNING "3w-xxxx: scsi%d: Connection shutdown failed.\n", tw_dev->host->host_no);
3552
        } else {
3553
                printk(KERN_NOTICE "3w-xxxx: Shutdown complete.\n");
3554
        }
3555
 
3556
        /* Re-enable interrupts */
3557
        tw_enable_and_clear_interrupts(tw_dev);
3558
 
3559
        return 0;
3560
} /* End tw_shutdown_device() */
3561
 
3562
/* This function will soft reset the controller */
3563
void tw_soft_reset(TW_Device_Extension *tw_dev)
3564
{
3565
        u32 control_reg_addr, control_reg_value;
3566
 
3567
        control_reg_addr = tw_dev->registers.control_reg_addr;
3568
        control_reg_value = (   TW_CONTROL_ISSUE_SOFT_RESET |
3569
                                TW_CONTROL_CLEAR_HOST_INTERRUPT |
3570
                                TW_CONTROL_CLEAR_ATTENTION_INTERRUPT |
3571
                                TW_CONTROL_MASK_COMMAND_INTERRUPT |
3572
                                TW_CONTROL_MASK_RESPONSE_INTERRUPT |
3573
                                TW_CONTROL_CLEAR_ERROR_STATUS |
3574
                                TW_CONTROL_DISABLE_INTERRUPTS);
3575
        outl(control_reg_value, control_reg_addr);
3576
} /* End tw_soft_reset() */
3577
 
3578
/* This function will free a request_id */
3579
int tw_state_request_finish(TW_Device_Extension *tw_dev, int request_id)
3580
{
3581
        dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_finish()\n");
3582
 
3583
        tw_dev->free_queue[tw_dev->free_tail] = request_id;
3584
        tw_dev->state[request_id] = TW_S_FINISHED;
3585
        if (tw_dev->free_tail == tw_dev->free_wrap)
3586
                tw_dev->free_tail = TW_Q_START;
3587
        else
3588
                tw_dev->free_tail++;
3589
 
3590
        dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_finish(): Freeing request_id %d\n", request_id);
3591
 
3592
        return 0;
3593
} /* End tw_state_request_finish() */
3594
 
3595
/* This function will assign an available request_id */
3596
int tw_state_request_start(TW_Device_Extension *tw_dev, int *request_id)
3597
{
3598
        int id = 0;
3599
 
3600
        dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_start()\n");
3601
 
3602
        /* Obtain next free request_id */
3603
        id = tw_dev->free_queue[tw_dev->free_head];
3604
        if (tw_dev->free_head == tw_dev->free_wrap)
3605
                tw_dev->free_head = TW_Q_START;
3606
        else
3607
                tw_dev->free_head++;
3608
 
3609
        *request_id = id;
3610
        tw_dev->state[id] = TW_S_STARTED;
3611
 
3612
        dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_start(): id = %d.\n", id);
3613
        return 0;
3614
} /* End tw_state_request_start() */
3615
 
3616
static void tw_unmap_scsi_data(struct pci_dev *pdev, Scsi_Cmnd *cmd)
3617
{
3618
        int dma_dir = scsi_to_pci_dma_dir(cmd->sc_data_direction);
3619
 
3620
        dprintk(KERN_WARNING "3w-xxxx: tw_unamp_scsi_data()\n");
3621
 
3622
        switch(cmd->SCp.phase) {
3623
                case 1:
3624
#ifdef BLK_BOUNCE_HIGH
3625
                        pci_unmap_page(pdev, cmd->SCp.have_data_in, cmd->request_bufflen, dma_dir);
3626
#else
3627
                        pci_unmap_single(pdev, cmd->SCp.have_data_in, cmd->request_bufflen, dma_dir);
3628
#endif
3629
                        break;
3630
                case 2:
3631
                        pci_unmap_sg(pdev, cmd->request_buffer, cmd->use_sg, dma_dir);
3632
                        break;
3633
        }
3634
} /* End tw_unmap_scsi_data() */
3635
 
3636
/* This function will unmask the command interrupt on the controller */
3637
void tw_unmask_command_interrupt(TW_Device_Extension *tw_dev)
3638
{
3639
        u32 control_reg_addr, control_reg_value;
3640
 
3641
        control_reg_addr = tw_dev->registers.control_reg_addr;
3642
        control_reg_value = TW_CONTROL_UNMASK_COMMAND_INTERRUPT;
3643
        outl(control_reg_value, control_reg_addr);
3644
} /* End tw_unmask_command_interrupt() */
3645
 
3646
/* Now get things going */
3647
static Scsi_Host_Template driver_template = TWXXXX;
3648
#include "scsi_module.c"
3649
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.