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