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