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