ia64/xen-unstable

changeset 347:e28ef71fed4d

bitkeeper revision 1.161 (3e8827bfgvKhhIcTx5141jdvnhh7gg)

megaraid support (beta)
new include file version.h makes porting easier
author jws@cairnwell.research
date Mon Mar 31 11:34:23 2003 +0000 (2003-03-31)
parents 6b300fe8e6b9
children 56fce5176629
files .rootkeys xen/drivers/scsi/megaraid.c xen/drivers/scsi/megaraid.h xen/include/xeno/version.h
line diff
     1.1 --- a/.rootkeys	Tue Mar 25 14:10:16 2003 +0000
     1.2 +++ b/.rootkeys	Mon Mar 31 11:34:23 2003 +0000
     1.3 @@ -191,6 +191,8 @@ 3e56411aOLzeD5CRbuXquOrX0lRijw xen/drive
     1.4  3ddb79beXZxwKh7cGyPfr40bhDyRrA xen/drivers/scsi/constants.h
     1.5  3e564120ZeinH9nf3IVSerB80T7dHg xen/drivers/scsi/hosts.c
     1.6  3ddb79beGiGljlTNq_kRnCBZECgC9Q xen/drivers/scsi/hosts.h
     1.7 +3e8827bdE8FgsI-QxZ4zKzYTRmACOQ xen/drivers/scsi/megaraid.c
     1.8 +3e8827bdEMIzjyF9OHnDRmJGp_O68g xen/drivers/scsi/megaraid.h
     1.9  3ddb79bexarQo1tQ541PPUyK9HXNDA xen/drivers/scsi/scsi.c
    1.10  3ddb79beBOiYxQUiWTHosepRlJyuGA xen/drivers/scsi/scsi.h
    1.11  3ddb79beVTYJj6_KMxYLJmCP7p9MuQ xen/drivers/scsi/scsi_dma.c
    1.12 @@ -331,6 +333,7 @@ 3ddb79c2HFkXuRxi1CriJtSFmY6Ybw xen/inclu
    1.13  3ddb79c2_m8lT9jDKse_tePj7zcnNQ xen/include/xeno/timex.h
    1.14  3ddb79c2e2C14HkndNEJlYwXaPrF5A xen/include/xeno/tqueue.h
    1.15  3ddb79c1-kVvF8cVa0k3ZHDdBMj01Q xen/include/xeno/types.h
    1.16 +3e8827bdaqPeZAWGVOwswgY9bWSx4g xen/include/xeno/version.h
    1.17  3ddb79c2Ae5KpzhC9LCYG7mP_Vi4Aw xen/include/xeno/vif.h
    1.18  3ddb79c4YQCQ6r0xNLLu0jfbM7pVmA xen/net/Makefile
    1.19  3ddb79c4AkfDkTCw0comx4L8wsUOMg xen/net/dev.c
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/xen/drivers/scsi/megaraid.c	Mon Mar 31 11:34:23 2003 +0000
     2.3 @@ -0,0 +1,5534 @@
     2.4 +/*===================================================================
     2.5 + *
     2.6 + *                    Linux MegaRAID device driver
     2.7 + *
     2.8 + * Copyright 2001  LSI Logic Corporation.
     2.9 + *
    2.10 + *              This program is free software; you can redistribute it and/or
    2.11 + *              modify it under the terms of the GNU General Public License
    2.12 + *              as published by the Free Software Foundation; either version
    2.13 + *              2 of the License, or (at your option) any later version.
    2.14 + *
    2.15 + * Version : v1.18d (Aug 7, 2002)
    2.16 + *
    2.17 + * Description: Linux device driver for LSI Logic MegaRAID controller
    2.18 + *
    2.19 + * Supported controllers: MegaRAID 418, 428, 438, 466, 762, 467, 471, 490
    2.20 + *                                      493.
    2.21 + * History:
    2.22 + *
    2.23 + * Version 0.90:
    2.24 + *     Original source contributed by Dell; integrated it into the kernel and
    2.25 + *     cleaned up some things.  Added support for 438/466 controllers.
    2.26 + * Version 0.91:
    2.27 + *     Aligned mailbox area on 16-byte boundary.
    2.28 + *     Added schedule() at the end to properly clean up.
    2.29 + *     Made improvements for conformity to linux driver standards.
    2.30 + *
    2.31 + * Version 0.92:
    2.32 + *     Added support for 2.1 kernels.
    2.33 + *         Reads from pci_dev struct, so it's not dependent on pcibios.
    2.34 + *         Added some missing virt_to_bus() translations.
    2.35 + *     Added support for SMP.
    2.36 + *         Changed global cli()'s to spinlocks for 2.1, and simulated
    2.37 + *          spinlocks for 2.0.
    2.38 + *     Removed setting of SA_INTERRUPT flag when requesting Irq.
    2.39 + *
    2.40 + * Version 0.92ac:
    2.41 + *     Small changes to the comments/formatting. Plus a couple of
    2.42 + *      added notes. Returned to the authors. No actual code changes
    2.43 + *      save printk levels.
    2.44 + *     8 Oct 98        Alan Cox <alan.cox@linux.org>
    2.45 + *
    2.46 + *     Merged with 2.1.131 source tree.
    2.47 + *     12 Dec 98       K. Baranowski <kgb@knm.org.pl>
    2.48 + *
    2.49 + * Version 0.93:
    2.50 + *     Added support for vendor specific ioctl commands (M_RD_IOCTL_CMD+xxh)
    2.51 + *     Changed some fields in MEGARAID struct to better values.
    2.52 + *     Added signature check for Rp controllers under 2.0 kernels
    2.53 + *     Changed busy-wait loop to be time-based
    2.54 + *     Fixed SMP race condition in isr
    2.55 + *     Added kfree (sgList) on release
    2.56 + *     Added #include linux/version.h to megaraid.h for hosts.h
    2.57 + *     Changed max_id to represent max logical drives instead of targets.
    2.58 + *
    2.59 + * Version 0.94:
    2.60 + *     Got rid of some excess locking/unlocking
    2.61 + *     Fixed slight memory corruption problem while memcpy'ing into mailbox
    2.62 + *     Changed logical drives to be reported as luns rather than targets
    2.63 + *     Changed max_id to 16 since it is now max targets/chan again.
    2.64 + *     Improved ioctl interface for upcoming megamgr
    2.65 + *
    2.66 + * Version 0.95:
    2.67 + *     Fixed problem of queueing multiple commands to adapter;
    2.68 + *       still has some strange problems on some setups, so still
    2.69 + *       defaults to single.  To enable parallel commands change
    2.70 + *       #define MULTI_IO in megaraid.h
    2.71 + *     Changed kmalloc allocation to be done in beginning.
    2.72 + *     Got rid of C++ style comments
    2.73 + *
    2.74 + * Version 0.96:
    2.75 + *     762 fully supported.
    2.76 + *
    2.77 + * Version 0.97:
    2.78 + *     Changed megaraid_command to use wait_queue.
    2.79 + *
    2.80 + * Version 1.00:
    2.81 + *     Checks to see if an irq occurred while in isr, and runs through
    2.82 + *       routine again.
    2.83 + *     Copies mailbox to temp area before processing in isr
    2.84 + *     Added barrier() in busy wait to fix volatility bug
    2.85 + *     Uses separate list for freed Scbs, keeps track of cmd state
    2.86 + *     Put spinlocks around entire queue function for now...
    2.87 + *     Full multi-io commands working stablely without previous problems
    2.88 + *     Added skipXX LILO option for Madrona motherboard support
    2.89 + *
    2.90 + * Version 1.01:
    2.91 + *     Fixed bug in mega_cmd_done() for megamgr control commands,
    2.92 + *       the host_byte in the result code from the scsi request to
    2.93 + *       scsi midlayer is set to DID_BAD_TARGET when adapter's
    2.94 + *       returned codes are 0xF0 and 0xF4.
    2.95 + *
    2.96 + * Version 1.02:
    2.97 + *     Fixed the tape drive bug by extending the adapter timeout value
    2.98 + *       for passthrough command to 60 seconds in mega_build_cmd().
    2.99 + *
   2.100 + * Version 1.03:
   2.101 + *    Fixed Madrona support.
   2.102 + *    Changed the adapter timeout value from 60 sec in 1.02 to 10 min
   2.103 + *      for bigger and slower tape drive.
   2.104 + *    Added driver version printout at driver loadup time
   2.105 + *
   2.106 + * Version 1.04
   2.107 + *    Added code for 40 ld FW support.
   2.108 + *    Added new ioctl command 0x81 to support NEW_READ/WRITE_CONFIG with
   2.109 + *      data area greater than 4 KB, which is the upper bound for data
   2.110 + *      tranfer through scsi_ioctl interface.
   2.111 + *    The additional 32 bit field for 64bit address in the newly defined
   2.112 + *      mailbox64 structure is set to 0 at this point.
   2.113 + *
   2.114 + * Version 1.05
   2.115 + *    Changed the queing implementation for handling SCBs and completed
   2.116 + *      commands.
   2.117 + *    Added spinlocks in the interrupt service routine to enable the driver
   2.118 + *      function in the SMP environment.
   2.119 + *    Fixed the problem of unnecessary aborts in the abort entry point, which
   2.120 + *      also enables the driver to handle large amount of I/O requests for
   2.121 + *      long duration of time.
   2.122 + * Version 1.06
   2.123 + *              Intel Release
   2.124 + * Version 1.07
   2.125 + *    Removed the usage of uaccess.h file for kernel versions less than
   2.126 + *    2.0.36, as this file is not present in those versions.
   2.127 + *
   2.128 + * Version 108
   2.129 + *    Modified mega_ioctl so that 40LD megamanager would run
   2.130 + *    Made some changes for 2.3.XX compilation , esp wait structures
   2.131 + *    Code merge between 1.05 and 1.06 .
   2.132 + *    Bug fixed problem with ioctl interface for concurrency between
   2.133 + *    8ld and 40ld firwmare
   2.134 + *    Removed the flawed semaphore logic for handling new config command
   2.135 + *    Added support for building own scatter / gather list for big user
   2.136 + *    mode buffers
   2.137 + *    Added /proc file system support ,so that information is available in
   2.138 + *    human readable format
   2.139 + *
   2.140 + * Version 1a08
   2.141 + *    Changes for IA64 kernels. Checked for CONFIG_PROC_FS flag
   2.142 + *
   2.143 + * Version 1b08
   2.144 + *    Include file changes.
   2.145 + * Version 1b08b
   2.146 + *    Change PCI ID value for the 471 card, use #defines when searching
   2.147 + *    for megaraid cards.
   2.148 + *
   2.149 + * Version 1.10
   2.150 + *
   2.151 + *      I) Changes made to make following ioctl commands work in 0x81 interface
   2.152 + *              a)DCMD_DELETE_LOGDRV
   2.153 + *              b)DCMD_GET_DISK_CONFIG
   2.154 + *              c)DCMD_DELETE_DRIVEGROUP
   2.155 + *              d)NC_SUBOP_ENQUIRY3
   2.156 + *              e)DCMD_CHANGE_LDNO
   2.157 + *              f)DCMD_CHANGE_LOOPID
   2.158 + *              g)DCMD_FC_READ_NVRAM_CONFIG
   2.159 + *      h)DCMD_WRITE_CONFIG
   2.160 + *      II) Added mega_build_kernel_sg function
   2.161 + *  III)Firmware flashing option added
   2.162 + *
   2.163 + * Version 1.10a
   2.164 + *
   2.165 + *      I)Dell updates included in the source code.
   2.166 + *              Note:   This change is not tested due to the unavailability of IA64 kernel
   2.167 + *      and it is in the #ifdef DELL_MODIFICATION macro which is not defined
   2.168 + *
   2.169 + * Version 1.10b
   2.170 + *
   2.171 + *      I)In M_RD_IOCTL_CMD_NEW command the wrong way of copying the data
   2.172 + *    to the user address corrected
   2.173 + *
   2.174 + * Version 1.10c
   2.175 + *
   2.176 + *      I) DCMD_GET_DISK_CONFIG opcode updated for the firmware changes.
   2.177 + *
   2.178 + * Version 1.11
   2.179 + *      I)  Version number changed from 1.10c to 1.11
   2.180 + *  II) DCMD_WRITE_CONFIG(0x0D) command in the driver changed from
   2.181 + *      scatter/gather list mode to direct pointer mode..
   2.182 + *     Fixed bug of undesirably detecting HP onboard controllers which
   2.183 + *       are disabled.
   2.184 + *
   2.185 + *      Version 1.12 (Sep 21, 2000)
   2.186 + *
   2.187 + *     I. Changes have been made for Dynamic DMA mapping in IA64 platform.
   2.188 + *                To enable all these changes define M_RD_DYNAMIC_DMA_SUPPORT in megaraid.h
   2.189 + *        II. Got rid of windows mode comments
   2.190 + *       III. Removed unwanted code segments
   2.191 + *    IV. Fixed bug of HP onboard controller information (commented with
   2.192 + *                 MEGA_HP_FIX)
   2.193 + *
   2.194 + *      Version 1a12
   2.195 + *      I.      reboot notifier and new ioctl changes ported from 1c09
   2.196 + *
   2.197 + *      Version 1b12
   2.198 + *      I.      Changes in new ioctl interface routines ( Nov 06, 2000 )
   2.199 + *
   2.200 + *      Version 1c12
   2.201 + *      I.      Changes in new ioctl interface routines ( Nov 07, 2000 )
   2.202 + *
   2.203 + *      Version 1d12
   2.204 + *      I.      Compilation error under kernel 2.4.0 for 32-bit machine in mega_ioctl
   2.205 + *
   2.206 + *      Version 1e12, 1f12
   2.207 + *      1.  Fixes for pci_map_single, pci_alloc_consistent along with mailbox
   2.208 + *          alignment
   2.209 + *
   2.210 + *	Version 1.13beta
   2.211 + *	Added Support for Full 64bit address space support. If firmware
   2.212 + *	supports 64bit, it goes to 64 bit mode even on x86 32bit 
   2.213 + *	systems. Data Corruption Issues while running on test9 kernel
   2.214 + *	on IA64 systems. This issue not seen on test11 on x86 system
   2.215 + *
   2.216 + *	Version 1.13c
   2.217 + *	1. Resolved Memory Leak when using M_RD_IOCTL_CMD interface
   2.218 + *	2. Resolved Queuing problem when MailBox Blocks
   2.219 + *	3. Added unregister_reboot_notifier support
   2.220 + * 
   2.221 + *	Version 1.13d
   2.222 + *	Experimental changes in interfacing with the controller in ISR
   2.223 + *
   2.224 + *	Version 1.13e
   2.225 + *	Fixed Broken 2.2.XX compilation changes + misc changes
   2.226 + *
   2.227 + *	Version 1.13f to 1.13i
   2.228 + *	misc changes + code clean up
   2.229 + *	Cleaned up the ioctl code and added set_mbox_xfer_addr()
   2.230 + *	Support for START_DEV (6)
   2.231 + * 	
   2.232 + *	Version 1.13j
   2.233 + *	Moved some code to megaraid.h file, replaced some hard coded values 
   2.234 + *      with respective macros. Changed some functions to static
   2.235 + *
   2.236 + *	Version 1.13k
   2.237 + *	Only some idendation correction to 1.13j 
   2.238 + *
   2.239 + *	Version 1.13l , 1.13m, 1.13n, 1.13o
   2.240 + *	Minor Identation changes + misc changes
   2.241 + *
   2.242 + *	Version 1.13q
   2.243 + *	Paded the new uioctl_t MIMD structure for maintaining alignment 
   2.244 + *	and size across 32 / 64 bit platforms
   2.245 + *	Changed the way MIMD IOCTL interface used virt_to_bus() to use pci
   2.246 + *	memory location
   2.247 + *
   2.248 + *	Version 1.13r
   2.249 + *	2.4.xx SCSI Changes.
   2.250 + *
   2.251 + *	Version 1.13s
   2.252 + *	Stats counter fixes
   2.253 + *	Temporary fix for some 64 bit firmwares in 2.4.XX kernels
   2.254 + *
   2.255 + *	Version	1.13t
   2.256 + *	Support for 64bit version of READ/WRITE/VIEW DISK CONFIG
   2.257 + *
   2.258 + *	Version 1.14
   2.259 + *	Did away with MEGADEV_IOCTL flag. It is now standard part of driver
   2.260 + *	without need for a special #define flag
   2.261 + *	Disabled old scsi ioctl path for kernel versions > 2.3.xx. This is due
   2.262 + *	to the nature in which the new scsi code queues a new scsi command to 
   2.263 + *	controller during SCSI IO Completion
   2.264 + *	Driver now checks for sub-system vendor id before taking ownership of
   2.265 + *	the controller
   2.266 + *
   2.267 + *	Version 1.14a
   2.268 + *	Added Host re-ordering
   2.269 + *
   2.270 + *	Version 1.14b
   2.271 + *	Corrected some issue which caused the older cards not to work
   2.272 + *	
   2.273 + *	Version 1.14c
   2.274 + *	IOCTL changes for not handling the non-64bit firmwares under 2.4.XX
   2.275 + *	kernel
   2.276 + *
   2.277 + *	Version 1.14d
   2.278 + *	Fixed Various MIMD Synchronization Issues
   2.279 + *	
   2.280 + *	Version 1.14e
   2.281 + *	Fixed the error handling during card initialization
   2.282 + *
   2.283 + *	Version 1.14f
   2.284 + *	Multiple invocations of mimd phase I ioctl stalls the cpu. Replaced
   2.285 + *	spinlock with semaphore(mutex)
   2.286 + *
   2.287 + *	Version 1.14g
   2.288 + *	Fixed running out of scbs issues while running MIMD apps under heavy IO
   2.289 + *
   2.290 + *	Version 1.14g-ac - 02/03/01
   2.291 + *	Reformatted to Linux format so I could compare to old one and cross
   2.292 + *	check bug fixes
   2.293 + *	Re fixed the assorted missing 'static' cases
   2.294 + *	Removed some unneeded version checks
   2.295 + *	Cleaned up some of the VERSION checks in the code
   2.296 + *	Left 2.0 support but removed 2.1.x support.
   2.297 + *	Collected much of the compat glue into one spot
   2.298 + *
   2.299 + *	Version 1.14g-ac2 - 22/03/01
   2.300 + *	Fixed a non obvious dereference after free in the driver unload path
   2.301 + *
   2.302 + *	Version 1.14i
   2.303 + *	changes for making 32bit application run on IA64
   2.304 + *
   2.305 + *	Version 1.14j
   2.306 + *	Tue Mar 13 14:27:54 EST 2001 - AM
   2.307 + *	Changes made in the driver to be able to run applications if the
   2.308 + *	system has memory >4GB.
   2.309 + *
   2.310 + *
   2.311 + *	Version 1.14k
   2.312 + *	Thu Mar 15 18:38:11 EST 2001 - AM
   2.313 + *
   2.314 + *	Firmware version check removed if subsysid==0x1111 and
   2.315 + *	subsysvid==0x1111, since its not yet initialized.
   2.316 + *
   2.317 + *	changes made to correctly calculate the base in mega_findCard.
   2.318 + *
   2.319 + *	Driver informational messages now appear on the console as well as
   2.320 + *	with dmesg
   2.321 + *
   2.322 + *	Older ioctl interface is returned failure on newer(2.4.xx) kernels.
   2.323 + *
   2.324 + *	Inclusion of "modversions.h" is still a debatable question. It is
   2.325 + *	included anyway with this release.
   2.326 + *
   2.327 + *	Version 1.14l
   2.328 + *	Mon Mar 19 17:39:46 EST 2001 - AM
   2.329 + *
   2.330 + *	Assorted changes to remove compilation error in 1.14k when compiled
   2.331 + *	with kernel < 2.4.0
   2.332 + *
   2.333 + *	Version 1.14m
   2.334 + *	Tue Mar 27 12:09:22 EST 2001 - AM
   2.335 + *
   2.336 + *	Added support for extended CDBs ( > 10 bytes ) and OBDR ( One Button
   2.337 + *	Disaster Recovery ) feature.
   2.338 + *
   2.339 + *
   2.340 + *	Version 1.14n
   2.341 + *	Tue Apr 10 14:28:13 EDT 2001 - AM
   2.342 + *
   2.343 + *	"modeversions.h" is no longer included in the code.
   2.344 + *	2.4.xx style mutex initialization used for older kernels also
   2.345 + *
   2.346 + *	Version 1.14o
   2.347 + *	Wed Apr 18 17:47:26 EDT 2001 - PJ
   2.348 + *
   2.349 + *	Before returning status for 'inquiry', we first check if request buffer
   2.350 + *	is SG list, and then return appropriate status
   2.351 + *
   2.352 + *	Version 1.14p
   2.353 + *	Wed Apr 25 13:44:48 EDT 2001 - PJ
   2.354 + *
   2.355 + *	SCSI result made appropriate in case of check conditions for extended
   2.356 + *	passthru commands
   2.357 + *
   2.358 + *	Do not support lun >7 for physically accessed devices 
   2.359 + *
   2.360 + *	
   2.361 + *	Version 1.15
   2.362 + *	Thu Apr 19 09:38:38 EDT 2001 - AM
   2.363 + *
   2.364 + *	1.14l rollover to 1.15 - merged with main trunk after 1.15d
   2.365 + *
   2.366 + *	Version 1.15b
   2.367 + *  Wed May 16 20:10:01 EDT 2001 - AM
   2.368 + *
   2.369 + *	"modeversions.h" is no longer included in the code.
   2.370 + *	2.4.xx style mutex initialization used for older kernels also
   2.371 + *	Brought in-sync with Alan's changes in 2.4.4
   2.372 + *	Note: 1.15a is on OBDR branch(main trunk), and is not merged with yet.
   2.373 + *
   2.374 + * Version 1.15c
   2.375 + * Mon May 21 23:10:42 EDT 2001 - AM
   2.376 + *
   2.377 + * ioctl interface uses 2.4.x conforming pci dma calls
   2.378 + * similar calls used for older kernels
   2.379 + *
   2.380 + * Version 1.15d
   2.381 + * Wed May 30 17:30:41 EDT 2001 - AM
   2.382 + *
   2.383 + * NULL is not a valid first argument for pci_alloc_consistent() on
   2.384 + * IA64(2.4.3-2.10.1). Code shuffling done in ioctl interface to get
   2.385 + * "pci_dev" before making calls to pci interface routines.
   2.386 + *
   2.387 + * Version 1.16pre
   2.388 + * Fri Jun  1 19:40:48 EDT 2001 - AM
   2.389 + *
   2.390 + * 1.14p and 1.15d merged
   2.391 + * ROMB support added
   2.392 + *
   2.393 + * Version 1.16-pre1
   2.394 + * Mon Jun  4 15:01:01 EDT 2001 - AM
   2.395 + *
   2.396 + * Non-ROMB firmware do no DMA support 0xA9 command. Value 0xFF
   2.397 + * (all channels are raid ) is chosen for those firmware.
   2.398 + *
   2.399 + * Version 1.16-pre2
   2.400 + * Mon Jun 11 18:15:31 EDT 2001 - AM
   2.401 + *
   2.402 + * Changes for boot from any logical drive
   2.403 + *
   2.404 + * Version 1.16
   2.405 + * Tue Jun 26 18:07:02 EDT 2001 - AM
   2.406 + *
   2.407 + * branched at 1.14p
   2.408 + *
   2.409 + * Check added for HP 1M/2M controllers if having firmware H.01.07 or
   2.410 + * H.01.08. If found, disable 64 bit support since these firmware have
   2.411 + * limitations for 64 bit addressing
   2.412 + *
   2.413 + *
   2.414 + * Version 1.17
   2.415 + * Thu Jul 12 11:14:09 EDT 2001 - AM
   2.416 + *
   2.417 + * 1.16pre2 and 1.16 merged.
   2.418 + *
   2.419 + * init_MUTEX and init_MUTEX_LOCKED are defined in 2.2.19. Pre-processor
   2.420 + * statements are added for them
   2.421 + *
   2.422 + * Linus's 2.4.7pre3 kernel introduces a new field 'max_sectors' in Scsi_Host
   2.423 + * structure, to improve IO performance.
   2.424 + *
   2.425 + *
   2.426 + * Version 1.17a
   2.427 + * Fri Jul 13 18:44:01 EDT 2001 - AM
   2.428 + *
   2.429 + * Starting from kernel 2.4.x, LUN is not < 8 - following SCSI-III. So to have
   2.430 + * our current formula working to calculate logical drive number, return
   2.431 + * failure for LUN > 7
   2.432 + *
   2.433 + *
   2.434 + * Version 1.17b
   2.435 + * Mon Jul 30 19:24:02 EDT 2001 - AM
   2.436 + *
   2.437 + * Added support for random deletion of logical drives
   2.438 + *
   2.439 + * Version 1.17c
   2.440 + * Tue Sep 25 09:37:49 EDT 2001 - Atul Mukker <atulm@lsil.com>
   2.441 + *
   2.442 + * With single and dual channel controllers, some virtaul channels are
   2.443 + * displayed negative.
   2.444 + *
   2.445 + * Version 1.17a-ac
   2.446 + * Mon Aug 6 14:59:29 BST 2001 - "Michael Johnson" <johnsom@home.com>
   2.447 + *
   2.448 + * Make the HP print formatting and check for buggy firmware runtime not
   2.449 + * ifdef dependant.
   2.450 + *
   2.451 + *
   2.452 + * Version 1.17d
   2.453 + * Thu Oct 11 10:48:45 EDT 2001 - Atul Mukker <atulm@lsil.com>
   2.454 + *
   2.455 + * Driver 1.17c oops when loaded without controller.
   2.456 + *
   2.457 + * Special case for "use_sg == 1" removed while building the scatter gather
   2.458 + * list.
   2.459 + *
   2.460 + * Version 1.18
   2.461 + * Thu Oct 11 15:02:53 EDT 2001 - Atul Mukker <atulm@lsil.com>
   2.462 + *
   2.463 + * References to AMI have been changed to LSI Logic.
   2.464 + *
   2.465 + * Version 1.18a
   2.466 + * Mon Mar 11 11:38:38 EST 2002 - Atul Mukker <Atul.Mukker@lsil.com>
   2.467 + *
   2.468 + * RAID On MotherBoard (ROMB) - boot from logical or physical drives
   2.469 + *
   2.470 + * Support added for discovery(ROMB) vendor and device ids.
   2.471 + *
   2.472 + * Data transfer length for passthru commands must be valid even if the
   2.473 + * command has an associated scatter-gather list.
   2.474 + *
   2.475 + *
   2.476 + * Version 1.18b
   2.477 + * Tue Apr 23 11:01:58 EDT 2002 - Atul Mukker <Atul.Mukker@lsil.com>
   2.478 + *
   2.479 + * typo corrected for scsi condition CHECK_CONDITION in mega_cmd_done()
   2.480 + *
   2.481 + * Support added for PCI_VENDOR_ID_LSI_LOGIC with device id
   2.482 + * PCI_DEVICE_ID_AMI_MEGARAID3.
   2.483 + *
   2.484 + *
   2.485 + * Version 1.18c
   2.486 + * Thu May 16 10:27:55 EDT 2002 - Atul Mukker <Atul.Mukker@lsil.com>
   2.487 + *
   2.488 + * Retrun valid return status for mega passthru commands resulting in
   2.489 + * contingent allegiance condition. Check for 64-bit passthru commands also.
   2.490 + *
   2.491 + * Do not check_region() anymore and check for return value of
   2.492 + * request_region()
   2.493 + *
   2.494 + * Send valid sense data to appliations using the private ioctl interface.
   2.495 + *
   2.496 + *
   2.497 + * Version 1.18d
   2.498 + * Wed Aug  7 18:51:51 EDT 2002 - Atul Mukker <atul.mukker@lsil.com>
   2.499 + *
   2.500 + * Added support for yellowstone and verde controller
   2.501 + *
   2.502 + *
   2.503 + * BUGS:
   2.504 + *     Some older 2.1 kernels (eg. 2.1.90) have a bug in pci.c that
   2.505 + *     fails to detect the controller as a pci device on the system.
   2.506 + *
   2.507 + *     Timeout period for upper scsi layer, i.e. SD_TIMEOUT in
   2.508 + *     /drivers/scsi/sd.c, is too short for this controller. SD_TIMEOUT
   2.509 + *     value must be increased to (30 * HZ) otherwise false timeouts
   2.510 + *     will occur in the upper layer.
   2.511 + *
   2.512 + *     Never set skip_id. The existing PCI code the megaraid uses fails
   2.513 + *     to properly check the vendor subid in some cases. Setting this then
   2.514 + *     makes it steal other i960's and crashes some boxes
   2.515 + *
   2.516 + *     Far too many ifdefs for versions.
   2.517 + *
   2.518 + *===================================================================*/
   2.519 +
   2.520 +
   2.521 +#include <xeno/config.h>
   2.522 +#include <xeno/version.h>
   2.523 +#include <xeno/module.h>
   2.524 +#include <xeno/types.h>
   2.525 +#include <xeno/errno.h>
   2.526 +#include <xeno/string.h>
   2.527 +#include <xeno/lib.h>
   2.528 +#include <xeno/kernel.h>
   2.529 +#include <xeno/ioport.h>
   2.530 +//#include <xeno/fcntl.h>
   2.531 +#include <xeno/delay.h>
   2.532 +#include <xeno/pci.h>
   2.533 +//#include <xeno/proc_fs.h>
   2.534 +#include <xeno/blk.h>
   2.535 +//#include <xeno/wait.h>
   2.536 +#include <xeno/tqueue.h>
   2.537 +#include <xeno/interrupt.h>
   2.538 +#include <xeno/mm.h>
   2.539 +//#include <asm/pgtable.h>
   2.540 +
   2.541 +#include <asm/ioctl.h>
   2.542 +#include <xeno/sched.h>
   2.543 +//#include <xeno/stat.h>
   2.544 +#include <xeno/slab.h>	/* for kmalloc() */
   2.545 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)	/* 0x20100 */
   2.546 +#include <xeno/bios32.h>
   2.547 +#else
   2.548 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)	/* 0x20300 */
   2.549 +#include <asm/spinlock.h>
   2.550 +#else
   2.551 +#include <xeno/spinlock.h>
   2.552 +#endif
   2.553 +#endif
   2.554 +
   2.555 +#include <asm/io.h>
   2.556 +#include <asm/irq.h>
   2.557 +
   2.558 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,0,24)	/* 0x020024 */
   2.559 +#include <asm/uaccess.h>
   2.560 +#endif
   2.561 +
   2.562 +/*
   2.563 + * These header files are required for Shutdown Notification routines
   2.564 + */
   2.565 +#include <xeno/notifier.h>
   2.566 +#include <xeno/reboot.h>
   2.567 +#include <xeno/init.h>
   2.568 +
   2.569 +#include "sd.h"
   2.570 +#include "scsi.h"
   2.571 +#include "hosts.h"
   2.572 +
   2.573 +#include "megaraid.h"
   2.574 +
   2.575 +/*
   2.576 + *================================================================
   2.577 + *  #Defines
   2.578 + *================================================================
   2.579 + */
   2.580 +
   2.581 +#define MAX_SERBUF 160
   2.582 +#define COM_BASE 0x2f8
   2.583 +
   2.584 +static ulong RDINDOOR (mega_host_config * megaCfg)
   2.585 +{
   2.586 +	return readl (megaCfg->base + 0x20);
   2.587 +}
   2.588 +
   2.589 +static void WRINDOOR (mega_host_config * megaCfg, ulong value)
   2.590 +{
   2.591 +	writel (value, megaCfg->base + 0x20);
   2.592 +}
   2.593 +
   2.594 +static ulong RDOUTDOOR (mega_host_config * megaCfg)
   2.595 +{
   2.596 +	return readl (megaCfg->base + 0x2C);
   2.597 +}
   2.598 +
   2.599 +static void WROUTDOOR (mega_host_config * megaCfg, ulong value)
   2.600 +{
   2.601 +	writel (value, megaCfg->base + 0x2C);
   2.602 +}
   2.603 +
   2.604 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)	/* 0x020200 */
   2.605 +#include <xeno/smp.h>
   2.606 +#define cpuid smp_processor_id()
   2.607 +#endif
   2.608 +
   2.609 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,4)
   2.610 +#define scsi_set_pci_device(x,y)
   2.611 +#endif
   2.612 +
   2.613 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)	/* 0x020400 */
   2.614 +
   2.615 +/*
   2.616 + *	Linux 2.4 and higher
   2.617 + *
   2.618 + *	No driver private lock
   2.619 + *	Use the io_request_lock not cli/sti
   2.620 + *	queue task is a simple api without irq forms
   2.621 + */
   2.622 +
   2.623 +MODULE_AUTHOR ("LSI Logic Corporation");
   2.624 +MODULE_DESCRIPTION ("LSI Logic MegaRAID driver");
   2.625 +MODULE_LICENSE ("GPL");
   2.626 +
   2.627 +#define DRIVER_LOCK_T
   2.628 +#define DRIVER_LOCK_INIT(p)
   2.629 +#define DRIVER_LOCK(p)
   2.630 +#define DRIVER_UNLOCK(p)
   2.631 +#define IO_LOCK_T unsigned long io_flags = 0
   2.632 +#define IO_LOCK spin_lock_irqsave(&io_request_lock,io_flags);
   2.633 +#define IO_UNLOCK spin_unlock_irqrestore(&io_request_lock,io_flags);
   2.634 +
   2.635 +#define queue_task_irq(a,b)     queue_task(a,b)
   2.636 +#define queue_task_irq_off(a,b) queue_task(a,b)
   2.637 +
   2.638 +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)	/* 0x020200 */
   2.639 +
   2.640 +/*
   2.641 + *	Linux 2.2 and higher
   2.642 + *
   2.643 + *	No driver private lock
   2.644 + *	Use the io_request_lock not cli/sti
   2.645 + *	No pci region api
   2.646 + *	queue_task is now a single simple API
   2.647 + */
   2.648 +
   2.649 +static char kernel_version[] = UTS_RELEASE;
   2.650 +MODULE_AUTHOR ("LSI Logic Corporation");
   2.651 +MODULE_DESCRIPTION ("LSI Logic MegaRAID driver");
   2.652 +
   2.653 +#define DRIVER_LOCK_T
   2.654 +#define DRIVER_LOCK_INIT(p)
   2.655 +#define DRIVER_LOCK(p)
   2.656 +#define DRIVER_UNLOCK(p)
   2.657 +#define IO_LOCK_T unsigned long io_flags = 0
   2.658 +#define IO_LOCK spin_lock_irqsave(&io_request_lock,io_flags);
   2.659 +#define IO_UNLOCK spin_unlock_irqrestore(&io_request_lock,io_flags);
   2.660 +
   2.661 +#define pci_free_consistent(a,b,c,d)
   2.662 +#define pci_unmap_single(a,b,c,d)
   2.663 +#define pci_enable_device(x) (0)
   2.664 +#define queue_task_irq(a,b)     queue_task(a,b)
   2.665 +#define queue_task_irq_off(a,b) queue_task(a,b)
   2.666 +
   2.667 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,19)	/* 0x020219 */
   2.668 +#define init_MUTEX_LOCKED(x)    (*(x)=MUTEX_LOCKED)
   2.669 +#define init_MUTEX(x)           (*(x)=MUTEX)
   2.670 +#define DECLARE_WAIT_QUEUE_HEAD(x)	struct wait_queue *x = NULL
   2.671 +#endif
   2.672 +
   2.673 +
   2.674 +#else
   2.675 +
   2.676 +/*
   2.677 + *	Linux 2.0 macros. Here we have to provide some of our own
   2.678 + *	functionality. We also only work little endian 32bit.
   2.679 + *	Again no pci_alloc/free api
   2.680 + *	IO_LOCK/IO_LOCK_T were never used in 2.0 so now are empty 
   2.681 + */
   2.682 + 
   2.683 +#define cpuid 0
   2.684 +#define DRIVER_LOCK_T long cpu_flags;
   2.685 +#define DRIVER_LOCK_INIT(p)
   2.686 +#define DRIVER_LOCK(p) \
   2.687 +       		save_flags(cpu_flags); \
   2.688 +       		cli();
   2.689 +#define DRIVER_UNLOCK(p) \
   2.690 +       		restore_flags(cpu_flags);
   2.691 +#define IO_LOCK_T
   2.692 +#define IO_LOCK(p)
   2.693 +#define IO_UNLOCK(p)
   2.694 +#define le32_to_cpu(x) (x)
   2.695 +#define cpu_to_le32(x) (x)
   2.696 +
   2.697 +#define pci_free_consistent(a,b,c,d)
   2.698 +#define pci_unmap_single(a,b,c,d)
   2.699 +
   2.700 +#define init_MUTEX_LOCKED(x)    (*(x)=MUTEX_LOCKED)
   2.701 +#define init_MUTEX(x)           (*(x)=MUTEX)
   2.702 +
   2.703 +#define pci_enable_device(x) (0)
   2.704 +
   2.705 +/*
   2.706 + *	2.0 lacks spinlocks, iounmap/ioremap
   2.707 + */
   2.708 +
   2.709 +#define ioremap vremap
   2.710 +#define iounmap vfree
   2.711 +
   2.712 + /* simulate spin locks */
   2.713 +typedef struct {
   2.714 +	volatile char lock;
   2.715 +} spinlock_t;
   2.716 +
   2.717 +#define spin_lock_init(x) { (x)->lock = 0;}
   2.718 +#define spin_lock_irqsave(x,flags) { while ((x)->lock) barrier();\
   2.719 +                                        (x)->lock=1; save_flags(flags);\
   2.720 +                                        cli();}
   2.721 +#define spin_unlock_irqrestore(x,flags) { (x)->lock=0; restore_flags(flags);}
   2.722 +
   2.723 +#define DECLARE_WAIT_QUEUE_HEAD(x)	struct wait_queue *x = NULL
   2.724 +
   2.725 +#endif
   2.726 +
   2.727 +
   2.728 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)	/* 0x020400 */
   2.729 +#define dma_alloc_consistent pci_alloc_consistent
   2.730 +#define dma_free_consistent pci_free_consistent
   2.731 +#else
   2.732 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,19)	/* 0x020219 */
   2.733 +typedef unsigned long dma_addr_t;
   2.734 +#endif
   2.735 +void *dma_alloc_consistent(void *, size_t, dma_addr_t *);
   2.736 +void dma_free_consistent(void *, size_t, void *, dma_addr_t);
   2.737 +int mega_get_order(int);
   2.738 +int pow_2(int);
   2.739 +#endif
   2.740 +
   2.741 +/* set SERDEBUG to 1 to enable serial debugging */
   2.742 +#define SERDEBUG 0
   2.743 +#if SERDEBUG
   2.744 +static void ser_init (void);
   2.745 +static void ser_puts (char *str);
   2.746 +static void ser_putc (char c);
   2.747 +static int ser_printk (const char *fmt, ...);
   2.748 +#endif
   2.749 +
   2.750 +#ifdef CONFIG_PROC_FS
   2.751 +#define COPY_BACK if (offset > megaCfg->procidx) { \
   2.752 +		*eof = TRUE; \
   2.753 +        megaCfg->procidx = 0; \
   2.754 +        megaCfg->procbuf[0] = 0; \
   2.755 +        return 0;} \
   2.756 + if ((count + offset) > megaCfg->procidx) { \
   2.757 +      count = megaCfg->procidx - offset; \
   2.758 +      *eof = TRUE; } \
   2.759 +      memcpy(page, &megaCfg->procbuf[offset], count); \
   2.760 +      megaCfg->procidx = 0; \
   2.761 +      megaCfg->procbuf[0] = 0;
   2.762 +#endif
   2.763 +
   2.764 +/*
   2.765 + * ================================================================
   2.766 + *                    Global variables
   2.767 + *================================================================
   2.768 + */
   2.769 +
   2.770 +/*  Use "megaraid=skipXX" as LILO option to prohibit driver from scanning
   2.771 +    XX scsi id on each channel.  Used for Madrona motherboard, where SAF_TE
   2.772 +    processor id cannot be scanned */
   2.773 +
   2.774 +static char *megaraid;
   2.775 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)	/* 0x20100 */
   2.776 +#ifdef MODULE
   2.777 +MODULE_PARM (megaraid, "s");
   2.778 +#endif
   2.779 +#endif
   2.780 +static int skip_id = -1;
   2.781 +static int numCtlrs = 0;
   2.782 +static mega_host_config *megaCtlrs[FC_MAX_CHANNELS] = { 0 };
   2.783 +#if XENO_KILLED
   2.784 +static struct proc_dir_entry *mega_proc_dir_entry;
   2.785 +#endif
   2.786 +
   2.787 +#if DEBUG
   2.788 +static u32 maxCmdTime = 0;
   2.789 +#endif
   2.790 +
   2.791 +static mega_scb *pLastScb = NULL;
   2.792 +#if XENO_KILLED
   2.793 +static struct notifier_block mega_notifier = {
   2.794 +	megaraid_reboot_notify,
   2.795 +	NULL,
   2.796 +	0
   2.797 +};
   2.798 +#endif
   2.799 +
   2.800 +/* For controller re-ordering */
   2.801 +struct mega_hbas mega_hbas[MAX_CONTROLLERS];
   2.802 +
   2.803 +/*
   2.804 + * The File Operations structure for the serial/ioctl interface of the driver
   2.805 + */
   2.806 +/* For controller re-ordering */ 
   2.807 +#if XENO_KILLED
   2.808 +static struct file_operations megadev_fops = {
   2.809 +	ioctl:megadev_ioctl_entry,
   2.810 +	open:megadev_open,
   2.811 +	release:megadev_close,
   2.812 +};
   2.813 +#endif
   2.814 +/*
   2.815 + * Array to structures for storing the information about the controllers. This
   2.816 + * information is sent to the user level applications, when they do an ioctl
   2.817 + * for this information.
   2.818 + */
   2.819 +static struct mcontroller mcontroller[MAX_CONTROLLERS];
   2.820 +
   2.821 +/* The current driver version */
   2.822 +static u32 driver_ver = 0x118C;
   2.823 +
   2.824 +#if XENO_KILLED
   2.825 +/* major number used by the device for character interface */
   2.826 +static int major;
   2.827 +
   2.828 +static struct semaphore mimd_ioctl_sem;
   2.829 +static struct semaphore mimd_entry_mtx;
   2.830 +#endif
   2.831 +
   2.832 +#if SERDEBUG
   2.833 +volatile static spinlock_t serial_lock;
   2.834 +#endif
   2.835 +
   2.836 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)	/* 0x20300 */
   2.837 +static struct proc_dir_entry proc_scsi_megaraid = {
   2.838 +	PROC_SCSI_MEGARAID, 8, "megaraid",
   2.839 +	S_IFDIR | S_IRUGO | S_IXUGO, 2
   2.840 +};
   2.841 +#endif
   2.842 +
   2.843 +#ifdef CONFIG_PROC_FS
   2.844 +extern struct proc_dir_entry proc_root;
   2.845 +#endif
   2.846 +
   2.847 +#define	IS_RAID_CH(this, ch)	( (this->mega_ch_class >> (ch)) & 0x01 )
   2.848 +
   2.849 +#if SERDEBUG
   2.850 +static char strbuf[MAX_SERBUF + 1];
   2.851 +
   2.852 +static void ser_init (void)
   2.853 +{
   2.854 +	unsigned port = COM_BASE;
   2.855 +
   2.856 +	outb (0x80, port + 3);
   2.857 +	outb (0, port + 1);
   2.858 +	/* 9600 Baud, if 19200: outb(6,port) */
   2.859 +	outb (12, port);
   2.860 +	outb (3, port + 3);
   2.861 +	outb (0, port + 1);
   2.862 +}
   2.863 +
   2.864 +static void ser_puts (char *str)
   2.865 +{
   2.866 +	char *ptr;
   2.867 +
   2.868 +	ser_init ();
   2.869 +	for (ptr = str; *ptr; ++ptr)
   2.870 +		ser_putc (*ptr);
   2.871 +}
   2.872 +
   2.873 +static void ser_putc (char c)
   2.874 +{
   2.875 +	unsigned port = COM_BASE;
   2.876 +
   2.877 +	while ((inb (port + 5) & 0x20) == 0) ;
   2.878 +	outb (c, port);
   2.879 +	if (c == 0x0a) {
   2.880 +		while ((inb (port + 5) & 0x20) == 0) ;
   2.881 +		outb (0x0d, port);
   2.882 +	}
   2.883 +}
   2.884 +
   2.885 +static int ser_printk (const char *fmt, ...)
   2.886 +{
   2.887 +	va_list args;
   2.888 +	int i;
   2.889 +	long flags;
   2.890 +
   2.891 +	spin_lock_irqsave (&serial_lock, flags);
   2.892 +	va_start (args, fmt);
   2.893 +	i = vsprintf (strbuf, fmt, args);
   2.894 +	ser_puts (strbuf);
   2.895 +	va_end (args);
   2.896 +	spin_unlock_irqrestore (&serial_lock, flags);
   2.897 +
   2.898 +	return i;
   2.899 +}
   2.900 +
   2.901 +#define TRACE(a)    { ser_printk a;}
   2.902 +
   2.903 +#else
   2.904 +#define TRACE(A)
   2.905 +#endif
   2.906 +
   2.907 +#define TRACE1(a)
   2.908 +
   2.909 +static void callDone (Scsi_Cmnd * SCpnt)
   2.910 +{
   2.911 +	if (SCpnt->result) {
   2.912 +		TRACE (("*** %.08lx %.02x <%d.%d.%d> = %x\n",
   2.913 +			SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel,
   2.914 +			SCpnt->target, SCpnt->lun, SCpnt->result));
   2.915 +	}
   2.916 +	SCpnt->scsi_done (SCpnt);
   2.917 +}
   2.918 +
   2.919 +/*-------------------------------------------------------------------------
   2.920 + *
   2.921 + *                      Local functions
   2.922 + *
   2.923 + *-------------------------------------------------------------------------*/
   2.924 +
   2.925 +/*=======================
   2.926 + * Free a SCB structure
   2.927 + *=======================
   2.928 + */
   2.929 +static void mega_freeSCB (mega_host_config * megaCfg, mega_scb * pScb)
   2.930 +{
   2.931 +
   2.932 +	mega_scb *pScbtmp;
   2.933 +
   2.934 +	if ((pScb == NULL) || (pScb->idx >= 0xFE)) {
   2.935 +		return;
   2.936 +	}
   2.937 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
   2.938 +	switch (pScb->dma_type) {
   2.939 +	case M_RD_DMA_TYPE_NONE:
   2.940 +		break;
   2.941 +	case M_RD_PTHRU_WITH_BULK_DATA:
   2.942 +		pci_unmap_single (megaCfg->dev, pScb->dma_h_bulkdata,
   2.943 +				  pScb->pthru->dataxferlen,
   2.944 +				  pScb->dma_direction);
   2.945 +		break;
   2.946 +	case M_RD_EPTHRU_WITH_BULK_DATA:
   2.947 +		pci_unmap_single (megaCfg->dev, pScb->dma_h_bulkdata,
   2.948 +				  pScb->epthru->dataxferlen,
   2.949 +				  pScb->dma_direction);
   2.950 +		break;
   2.951 +	case M_RD_PTHRU_WITH_SGLIST:
   2.952 +	{
   2.953 +		int count;
   2.954 +		for (count = 0; count < pScb->sglist_count; count++) {
   2.955 +			pci_unmap_single (megaCfg->dev,
   2.956 +					  pScb->dma_h_sglist[count],
   2.957 +					  pScb->sgList[count].length,
   2.958 +					  pScb->dma_direction);
   2.959 +
   2.960 +		}
   2.961 +		break;
   2.962 +	}
   2.963 +	case M_RD_BULK_DATA_ONLY:
   2.964 +		pci_unmap_single (megaCfg->dev,
   2.965 +				  pScb->dma_h_bulkdata,
   2.966 +				  pScb->iDataSize, pScb->dma_direction);
   2.967 +
   2.968 +		break;
   2.969 +	case M_RD_SGLIST_ONLY:
   2.970 +		pci_unmap_sg (megaCfg->dev,
   2.971 +			      pScb->SCpnt->request_buffer,
   2.972 +			      pScb->SCpnt->use_sg, pScb->dma_direction);
   2.973 +		break;
   2.974 +	default:
   2.975 +		break;
   2.976 +	}
   2.977 +#endif
   2.978 +
   2.979 +	/* Unlink from pending queue */
   2.980 +	if (pScb == megaCfg->qPendingH) {
   2.981 +
   2.982 +		if (megaCfg->qPendingH == megaCfg->qPendingT)
   2.983 +			megaCfg->qPendingH = megaCfg->qPendingT = NULL;
   2.984 +		else
   2.985 +			megaCfg->qPendingH = megaCfg->qPendingH->next;
   2.986 +
   2.987 +		megaCfg->qPcnt--;
   2.988 +
   2.989 +	} else {
   2.990 +		for (pScbtmp = megaCfg->qPendingH; pScbtmp;
   2.991 +		     pScbtmp = pScbtmp->next) {
   2.992 +
   2.993 +			if (pScbtmp->next == pScb) {
   2.994 +
   2.995 +				pScbtmp->next = pScb->next;
   2.996 +
   2.997 +				if (pScb == megaCfg->qPendingT) {
   2.998 +					megaCfg->qPendingT = pScbtmp;
   2.999 +				}
  2.1000 +
  2.1001 +				megaCfg->qPcnt--;
  2.1002 +				break;
  2.1003 +			}
  2.1004 +		}
  2.1005 +	}
  2.1006 +
  2.1007 +	/* Link back into free list */
  2.1008 +	pScb->state = SCB_FREE;
  2.1009 +	pScb->SCpnt = NULL;
  2.1010 +
  2.1011 +	if (megaCfg->qFreeH == (mega_scb *) NULL) {
  2.1012 +		megaCfg->qFreeH = megaCfg->qFreeT = pScb;
  2.1013 +	} else {
  2.1014 +		megaCfg->qFreeT->next = pScb;
  2.1015 +		megaCfg->qFreeT = pScb;
  2.1016 +	}
  2.1017 +
  2.1018 +	megaCfg->qFreeT->next = NULL;
  2.1019 +	megaCfg->qFcnt++;
  2.1020 +
  2.1021 +}
  2.1022 +
  2.1023 +/*===========================
  2.1024 + * Allocate a SCB structure
  2.1025 + *===========================
  2.1026 + */
  2.1027 +static mega_scb *mega_allocateSCB (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
  2.1028 +{
  2.1029 +	mega_scb *pScb;
  2.1030 +
  2.1031 +	/* Unlink command from Free List */
  2.1032 +	if ((pScb = megaCfg->qFreeH) != NULL) {
  2.1033 +		megaCfg->qFreeH = pScb->next;
  2.1034 +		megaCfg->qFcnt--;
  2.1035 +
  2.1036 +		pScb->isrcount = jiffies;
  2.1037 +		pScb->next = NULL;
  2.1038 +		pScb->state = SCB_ACTIVE;
  2.1039 +		pScb->SCpnt = SCpnt;
  2.1040 +
  2.1041 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.1042 +		pScb->dma_type = M_RD_DMA_TYPE_NONE;
  2.1043 +#endif
  2.1044 +
  2.1045 +		return pScb;
  2.1046 +	}
  2.1047 +
  2.1048 +	printk (KERN_WARNING "Megaraid: Could not allocate free SCB!!!\n");
  2.1049 +
  2.1050 +	return NULL;
  2.1051 +}
  2.1052 +
  2.1053 +/* Run through the list of completed requests  and finish it */
  2.1054 +static void mega_rundoneq (mega_host_config * megaCfg)
  2.1055 +{
  2.1056 +	Scsi_Cmnd *SCpnt;
  2.1057 +
  2.1058 +	while ((SCpnt = megaCfg->qCompletedH) != NULL) {
  2.1059 +		megaCfg->qCompletedH = (Scsi_Cmnd *) SCpnt->host_scribble;
  2.1060 +		megaCfg->qCcnt--;
  2.1061 +
  2.1062 +		SCpnt->host_scribble = (unsigned char *) NULL;	/* XC : sep 14 */
  2.1063 +		/* Callback */
  2.1064 +		callDone (SCpnt);
  2.1065 +	}
  2.1066 +
  2.1067 +	megaCfg->qCompletedH = megaCfg->qCompletedT = NULL;
  2.1068 +}
  2.1069 +
  2.1070 +/*
  2.1071 + * Runs through the list of pending requests
  2.1072 + * Assumes that mega_lock spin_lock has been acquired.
  2.1073 + */
  2.1074 +static int mega_runpendq (mega_host_config * megaCfg)
  2.1075 +{
  2.1076 +	mega_scb *pScb;
  2.1077 +	int rc;
  2.1078 +
  2.1079 +	/* Issue any pending commands to the card */
  2.1080 +	for (pScb = megaCfg->qPendingH; pScb; pScb = pScb->next) {
  2.1081 +		if (pScb->state == SCB_ACTIVE) {
  2.1082 +			if ((rc =
  2.1083 +			     megaIssueCmd (megaCfg, pScb->mboxData, pScb, 1)) == -1)
  2.1084 +				return rc;
  2.1085 +		}
  2.1086 +	}
  2.1087 +	return 0;
  2.1088 +}
  2.1089 +
  2.1090 +/* Add command to the list of completed requests */
  2.1091 +
  2.1092 +static void mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb, int status)
  2.1093 +{
  2.1094 +	int islogical;
  2.1095 +	Scsi_Cmnd *SCpnt;
  2.1096 +	mega_passthru *pthru;
  2.1097 +	mega_ext_passthru *epthru;
  2.1098 +	mega_mailbox *mbox;
  2.1099 +	struct scatterlist *sgList;
  2.1100 +	u8	c;
  2.1101 +
  2.1102 +	if (pScb == NULL) {
  2.1103 +		TRACE (("NULL pScb in mega_cmd_done!"));
  2.1104 +		printk(KERN_CRIT "NULL pScb in mega_cmd_done!");
  2.1105 +	}
  2.1106 +
  2.1107 +	SCpnt = pScb->SCpnt;
  2.1108 +
  2.1109 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.1110 +	pthru = pScb->pthru;
  2.1111 +	epthru = pScb->epthru;
  2.1112 +#else
  2.1113 +	pthru = &pScb->pthru;
  2.1114 +	epthru = &pScb->epthru;
  2.1115 +#endif
  2.1116 +
  2.1117 +	mbox = (mega_mailbox *) & pScb->mboxData;
  2.1118 +
  2.1119 +	if (SCpnt == NULL) {
  2.1120 +		TRACE (("NULL SCpnt in mega_cmd_done!"));
  2.1121 +		TRACE (("pScb->idx = ", pScb->idx));
  2.1122 +		TRACE (("pScb->state = ", pScb->state));
  2.1123 +		TRACE (("pScb->state = ", pScb->state));
  2.1124 +		panic(KERN_ERR "megaraid:Problem...!\n");
  2.1125 +	}
  2.1126 +
  2.1127 +#if 0
  2.1128 +	islogical = ( (SCpnt->channel >= megaCfg->productInfo.SCSIChanPresent) &&
  2.1129 +					(SCpnt->channel <= megaCfg->host->max_channel) );
  2.1130 +#endif
  2.1131 +#if 0
  2.1132 +	islogical = (SCpnt->channel == megaCfg->host->max_channel);
  2.1133 +#endif
  2.1134 +	islogical = megaCfg->logdrv_chan[SCpnt->channel];
  2.1135 +
  2.1136 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.1137 +	/* Special Case to handle PassThrough->XferAddrress > 4GB */
  2.1138 +	switch (SCpnt->cmnd[0]) {
  2.1139 +	case INQUIRY:
  2.1140 +	case READ_CAPACITY:
  2.1141 +		memcpy (SCpnt->request_buffer,
  2.1142 +			pScb->bounce_buffer, SCpnt->request_bufflen);
  2.1143 +		break;
  2.1144 +	}
  2.1145 +#endif
  2.1146 +
  2.1147 +	mega_freeSCB (megaCfg, pScb);
  2.1148 +
  2.1149 +	/*
  2.1150 +	 * Do not return the presence of hard disk on the channel so, inquiry
  2.1151 +	 * sent, and returned data==hard disk or removable hard disk and not
  2.1152 +	 * logical, request should return failure! - PJ
  2.1153 +	 */
  2.1154 +#if 0
  2.1155 +	if (SCpnt->cmnd[0] == INQUIRY && ((((u_char *) SCpnt->request_buffer)[0] & 0x1F) == TYPE_DISK) && !islogical) {
  2.1156 +		status = 0xF0;
  2.1157 +	}
  2.1158 +#endif
  2.1159 +	if (SCpnt->cmnd[0] == INQUIRY && !islogical) {
  2.1160 +		if ( SCpnt->use_sg ) {
  2.1161 +			sgList = (struct scatterlist *)SCpnt->request_buffer;
  2.1162 +			memcpy(&c, sgList[0].address, 0x1);
  2.1163 +		} else {
  2.1164 +			memcpy(&c, SCpnt->request_buffer, 0x1);
  2.1165 +		}
  2.1166 +#if 0
  2.1167 +		if( (c & 0x1F ) == TYPE_DISK ) {
  2.1168 +			status = 0xF0;
  2.1169 +		}
  2.1170 +#endif
  2.1171 +		if(IS_RAID_CH(megaCfg, SCpnt->channel) && ((c & 0x1F) == TYPE_DISK)) {
  2.1172 +			status = 0xF0;
  2.1173 +		}
  2.1174 +	}
  2.1175 +
  2.1176 +
  2.1177 +	/* clear result; otherwise, success returns corrupt value */
  2.1178 +	SCpnt->result = 0;
  2.1179 +
  2.1180 +	if ( 0 && SCpnt->cmnd[0] & M_RD_IOCTL_CMD ) {	/* i.e. ioctl cmd such as M_RD_IOCTL_CMD, M_RD_IOCTL_CMD_NEW of megamgr */
  2.1181 +		switch (status) {
  2.1182 +		case 2:
  2.1183 +		case 0xF0:
  2.1184 +		case 0xF4:
  2.1185 +			SCpnt->result = (DID_BAD_TARGET << 16) | status;
  2.1186 +			break;
  2.1187 +		default:
  2.1188 +			SCpnt->result |= status;
  2.1189 +		}		/*end of switch */
  2.1190 +	} else {
  2.1191 +		/* Convert MegaRAID status to Linux error code */
  2.1192 +		switch (status) {
  2.1193 +		case 0x00:	/* SUCCESS , i.e. SCSI_STATUS_GOOD */
  2.1194 +			SCpnt->result |= (DID_OK << 16);
  2.1195 +			break;
  2.1196 +
  2.1197 +		case 0x02:	/* ERROR_ABORTED, i.e. SCSI_STATUS_CHECK_CONDITION */
  2.1198 +
  2.1199 +			/*set sense_buffer and result fields */
  2.1200 +			if (mbox->cmd == MEGA_MBOXCMD_PASSTHRU || mbox->cmd ==
  2.1201 +							MEGA_MBOXCMD_PASSTHRU64 ) {
  2.1202 +
  2.1203 +				memcpy (SCpnt->sense_buffer, pthru->reqsensearea, 14);
  2.1204 +
  2.1205 +				SCpnt->result = (DRIVER_SENSE << 24) | (DID_OK << 16) |
  2.1206 +						(CHECK_CONDITION << 1);
  2.1207 +
  2.1208 +			} else if (mbox->cmd == MEGA_MBOXCMD_EXTPASSTHRU) {
  2.1209 +
  2.1210 +				memcpy( SCpnt->sense_buffer, epthru->reqsensearea, 14);
  2.1211 +
  2.1212 +				SCpnt->result = (DRIVER_SENSE << 24) | (DID_OK << 16) |
  2.1213 +						(CHECK_CONDITION << 1);
  2.1214 +
  2.1215 +			} else {
  2.1216 +				SCpnt->sense_buffer[0] = 0x70;
  2.1217 +				SCpnt->sense_buffer[2] = ABORTED_COMMAND;
  2.1218 +				SCpnt->result |= (CHECK_CONDITION << 1);
  2.1219 +			}
  2.1220 +			break;
  2.1221 +
  2.1222 +		case 0x08:	/* ERR_DEST_DRIVE_FAILED, i.e. SCSI_STATUS_BUSY */
  2.1223 +			SCpnt->result |= (DID_BUS_BUSY << 16) | status;
  2.1224 +			break;
  2.1225 +
  2.1226 +		default:
  2.1227 +			SCpnt->result |= (DID_BAD_TARGET << 16) | status;
  2.1228 +			break;
  2.1229 +		}
  2.1230 +	}
  2.1231 +
  2.1232 +	/* Add Scsi_Command to end of completed queue */
  2.1233 +	if (megaCfg->qCompletedH == NULL) {
  2.1234 +		megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
  2.1235 +	} else {
  2.1236 +		megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
  2.1237 +		megaCfg->qCompletedT = SCpnt;
  2.1238 +	}
  2.1239 +
  2.1240 +	megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
  2.1241 +	megaCfg->qCcnt++;
  2.1242 +}
  2.1243 +
  2.1244 +/*-------------------------------------------------------------------
  2.1245 + *
  2.1246 + *                 Build a SCB from a Scsi_Cmnd
  2.1247 + *
  2.1248 + * Returns a SCB pointer, or NULL
  2.1249 + * If NULL is returned, the scsi_done function MUST have been called
  2.1250 + *
  2.1251 + *-------------------------------------------------------------------*/
  2.1252 +
  2.1253 +static mega_scb *mega_build_cmd (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
  2.1254 +{
  2.1255 +	mega_scb *pScb;
  2.1256 +	mega_mailbox *mbox;
  2.1257 +	mega_passthru *pthru;
  2.1258 +	mega_ext_passthru *epthru;
  2.1259 +	long seg;
  2.1260 +	char islogical;
  2.1261 +	int		max_ldrv_num;
  2.1262 +	int		channel = 0;
  2.1263 +	int		target = 0;
  2.1264 +	int		ldrv_num = 0;	/* logical drive number */
  2.1265 +
  2.1266 +	if ((SCpnt->cmnd[0] == MEGADEVIOC))
  2.1267 +		return megadev_doioctl (megaCfg, SCpnt);
  2.1268 +
  2.1269 +	if ((SCpnt->cmnd[0] == M_RD_IOCTL_CMD)
  2.1270 +		    || (SCpnt->cmnd[0] == M_RD_IOCTL_CMD_NEW))
  2.1271 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)  
  2.1272 +		return mega_ioctl (megaCfg, SCpnt);	/* Handle IOCTL command */
  2.1273 +#else
  2.1274 +	{
  2.1275 +		printk(KERN_WARNING "megaraid ioctl: older interface - "
  2.1276 +				"not supported.\n");
  2.1277 +		return NULL;
  2.1278 +	}
  2.1279 +#endif
  2.1280 +
  2.1281 +#if 0
  2.1282 +	islogical = ( (SCpnt->channel >= megaCfg->productInfo.SCSIChanPresent) &&
  2.1283 +					(SCpnt->channel <= megaCfg->host->max_channel) );
  2.1284 +#endif
  2.1285 +#if 0
  2.1286 +	islogical = (IS_RAID_CH(SCpnt->channel) && /* virtual ch is raid - AM */
  2.1287 +						(SCpnt->channel == megaCfg->host->max_channel));
  2.1288 +#endif
  2.1289 +
  2.1290 +	/*
  2.1291 +	 * We know on what channels are our logical drives - mega_findCard()
  2.1292 +	 */
  2.1293 +	islogical = megaCfg->logdrv_chan[SCpnt->channel];
  2.1294 +
  2.1295 +	/*
  2.1296 +	 * The theory: If physical drive is chosen for boot, all the physical
  2.1297 +	 * devices are exported before the logical drives, otherwise physical
  2.1298 +	 * devices are pushed after logical drives, in which case - Kernel sees
  2.1299 +	 * the physical devices on virtual channel which is obviously converted
  2.1300 +	 * to actual channel on the HBA.
  2.1301 +	 */
  2.1302 +	if( megaCfg->boot_pdrv_enabled ) {
  2.1303 +		if( islogical ) {
  2.1304 +			/* logical channel */
  2.1305 +			channel = SCpnt->channel - megaCfg->productInfo.SCSIChanPresent;
  2.1306 +		}
  2.1307 +		else {
  2.1308 +			channel = SCpnt->channel; /* this is physical channel */
  2.1309 +			target = SCpnt->target;
  2.1310 +
  2.1311 +			/*
  2.1312 +			 * boot from a physical disk, that disk needs to be exposed first
  2.1313 +			 * IF both the channels are SCSI, then booting from the second
  2.1314 +			 * channel is not allowed.
  2.1315 +			 */
  2.1316 +			if( target == 0 ) {
  2.1317 +				target = megaCfg->boot_pdrv_tgt;
  2.1318 +			}
  2.1319 +			else if( target == megaCfg->boot_pdrv_tgt ) {
  2.1320 +				target = 0;
  2.1321 +			}
  2.1322 +		}
  2.1323 +	}
  2.1324 +	else {
  2.1325 +		if( islogical ) {
  2.1326 +			channel = SCpnt->channel; /* this is the logical channel */
  2.1327 +		}
  2.1328 +		else {
  2.1329 +			channel = SCpnt->channel - NVIRT_CHAN;	/* physical channel */
  2.1330 +			target = SCpnt->target;
  2.1331 +		}
  2.1332 +	}
  2.1333 +
  2.1334 +	if ( ! megaCfg->support_ext_cdb ) {
  2.1335 +		if (!islogical && SCpnt->lun != 0) {
  2.1336 +			SCpnt->result = (DID_BAD_TARGET << 16);
  2.1337 +			callDone (SCpnt);
  2.1338 +			return NULL;
  2.1339 +		}
  2.1340 +	}
  2.1341 +
  2.1342 +	if (!islogical && SCpnt->target == skip_id) {
  2.1343 +		SCpnt->result = (DID_BAD_TARGET << 16);
  2.1344 +		callDone (SCpnt);
  2.1345 +		return NULL;
  2.1346 +	}
  2.1347 +
  2.1348 +	if (islogical) {
  2.1349 +
  2.1350 +		/* have just LUN 0 for each target on virtual channels */
  2.1351 +		if( SCpnt->lun != 0 ) {
  2.1352 +			SCpnt->result = (DID_BAD_TARGET << 16);
  2.1353 +			callDone (SCpnt);
  2.1354 +			return NULL;
  2.1355 +		}
  2.1356 +
  2.1357 +		ldrv_num = mega_get_ldrv_num(megaCfg, SCpnt, channel);
  2.1358 +
  2.1359 +	    max_ldrv_num = (megaCfg->flag & BOARD_40LD) ?
  2.1360 +						FC_MAX_LOGICAL_DRIVES : MAX_LOGICAL_DRIVES;
  2.1361 +
  2.1362 +		 /*
  2.1363 +		  * max_ldrv_num increases by 0x80 if some logical drive was deleted.
  2.1364 +		  */
  2.1365 +		if(megaCfg->read_ldidmap) {
  2.1366 +			max_ldrv_num += 0x80;
  2.1367 +		}
  2.1368 +
  2.1369 +		if( ldrv_num > max_ldrv_num ) {
  2.1370 +			SCpnt->result = (DID_BAD_TARGET << 16);
  2.1371 +			callDone (SCpnt);
  2.1372 +			return NULL;
  2.1373 +		}
  2.1374 +
  2.1375 +	} else {
  2.1376 +		if ( SCpnt->lun > 7) {
  2.1377 +				/* Do not support lun >7 for physically accessed devices */
  2.1378 +			SCpnt->result = (DID_BAD_TARGET << 16);
  2.1379 +			callDone (SCpnt);
  2.1380 +			return NULL;
  2.1381 +		}
  2.1382 +	}
  2.1383 +	/*-----------------------------------------------------
  2.1384 +	 *
  2.1385 +	 *               Logical drive commands
  2.1386 +	 *
  2.1387 +	 *-----------------------------------------------------*/
  2.1388 +	if (islogical) {
  2.1389 +		switch (SCpnt->cmnd[0]) {
  2.1390 +		case TEST_UNIT_READY:
  2.1391 +			memset (SCpnt->request_buffer, 0, SCpnt->request_bufflen);
  2.1392 +			SCpnt->result = (DID_OK << 16);
  2.1393 +			callDone (SCpnt);
  2.1394 +			return NULL;
  2.1395 +
  2.1396 +		case MODE_SENSE:
  2.1397 +			memset (SCpnt->request_buffer, 0, SCpnt->cmnd[4]);
  2.1398 +			SCpnt->result = (DID_OK << 16);
  2.1399 +			callDone (SCpnt);
  2.1400 +			return NULL;
  2.1401 +
  2.1402 +		case READ_CAPACITY:
  2.1403 +		case INQUIRY:
  2.1404 +			if(!(megaCfg->flag & (1L << SCpnt->channel))) {
  2.1405 +				printk(KERN_NOTICE
  2.1406 +					"scsi%d: scanning virtual channel %d for logical drives.\n",
  2.1407 +					megaCfg->host->host_no, channel);
  2.1408 +
  2.1409 +				megaCfg->flag |= (1L << SCpnt->channel);
  2.1410 +			}
  2.1411 +
  2.1412 +			/* Allocate a SCB and initialize passthru */
  2.1413 +			if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
  2.1414 +				SCpnt->result = (DID_ERROR << 16);
  2.1415 +				callDone (SCpnt);
  2.1416 +				return NULL;
  2.1417 +			}
  2.1418 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.1419 +			pthru = pScb->pthru;
  2.1420 +#else
  2.1421 +			pthru = &pScb->pthru;
  2.1422 +#endif
  2.1423 +
  2.1424 +			mbox = (mega_mailbox *) & pScb->mboxData;
  2.1425 +			memset (mbox, 0, sizeof (pScb->mboxData));
  2.1426 +			memset (pthru, 0, sizeof (mega_passthru));
  2.1427 +			pthru->timeout = 0;
  2.1428 +			pthru->ars = 1;
  2.1429 +			pthru->reqsenselen = 14;
  2.1430 +			pthru->islogical = 1;
  2.1431 +			pthru->logdrv = ldrv_num;
  2.1432 +			pthru->cdblen = SCpnt->cmd_len;
  2.1433 +
  2.1434 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.1435 +			/*Not sure about the direction */
  2.1436 +			pScb->dma_direction = PCI_DMA_BIDIRECTIONAL;
  2.1437 +			pScb->dma_type = M_RD_PTHRU_WITH_BULK_DATA;
  2.1438 +
  2.1439 +#if 0
  2.1440 +/* Normal Code w/o the need for bounce buffer */
  2.1441 +			pScb->dma_h_bulkdata
  2.1442 +			    = pci_map_single (megaCfg->dev,
  2.1443 +					      SCpnt->request_buffer,
  2.1444 +					      SCpnt->request_bufflen,
  2.1445 +					      pScb->dma_direction);
  2.1446 +
  2.1447 +			pthru->dataxferaddr = pScb->dma_h_bulkdata;
  2.1448 +#else
  2.1449 +/* Special Code to use bounce buffer for READ_CAPA/INQ */
  2.1450 +			pthru->dataxferaddr = pScb->dma_bounce_buffer;
  2.1451 +			pScb->dma_type = M_RD_DMA_TYPE_NONE;
  2.1452 +#endif
  2.1453 +
  2.1454 +#else
  2.1455 +			pthru->dataxferaddr =
  2.1456 +			    virt_to_bus (SCpnt->request_buffer);
  2.1457 +#endif
  2.1458 +
  2.1459 +			pthru->dataxferlen = SCpnt->request_bufflen;
  2.1460 +			memcpy (pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len);
  2.1461 +
  2.1462 +			/* Initialize mailbox area */
  2.1463 +			mbox->cmd = MEGA_MBOXCMD_PASSTHRU;
  2.1464 +
  2.1465 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.1466 +			mbox->xferaddr = pScb->dma_passthruhandle64;
  2.1467 +			TRACE1 (("M_RD_PTHRU_WITH_BULK_DATA Enabled \n"));
  2.1468 +#else
  2.1469 +			mbox->xferaddr = virt_to_bus (pthru);
  2.1470 +#endif
  2.1471 +			return pScb;
  2.1472 +
  2.1473 +		case READ_6:
  2.1474 +		case WRITE_6:
  2.1475 +		case READ_10:
  2.1476 +		case WRITE_10:
  2.1477 +			/* Allocate a SCB and initialize mailbox */
  2.1478 +			if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
  2.1479 +				SCpnt->result = (DID_ERROR << 16);
  2.1480 +				callDone (SCpnt);
  2.1481 +				return NULL;
  2.1482 +			}
  2.1483 +			mbox = (mega_mailbox *) & pScb->mboxData;
  2.1484 +
  2.1485 +			memset (mbox, 0, sizeof (pScb->mboxData));
  2.1486 +			mbox->logdrv = ldrv_num;
  2.1487 +
  2.1488 +			if (megaCfg->flag & BOARD_64BIT) {
  2.1489 +				mbox->cmd = (*SCpnt->cmnd == READ_6
  2.1490 +					     || *SCpnt->cmnd ==
  2.1491 +					     READ_10) ? MEGA_MBOXCMD_LREAD64 :
  2.1492 +				    MEGA_MBOXCMD_LWRITE64;
  2.1493 +			} else {
  2.1494 +				mbox->cmd = (*SCpnt->cmnd == READ_6
  2.1495 +					     || *SCpnt->cmnd ==
  2.1496 +					     READ_10) ? MEGA_MBOXCMD_LREAD :
  2.1497 +				    MEGA_MBOXCMD_LWRITE;
  2.1498 +			}
  2.1499 +
  2.1500 +			/* 6-byte */
  2.1501 +			if (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == WRITE_6) {
  2.1502 +				mbox->numsectors = (u32) SCpnt->cmnd[4];
  2.1503 +				mbox->lba =
  2.1504 +				    ((u32) SCpnt->cmnd[1] << 16) |
  2.1505 +				    ((u32) SCpnt->cmnd[2] << 8) |
  2.1506 +				    (u32) SCpnt->cmnd[3];
  2.1507 +				mbox->lba &= 0x1FFFFF;
  2.1508 +
  2.1509 +				if (*SCpnt->cmnd == READ_6) {
  2.1510 +					megaCfg->nReads[(int)ldrv_num]++;
  2.1511 +					megaCfg->nReadBlocks[(int)ldrv_num] +=
  2.1512 +					    mbox->numsectors;
  2.1513 +				} else {
  2.1514 +					megaCfg->nWrites[(int)ldrv_num]++;
  2.1515 +					megaCfg->nWriteBlocks[(int)ldrv_num] +=
  2.1516 +					    mbox->numsectors;
  2.1517 +				}
  2.1518 +			}
  2.1519 +
  2.1520 +			/* 10-byte */
  2.1521 +			if (*SCpnt->cmnd == READ_10 || *SCpnt->cmnd == WRITE_10) {
  2.1522 +				mbox->numsectors =
  2.1523 +				    (u32) SCpnt->cmnd[8] |
  2.1524 +				    ((u32) SCpnt->cmnd[7] << 8);
  2.1525 +				mbox->lba =
  2.1526 +				    ((u32) SCpnt->cmnd[2] << 24) |
  2.1527 +				    ((u32) SCpnt->cmnd[3] << 16) |
  2.1528 +				    ((u32) SCpnt->cmnd[4] << 8) |
  2.1529 +				    (u32) SCpnt->cmnd[5];
  2.1530 +
  2.1531 +				if (*SCpnt->cmnd == READ_10) {
  2.1532 +					megaCfg->nReads[(int)ldrv_num]++;
  2.1533 +					megaCfg->nReadBlocks[(int)ldrv_num] +=
  2.1534 +					    mbox->numsectors;
  2.1535 +				} else {
  2.1536 +					megaCfg->nWrites[(int)ldrv_num]++;
  2.1537 +					megaCfg->nWriteBlocks[(int)ldrv_num] +=
  2.1538 +					    mbox->numsectors;
  2.1539 +				}
  2.1540 +			}
  2.1541 +
  2.1542 +			/* 12-byte */
  2.1543 +			if (*SCpnt->cmnd == READ_12 || *SCpnt->cmnd == WRITE_12) {
  2.1544 +				mbox->lba =
  2.1545 +				    ((u32) SCpnt->cmnd[2] << 24) |
  2.1546 +				    ((u32) SCpnt->cmnd[3] << 16) |
  2.1547 +				    ((u32) SCpnt->cmnd[4] << 8) |
  2.1548 +				    (u32) SCpnt->cmnd[5];
  2.1549 +
  2.1550 +				mbox->numsectors =
  2.1551 +				    ((u32) SCpnt->cmnd[6] << 24) |
  2.1552 +				    ((u32) SCpnt->cmnd[7] << 16) |
  2.1553 +				    ((u32) SCpnt->cmnd[8] << 8) |
  2.1554 +				    (u32) SCpnt->cmnd[9];
  2.1555 +
  2.1556 +				if (*SCpnt->cmnd == READ_12) {
  2.1557 +					megaCfg->nReads[(int)ldrv_num]++;
  2.1558 +					megaCfg->nReadBlocks[(int)ldrv_num] +=
  2.1559 +					    mbox->numsectors;
  2.1560 +				} else {
  2.1561 +					megaCfg->nWrites[(int)ldrv_num]++;
  2.1562 +					megaCfg->nWriteBlocks[(int)ldrv_num] +=
  2.1563 +					    mbox->numsectors;
  2.1564 +				}
  2.1565 +			}
  2.1566 +
  2.1567 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.1568 +			if (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == READ_10
  2.1569 +					|| *SCpnt->cmnd == READ_12) {
  2.1570 +				pScb->dma_direction = PCI_DMA_FROMDEVICE;
  2.1571 +			} else {	/*WRITE_6 or WRITE_10 */
  2.1572 +				pScb->dma_direction = PCI_DMA_TODEVICE;
  2.1573 +			}
  2.1574 +#endif
  2.1575 +
  2.1576 +			/* Calculate Scatter-Gather info */
  2.1577 +			mbox->numsgelements = mega_build_sglist (megaCfg, pScb,
  2.1578 +								 (u32 *)&mbox->xferaddr, (u32 *)&seg);
  2.1579 +
  2.1580 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.1581 +			pScb->iDataSize = seg;
  2.1582 +
  2.1583 +			if (mbox->numsgelements) {
  2.1584 +				pScb->dma_type = M_RD_SGLIST_ONLY;
  2.1585 +				TRACE1 (("M_RD_SGLIST_ONLY Enabled \n"));
  2.1586 +			} else {
  2.1587 +				pScb->dma_type = M_RD_BULK_DATA_ONLY;
  2.1588 +				TRACE1 (("M_RD_BULK_DATA_ONLY Enabled \n"));
  2.1589 +			}
  2.1590 +#endif
  2.1591 +
  2.1592 +			return pScb;
  2.1593 +		default:
  2.1594 +			SCpnt->result = (DID_BAD_TARGET << 16);
  2.1595 +			callDone (SCpnt);
  2.1596 +			return NULL;
  2.1597 +		}
  2.1598 +	}
  2.1599 +	/*-----------------------------------------------------
  2.1600 +	 *
  2.1601 +	 *               Passthru drive commands
  2.1602 +	 *
  2.1603 +	 *-----------------------------------------------------*/
  2.1604 +	else {
  2.1605 +		/* Allocate a SCB and initialize passthru */
  2.1606 +		if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
  2.1607 +			SCpnt->result = (DID_ERROR << 16);
  2.1608 +			callDone (SCpnt);
  2.1609 +			return NULL;
  2.1610 +		}
  2.1611 +
  2.1612 +		mbox = (mega_mailbox *) pScb->mboxData;
  2.1613 +		memset (mbox, 0, sizeof (pScb->mboxData));
  2.1614 +
  2.1615 +		if ( megaCfg->support_ext_cdb && SCpnt->cmd_len > 10 ) {
  2.1616 +			epthru = mega_prepare_extpassthru(megaCfg, pScb, SCpnt, channel,
  2.1617 +					target);
  2.1618 +			mbox->cmd = MEGA_MBOXCMD_EXTPASSTHRU;
  2.1619 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.1620 +			mbox->xferaddr = pScb->dma_ext_passthruhandle64;
  2.1621 +
  2.1622 +			if(epthru->numsgelements) {
  2.1623 +				pScb->dma_type = M_RD_PTHRU_WITH_SGLIST;
  2.1624 +			} else {
  2.1625 +				pScb->dma_type = M_RD_EPTHRU_WITH_BULK_DATA;
  2.1626 +			}
  2.1627 +#else
  2.1628 +			mbox->xferaddr = virt_to_bus(epthru);
  2.1629 +#endif
  2.1630 +		}
  2.1631 +		else {
  2.1632 +			pthru = mega_prepare_passthru(megaCfg, pScb, SCpnt, channel,
  2.1633 +					target);
  2.1634 +
  2.1635 +			/* Initialize mailbox */
  2.1636 +			mbox->cmd = MEGA_MBOXCMD_PASSTHRU;
  2.1637 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.1638 +			mbox->xferaddr = pScb->dma_passthruhandle64;
  2.1639 +
  2.1640 +			if (pthru->numsgelements) {
  2.1641 +				pScb->dma_type = M_RD_PTHRU_WITH_SGLIST;
  2.1642 +			} else {
  2.1643 +				pScb->dma_type = M_RD_PTHRU_WITH_BULK_DATA;
  2.1644 +			}
  2.1645 +#else
  2.1646 +			mbox->xferaddr = virt_to_bus(pthru);
  2.1647 +#endif
  2.1648 +		}
  2.1649 +		return pScb;
  2.1650 +	}
  2.1651 +	return NULL;
  2.1652 +}
  2.1653 +
  2.1654 +static int
  2.1655 +mega_get_ldrv_num(mega_host_config *this_hba, Scsi_Cmnd *sc, int channel)
  2.1656 +{
  2.1657 +	int		tgt;
  2.1658 +	int		ldrv_num;
  2.1659 +
  2.1660 +	tgt = sc->target;
  2.1661 +	
  2.1662 +	if ( tgt > 7 ) tgt--;	/* we do not get inquires for tgt 7 */
  2.1663 +
  2.1664 +	ldrv_num = (channel * 15) + tgt; /* 14 targets per channel */
  2.1665 +
  2.1666 +	/*
  2.1667 +	 * If we have a logical drive with boot enabled, project it first
  2.1668 +	 */
  2.1669 +	if( this_hba->boot_ldrv_enabled ) {
  2.1670 +		if( ldrv_num == 0 ) {
  2.1671 +			ldrv_num = this_hba->boot_ldrv;
  2.1672 +		}
  2.1673 +		else {
  2.1674 +			if( ldrv_num <= this_hba->boot_ldrv ) {
  2.1675 +				ldrv_num--;
  2.1676 +			}
  2.1677 +		}
  2.1678 +	}
  2.1679 +
  2.1680 +	/*
  2.1681 +	 * If "delete logical drive" feature is enabled on this controller.
  2.1682 +	 * Do only if at least one delete logical drive operation was done.
  2.1683 +	 *
  2.1684 +	 * Also, after logical drive deletion, instead of logical drive number,
  2.1685 +	 * the value returned should be 0x80+logical drive id.
  2.1686 +	 *
  2.1687 +	 * These is valid only for IO commands.
  2.1688 +	 */
  2.1689 +
  2.1690 +	 if( this_hba->support_random_del && this_hba->read_ldidmap ) {
  2.1691 +		switch(sc->cmnd[0]) {
  2.1692 +		case READ_6:	/* fall through */
  2.1693 +		case WRITE_6:	/* fall through */
  2.1694 +		case READ_10:	/* fall through */
  2.1695 +		case WRITE_10:
  2.1696 +			ldrv_num += 0x80;
  2.1697 +		}
  2.1698 +	 }
  2.1699 +
  2.1700 +	 return ldrv_num;
  2.1701 +}
  2.1702 +
  2.1703 +
  2.1704 +static mega_passthru *
  2.1705 +mega_prepare_passthru(mega_host_config *megacfg, mega_scb *scb, Scsi_Cmnd *sc,
  2.1706 +		int channel, int target)
  2.1707 +{
  2.1708 +	mega_passthru *pthru;
  2.1709 +
  2.1710 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.1711 +	pthru = scb->pthru;
  2.1712 +#else
  2.1713 +	pthru = &scb->pthru;
  2.1714 +#endif
  2.1715 +	memset (pthru, 0, sizeof (mega_passthru));
  2.1716 +
  2.1717 +	/* set adapter timeout value to 10 min. for tape drive	*/
  2.1718 +	/* 0=6sec/1=60sec/2=10min/3=3hrs 			*/
  2.1719 +	pthru->timeout = 2;
  2.1720 +	pthru->ars = 1;
  2.1721 +	pthru->reqsenselen = 14;
  2.1722 +	pthru->islogical = 0;
  2.1723 +	pthru->channel = (megacfg->flag & BOARD_40LD) ? 0 : channel;
  2.1724 +	pthru->target = (megacfg->flag & BOARD_40LD) ?
  2.1725 +	    (channel << 4) | target : target;
  2.1726 +	pthru->cdblen = sc->cmd_len;
  2.1727 +	pthru->logdrv = sc->lun;
  2.1728 +
  2.1729 +	memcpy (pthru->cdb, sc->cmnd, sc->cmd_len);
  2.1730 +
  2.1731 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.1732 +	/* Not sure about the direction */
  2.1733 +	scb->dma_direction = PCI_DMA_BIDIRECTIONAL;
  2.1734 +
  2.1735 +	/* Special Code for Handling READ_CAPA/ INQ using bounce buffers */
  2.1736 +	switch (sc->cmnd[0]) {
  2.1737 +	case INQUIRY:
  2.1738 +	case READ_CAPACITY:
  2.1739 +
  2.1740 +		if(!(megacfg->flag & (1L << sc->channel))) {
  2.1741 +			printk(KERN_NOTICE
  2.1742 +				"scsi%d: scanning physical channel %d for devices.\n",
  2.1743 +				megacfg->host->host_no, channel);
  2.1744 +
  2.1745 +			megacfg->flag |= (1L << sc->channel);
  2.1746 +		}
  2.1747 +
  2.1748 +		pthru->numsgelements = 0;
  2.1749 +		pthru->dataxferaddr = scb->dma_bounce_buffer;
  2.1750 +		pthru->dataxferlen = sc->request_bufflen;
  2.1751 +		break;
  2.1752 +	default:
  2.1753 +		pthru->numsgelements =
  2.1754 +			mega_build_sglist(
  2.1755 +				megacfg, scb, (u32 *)&pthru->dataxferaddr,
  2.1756 +				(u32 *)&pthru->dataxferlen
  2.1757 +			);
  2.1758 +		break;
  2.1759 +	}
  2.1760 +#else
  2.1761 +	pthru->numsgelements =
  2.1762 +		mega_build_sglist(
  2.1763 +			megacfg, scb, (u32 *)&pthru->dataxferaddr,
  2.1764 +			(u32 *)&pthru->dataxferlen
  2.1765 +		);
  2.1766 +#endif
  2.1767 +	return pthru;
  2.1768 +}
  2.1769 +
  2.1770 +static mega_ext_passthru *
  2.1771 +mega_prepare_extpassthru(mega_host_config *megacfg, mega_scb *scb,
  2.1772 +		Scsi_Cmnd *sc, int channel, int target)
  2.1773 +{
  2.1774 +	mega_ext_passthru *epthru;
  2.1775 +
  2.1776 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.1777 +	epthru = scb->epthru;
  2.1778 +#else
  2.1779 +	epthru = &scb->epthru;
  2.1780 +#endif
  2.1781 +	memset(epthru, 0, sizeof(mega_ext_passthru));
  2.1782 +
  2.1783 +	/* set adapter timeout value to 10 min. for tape drive	*/
  2.1784 +	/* 0=6sec/1=60sec/2=10min/3=3hrs 			*/
  2.1785 +	epthru->timeout = 2;
  2.1786 +	epthru->ars = 1;
  2.1787 +	epthru->reqsenselen = 14;
  2.1788 +	epthru->islogical = 0;
  2.1789 +	epthru->channel = (megacfg->flag & BOARD_40LD) ? 0 : channel;
  2.1790 +	epthru->target = (megacfg->flag & BOARD_40LD) ?
  2.1791 +	    (channel << 4) | target : target;
  2.1792 +	epthru->cdblen = sc->cmd_len;
  2.1793 +	epthru->logdrv = sc->lun;
  2.1794 +
  2.1795 +	memcpy(epthru->cdb, sc->cmnd, sc->cmd_len);
  2.1796 +
  2.1797 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.1798 +	/* Not sure about the direction */
  2.1799 +	scb->dma_direction = PCI_DMA_BIDIRECTIONAL;
  2.1800 +
  2.1801 +	/* Special Code for Handling READ_CAPA/ INQ using bounce buffers */
  2.1802 +	switch (sc->cmnd[0]) {
  2.1803 +	case INQUIRY:
  2.1804 +	case READ_CAPACITY:
  2.1805 +		if(!(megacfg->flag & (1L << sc->channel))) {
  2.1806 +			printk(KERN_NOTICE
  2.1807 +				"scsi%d: scanning physical channel %d for devices.\n",
  2.1808 +				megacfg->host->host_no, channel);
  2.1809 +
  2.1810 +			megacfg->flag |= (1L << sc->channel);
  2.1811 +		}
  2.1812 +
  2.1813 +		epthru->numsgelements = 0;
  2.1814 +		epthru->dataxferaddr = scb->dma_bounce_buffer;
  2.1815 +		epthru->dataxferlen = sc->request_bufflen;
  2.1816 +		break;
  2.1817 +	default:
  2.1818 +		epthru->numsgelements =
  2.1819 +			mega_build_sglist(
  2.1820 +				megacfg, scb, (u32 *)&epthru->dataxferaddr,
  2.1821 +				(u32 *)&epthru->dataxferlen
  2.1822 +			);
  2.1823 +		break;
  2.1824 +	}
  2.1825 +#else
  2.1826 +	epthru->numsgelements =
  2.1827 +		mega_build_sglist(
  2.1828 +			megacfg, scb, (u32 *)&epthru->dataxferaddr,
  2.1829 +			(u32 *)&epthru->dataxferlen
  2.1830 +		);
  2.1831 +#endif
  2.1832 +	return epthru;
  2.1833 +}
  2.1834 +
  2.1835 +/* Handle Driver Level IOCTLs
  2.1836 + * Return value of 0 indicates this function could not handle , so continue
  2.1837 + * processing
  2.1838 +*/
  2.1839 +
  2.1840 +static int mega_driver_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
  2.1841 +{
  2.1842 +	unsigned char *data = (unsigned char *) SCpnt->request_buffer;
  2.1843 +	mega_driver_info driver_info;
  2.1844 +
  2.1845 +	/* If this is not our command dont do anything */
  2.1846 +	if (SCpnt->cmnd[0] != M_RD_DRIVER_IOCTL_INTERFACE)
  2.1847 +		return 0;
  2.1848 +
  2.1849 +	switch (SCpnt->cmnd[1]) {
  2.1850 +	case GET_DRIVER_INFO:
  2.1851 +		if (SCpnt->request_bufflen < sizeof (driver_info)) {
  2.1852 +			SCpnt->result = DID_BAD_TARGET << 16;
  2.1853 +			callDone (SCpnt);
  2.1854 +			return 1;
  2.1855 +		}
  2.1856 +
  2.1857 +		driver_info.size = sizeof (driver_info) - sizeof (int);
  2.1858 +		driver_info.version = MEGARAID_IOCTL_VERSION;
  2.1859 +		memcpy (data, &driver_info, sizeof (driver_info));
  2.1860 +		break;
  2.1861 +	default:
  2.1862 +		SCpnt->result = DID_BAD_TARGET << 16;
  2.1863 +	}
  2.1864 +
  2.1865 +	callDone (SCpnt);
  2.1866 +	return 1;
  2.1867 +}
  2.1868 +
  2.1869 +static void inline set_mbox_xfer_addr (mega_host_config * megaCfg, mega_scb * pScb,
  2.1870 +		    mega_ioctl_mbox * mbox, u32 direction)
  2.1871 +{
  2.1872 +
  2.1873 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.1874 +	switch (direction) {
  2.1875 +	case TO_DEVICE:
  2.1876 +		pScb->dma_direction = PCI_DMA_TODEVICE;
  2.1877 +		break;
  2.1878 +	case FROM_DEVICE:
  2.1879 +		pScb->dma_direction = PCI_DMA_FROMDEVICE;
  2.1880 +		break;
  2.1881 +	case FROMTO_DEVICE:
  2.1882 +		pScb->dma_direction = PCI_DMA_BIDIRECTIONAL;
  2.1883 +		break;
  2.1884 +	}
  2.1885 +
  2.1886 +	pScb->dma_h_bulkdata
  2.1887 +	    = pci_map_single (megaCfg->dev,
  2.1888 +			      pScb->buff_ptr,
  2.1889 +			      pScb->iDataSize, pScb->dma_direction);
  2.1890 +	mbox->xferaddr = pScb->dma_h_bulkdata;
  2.1891 +	pScb->dma_type = M_RD_BULK_DATA_ONLY;
  2.1892 +	TRACE1 (("M_RD_BULK_DATA_ONLY Enabled \n"));
  2.1893 +#else
  2.1894 +	mbox->xferaddr = virt_to_bus (pScb->buff_ptr);
  2.1895 +#endif
  2.1896 +}
  2.1897 +
  2.1898 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
  2.1899 +
  2.1900 +/*--------------------------------------------------------------------
  2.1901 + * build RAID commands for controller, passed down through ioctl()
  2.1902 + *--------------------------------------------------------------------*/
  2.1903 +static mega_scb *mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
  2.1904 +{
  2.1905 +	mega_scb *pScb;
  2.1906 +	mega_ioctl_mbox *mbox;
  2.1907 +	mega_mailbox *mailbox;
  2.1908 +	mega_passthru *pthru;
  2.1909 +	u8 *mboxdata;
  2.1910 +	long seg, i = 0;
  2.1911 +	unsigned char *data = (unsigned char *) SCpnt->request_buffer;
  2.1912 +
  2.1913 +	if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
  2.1914 +		SCpnt->result = (DID_ERROR << 16);
  2.1915 +		callDone (SCpnt);
  2.1916 +		return NULL;
  2.1917 +	}
  2.1918 +	pthru = &pScb->pthru;
  2.1919 +
  2.1920 +	mboxdata = (u8 *) & pScb->mboxData;
  2.1921 +	mbox = (mega_ioctl_mbox *) & pScb->mboxData;
  2.1922 +	mailbox = (mega_mailbox *) & pScb->mboxData;
  2.1923 +	memset (mailbox, 0, sizeof (pScb->mboxData));
  2.1924 +
  2.1925 +	if (data[0] == 0x03) {	/* passthrough command */
  2.1926 +		unsigned char cdblen = data[2];
  2.1927 +		memset (pthru, 0, sizeof (mega_passthru));
  2.1928 +		pthru->islogical = (data[cdblen + 3] & 0x80) ? 1 : 0;
  2.1929 +		pthru->timeout = data[cdblen + 3] & 0x07;
  2.1930 +		pthru->reqsenselen = 14;
  2.1931 +		pthru->ars = (data[cdblen + 3] & 0x08) ? 1 : 0;
  2.1932 +		pthru->logdrv = data[cdblen + 4];
  2.1933 +		pthru->channel = data[cdblen + 5];
  2.1934 +		pthru->target = data[cdblen + 6];
  2.1935 +		pthru->cdblen = cdblen;
  2.1936 +		memcpy (pthru->cdb, &data[3], cdblen);
  2.1937 +
  2.1938 +		mailbox->cmd = MEGA_MBOXCMD_PASSTHRU;
  2.1939 +
  2.1940 +
  2.1941 +		pthru->numsgelements = mega_build_sglist (megaCfg, pScb,
  2.1942 +							  (u32 *) & pthru->
  2.1943 +							  dataxferaddr,
  2.1944 +							  (u32 *) & pthru->
  2.1945 +							  dataxferlen);
  2.1946 +
  2.1947 +		mailbox->xferaddr = virt_to_bus (pthru);
  2.1948 +
  2.1949 +		for (i = 0; i < (SCpnt->request_bufflen - cdblen - 7); i++) {
  2.1950 +			data[i] = data[i + cdblen + 7];
  2.1951 +		}
  2.1952 +		return pScb;
  2.1953 +	}
  2.1954 +	/* else normal (nonpassthru) command */
  2.1955 +
  2.1956 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,0,24)	/*0x020024 */
  2.1957 +	/*
  2.1958 +	 *usage of the function copy from user is used in case of data more than
  2.1959 +	 *4KB.This is used only with adapters which supports more than 8 logical
  2.1960 +	 * drives.This feature is disabled on kernels earlier or same as 2.0.36
  2.1961 +	 * as the uaccess.h file is not available with those kernels.
  2.1962 +	 */
  2.1963 +
  2.1964 +	if (SCpnt->cmnd[0] == M_RD_IOCTL_CMD_NEW) {
  2.1965 +		/* use external data area for large xfers  */
  2.1966 +		/* If cmnd[0] is set to M_RD_IOCTL_CMD_NEW then *
  2.1967 +		 *   cmnd[4..7] = external user buffer     *
  2.1968 +		 *   cmnd[8..11] = length of buffer        *
  2.1969 +		 *                                         */
  2.1970 +      	char *user_area = (char *)*((u32*)&SCpnt->cmnd[4]);
  2.1971 +		u32 xfer_size = *((u32 *) & SCpnt->cmnd[8]);
  2.1972 +		switch (data[0]) {
  2.1973 +		case FW_FIRE_WRITE:
  2.1974 +		case FW_FIRE_FLASH:
  2.1975 +			if ((ulong) user_area & (PAGE_SIZE - 1)) {
  2.1976 +				printk
  2.1977 +				    ("megaraid:user address not aligned on 4K boundary.Error.\n");
  2.1978 +				SCpnt->result = (DID_ERROR << 16);
  2.1979 +				callDone (SCpnt);
  2.1980 +				return NULL;
  2.1981 +			}
  2.1982 +			break;
  2.1983 +		default:
  2.1984 +			break;
  2.1985 +		}
  2.1986 +
  2.1987 +		if (!(pScb->buff_ptr = kmalloc (xfer_size, GFP_KERNEL))) {
  2.1988 +			printk
  2.1989 +			    ("megaraid: Insufficient mem for M_RD_IOCTL_CMD_NEW.\n");
  2.1990 +			SCpnt->result = (DID_ERROR << 16);
  2.1991 +			callDone (SCpnt);
  2.1992 +			return NULL;
  2.1993 +		}
  2.1994 +
  2.1995 +		copy_from_user (pScb->buff_ptr, user_area, xfer_size);
  2.1996 +		pScb->iDataSize = xfer_size;
  2.1997 +
  2.1998 +		switch (data[0]) {
  2.1999 +		case DCMD_FC_CMD:
  2.2000 +			switch (data[1]) {
  2.2001 +			case DCMD_FC_READ_NVRAM_CONFIG:
  2.2002 +			case DCMD_GET_DISK_CONFIG:
  2.2003 +				{
  2.2004 +					if ((ulong) pScb->
  2.2005 +					    buff_ptr & (PAGE_SIZE - 1)) {
  2.2006 +						printk
  2.2007 +						    ("megaraid:user address not sufficient Error.\n");
  2.2008 +						SCpnt->result =
  2.2009 +						    (DID_ERROR << 16);
  2.2010 +						callDone (SCpnt);
  2.2011 +						return NULL;
  2.2012 +					}
  2.2013 +
  2.2014 +					/*building SG list */
  2.2015 +					mega_build_kernel_sg (pScb->buff_ptr,
  2.2016 +							      xfer_size,
  2.2017 +							      pScb, mbox);
  2.2018 +					break;
  2.2019 +				}
  2.2020 +			default:
  2.2021 +				break;
  2.2022 +			}	/*switch (data[1]) */
  2.2023 +			break;
  2.2024 +		}
  2.2025 +
  2.2026 +	}
  2.2027 +#endif
  2.2028 +
  2.2029 +	mbox->cmd = data[0];
  2.2030 +	mbox->channel = data[1];
  2.2031 +	mbox->param = data[2];
  2.2032 +	mbox->pad[0] = data[3];
  2.2033 +	mbox->logdrv = data[4];
  2.2034 +
  2.2035 +	if (SCpnt->cmnd[0] == M_RD_IOCTL_CMD_NEW) {
  2.2036 +		switch (data[0]) {
  2.2037 +		case FW_FIRE_WRITE:
  2.2038 +			mbox->cmd = FW_FIRE_WRITE;
  2.2039 +			mbox->channel = data[1];	/* Current Block Number */
  2.2040 +			set_mbox_xfer_addr (megaCfg, pScb, mbox, TO_DEVICE);
  2.2041 +			mbox->numsgelements = 0;
  2.2042 +			break;
  2.2043 +		case FW_FIRE_FLASH:
  2.2044 +			mbox->cmd = FW_FIRE_FLASH;
  2.2045 +			mbox->channel = data[1] | 0x80;	/* Origin */
  2.2046 +			set_mbox_xfer_addr (megaCfg, pScb, mbox, TO_DEVICE);
  2.2047 +			mbox->numsgelements = 0;
  2.2048 +			break;
  2.2049 +		case DCMD_FC_CMD:
  2.2050 +			*(mboxdata + 0) = data[0];	/*mailbox byte 0: DCMD_FC_CMD */
  2.2051 +			*(mboxdata + 2) = data[1];	/*sub command */
  2.2052 +			switch (data[1]) {
  2.2053 +			case DCMD_FC_READ_NVRAM_CONFIG:
  2.2054 +			case DCMD_FC_READ_NVRAM_CONFIG_64:
  2.2055 +				/* number of elements in SG list */
  2.2056 +				*(mboxdata + 3) = mbox->numsgelements;
  2.2057 +				if (megaCfg->flag & BOARD_64BIT)
  2.2058 +					*(mboxdata + 2) =
  2.2059 +					    DCMD_FC_READ_NVRAM_CONFIG_64;
  2.2060 +				break;
  2.2061 +			case DCMD_WRITE_CONFIG:
  2.2062 +			case DCMD_WRITE_CONFIG_64:
  2.2063 +				if (megaCfg->flag & BOARD_64BIT)
  2.2064 +					*(mboxdata + 2) = DCMD_WRITE_CONFIG_64;
  2.2065 +				set_mbox_xfer_addr (megaCfg, pScb, mbox,
  2.2066 +						    TO_DEVICE);
  2.2067 +				mbox->numsgelements = 0;
  2.2068 +				break;
  2.2069 +			case DCMD_GET_DISK_CONFIG:
  2.2070 +			case DCMD_GET_DISK_CONFIG_64:
  2.2071 +				if (megaCfg->flag & BOARD_64BIT)
  2.2072 +					*(mboxdata + 2) =
  2.2073 +					    DCMD_GET_DISK_CONFIG_64;
  2.2074 +				*(mboxdata + 3) = data[2];	/*number of elements in SG list */
  2.2075 +				/*nr of elements in SG list */
  2.2076 +				*(mboxdata + 4) = mbox->numsgelements;
  2.2077 +				break;
  2.2078 +			case DCMD_DELETE_LOGDRV:
  2.2079 +			case DCMD_DELETE_DRIVEGROUP:
  2.2080 +			case NC_SUBOP_ENQUIRY3:
  2.2081 +				*(mboxdata + 3) = data[2];
  2.2082 +				set_mbox_xfer_addr (megaCfg, pScb, mbox,
  2.2083 +						    FROMTO_DEVICE);
  2.2084 +				mbox->numsgelements = 0;
  2.2085 +				break;
  2.2086 +			case DCMD_CHANGE_LDNO:
  2.2087 +			case DCMD_CHANGE_LOOPID:
  2.2088 +				*(mboxdata + 3) = data[2];
  2.2089 +				*(mboxdata + 4) = data[3];
  2.2090 +				set_mbox_xfer_addr (megaCfg, pScb, mbox,
  2.2091 +						    TO_DEVICE);
  2.2092 +				mbox->numsgelements = 0;
  2.2093 +				break;
  2.2094 +			default:
  2.2095 +				set_mbox_xfer_addr (megaCfg, pScb, mbox,
  2.2096 +						    FROMTO_DEVICE);
  2.2097 +				mbox->numsgelements = 0;
  2.2098 +				break;
  2.2099 +			}	/*switch */
  2.2100 +			break;
  2.2101 +		default:
  2.2102 +			set_mbox_xfer_addr (megaCfg, pScb, mbox, FROMTO_DEVICE);
  2.2103 +			mbox->numsgelements = 0;
  2.2104 +			break;
  2.2105 +		}
  2.2106 +	} else {
  2.2107 +
  2.2108 +		mbox->numsgelements = mega_build_sglist (megaCfg, pScb,
  2.2109 +							 (u32 *) & mbox->
  2.2110 +							 xferaddr,
  2.2111 +							 (u32 *) & seg);
  2.2112 +
  2.2113 +		/* Handling some of the fw special commands */
  2.2114 +		switch (data[0]) {
  2.2115 +		case 6:	/* START_DEV */
  2.2116 +			mbox->xferaddr = *((u32 *) & data[i + 6]);
  2.2117 +			break;
  2.2118 +		default:
  2.2119 +			break;
  2.2120 +		}
  2.2121 +
  2.2122 +		for (i = 0; i < (SCpnt->request_bufflen - 6); i++) {
  2.2123 +			data[i] = data[i + 6];
  2.2124 +		}
  2.2125 +	}
  2.2126 +
  2.2127 +	return (pScb);
  2.2128 +}
  2.2129 +
  2.2130 +
  2.2131 +static void mega_build_kernel_sg (char *barea, ulong xfersize, mega_scb * pScb, mega_ioctl_mbox * mbox)
  2.2132 +{
  2.2133 +	ulong i, buffer_area, len, end, end_page, x, idx = 0;
  2.2134 +
  2.2135 +	buffer_area = (ulong) barea;
  2.2136 +	i = buffer_area;
  2.2137 +	end = buffer_area + xfersize;
  2.2138 +	end_page = (end) & ~(PAGE_SIZE - 1);
  2.2139 +
  2.2140 +	do {
  2.2141 +		len = PAGE_SIZE - (i % PAGE_SIZE);
  2.2142 +		x = pScb->sgList[idx].address =
  2.2143 +		    virt_to_bus ((volatile void *) i);
  2.2144 +		pScb->sgList[idx].length = len;
  2.2145 +		i += len;
  2.2146 +		idx++;
  2.2147 +	} while (i < end_page);
  2.2148 +
  2.2149 +	if ((end - i) < 0) {
  2.2150 +		printk ("megaraid:Error in user address\n");
  2.2151 +	}
  2.2152 +
  2.2153 +	if (end - i) {
  2.2154 +		pScb->sgList[idx].address = virt_to_bus ((volatile void *) i);
  2.2155 +		pScb->sgList[idx].length = end - i;
  2.2156 +		idx++;
  2.2157 +	}
  2.2158 +	mbox->xferaddr = virt_to_bus (pScb->sgList);
  2.2159 +	mbox->numsgelements = idx;
  2.2160 +}
  2.2161 +#endif
  2.2162 +
  2.2163 +
  2.2164 +#if DEBUG
  2.2165 +static unsigned int cum_time = 0;
  2.2166 +static unsigned int cum_time_cnt = 0;
  2.2167 +
  2.2168 +static void showMbox (mega_scb * pScb)
  2.2169 +{
  2.2170 +	mega_mailbox *mbox;
  2.2171 +
  2.2172 +	if (pScb == NULL)
  2.2173 +		return;
  2.2174 +
  2.2175 +	mbox = (mega_mailbox *) pScb->mboxData;
  2.2176 +	printk ("%u cmd:%x id:%x #scts:%x lba:%x addr:%x logdrv:%x #sg:%x\n",
  2.2177 +		pScb->SCpnt->pid,
  2.2178 +		mbox->cmd, mbox->cmdid, mbox->numsectors,
  2.2179 +		mbox->lba, mbox->xferaddr, mbox->logdrv, mbox->numsgelements);
  2.2180 +}
  2.2181 +
  2.2182 +#endif
  2.2183 +
  2.2184 +/*--------------------------------------------------------------------
  2.2185 + * Interrupt service routine
  2.2186 + *--------------------------------------------------------------------*/
  2.2187 +static void megaraid_isr (int irq, void *devp, struct pt_regs *regs)
  2.2188 +{
  2.2189 +	IO_LOCK_T;
  2.2190 +	mega_host_config * megaCfg;
  2.2191 +	u_char byte, idx, sIdx, tmpBox[MAILBOX_SIZE];
  2.2192 +	u32 dword = 0;
  2.2193 +	mega_mailbox *mbox;
  2.2194 +	mega_scb *pScb;
  2.2195 +	u_char qCnt, qStatus;
  2.2196 +	u_char completed[MAX_FIRMWARE_STATUS];
  2.2197 +	Scsi_Cmnd *SCpnt;
  2.2198 +
  2.2199 +	megaCfg = (mega_host_config *) devp;
  2.2200 +	mbox = (mega_mailbox *) tmpBox;
  2.2201 +
  2.2202 +	if (megaCfg->host->irq == irq) {
  2.2203 +		if (megaCfg->flag & IN_ISR) {
  2.2204 +			TRACE (("ISR called reentrantly!!\n"));
  2.2205 +			printk ("ISR called reentrantly!!\n");
  2.2206 +		}
  2.2207 +		megaCfg->flag |= IN_ISR;
  2.2208 +
  2.2209 +		if (mega_busyWaitMbox (megaCfg)) {
  2.2210 +			printk (KERN_WARNING "Error: mailbox busy in isr!\n");
  2.2211 +		}
  2.2212 +
  2.2213 +		/* Check if a valid interrupt is pending */
  2.2214 +		if (megaCfg->flag & BOARD_QUARTZ) {
  2.2215 +			dword = RDOUTDOOR (megaCfg);
  2.2216 +			if (dword != 0x10001234) {
  2.2217 +				/* Spurious interrupt */
  2.2218 +				megaCfg->flag &= ~IN_ISR;
  2.2219 +				return;
  2.2220 +			}
  2.2221 +		} else {
  2.2222 +			byte = READ_PORT (megaCfg->host->io_port, INTR_PORT);
  2.2223 +			if ((byte & VALID_INTR_BYTE) == 0) {
  2.2224 +				/* Spurious interrupt */
  2.2225 +				megaCfg->flag &= ~IN_ISR;
  2.2226 +				return;
  2.2227 +			}
  2.2228 +			WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);
  2.2229 +		}
  2.2230 +
  2.2231 +		for (idx = 0; idx < MAX_FIRMWARE_STATUS; idx++)
  2.2232 +			completed[idx] = 0;
  2.2233 +
  2.2234 +		IO_LOCK;
  2.2235 +
  2.2236 +		megaCfg->nInterrupts++;
  2.2237 +		qCnt = 0xff;
  2.2238 +		while ((qCnt = megaCfg->mbox->numstatus) == 0xFF) ;
  2.2239 +
  2.2240 +		qStatus = 0xff;
  2.2241 +		while ((qStatus = megaCfg->mbox->status) == 0xFF) ;
  2.2242 +
  2.2243 +		/* Get list of completed requests */
  2.2244 +		for (idx = 0; idx < qCnt; idx++) {
  2.2245 +			while ((sIdx = megaCfg->mbox->completed[idx]) == 0xFF) {
  2.2246 +				printk ("p");
  2.2247 +			}
  2.2248 +			completed[idx] = sIdx;
  2.2249 +			sIdx = 0xFF;
  2.2250 +		}
  2.2251 +
  2.2252 +		if (megaCfg->flag & BOARD_QUARTZ) {
  2.2253 +			WROUTDOOR (megaCfg, dword);
  2.2254 +			/* Acknowledge interrupt */
  2.2255 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.2256 +			/* In this case mbox contains physical address */
  2.2257 +#if 0
  2.2258 +			WRINDOOR (megaCfg, megaCfg->adjdmahandle64 | 0x2);
  2.2259 +#else
  2.2260 +			WRINDOOR (megaCfg, 0x2);
  2.2261 +#endif
  2.2262 +
  2.2263 +#else
  2.2264 +
  2.2265 +#if 0
  2.2266 +			WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2);
  2.2267 +#else
  2.2268 +			WRINDOOR (megaCfg, 0x2);
  2.2269 +#endif
  2.2270 +
  2.2271 +#endif
  2.2272 +
  2.2273 +#if 0
  2.2274 +			while (RDINDOOR (megaCfg) & 0x02) ;
  2.2275 +#endif
  2.2276 +		} else {
  2.2277 +			CLEAR_INTR (megaCfg->host->io_port);
  2.2278 +		}
  2.2279 +
  2.2280 +#if DEBUG
  2.2281 +		if (qCnt >= MAX_FIRMWARE_STATUS) {
  2.2282 +			printk ("megaraid_isr: cmplt=%d ", qCnt);
  2.2283 +		}
  2.2284 +#endif
  2.2285 +
  2.2286 +		for (idx = 0; idx < qCnt; idx++) {
  2.2287 +			sIdx = completed[idx];
  2.2288 +			if ((sIdx > 0) && (sIdx <= MAX_COMMANDS)) {
  2.2289 +				pScb = &megaCfg->scbList[sIdx - 1];
  2.2290 +
  2.2291 +				/* ASSERT(pScb->state == SCB_ISSUED); */
  2.2292 +
  2.2293 +#if DEBUG
  2.2294 +				if (((jiffies) - pScb->isrcount) > maxCmdTime) {
  2.2295 +					maxCmdTime = (jiffies) - pScb->isrcount;
  2.2296 +					printk
  2.2297 +					    ("megaraid_isr : cmd time = %u\n",
  2.2298 +					     maxCmdTime);
  2.2299 +				}
  2.2300 +#endif
  2.2301 +				/*
  2.2302 +				 * Assuming that the scsi command, for which 
  2.2303 +				 * an abort request was received earlier, has 
  2.2304 +				 * completed.
  2.2305 +				 */
  2.2306 +				if (pScb->state == SCB_ABORTED) {
  2.2307 +					SCpnt = pScb->SCpnt;
  2.2308 +				}
  2.2309 +				if (pScb->state == SCB_RESET) {
  2.2310 +					SCpnt = pScb->SCpnt;
  2.2311 +					mega_freeSCB (megaCfg, pScb);
  2.2312 +					SCpnt->result = (DID_RESET << 16);
  2.2313 +					if (megaCfg->qCompletedH == NULL) {
  2.2314 +						megaCfg->qCompletedH =
  2.2315 +						    megaCfg->qCompletedT =
  2.2316 +						    SCpnt;
  2.2317 +					} else {
  2.2318 +						megaCfg->qCompletedT->
  2.2319 +						    host_scribble =
  2.2320 +						    (unsigned char *) SCpnt;
  2.2321 +						megaCfg->qCompletedT = SCpnt;
  2.2322 +					}
  2.2323 +					megaCfg->qCompletedT->host_scribble =
  2.2324 +					    (unsigned char *) NULL;
  2.2325 +					megaCfg->qCcnt++;
  2.2326 +					continue;
  2.2327 +				}
  2.2328 +
  2.2329 +				/* We don't want the ISR routine to touch M_RD_IOCTL_CMD_NEW commands, so
  2.2330 +				 * don't mark them as complete, instead we pop their semaphore so
  2.2331 +				 * that the queue routine can finish them off
  2.2332 +				 */
  2.2333 +				if (pScb->SCpnt->cmnd[0] == M_RD_IOCTL_CMD_NEW) {
  2.2334 +					/* save the status byte for the queue routine to use */
  2.2335 +					pScb->SCpnt->result = qStatus;
  2.2336 +#if XENO_KILLED
  2.2337 +					up (&pScb->ioctl_sem);
  2.2338 +#endif
  2.2339 +				} else {
  2.2340 +					/* Mark command as completed */
  2.2341 +					mega_cmd_done (megaCfg, pScb, qStatus);
  2.2342 +				}
  2.2343 +			} else {
  2.2344 +				printk
  2.2345 +				    ("megaraid: wrong cmd id completed from firmware:id=%x\n",
  2.2346 +				     sIdx);
  2.2347 +			}
  2.2348 +		}
  2.2349 +
  2.2350 +		mega_rundoneq (megaCfg);
  2.2351 +
  2.2352 +		megaCfg->flag &= ~IN_ISR;
  2.2353 +		/* Loop through any pending requests */
  2.2354 +		mega_runpendq (megaCfg);
  2.2355 +		IO_UNLOCK;
  2.2356 +
  2.2357 +	}
  2.2358 +
  2.2359 +}
  2.2360 +
  2.2361 +/*==================================================*/
  2.2362 +/* Wait until the controller's mailbox is available */
  2.2363 +/*==================================================*/
  2.2364 +
  2.2365 +static int mega_busyWaitMbox (mega_host_config * megaCfg)
  2.2366 +{
  2.2367 +	mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox;
  2.2368 +	long counter;
  2.2369 +
  2.2370 +	for (counter = 0; counter < 10000; counter++) {
  2.2371 +		if (!mbox->busy) {
  2.2372 +			return 0;
  2.2373 +		}
  2.2374 +		udelay (100);
  2.2375 +		barrier ();
  2.2376 +	}
  2.2377 +	return -1;		/* give up after 1 second */
  2.2378 +}
  2.2379 +
  2.2380 +/*=====================================================
  2.2381 + * Post a command to the card
  2.2382 + *
  2.2383 + * Arguments:
  2.2384 + *   mega_host_config *megaCfg - Controller structure
  2.2385 + *   u_char *mboxData - Mailbox area, 16 bytes
  2.2386 + *   mega_scb *pScb   - SCB posting (or NULL if N/A)
  2.2387 + *   int intr         - if 1, interrupt, 0 is blocking
  2.2388 + * Return Value: (added on 7/26 for 40ld/64bit)
  2.2389 + *   -1: the command was not actually issued out
  2.2390 + *   other cases:
  2.2391 + *     intr==0, return ScsiStatus, i.e. mbox->status
  2.2392 + *     intr==1, return 0
  2.2393 + *=====================================================
  2.2394 + */
  2.2395 +static int megaIssueCmd (mega_host_config * megaCfg, u_char * mboxData, 
  2.2396 +		mega_scb * pScb, int intr)
  2.2397 +{
  2.2398 +	volatile mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox;
  2.2399 +
  2.2400 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.2401 +	volatile mega_mailbox64 *mbox64 = (mega_mailbox64 *) megaCfg->mbox64;
  2.2402 +#endif
  2.2403 +
  2.2404 +	u_char byte;
  2.2405 +
  2.2406 +#ifdef __LP64__
  2.2407 +	u64 phys_mbox;
  2.2408 +#else
  2.2409 +	u32 phys_mbox;
  2.2410 +#endif
  2.2411 +	u8 retval = -1;
  2.2412 +
  2.2413 +	mboxData[0x1] = (pScb ? pScb->idx + 1 : 0xFE);	/* Set cmdid */
  2.2414 +	mboxData[0xF] = 1;	/* Set busy */
  2.2415 +
  2.2416 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.2417 +	/* In this case mbox contains physical address */
  2.2418 +	phys_mbox = megaCfg->adjdmahandle64;
  2.2419 +#else
  2.2420 +	phys_mbox = virt_to_bus (megaCfg->mbox);
  2.2421 +#endif
  2.2422 +
  2.2423 +#if DEBUG
  2.2424 +	ShowMbox (pScb);
  2.2425 +#endif
  2.2426 +
  2.2427 +	/* Wait until mailbox is free */
  2.2428 +	if (mega_busyWaitMbox (megaCfg)) {
  2.2429 +		printk ("Blocked mailbox......!!\n");
  2.2430 +		udelay (1000);
  2.2431 +
  2.2432 +#if DEBUG
  2.2433 +		showMbox (pLastScb);
  2.2434 +#endif
  2.2435 +
  2.2436 +		/* Abort command */
  2.2437 +		if (pScb == NULL) {
  2.2438 +			TRACE (("NULL pScb in megaIssue\n"));
  2.2439 +			printk ("NULL pScb in megaIssue\n");
  2.2440 +		}
  2.2441 +		mega_cmd_done (megaCfg, pScb, 0x08);
  2.2442 +		return -1;
  2.2443 +	}
  2.2444 +
  2.2445 +	pLastScb = pScb;
  2.2446 +
  2.2447 +	/* Copy mailbox data into host structure */
  2.2448 +	megaCfg->mbox64->xferSegment_lo = 0;
  2.2449 +	megaCfg->mbox64->xferSegment_hi = 0;
  2.2450 +
  2.2451 +	memcpy ((char *) mbox, mboxData, 16);
  2.2452 +
  2.2453 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.2454 +	switch (mboxData[0]) {
  2.2455 +	case MEGA_MBOXCMD_LREAD64:
  2.2456 +	case MEGA_MBOXCMD_LWRITE64:
  2.2457 +		mbox64->xferSegment_lo = mbox->xferaddr;
  2.2458 +		mbox64->xferSegment_hi = 0;
  2.2459 +		mbox->xferaddr = 0xFFFFFFFF;
  2.2460 +		break;
  2.2461 +	}
  2.2462 +#endif
  2.2463 +
  2.2464 +	/* Kick IO */
  2.2465 +	if (intr) {
  2.2466 +		/* Issue interrupt (non-blocking) command */
  2.2467 +		if (megaCfg->flag & BOARD_QUARTZ) {
  2.2468 +			mbox->mraid_poll = 0;
  2.2469 +			mbox->mraid_ack = 0;
  2.2470 +
  2.2471 +			WRINDOOR (megaCfg, phys_mbox | 0x1);
  2.2472 +		} else {
  2.2473 +			ENABLE_INTR (megaCfg->host->io_port);
  2.2474 +			ISSUE_COMMAND (megaCfg->host->io_port);
  2.2475 +		}
  2.2476 +		pScb->state = SCB_ISSUED;
  2.2477 +
  2.2478 +		retval = 0;
  2.2479 +	} else {		/* Issue non-ISR (blocking) command */
  2.2480 +		disable_irq (megaCfg->host->irq);
  2.2481 +		if (megaCfg->flag & BOARD_QUARTZ) {
  2.2482 +			mbox->mraid_poll = 0;
  2.2483 +			mbox->mraid_ack = 0;
  2.2484 +			mbox->numstatus = 0xFF;
  2.2485 +			mbox->status = 0xFF;
  2.2486 +			WRINDOOR (megaCfg, phys_mbox | 0x1);
  2.2487 +
  2.2488 +			while (mbox->numstatus == 0xFF) ;
  2.2489 +			while (mbox->status == 0xFF) ;
  2.2490 +			while (mbox->mraid_poll != 0x77) ;
  2.2491 +			mbox->mraid_poll = 0;
  2.2492 +			mbox->mraid_ack = 0x77;
  2.2493 +
  2.2494 +			/* while ((cmdDone = RDOUTDOOR (megaCfg)) != 0x10001234);
  2.2495 +			   WROUTDOOR (megaCfg, cmdDone); */
  2.2496 +
  2.2497 +			if (pScb) {
  2.2498 +				mega_cmd_done (megaCfg, pScb, mbox->status);
  2.2499 +			}
  2.2500 +
  2.2501 +			WRINDOOR (megaCfg, phys_mbox | 0x2);
  2.2502 +			while (RDINDOOR (megaCfg) & 0x2) ;
  2.2503 +
  2.2504 +		} else {
  2.2505 +			DISABLE_INTR (megaCfg->host->io_port);
  2.2506 +			ISSUE_COMMAND (megaCfg->host->io_port);
  2.2507 +
  2.2508 +			while (!
  2.2509 +			       ((byte =
  2.2510 +				 READ_PORT (megaCfg->host->io_port,
  2.2511 +					    INTR_PORT)) & INTR_VALID)) ;
  2.2512 +			WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);
  2.2513 +
  2.2514 +			ENABLE_INTR (megaCfg->host->io_port);
  2.2515 +			CLEAR_INTR (megaCfg->host->io_port);
  2.2516 +
  2.2517 +			if (pScb) {
  2.2518 +				mega_cmd_done (megaCfg, pScb, mbox->status);
  2.2519 +			} else {
  2.2520 +				TRACE (("Error: NULL pScb!\n"));
  2.2521 +			}
  2.2522 +		}
  2.2523 +		enable_irq (megaCfg->host->irq);
  2.2524 +		retval = mbox->status;
  2.2525 +	}
  2.2526 +#if DEBUG
  2.2527 +	while (mega_busyWaitMbox (megaCfg)) {
  2.2528 +		printk(KERN_ERR "Blocked mailbox on exit......!\n");
  2.2529 +		udelay (1000);
  2.2530 +	}
  2.2531 +#endif
  2.2532 +
  2.2533 +	return retval;
  2.2534 +}
  2.2535 +
  2.2536 +/*-------------------------------------------------------------------
  2.2537 + * Copies data to SGLIST
  2.2538 + *-------------------------------------------------------------------*/
  2.2539 +/* Note:
  2.2540 +	For 64 bit cards, we need a minimum of one SG element for read/write
  2.2541 +*/
  2.2542 +
  2.2543 +static int
  2.2544 +mega_build_sglist (mega_host_config * megaCfg, mega_scb * scb,
  2.2545 +		   u32 * buffer, u32 * length)
  2.2546 +{
  2.2547 +	struct scatterlist *sgList;
  2.2548 +	int idx;
  2.2549 +
  2.2550 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.2551 +	int sgcnt;
  2.2552 +#endif
  2.2553 +
  2.2554 +	mega_mailbox *mbox = NULL;
  2.2555 +
  2.2556 +	mbox = (mega_mailbox *) scb->mboxData;
  2.2557 +	/* Scatter-gather not used */
  2.2558 +	if (scb->SCpnt->use_sg == 0) {
  2.2559 +
  2.2560 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.2561 +		scb->dma_h_bulkdata = pci_map_single (megaCfg->dev,
  2.2562 +				      scb->SCpnt->request_buffer,
  2.2563 +				      scb->SCpnt->request_bufflen,
  2.2564 +				      scb->dma_direction);
  2.2565 +		/* We need to handle special commands like READ64, WRITE64
  2.2566 +		   as they need a minimum of 1 SG irrespective of actually SG
  2.2567 +		 */
  2.2568 +		if ((megaCfg->flag & BOARD_64BIT) &&
  2.2569 +		    ((mbox->cmd == MEGA_MBOXCMD_LREAD64) ||
  2.2570 +		     (mbox->cmd == MEGA_MBOXCMD_LWRITE64))) {
  2.2571 +			scb->sg64List[0].address = scb->dma_h_bulkdata;
  2.2572 +			scb->sg64List[0].length = scb->SCpnt->request_bufflen;
  2.2573 +			*buffer = scb->dma_sghandle64;
  2.2574 +			*length = (u32)scb->SCpnt->request_bufflen;
  2.2575 +			scb->sglist_count = 1;
  2.2576 +			return 1;
  2.2577 +		} else {
  2.2578 +			*buffer = scb->dma_h_bulkdata;
  2.2579 +			*length = (u32) scb->SCpnt->request_bufflen;
  2.2580 +		}
  2.2581 +#else
  2.2582 +		*buffer = virt_to_bus (scb->SCpnt->request_buffer);
  2.2583 +		*length = (u32) scb->SCpnt->request_bufflen;
  2.2584 +#endif
  2.2585 +		return 0;
  2.2586 +	}
  2.2587 +
  2.2588 +	sgList = (struct scatterlist *) scb->SCpnt->request_buffer;
  2.2589 +#if 0
  2.2590 +	if (scb->SCpnt->use_sg == 1) {
  2.2591 +
  2.2592 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.2593 +		scb->dma_h_bulkdata = pci_map_single (megaCfg->dev,
  2.2594 +				      sgList[0].address,
  2.2595 +				      sgList[0].length, scb->dma_direction);
  2.2596 +
  2.2597 +		if ((megaCfg->flag & BOARD_64BIT) &&
  2.2598 +		    ((mbox->cmd == MEGA_MBOXCMD_LREAD64) ||
  2.2599 +		     (mbox->cmd == MEGA_MBOXCMD_LWRITE64))) {
  2.2600 +			scb->sg64List[0].address = scb->dma_h_bulkdata;
  2.2601 +			scb->sg64List[0].length = scb->SCpnt->request_bufflen;
  2.2602 +			*buffer = scb->dma_sghandle64;
  2.2603 +			*length = 0;
  2.2604 +			scb->sglist_count = 1;
  2.2605 +			return 1;
  2.2606 +		} else {
  2.2607 +			*buffer = scb->dma_h_bulkdata;
  2.2608 +			*length = (u32) sgList[0].length;
  2.2609 +		}
  2.2610 +#else
  2.2611 +		*buffer = virt_to_bus (sgList[0].address);
  2.2612 +		*length = (u32) sgList[0].length;
  2.2613 +#endif
  2.2614 +
  2.2615 +		return 0;
  2.2616 +	}
  2.2617 +#endif
  2.2618 +	/* Copy Scatter-Gather list info into controller structure */
  2.2619 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.2620 +	sgcnt = pci_map_sg (megaCfg->dev,
  2.2621 +			    sgList, scb->SCpnt->use_sg, scb->dma_direction);
  2.2622 +
  2.2623 +	/* Determine the validity of the new count  */
  2.2624 +	if (sgcnt == 0)
  2.2625 +		printk ("pci_map_sg returned zero!!! ");
  2.2626 +
  2.2627 +	for (idx = 0; idx < sgcnt; idx++, sgList++) {
  2.2628 +
  2.2629 +		if ((megaCfg->flag & BOARD_64BIT) &&
  2.2630 +		    ((mbox->cmd == MEGA_MBOXCMD_LREAD64) ||
  2.2631 +		     (mbox->cmd == MEGA_MBOXCMD_LWRITE64))) {
  2.2632 +			scb->sg64List[idx].address = sg_dma_address (sgList);
  2.2633 +			scb->sg64List[idx].length = sg_dma_len (sgList);
  2.2634 +		} else {
  2.2635 +			scb->sgList[idx].address = sg_dma_address (sgList);
  2.2636 +			scb->sgList[idx].length = sg_dma_len (sgList);
  2.2637 +		}
  2.2638 +
  2.2639 +	}
  2.2640 +
  2.2641 +#else
  2.2642 +	for (idx = 0; idx < scb->SCpnt->use_sg; idx++) {
  2.2643 +		scb->sgList[idx].address = virt_to_bus (sgList[idx].address);
  2.2644 +		scb->sgList[idx].length = (u32) sgList[idx].length;
  2.2645 +	}
  2.2646 +#endif
  2.2647 +
  2.2648 +	/* Reset pointer and length fields */
  2.2649 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.2650 +	*buffer = scb->dma_sghandle64;
  2.2651 +	scb->sglist_count = scb->SCpnt->use_sg;
  2.2652 +#else
  2.2653 +	*buffer = virt_to_bus (scb->sgList);
  2.2654 +#endif
  2.2655 +
  2.2656 +#if 0
  2.2657 +	*length = 0;
  2.2658 +#endif
  2.2659 +	/*
  2.2660 +	 * For passthru command, dataxferlen must be set, even for commands with a
  2.2661 +	 * sg list
  2.2662 +	 */
  2.2663 +	*length = (u32)scb->SCpnt->request_bufflen;
  2.2664 +
  2.2665 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.2666 +	/* Return count of SG requests */
  2.2667 +	return sgcnt;
  2.2668 +#else
  2.2669 +	/* Return count of SG requests */
  2.2670 +	return scb->SCpnt->use_sg;
  2.2671 +#endif
  2.2672 +}
  2.2673 +
  2.2674 +/*--------------------------------------------------------------------
  2.2675 + * Initializes the address of the controller's mailbox register
  2.2676 + *  The mailbox register is used to issue commands to the card.
  2.2677 + *  Format of the mailbox area:
  2.2678 + *   00 01 command
  2.2679 + *   01 01 command id
  2.2680 + *   02 02 # of sectors
  2.2681 + *   04 04 logical bus address
  2.2682 + *   08 04 physical buffer address
  2.2683 + *   0C 01 logical drive #
  2.2684 + *   0D 01 length of scatter/gather list
  2.2685 + *   0E 01 reserved
  2.2686 + *   0F 01 mailbox busy
  2.2687 + *   10 01 numstatus byte
  2.2688 + *   11 01 status byte
  2.2689 + *--------------------------------------------------------------------*/
  2.2690 +static int
  2.2691 +mega_register_mailbox (mega_host_config * megaCfg, u32 paddr)
  2.2692 +{
  2.2693 +	/* align on 16-byte boundary */
  2.2694 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.2695 +	megaCfg->mbox = &megaCfg->mailbox64ptr->mailbox;
  2.2696 +#else
  2.2697 +	megaCfg->mbox = &megaCfg->mailbox64.mailbox;
  2.2698 +#endif
  2.2699 +
  2.2700 +#ifdef __LP64__
  2.2701 +	megaCfg->mbox = (mega_mailbox *) ((((u64) megaCfg->mbox) + 16) & ((u64) (-1) ^ 0x0F));
  2.2702 +	megaCfg->adjdmahandle64 = (megaCfg->dma_handle64 + 16) & ((u64) (-1) ^ 0x0F);
  2.2703 +	megaCfg->mbox64 = (mega_mailbox64 *) ((u_char *) megaCfg->mbox - sizeof (u64));
  2.2704 +	paddr = (paddr + 4 + 16) & ((u64) (-1) ^ 0x0F);
  2.2705 +#else
  2.2706 +	megaCfg->mbox
  2.2707 +	    = (mega_mailbox *) ((((u32) megaCfg->mbox) + 16) & 0xFFFFFFF0);
  2.2708 +
  2.2709 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.2710 +	megaCfg->adjdmahandle64 = ((megaCfg->dma_handle64 + 16) & 0xFFFFFFF0);
  2.2711 +#endif
  2.2712 +
  2.2713 +	megaCfg->mbox64 = (mega_mailbox64 *) ((u_char *) megaCfg->mbox - 8);
  2.2714 +	paddr = (paddr + 4 + 16) & 0xFFFFFFF0;
  2.2715 +#endif
  2.2716 +
  2.2717 +	/* Register mailbox area with the firmware */
  2.2718 +	if (!(megaCfg->flag & BOARD_QUARTZ)) {
  2.2719 +		WRITE_PORT (megaCfg->host->io_port, MBOX_PORT0, paddr & 0xFF);
  2.2720 +		WRITE_PORT (megaCfg->host->io_port, MBOX_PORT1,
  2.2721 +			    (paddr >> 8) & 0xFF);
  2.2722 +		WRITE_PORT (megaCfg->host->io_port, MBOX_PORT2,
  2.2723 +			    (paddr >> 16) & 0xFF);
  2.2724 +		WRITE_PORT (megaCfg->host->io_port, MBOX_PORT3,
  2.2725 +			    (paddr >> 24) & 0xFF);
  2.2726 +		WRITE_PORT (megaCfg->host->io_port, ENABLE_MBOX_REGION,
  2.2727 +			    ENABLE_MBOX_BYTE);
  2.2728 +
  2.2729 +		CLEAR_INTR (megaCfg->host->io_port);
  2.2730 +		ENABLE_INTR (megaCfg->host->io_port);
  2.2731 +	}
  2.2732 +	return 0;
  2.2733 +}
  2.2734 +
  2.2735 +/*---------------------------------------------------------------------------
  2.2736 + * mega_Convert8ldTo40ld() -- takes all info in AdapterInquiry structure and
  2.2737 + * puts it into ProductInfo and Enquiry3 structures for later use
  2.2738 + *---------------------------------------------------------------------------*/
  2.2739 +static void mega_Convert8ldTo40ld (mega_RAIDINQ * inquiry,
  2.2740 +		       mega_Enquiry3 * enquiry3,
  2.2741 +		       megaRaidProductInfo * productInfo)
  2.2742 +{
  2.2743 +	int i;
  2.2744 +
  2.2745 +	productInfo->MaxConcCmds = inquiry->AdpInfo.MaxConcCmds;
  2.2746 +	enquiry3->rbldRate = inquiry->AdpInfo.RbldRate;
  2.2747 +	productInfo->SCSIChanPresent = inquiry->AdpInfo.ChanPresent;
  2.2748 +
  2.2749 +	for (i = 0; i < 4; i++) {
  2.2750 +		productInfo->FwVer[i] = inquiry->AdpInfo.FwVer[i];
  2.2751 +		productInfo->BiosVer[i] = inquiry->AdpInfo.BiosVer[i];
  2.2752 +	}
  2.2753 +	enquiry3->cacheFlushInterval = inquiry->AdpInfo.CacheFlushInterval;
  2.2754 +	productInfo->DramSize = inquiry->AdpInfo.DramSize;
  2.2755 +
  2.2756 +	enquiry3->numLDrv = inquiry->LogdrvInfo.NumLDrv;
  2.2757 +
  2.2758 +	for (i = 0; i < MAX_LOGICAL_DRIVES; i++) {
  2.2759 +		enquiry3->lDrvSize[i] = inquiry->LogdrvInfo.LDrvSize[i];
  2.2760 +		enquiry3->lDrvProp[i] = inquiry->LogdrvInfo.LDrvProp[i];
  2.2761 +		enquiry3->lDrvState[i]
  2.2762 +		    = inquiry->LogdrvInfo.LDrvState[i];
  2.2763 +	}
  2.2764 +
  2.2765 +	for (i = 0; i < (MAX_PHYSICAL_DRIVES); i++) {
  2.2766 +		enquiry3->pDrvState[i]
  2.2767 +		    = inquiry->PhysdrvInfo.PDrvState[i];
  2.2768 +	}
  2.2769 +}
  2.2770 +
  2.2771 +/*-------------------------------------------------------------------
  2.2772 + * Issue an adapter info query to the controller
  2.2773 + *-------------------------------------------------------------------*/
  2.2774 +static int mega_i_query_adapter (mega_host_config * megaCfg)
  2.2775 +{
  2.2776 +	mega_Enquiry3 *enquiry3Pnt;
  2.2777 +	mega_mailbox *mbox;
  2.2778 +	u_char mboxData[16];
  2.2779 +
  2.2780 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.2781 +	dma_addr_t raid_inq_dma_handle = 0, prod_info_dma_handle = 0, enquiry3_dma_handle = 0;
  2.2782 +#endif
  2.2783 +	u8 retval;
  2.2784 +
  2.2785 +	/* Initialize adapter inquiry mailbox */
  2.2786 +
  2.2787 +	mbox = (mega_mailbox *) mboxData;
  2.2788 +
  2.2789 +	memset ((void *) megaCfg->mega_buffer, 0,
  2.2790 +		sizeof (megaCfg->mega_buffer));
  2.2791 +	memset (mbox, 0, 16);
  2.2792 +
  2.2793 +/*
  2.2794 + * Try to issue Enquiry3 command
  2.2795 + * if not succeeded, then issue MEGA_MBOXCMD_ADAPTERINQ command and
  2.2796 + * update enquiry3 structure
  2.2797 + */
  2.2798 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.2799 +	enquiry3_dma_handle = pci_map_single (megaCfg->dev,
  2.2800 +			      (void *) megaCfg->mega_buffer,
  2.2801 +			      (2 * 1024L), PCI_DMA_FROMDEVICE);
  2.2802 +
  2.2803 +	mbox->xferaddr = enquiry3_dma_handle;
  2.2804 +#else
  2.2805 +	/*Taken care */
  2.2806 +	mbox->xferaddr = virt_to_bus ((void *) megaCfg->mega_buffer);
  2.2807 +#endif
  2.2808 +
  2.2809 +	/* Initialize mailbox databuffer addr */
  2.2810 +	enquiry3Pnt = (mega_Enquiry3 *) megaCfg->mega_buffer;
  2.2811 +	/* point mega_Enguiry3 to the data buf */
  2.2812 +
  2.2813 +	mboxData[0] = FC_NEW_CONFIG;	/* i.e. mbox->cmd=0xA1 */
  2.2814 +	mboxData[2] = NC_SUBOP_ENQUIRY3;	/* i.e. 0x0F */
  2.2815 +	mboxData[3] = ENQ3_GET_SOLICITED_FULL;	/* i.e. 0x02 */
  2.2816 +
  2.2817 +	/* Issue a blocking command to the card */
  2.2818 +	if ((retval = megaIssueCmd (megaCfg, mboxData, NULL, 0)) != 0) {	/* the adapter does not support 40ld */
  2.2819 +		mega_RAIDINQ adapterInquiryData;
  2.2820 +		mega_RAIDINQ *adapterInquiryPnt = &adapterInquiryData;
  2.2821 +
  2.2822 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.2823 +		raid_inq_dma_handle = pci_map_single (megaCfg->dev,
  2.2824 +				      (void *) adapterInquiryPnt,
  2.2825 +				      sizeof (mega_RAIDINQ),
  2.2826 +				      PCI_DMA_FROMDEVICE);
  2.2827 +		mbox->xferaddr = raid_inq_dma_handle;
  2.2828 +#else
  2.2829 +		/*taken care */
  2.2830 +		mbox->xferaddr = virt_to_bus ((void *) adapterInquiryPnt);
  2.2831 +#endif
  2.2832 +
  2.2833 +		mbox->cmd = MEGA_MBOXCMD_ADAPTERINQ;	/*issue old 0x05 command to adapter */
  2.2834 +		/* Issue a blocking command to the card */ ;
  2.2835 +		retval = megaIssueCmd (megaCfg, mboxData, NULL, 0);
  2.2836 +
  2.2837 +		pci_unmap_single (megaCfg->dev,
  2.2838 +				  raid_inq_dma_handle,
  2.2839 +				  sizeof (mega_RAIDINQ), PCI_DMA_FROMDEVICE);
  2.2840 +
  2.2841 +		/*update Enquiry3 and ProductInfo structures with mega_RAIDINQ structure*/
  2.2842 +		mega_Convert8ldTo40ld (adapterInquiryPnt,
  2.2843 +				       enquiry3Pnt,
  2.2844 +				       (megaRaidProductInfo *) & megaCfg->
  2.2845 +				       productInfo);
  2.2846 +
  2.2847 +	} else {		/* adapter supports 40ld */
  2.2848 +		megaCfg->flag |= BOARD_40LD;
  2.2849 +
  2.2850 +		pci_unmap_single (megaCfg->dev,
  2.2851 +				  enquiry3_dma_handle,
  2.2852 +				  (2 * 1024L), PCI_DMA_FROMDEVICE);
  2.2853 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.2854 +/*get productInfo, which is static information and will be unchanged*/
  2.2855 +		prod_info_dma_handle
  2.2856 +		    = pci_map_single (megaCfg->dev,
  2.2857 +				      (void *) &megaCfg->productInfo,
  2.2858 +				      sizeof (megaRaidProductInfo),
  2.2859 +				      PCI_DMA_FROMDEVICE);
  2.2860 +		mbox->xferaddr = prod_info_dma_handle;
  2.2861 +#else
  2.2862 +		/*taken care */
  2.2863 +		mbox->xferaddr = virt_to_bus ((void *) &megaCfg->productInfo);
  2.2864 +#endif
  2.2865 +
  2.2866 +		mboxData[0] = FC_NEW_CONFIG;	/* i.e. mbox->cmd=0xA1 */
  2.2867 +		mboxData[2] = NC_SUBOP_PRODUCT_INFO;	/* i.e. 0x0E */
  2.2868 +
  2.2869 +		if ((retval = megaIssueCmd (megaCfg, mboxData, NULL, 0)) != 0)
  2.2870 +			printk ("megaraid: Product_info cmd failed with error: %d\n",
  2.2871 +				retval);
  2.2872 +
  2.2873 +		pci_unmap_single (megaCfg->dev,
  2.2874 +				  prod_info_dma_handle,
  2.2875 +				  sizeof (megaRaidProductInfo),
  2.2876 +				  PCI_DMA_FROMDEVICE);
  2.2877 +	}
  2.2878 +
  2.2879 +	/*
  2.2880 +	 * kernel scans the channels from 0 to <= max_channel
  2.2881 +	 */
  2.2882 +	megaCfg->host->max_channel =
  2.2883 +		megaCfg->productInfo.SCSIChanPresent + NVIRT_CHAN -1;
  2.2884 +
  2.2885 +	megaCfg->host->max_id = 16;	/* max targets per channel */
  2.2886 +
  2.2887 +	megaCfg->host->max_lun = 7;	/* Upto 7 luns for non disk devices */
  2.2888 +
  2.2889 +	megaCfg->host->cmd_per_lun = MAX_CMD_PER_LUN;
  2.2890 +
  2.2891 +	megaCfg->numldrv = enquiry3Pnt->numLDrv;
  2.2892 +	megaCfg->max_cmds = megaCfg->productInfo.MaxConcCmds;
  2.2893 +	if (megaCfg->max_cmds > MAX_COMMANDS)
  2.2894 +		megaCfg->max_cmds = MAX_COMMANDS - 1;
  2.2895 +
  2.2896 +	megaCfg->host->can_queue = megaCfg->max_cmds - 1;
  2.2897 +
  2.2898 +	/* use HP firmware and bios version encoding */
  2.2899 +	if (megaCfg->productInfo.subSystemVendorID == HP_SUBSYS_ID) {
  2.2900 +		sprintf (megaCfg->fwVer, "%c%d%d.%d%d",
  2.2901 +			 megaCfg->productInfo.FwVer[2],
  2.2902 +			 megaCfg->productInfo.FwVer[1] >> 8,
  2.2903 +			 megaCfg->productInfo.FwVer[1] & 0x0f,
  2.2904 +			 megaCfg->productInfo.FwVer[0] >> 8,
  2.2905 +			 megaCfg->productInfo.FwVer[0] & 0x0f);
  2.2906 +		sprintf (megaCfg->biosVer, "%c%d%d.%d%d",
  2.2907 +			 megaCfg->productInfo.BiosVer[2],
  2.2908 +			 megaCfg->productInfo.BiosVer[1] >> 8,
  2.2909 +			 megaCfg->productInfo.BiosVer[1] & 0x0f,
  2.2910 +			 megaCfg->productInfo.BiosVer[0] >> 8,
  2.2911 +			 megaCfg->productInfo.BiosVer[0] & 0x0f);
  2.2912 +	} else {
  2.2913 +		memcpy (megaCfg->fwVer, (char *) megaCfg->productInfo.FwVer, 4);
  2.2914 +		megaCfg->fwVer[4] = 0;
  2.2915 +
  2.2916 +		memcpy (megaCfg->biosVer, (char *) megaCfg->productInfo.BiosVer, 4);
  2.2917 +		megaCfg->biosVer[4] = 0;
  2.2918 +	}
  2.2919 +	megaCfg->support_ext_cdb = mega_support_ext_cdb(megaCfg);
  2.2920 +
  2.2921 +	printk (KERN_NOTICE "megaraid: [%s:%s] detected %d logical drives" M_RD_CRLFSTR,
  2.2922 +		megaCfg->fwVer, megaCfg->biosVer, megaCfg->numldrv);
  2.2923 +
  2.2924 +	if ( megaCfg->support_ext_cdb ) {
  2.2925 +		printk(KERN_NOTICE "megaraid: supports extended CDBs.\n");
  2.2926 +	}
  2.2927 +
  2.2928 +	/*
  2.2929 +	 * I hope that I can unmap here, reason DMA transaction is not required any more
  2.2930 +	 * after this
  2.2931 +	 */
  2.2932 +
  2.2933 +	return 0;
  2.2934 +}
  2.2935 +
  2.2936 +/*-------------------------------------------------------------------------
  2.2937 + *
  2.2938 + *                      Driver interface functions
  2.2939 + *
  2.2940 + *-------------------------------------------------------------------------*/
  2.2941 +
  2.2942 +/*----------------------------------------------------------
  2.2943 + * Returns data to be displayed in /proc/scsi/megaraid/X
  2.2944 + *----------------------------------------------------------*/
  2.2945 +#if XENO_KILLED
  2.2946 +int megaraid_proc_info (char *buffer, char **start, off_t offset,
  2.2947 +		    int length, int host_no, int inout)
  2.2948 +{
  2.2949 +	*start = buffer;
  2.2950 +	return 0;
  2.2951 +}
  2.2952 +#endif
  2.2953 +
  2.2954 +static int mega_findCard (Scsi_Host_Template * pHostTmpl,
  2.2955 +	       u16 pciVendor, u16 pciDev, long flag)
  2.2956 +{
  2.2957 +	mega_host_config *megaCfg = NULL;
  2.2958 +	struct Scsi_Host *host = NULL;
  2.2959 +	u_char pciBus, pciDevFun, megaIrq;
  2.2960 +
  2.2961 +	u16 magic;
  2.2962 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.2963 +	u32 magic64;
  2.2964 +#endif
  2.2965 +
  2.2966 +	int		i, j;
  2.2967 +
  2.2968 +#ifdef __LP64__
  2.2969 +	u64 megaBase;
  2.2970 +#else
  2.2971 +	u32 megaBase;
  2.2972 +#endif
  2.2973 +
  2.2974 +	u16 pciIdx = 0;
  2.2975 +	u16 numFound = 0;
  2.2976 +	u16 subsysid, subsysvid;
  2.2977 +#if 0
  2.2978 +	u8 mega_ch_class;
  2.2979 +#endif
  2.2980 +
  2.2981 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)	/* 0x20100 */
  2.2982 +	while (!pcibios_find_device
  2.2983 +	       (pciVendor, pciDev, pciIdx, &pciBus, &pciDevFun)) {
  2.2984 +#else
  2.2985 +
  2.2986 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)	/*0x20300 */
  2.2987 +	struct pci_dev *pdev = NULL;
  2.2988 +#else
  2.2989 +	struct pci_dev *pdev = pci_devices;
  2.2990 +#endif
  2.2991 +
  2.2992 +	while ((pdev = pci_find_device (pciVendor, pciDev, pdev))) {
  2.2993 +		if(pci_enable_device (pdev))
  2.2994 +			continue;
  2.2995 +		pciBus = pdev->bus->number;
  2.2996 +		pciDevFun = pdev->devfn;
  2.2997 +#endif
  2.2998 +		if ((flag & BOARD_QUARTZ) && (skip_id == -1)) {
  2.2999 +				if( (pciVendor == PCI_VENDOR_ID_PERC4_DI_YSTONE &&
  2.3000 +					pciDev == PCI_DEVICE_ID_PERC4_DI_YSTONE) ||
  2.3001 +					(pciVendor == PCI_VENDOR_ID_PERC4_QC_VERDE &&
  2.3002 +					pciDev == PCI_DEVICE_ID_PERC4_QC_VERDE) ) {
  2.3003 +
  2.3004 +					flag |= BOARD_64BIT;
  2.3005 +				}
  2.3006 +				else {
  2.3007 +					pcibios_read_config_word (pciBus, pciDevFun,
  2.3008 +								  PCI_CONF_AMISIG, &magic);
  2.3009 +					if ((magic != AMI_SIGNATURE)
  2.3010 +						&& (magic != AMI_SIGNATURE_471)) {
  2.3011 +						pciIdx++;
  2.3012 +						continue;	/* not an AMI board */
  2.3013 +					}
  2.3014 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.3015 +					pcibios_read_config_dword (pciBus, pciDevFun,
  2.3016 +								   PCI_CONF_AMISIG64, &magic64);
  2.3017 +
  2.3018 +					if (magic64 == AMI_64BIT_SIGNATURE)
  2.3019 +						flag |= BOARD_64BIT;
  2.3020 +#endif
  2.3021 +				}
  2.3022 +		}
  2.3023 +
  2.3024 +		/* Hmmm...Should we not make this more modularized so that in future we dont add
  2.3025 +		   for each firmware */
  2.3026 +
  2.3027 +		if (flag & BOARD_QUARTZ) {
  2.3028 +			/* Check to see if this is a Dell PERC RAID controller model 466 */
  2.3029 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)	/* 0x20100 */
  2.3030 +			pcibios_read_config_word (pciBus, pciDevFun,
  2.3031 +						  PCI_SUBSYSTEM_VENDOR_ID,
  2.3032 +						  &subsysvid);
  2.3033 +			pcibios_read_config_word (pciBus, pciDevFun,
  2.3034 +						  PCI_SUBSYSTEM_ID, &subsysid);
  2.3035 +#else
  2.3036 +			pci_read_config_word (pdev,
  2.3037 +					      PCI_SUBSYSTEM_VENDOR_ID,
  2.3038 +					      &subsysvid);
  2.3039 +			pci_read_config_word (pdev,
  2.3040 +					      PCI_SUBSYSTEM_ID, &subsysid);
  2.3041 +#endif
  2.3042 +
  2.3043 +			/*
  2.3044 +			 * If we do not find the valid subsys vendor id, refuse to load
  2.3045 +			 * the driver. This is part of PCI200X compliance
  2.3046 +			 */
  2.3047 +			if( (subsysvid != AMI_SUBSYS_ID) &&
  2.3048 +					(subsysvid != DELL_SUBSYS_ID) &&
  2.3049 +					(subsysvid != LSI_SUBSYS_ID) &&
  2.3050 +					(subsysvid != HP_SUBSYS_ID) ) continue;
  2.3051 +
  2.3052 +		}
  2.3053 +
  2.3054 +		printk (KERN_NOTICE
  2.3055 +			"megaraid: found 0x%4.04x:0x%4.04x:idx %d:bus %d:slot %d:func %d\n",
  2.3056 +			pciVendor, pciDev, pciIdx, pciBus, PCI_SLOT (pciDevFun),
  2.3057 +			PCI_FUNC (pciDevFun));
  2.3058 +		/* Read the base port and IRQ from PCI */
  2.3059 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)	/* 0x20100 */
  2.3060 +		pcibios_read_config_dword (pciBus, pciDevFun,
  2.3061 +					   PCI_BASE_ADDRESS_0,
  2.3062 +					   (u_int *) & megaBase);
  2.3063 +		pcibios_read_config_byte (pciBus, pciDevFun,
  2.3064 +					  PCI_INTERRUPT_LINE, &megaIrq);
  2.3065 +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)	/*0x20300 */
  2.3066 +		megaBase = pdev->base_address[0];
  2.3067 +		megaIrq = pdev->irq;
  2.3068 +#else
  2.3069 +
  2.3070 +		megaBase = pci_resource_start (pdev, 0);
  2.3071 +		megaIrq = pdev->irq;
  2.3072 +#endif
  2.3073 +
  2.3074 +		pciIdx++;
  2.3075 +
  2.3076 +		if (flag & BOARD_QUARTZ) {
  2.3077 +			megaBase &= PCI_BASE_ADDRESS_MEM_MASK;
  2.3078 +			megaBase = (long) ioremap (megaBase, 128);
  2.3079 +			if (!megaBase)
  2.3080 +				continue;
  2.3081 +		} else {
  2.3082 +			megaBase &= PCI_BASE_ADDRESS_IO_MASK;
  2.3083 +			megaBase += 0x10;
  2.3084 +		}
  2.3085 +
  2.3086 +		/* Initialize SCSI Host structure */
  2.3087 +		host = scsi_register (pHostTmpl, sizeof (mega_host_config));
  2.3088 +		if (!host)
  2.3089 +			goto err_unmap;
  2.3090 +
  2.3091 +		/*
  2.3092 +		 * Comment the following initialization if you know 'max_sectors' is
  2.3093 +		 * not defined for this kernel.
  2.3094 +		 * This field was introduced in Linus's kernel 2.4.7pre3 and it
  2.3095 +		 * greatly increases the IO performance - AM
  2.3096 +		 */
  2.3097 +		host->max_sectors = 1024;
  2.3098 +
  2.3099 +		scsi_set_pci_device(host, pdev);
  2.3100 +		megaCfg = (mega_host_config *) host->hostdata;
  2.3101 +		memset (megaCfg, 0, sizeof (mega_host_config));
  2.3102 +
  2.3103 +		printk (KERN_NOTICE "scsi%d : Found a MegaRAID controller at 0x%x, IRQ: %d"
  2.3104 +			M_RD_CRLFSTR, host->host_no, (u_int) megaBase, megaIrq);
  2.3105 +
  2.3106 +		if (flag & BOARD_64BIT)
  2.3107 +			printk (KERN_NOTICE "scsi%d : Enabling 64 bit support\n",
  2.3108 +				host->host_no);
  2.3109 +
  2.3110 +		/* Copy resource info into structure */
  2.3111 +		megaCfg->qCompletedH = NULL;
  2.3112 +		megaCfg->qCompletedT = NULL;
  2.3113 +		megaCfg->qPendingH = NULL;
  2.3114 +		megaCfg->qPendingT = NULL;
  2.3115 +		megaCfg->qFreeH = NULL;
  2.3116 +		megaCfg->qFreeT = NULL;
  2.3117 +		megaCfg->qFcnt = 0;
  2.3118 +		megaCfg->qPcnt = 0;
  2.3119 +		megaCfg->qCcnt = 0;
  2.3120 +		megaCfg->lock_free = SPIN_LOCK_UNLOCKED;
  2.3121 +		megaCfg->lock_pend = SPIN_LOCK_UNLOCKED;
  2.3122 +		megaCfg->lock_scsicmd = SPIN_LOCK_UNLOCKED;
  2.3123 +		megaCfg->flag = flag;
  2.3124 +		megaCfg->int_qh = NULL;
  2.3125 +		megaCfg->int_qt = NULL;
  2.3126 +		megaCfg->int_qlen = 0;
  2.3127 +
  2.3128 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.3129 +		megaCfg->dev = pdev;
  2.3130 +#endif
  2.3131 +		megaCfg->host = host;
  2.3132 +		megaCfg->base = megaBase;
  2.3133 +		megaCfg->host->irq = megaIrq;
  2.3134 +		megaCfg->host->io_port = megaBase;
  2.3135 +		megaCfg->host->n_io_port = 16;
  2.3136 +		megaCfg->host->unique_id = (pciBus << 8) | pciDevFun;
  2.3137 +		megaCtlrs[numCtlrs] = megaCfg;
  2.3138 +
  2.3139 +		if (!(flag & BOARD_QUARTZ)) {
  2.3140 +
  2.3141 +			/* Request our IO Range */
  2.3142 +			if( !request_region(megaBase, 16, "megaraid") )
  2.3143 +				goto err_unregister;
  2.3144 +		}
  2.3145 +
  2.3146 +		/* Request our IRQ */
  2.3147 +		if (request_irq (megaIrq, megaraid_isr, SA_SHIRQ,
  2.3148 +				 "megaraid", megaCfg)) {
  2.3149 +			printk (KERN_WARNING
  2.3150 +				"megaraid: Couldn't register IRQ %d!\n",
  2.3151 +				megaIrq);
  2.3152 +			goto err_release;
  2.3153 +		}
  2.3154 +
  2.3155 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.3156 +		/*
  2.3157 +		 * unmap while releasing the driver, Is it required to be 
  2.3158 +		 * PCI_DMA_BIDIRECTIONAL 
  2.3159 +		*/
  2.3160 +
  2.3161 +		megaCfg->mailbox64ptr
  2.3162 +		    = pci_alloc_consistent (megaCfg->dev,
  2.3163 +					    sizeof (mega_mailbox64),
  2.3164 +					    &(megaCfg->dma_handle64));
  2.3165 +
  2.3166 +		mega_register_mailbox (megaCfg,
  2.3167 +				       virt_to_bus ((void *) megaCfg->
  2.3168 +						    mailbox64ptr));
  2.3169 +#else
  2.3170 +		mega_register_mailbox (megaCfg,
  2.3171 +				       virt_to_bus ((void *) &megaCfg->
  2.3172 +						    mailbox64));
  2.3173 +#endif
  2.3174 +
  2.3175 +		mega_i_query_adapter (megaCfg);
  2.3176 +
  2.3177 +		if ((subsysid == 0x1111) && (subsysvid == 0x1111)) {
  2.3178 +
  2.3179 +			/*
  2.3180 +			 * Which firmware
  2.3181 +			 */
  2.3182 +			if( strcmp(megaCfg->fwVer, "3.00") == 0 ||
  2.3183 +					strcmp(megaCfg->fwVer, "3.01") == 0 ) {
  2.3184 +
  2.3185 +				printk( KERN_WARNING
  2.3186 +					"megaraid: Your  card is a Dell PERC 2/SC RAID controller "
  2.3187 +					"with  firmware\nmegaraid: 3.00 or 3.01.  This driver is "
  2.3188 +					"known to have corruption issues\nmegaraid: with those "
  2.3189 +					"firmware versions on this specific card.  In order\n"
  2.3190 +					"megaraid: to protect your data, please upgrade your "
  2.3191 +					"firmware to version\nmegaraid: 3.10 or later, available "
  2.3192 +					"from the Dell Technical Support web\nmegaraid: site at\n"
  2.3193 +					"http://support.dell.com/us/en/filelib/download/"
  2.3194 +					"index.asp?fileid=2940\n"
  2.3195 +				);
  2.3196 +			}
  2.3197 +		}
  2.3198 +
  2.3199 +		/*
  2.3200 +		 * If we have a HP 1M(0x60E7)/2M(0x60E8) controller with
  2.3201 +		 * firmware H.01.07 or H.01.08, disable 64 bit support,
  2.3202 +		 * since this firmware cannot handle 64 bit addressing
  2.3203 +		 */
  2.3204 +
  2.3205 +		if( (subsysvid == HP_SUBSYS_ID) &&
  2.3206 +				((subsysid == 0x60E7)||(subsysid == 0x60E8)) ) {
  2.3207 +
  2.3208 +			/*
  2.3209 +			 * which firmware
  2.3210 +			 */
  2.3211 +			if( strcmp(megaCfg->fwVer, "H01.07") == 0 || 
  2.3212 +			    strcmp(megaCfg->fwVer, "H01.08") == 0 ||
  2.3213 +			    strcmp(megaCfg->fwVer, "H01.09") == 0 )
  2.3214 +			{
  2.3215 +				printk(KERN_WARNING
  2.3216 +						"megaraid: Firmware H.01.07/8/9 on 1M/2M "
  2.3217 +						"controllers\nmegaraid: do not support 64 bit "
  2.3218 +						"addressing.\n"
  2.3219 +						"megaraid: DISABLING 64 bit support.\n");
  2.3220 +				megaCfg->flag &= ~BOARD_64BIT;
  2.3221 +			}
  2.3222 +		}
  2.3223 +
  2.3224 +		if (mega_is_bios_enabled (megaCfg)) {
  2.3225 +			mega_hbas[numCtlrs].is_bios_enabled = 1;
  2.3226 +		}
  2.3227 +
  2.3228 +		/*
  2.3229 +		 * Find out which channel is raid and which is scsi
  2.3230 +		 */
  2.3231 +		mega_enum_raid_scsi(megaCfg);
  2.3232 +
  2.3233 +		/*
  2.3234 +		 * Find out if a logical drive is set as the boot drive. If there is
  2.3235 +		 * one, will make that as the first logical drive.
  2.3236 +		 * ROMB: Do we have to boot from a physical drive. Then all the
  2.3237 +		 * physical drives would appear before the logical disks. Else, all
  2.3238 +		 * the physical drives would be exported to the mid layer after
  2.3239 +		 * logical disks.
  2.3240 +		 */
  2.3241 +		mega_get_boot_drv(megaCfg);
  2.3242 +
  2.3243 +		if( ! megaCfg->boot_pdrv_enabled ) {
  2.3244 +			for( i = 0; i < NVIRT_CHAN; i++ )
  2.3245 +				megaCfg->logdrv_chan[i] = 1;
  2.3246 +
  2.3247 +			for( i = NVIRT_CHAN; i < MAX_CHANNEL + NVIRT_CHAN; i++ )
  2.3248 +				megaCfg->logdrv_chan[i] = 0;
  2.3249 +
  2.3250 +			megaCfg->mega_ch_class <<= NVIRT_CHAN;
  2.3251 +		}
  2.3252 +		else {
  2.3253 +			j = megaCfg->productInfo.SCSIChanPresent;
  2.3254 +			for( i = 0; i < j; i++ )
  2.3255 +				megaCfg->logdrv_chan[i] = 0;
  2.3256 +
  2.3257 +			for( i = j; i < NVIRT_CHAN + j; i++ )
  2.3258 +				megaCfg->logdrv_chan[i] = 1;
  2.3259 +		}
  2.3260 +
  2.3261 +
  2.3262 +		mega_hbas[numCtlrs].hostdata_addr = megaCfg;
  2.3263 +
  2.3264 +		/*
  2.3265 +		 * Do we support random deletion and addition of logical drives
  2.3266 +		 */
  2.3267 +		megaCfg->read_ldidmap = 0;	/* set it after first logdrv delete cmd */
  2.3268 +		megaCfg->support_random_del = mega_support_random_del(megaCfg);
  2.3269 +
  2.3270 +		/* Initialize SCBs */
  2.3271 +		if (mega_init_scb (megaCfg)) {
  2.3272 +			pci_free_consistent (megaCfg->dev,
  2.3273 +					     sizeof (mega_mailbox64),
  2.3274 +					     (void *) megaCfg->mailbox64ptr,
  2.3275 +					     megaCfg->dma_handle64);
  2.3276 +			scsi_unregister (host);
  2.3277 +			continue;
  2.3278 +		}
  2.3279 +
  2.3280 +		/*
  2.3281 +		 * Fill in the structure which needs to be passed back to the
  2.3282 +		 * application when it does an ioctl() for controller related
  2.3283 +		 * information.
  2.3284 +		 */
  2.3285 +
  2.3286 +		i = numCtlrs;
  2.3287 +		numCtlrs++;
  2.3288 +
  2.3289 +		mcontroller[i].base = megaBase;
  2.3290 +		mcontroller[i].irq = megaIrq;
  2.3291 +		mcontroller[i].numldrv = megaCfg->numldrv;
  2.3292 +		mcontroller[i].pcibus = pciBus;
  2.3293 +		mcontroller[i].pcidev = pciDev;
  2.3294 +		mcontroller[i].pcifun = PCI_FUNC (pciDevFun);
  2.3295 +		mcontroller[i].pciid = pciIdx;
  2.3296 +		mcontroller[i].pcivendor = pciVendor;
  2.3297 +		mcontroller[i].pcislot = PCI_SLOT (pciDevFun);
  2.3298 +		mcontroller[i].uid = (pciBus << 8) | pciDevFun;
  2.3299 +
  2.3300 +		numFound++;
  2.3301 +
  2.3302 +		/* Set the Mode of addressing to 64 bit */
  2.3303 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.3304 +		if ((megaCfg->flag & BOARD_64BIT) && BITS_PER_LONG == 64)
  2.3305 +#ifdef __LP64__
  2.3306 +			pdev->dma_mask = 0xffffffffffffffff;
  2.3307 +#else
  2.3308 +			pdev->dma_mask = 0xffffffff;
  2.3309 +#endif
  2.3310 +#endif
  2.3311 +		continue;
  2.3312 +	      err_release:
  2.3313 +		if (flag & BOARD_QUARTZ)
  2.3314 +			release_region (megaBase, 16);
  2.3315 +	      err_unregister:
  2.3316 +		scsi_unregister (host);
  2.3317 +	      err_unmap:
  2.3318 +		if (flag & BOARD_QUARTZ)
  2.3319 +			iounmap ((void *) megaBase);
  2.3320 +	}
  2.3321 +	return numFound;
  2.3322 +}
  2.3323 +
  2.3324 +/*---------------------------------------------------------
  2.3325 + * Detects if a megaraid controller exists in this system
  2.3326 + *---------------------------------------------------------*/
  2.3327 +
  2.3328 +int megaraid_detect (Scsi_Host_Template * pHostTmpl)
  2.3329 +{
  2.3330 +#if XENO_KILLED
  2.3331 +  int ctlridx = 0;
  2.3332 +#endif
  2.3333 +  int count = 0;
  2.3334 +
  2.3335 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)	/*0x20300 */
  2.3336 +	pHostTmpl->proc_dir = &proc_scsi_megaraid;
  2.3337 +#else
  2.3338 +	pHostTmpl->proc_name = "megaraid";
  2.3339 +#endif
  2.3340 +
  2.3341 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)	/* 0x20100 */
  2.3342 +	if (!pcibios_present ()) {
  2.3343 +		printk (KERN_WARNING "megaraid: PCI bios not present."
  2.3344 +			M_RD_CRLFSTR);
  2.3345 +		return 0;
  2.3346 +	}
  2.3347 +#endif
  2.3348 +	skip_id = -1;
  2.3349 +	if (megaraid && !strncmp (megaraid, "skip", strlen ("skip"))) {
  2.3350 +		if (megaraid[4] != '\0') {
  2.3351 +			skip_id = megaraid[4] - '0';
  2.3352 +			if (megaraid[5] != '\0') {
  2.3353 +				skip_id = (skip_id * 10) + (megaraid[5] - '0');
  2.3354 +			}
  2.3355 +		}
  2.3356 +		skip_id = (skip_id > 15) ? -1 : skip_id;
  2.3357 +	}
  2.3358 +
  2.3359 +	printk (KERN_NOTICE "megaraid: " MEGARAID_VERSION);
  2.3360 +
  2.3361 +	memset (mega_hbas, 0, sizeof (mega_hbas));
  2.3362 +
  2.3363 +	/* Detect ROMBs first */
  2.3364 +	count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_DISCOVERY,
  2.3365 +				PCI_DEVICE_ID_DISCOVERY, BOARD_QUARTZ);
  2.3366 +	count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_PERC4_DI_YSTONE,
  2.3367 +				PCI_DEVICE_ID_PERC4_DI_YSTONE, BOARD_QUARTZ);
  2.3368 +	/* Then detect cards based on date they were produced, oldest first */
  2.3369 +	count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_AMI,
  2.3370 +				PCI_DEVICE_ID_AMI_MEGARAID, 0);
  2.3371 +	count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_AMI,
  2.3372 +				PCI_DEVICE_ID_AMI_MEGARAID2, 0);
  2.3373 +	count += mega_findCard (pHostTmpl, 0x8086,
  2.3374 +				PCI_DEVICE_ID_AMI_MEGARAID3, BOARD_QUARTZ);
  2.3375 +	count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_AMI,
  2.3376 +				PCI_DEVICE_ID_AMI_MEGARAID3, BOARD_QUARTZ);
  2.3377 +	count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_LSI_LOGIC,
  2.3378 +				PCI_DEVICE_ID_AMI_MEGARAID3, BOARD_QUARTZ);
  2.3379 +	count += mega_findCard (pHostTmpl, PCI_VENDOR_ID_PERC4_QC_VERDE,
  2.3380 +				PCI_DEVICE_ID_PERC4_QC_VERDE, BOARD_QUARTZ);
  2.3381 +
  2.3382 +	mega_reorder_hosts ();
  2.3383 +
  2.3384 +#ifdef CONFIG_PROC_FS
  2.3385 +	if (count) {
  2.3386 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)	/*0x20300 */
  2.3387 +		mega_proc_dir_entry = proc_mkdir ("megaraid", &proc_root);
  2.3388 +#else
  2.3389 +		mega_proc_dir_entry = create_proc_entry ("megaraid",
  2.3390 +							 S_IFDIR | S_IRUGO |
  2.3391 +							 S_IXUGO, &proc_root);
  2.3392 +#endif
  2.3393 +		if (!mega_proc_dir_entry)
  2.3394 +			printk ("megaraid: failed to create megaraid root\n");
  2.3395 +		else
  2.3396 +			for (ctlridx = 0; ctlridx < count; ctlridx++)
  2.3397 +				mega_create_proc_entry (ctlridx,
  2.3398 +							mega_proc_dir_entry);
  2.3399 +	}
  2.3400 +#endif
  2.3401 +
  2.3402 +	/*
  2.3403 +	 * Register the driver as a character device, for applications to access
  2.3404 +	 * it for ioctls.
  2.3405 +	 * Ideally, this should go in the init_module() routine, but since it is
  2.3406 +	 * hidden in the file "scsi_module.c" ( included in the end ), we define
  2.3407 +	 * it here
  2.3408 +	 * First argument (major) to register_chrdev implies a dynamic major
  2.3409 +	 * number allocation.
  2.3410 +	 */
  2.3411 +#if XENO_KILLED
  2.3412 +	if (count) {
  2.3413 +		major = register_chrdev (0, "megadev", &megadev_fops);
  2.3414 +
  2.3415 +		/*
  2.3416 +		 * Register the Shutdown Notification hook in kernel
  2.3417 +		 */
  2.3418 +		if (register_reboot_notifier (&mega_notifier)) {
  2.3419 +			printk ("MegaRAID Shutdown routine not registered!!\n");
  2.3420 +		}
  2.3421 +
  2.3422 +		init_MUTEX (&mimd_entry_mtx);
  2.3423 +	}
  2.3424 +#endif
  2.3425 +
  2.3426 +	return count;
  2.3427 +}
  2.3428 +
  2.3429 +/*---------------------------------------------------------------------
  2.3430 + * Release the controller's resources
  2.3431 + *---------------------------------------------------------------------*/
  2.3432 +int megaraid_release (struct Scsi_Host *pSHost)
  2.3433 +{
  2.3434 +	mega_host_config *megaCfg;
  2.3435 +	mega_mailbox *mbox;
  2.3436 +	u_char mboxData[16];
  2.3437 +#ifdef CONFIG_PROC_FS
  2.3438 +	int i;
  2.3439 +#endif
  2.3440 +
  2.3441 +	megaCfg = (mega_host_config *) pSHost->hostdata;
  2.3442 +	mbox = (mega_mailbox *) mboxData;
  2.3443 +
  2.3444 +	/* Flush cache to disk */
  2.3445 +	memset (mbox, 0, 16);
  2.3446 +	mboxData[0] = 0xA;
  2.3447 +
  2.3448 +	free_irq (megaCfg->host->irq, megaCfg);	/* Must be freed first, otherwise
  2.3449 +						   extra interrupt is generated */
  2.3450 +
  2.3451 +	/* Issue a blocking (interrupts disabled) command to the card */
  2.3452 +	megaIssueCmd (megaCfg, mboxData, NULL, 0);
  2.3453 +
  2.3454 +	/* Free our resources */
  2.3455 +	if (megaCfg->flag & BOARD_QUARTZ) {
  2.3456 +		iounmap ((void *) megaCfg->base);
  2.3457 +	} else {
  2.3458 +		release_region (megaCfg->host->io_port, 16);
  2.3459 +	}
  2.3460 +
  2.3461 +	mega_freeSgList (megaCfg);
  2.3462 +	pci_free_consistent (megaCfg->dev,
  2.3463 +			     sizeof (mega_mailbox64),
  2.3464 +			     (void *) megaCfg->mailbox64ptr,
  2.3465 +			     megaCfg->dma_handle64);
  2.3466 +
  2.3467 +#ifdef CONFIG_PROC_FS
  2.3468 +	if (megaCfg->controller_proc_dir_entry) {
  2.3469 +		remove_proc_entry ("stat", megaCfg->controller_proc_dir_entry);
  2.3470 +		remove_proc_entry ("status",
  2.3471 +				   megaCfg->controller_proc_dir_entry);
  2.3472 +		remove_proc_entry ("config",
  2.3473 +				   megaCfg->controller_proc_dir_entry);
  2.3474 +		remove_proc_entry ("mailbox",
  2.3475 +				   megaCfg->controller_proc_dir_entry);
  2.3476 +		for (i = 0; i < numCtlrs; i++) {
  2.3477 +			char buf[12] = { 0 };
  2.3478 +			sprintf (buf, "%d", i);
  2.3479 +			remove_proc_entry (buf, mega_proc_dir_entry);
  2.3480 +		}
  2.3481 +		remove_proc_entry ("megaraid", &proc_root);
  2.3482 +	}
  2.3483 +#endif
  2.3484 +
  2.3485 +	/*
  2.3486 +	 *	Release the controller memory. A word of warning this frees
  2.3487 +	 *	hostdata and that includes megaCfg-> so be careful what you
  2.3488 +	 *	dereference beyond this point
  2.3489 +	 */
  2.3490 +	 
  2.3491 +	scsi_unregister (pSHost);
  2.3492 +
  2.3493 +	/*
  2.3494 +	 * Unregister the character device interface to the driver. Ideally this
  2.3495 +	 * should have been done in cleanup_module routine. Since this is hidden
  2.3496 +	 * in file "scsi_module.c", we do it here.
  2.3497 +	 * major is the major number of the character device returned by call to
  2.3498 +	 * register_chrdev() routine.
  2.3499 +	 */
  2.3500 +
  2.3501 +#if XENO_KILLED
  2.3502 +	unregister_chrdev (major, "megadev");
  2.3503 +	unregister_reboot_notifier (&mega_notifier);
  2.3504 +#endif
  2.3505 +
  2.3506 +	return 0;
  2.3507 +}
  2.3508 +
  2.3509 +static int mega_is_bios_enabled (mega_host_config * megacfg)
  2.3510 +{
  2.3511 +	mega_mailbox *mboxpnt;
  2.3512 +	unsigned char mbox[16];
  2.3513 +	int ret;
  2.3514 +
  2.3515 +	mboxpnt = (mega_mailbox *) mbox;
  2.3516 +
  2.3517 +	memset (mbox, 0, sizeof (mbox));
  2.3518 +	memset ((void *) megacfg->mega_buffer,
  2.3519 +		0, sizeof (megacfg->mega_buffer));
  2.3520 +
  2.3521 +	/*
  2.3522 +	 * issue command to find out if the BIOS is enabled for this controller
  2.3523 +	 */
  2.3524 +	mbox[0] = IS_BIOS_ENABLED;
  2.3525 +	mbox[2] = GET_BIOS;
  2.3526 +
  2.3527 +	mboxpnt->xferaddr = virt_to_bus ((void *) megacfg->mega_buffer);
  2.3528 +
  2.3529 +	ret = megaIssueCmd (megacfg, mbox, NULL, 0);
  2.3530 +
  2.3531 +	return (*(char *) megacfg->mega_buffer);
  2.3532 +}
  2.3533 +
  2.3534 +/*
  2.3535 + * Find out what channels are RAID/SCSI
  2.3536 + */
  2.3537 +static void
  2.3538 +mega_enum_raid_scsi(mega_host_config *megacfg)
  2.3539 +{
  2.3540 +	mega_mailbox *mboxp;
  2.3541 +	unsigned char mbox[16];
  2.3542 +	int		i;
  2.3543 +
  2.3544 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.3545 +	dma_addr_t	dma_handle;
  2.3546 +#endif
  2.3547 +
  2.3548 +	mboxp = (mega_mailbox *)mbox;
  2.3549 +
  2.3550 +	memset(mbox, 0, sizeof(mbox));
  2.3551 +	/*
  2.3552 +	 * issue command to find out what channels are raid/scsi
  2.3553 +	 */
  2.3554 +	mbox[0] = CHNL_CLASS;
  2.3555 +	mbox[2] = GET_CHNL_CLASS;
  2.3556 +
  2.3557 +	memset((void *)megacfg->mega_buffer, 0, sizeof(megacfg->mega_buffer));
  2.3558 +
  2.3559 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.3560 +	dma_handle = pci_map_single(megacfg->dev, (void *)megacfg->mega_buffer,
  2.3561 +			      (2 * 1024L), PCI_DMA_FROMDEVICE);
  2.3562 +
  2.3563 +	mboxp->xferaddr = dma_handle;
  2.3564 +#else
  2.3565 +	mboxp->xferaddr = virt_to_bus((void *)megacfg->mega_buffer);
  2.3566 +#endif
  2.3567 +
  2.3568 +	/*
  2.3569 +	 * Non-ROMB firware fail this command, so all channels
  2.3570 +	 * must be shown RAID
  2.3571 +	 */
  2.3572 +	megacfg->mega_ch_class = 0xFF;
  2.3573 +	if( megaIssueCmd(megacfg, mbox, NULL, 0) == 0 ) {
  2.3574 +		megacfg->mega_ch_class = *((char *)megacfg->mega_buffer);
  2.3575 +	}
  2.3576 +
  2.3577 +	for( i = 0; i < megacfg->productInfo.SCSIChanPresent; i++ ) {
  2.3578 +		if( (megacfg->mega_ch_class >> i) & 0x01 )
  2.3579 +			printk(KERN_NOTICE"megaraid: channel[%d] is raid.\n", i+1);
  2.3580 +		else
  2.3581 +			printk(KERN_NOTICE"megaraid: channel[%d] is scsi.\n", i+1);
  2.3582 +	}
  2.3583 +
  2.3584 +
  2.3585 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.3586 +	pci_unmap_single(megacfg->dev, dma_handle,
  2.3587 +				  (2 * 1024L), PCI_DMA_FROMDEVICE);
  2.3588 +#endif
  2.3589 +
  2.3590 +}
  2.3591 +
  2.3592 +
  2.3593 +/*
  2.3594 + * get the boot logical drive number if enabled
  2.3595 + */
  2.3596 +void
  2.3597 +mega_get_boot_drv(mega_host_config *megacfg)
  2.3598 +{
  2.3599 +	mega_mailbox *mboxp;
  2.3600 +	unsigned char mbox[16];
  2.3601 +	struct private_bios_data *prv_bios_data;
  2.3602 +	u16		cksum = 0;
  2.3603 +	u8		*cksum_p;
  2.3604 +	u8		boot_pdrv;
  2.3605 +	int		i;
  2.3606 +
  2.3607 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.3608 +	dma_addr_t	dma_handle;
  2.3609 +#endif
  2.3610 +
  2.3611 +	mboxp = (mega_mailbox *)mbox;
  2.3612 +
  2.3613 +	memset(mbox, 0, sizeof(mbox));
  2.3614 +
  2.3615 +	mbox[0] = BIOS_PVT_DATA;
  2.3616 +	mbox[2] = GET_BIOS_PVT_DATA;
  2.3617 +
  2.3618 +	memset((void *)megacfg->mega_buffer, 0, sizeof(megacfg->mega_buffer));
  2.3619 +
  2.3620 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.3621 +	dma_handle = pci_map_single(megacfg->dev, (void *)megacfg->mega_buffer,
  2.3622 +			      (2 * 1024L), PCI_DMA_FROMDEVICE);
  2.3623 +
  2.3624 +	mboxp->xferaddr = dma_handle;
  2.3625 +#else
  2.3626 +	mboxp->xferaddr = virt_to_bus((void *)megacfg->mega_buffer);
  2.3627 +#endif
  2.3628 +
  2.3629 +	megacfg->boot_ldrv_enabled = 0;
  2.3630 +	megacfg->boot_ldrv = 0;
  2.3631 +
  2.3632 +	megacfg->boot_pdrv_enabled = 0;
  2.3633 +	megacfg->boot_pdrv_ch = 0;
  2.3634 +	megacfg->boot_pdrv_tgt = 0;
  2.3635 +
  2.3636 +	if( megaIssueCmd(megacfg, mbox, NULL, 0) == 0 ) {
  2.3637 +		prv_bios_data = (struct private_bios_data *)megacfg->mega_buffer;
  2.3638 +
  2.3639 +		cksum = 0;
  2.3640 +		cksum_p = (u8 *)prv_bios_data;
  2.3641 +		for( i = 0; i < 14; i++ ) {
  2.3642 +			cksum += *cksum_p++;
  2.3643 +		}
  2.3644 +
  2.3645 +		if( prv_bios_data->cksum == (u16)(0-cksum) ) {
  2.3646 +
  2.3647 +			/*
  2.3648 +			 * If MSB is set, a physical drive is set as boot device
  2.3649 +			 */
  2.3650 +			if( prv_bios_data->boot_drv & 0x80 ) {
  2.3651 +				megacfg->boot_pdrv_enabled = 1;
  2.3652 +				boot_pdrv = prv_bios_data->boot_drv & 0x7F;
  2.3653 +				megacfg->boot_pdrv_ch = boot_pdrv / 16;
  2.3654 +				megacfg->boot_pdrv_tgt = boot_pdrv % 16;
  2.3655 +			}
  2.3656 +			else {
  2.3657 +				megacfg->boot_ldrv_enabled = 1;
  2.3658 +				megacfg->boot_ldrv = prv_bios_data->boot_drv;
  2.3659 +			}
  2.3660 +		}
  2.3661 +	}
  2.3662 +
  2.3663 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.3664 +	pci_unmap_single(megacfg->dev, dma_handle,
  2.3665 +				  (2 * 1024L), PCI_DMA_FROMDEVICE);
  2.3666 +#endif
  2.3667 +
  2.3668 +}
  2.3669 +
  2.3670 +
  2.3671 +static void mega_reorder_hosts (void)
  2.3672 +{
  2.3673 +	struct Scsi_Host *shpnt;
  2.3674 +	struct Scsi_Host *shone;
  2.3675 +	struct Scsi_Host *shtwo;
  2.3676 +	mega_host_config *boot_host;
  2.3677 +	int i;
  2.3678 +
  2.3679 +	/*
  2.3680 +	 * Find the (first) host which has it's BIOS enabled
  2.3681 +	 */
  2.3682 +	boot_host = NULL;
  2.3683 +	for (i = 0; i < MAX_CONTROLLERS; i++) {
  2.3684 +		if (mega_hbas[i].is_bios_enabled) {
  2.3685 +			boot_host = mega_hbas[i].hostdata_addr;
  2.3686 +			break;
  2.3687 +		}
  2.3688 +	}
  2.3689 +
  2.3690 +	if (boot_host == NULL) {
  2.3691 +		printk (KERN_WARNING "megaraid: no BIOS enabled.\n");
  2.3692 +		return;
  2.3693 +	}
  2.3694 +
  2.3695 +	/*
  2.3696 +	 * Traverse through the list of SCSI hosts for our HBA locations
  2.3697 +	 */
  2.3698 +	shone = shtwo = NULL;
  2.3699 +	for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
  2.3700 +		/* Is it one of ours? */
  2.3701 +		for (i = 0; i < MAX_CONTROLLERS; i++) {
  2.3702 +			if ((mega_host_config *) shpnt->hostdata ==
  2.3703 +			    mega_hbas[i].hostdata_addr) {
  2.3704 +				/* Does this one has BIOS enabled */
  2.3705 +				if (mega_hbas[i].hostdata_addr == boot_host) {
  2.3706 +
  2.3707 +					/* Are we first */
  2.3708 +					if (shtwo == NULL)	/* Yes! */
  2.3709 +						return;
  2.3710 +					else {	/* :-( */
  2.3711 +						shone = shpnt;
  2.3712 +					}
  2.3713 +				} else {
  2.3714 +					if (!shtwo) {
  2.3715 +						/* were we here before? xchng first */
  2.3716 +						shtwo = shpnt;
  2.3717 +					}
  2.3718 +				}
  2.3719 +				break;
  2.3720 +			}
  2.3721 +		}
  2.3722 +		/*
  2.3723 +		 * Have we got the boot host and one which does not have the bios
  2.3724 +		 * enabled.
  2.3725 +		 */
  2.3726 +		if (shone && shtwo)
  2.3727 +			break;
  2.3728 +	}
  2.3729 +	if (shone && shtwo) {
  2.3730 +		mega_swap_hosts (shone, shtwo);
  2.3731 +	}
  2.3732 +
  2.3733 +	return;
  2.3734 +}
  2.3735 +
  2.3736 +static void mega_swap_hosts (struct Scsi_Host *shone, struct Scsi_Host *shtwo)
  2.3737 +{
  2.3738 +	struct Scsi_Host *prevtoshtwo;
  2.3739 +	struct Scsi_Host *prevtoshone;
  2.3740 +	struct Scsi_Host *save = NULL;;
  2.3741 +
  2.3742 +	/* Are these two nodes adjacent */
  2.3743 +	if (shtwo->next == shone) {
  2.3744 +
  2.3745 +		if (shtwo == scsi_hostlist && shone->next == NULL) {
  2.3746 +
  2.3747 +			/* just two nodes */
  2.3748 +			scsi_hostlist = shone;
  2.3749 +			shone->next = shtwo;
  2.3750 +			shtwo->next = NULL;
  2.3751 +		} else if (shtwo == scsi_hostlist) {
  2.3752 +			/* first two nodes of the list */
  2.3753 +
  2.3754 +			scsi_hostlist = shone;
  2.3755 +			shtwo->next = shone->next;
  2.3756 +			scsi_hostlist->next = shtwo;
  2.3757 +		} else if (shone->next == NULL) {
  2.3758 +			/* last two nodes of the list */
  2.3759 +
  2.3760 +			prevtoshtwo = scsi_hostlist;
  2.3761 +
  2.3762 +			while (prevtoshtwo->next != shtwo)
  2.3763 +				prevtoshtwo = prevtoshtwo->next;
  2.3764 +
  2.3765 +			prevtoshtwo->next = shone;
  2.3766 +			shone->next = shtwo;
  2.3767 +			shtwo->next = NULL;
  2.3768 +		} else {
  2.3769 +			prevtoshtwo = scsi_hostlist;
  2.3770 +
  2.3771 +			while (prevtoshtwo->next != shtwo)
  2.3772 +				prevtoshtwo = prevtoshtwo->next;
  2.3773 +
  2.3774 +			prevtoshtwo->next = shone;
  2.3775 +			shtwo->next = shone->next;
  2.3776 +			shone->next = shtwo;
  2.3777 +		}
  2.3778 +
  2.3779 +	} else if (shtwo == scsi_hostlist && shone->next == NULL) {
  2.3780 +		/* shtwo at head, shone at tail, not adjacent */
  2.3781 +
  2.3782 +		prevtoshone = scsi_hostlist;
  2.3783 +
  2.3784 +		while (prevtoshone->next != shone)
  2.3785 +			prevtoshone = prevtoshone->next;
  2.3786 +
  2.3787 +		scsi_hostlist = shone;
  2.3788 +		shone->next = shtwo->next;
  2.3789 +		prevtoshone->next = shtwo;
  2.3790 +		shtwo->next = NULL;
  2.3791 +	} else if (shtwo == scsi_hostlist && shone->next != NULL) {
  2.3792 +		/* shtwo at head, shone is not at tail */
  2.3793 +
  2.3794 +		prevtoshone = scsi_hostlist;
  2.3795 +		while (prevtoshone->next != shone)
  2.3796 +			prevtoshone = prevtoshone->next;
  2.3797 +
  2.3798 +		scsi_hostlist = shone;
  2.3799 +		prevtoshone->next = shtwo;
  2.3800 +		save = shtwo->next;
  2.3801 +		shtwo->next = shone->next;
  2.3802 +		shone->next = save;
  2.3803 +	} else if (shone->next == NULL) {
  2.3804 +		/* shtwo not at head, shone at tail */
  2.3805 +
  2.3806 +		prevtoshtwo = scsi_hostlist;
  2.3807 +		prevtoshone = scsi_hostlist;
  2.3808 +
  2.3809 +		while (prevtoshtwo->next != shtwo)
  2.3810 +			prevtoshtwo = prevtoshtwo->next;
  2.3811 +		while (prevtoshone->next != shone)
  2.3812 +			prevtoshone = prevtoshone->next;
  2.3813 +
  2.3814 +		prevtoshtwo->next = shone;
  2.3815 +		shone->next = shtwo->next;
  2.3816 +		prevtoshone->next = shtwo;
  2.3817 +		shtwo->next = NULL;
  2.3818 +
  2.3819 +	} else {
  2.3820 +		prevtoshtwo = scsi_hostlist;
  2.3821 +		prevtoshone = scsi_hostlist;
  2.3822 +		save = NULL;;
  2.3823 +
  2.3824 +		while (prevtoshtwo->next != shtwo)
  2.3825 +			prevtoshtwo = prevtoshtwo->next;
  2.3826 +		while (prevtoshone->next != shone)
  2.3827 +			prevtoshone = prevtoshone->next;
  2.3828 +
  2.3829 +		prevtoshtwo->next = shone;
  2.3830 +		save = shone->next;
  2.3831 +		shone->next = shtwo->next;
  2.3832 +		prevtoshone->next = shtwo;
  2.3833 +		shtwo->next = save;
  2.3834 +	}
  2.3835 +	return;
  2.3836 +}
  2.3837 +
  2.3838 +static inline void mega_freeSgList (mega_host_config * megaCfg)
  2.3839 +{
  2.3840 +	int i;
  2.3841 +
  2.3842 +	for (i = 0; i < megaCfg->max_cmds; i++) {
  2.3843 +		if (megaCfg->scbList[i].sgList)
  2.3844 +			pci_free_consistent (megaCfg->dev,
  2.3845 +					     sizeof (mega_64sglist) *
  2.3846 +					     MAX_SGLIST,
  2.3847 +					     megaCfg->scbList[i].sgList,
  2.3848 +					     megaCfg->scbList[i].
  2.3849 +					     dma_sghandle64);
  2.3850 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)	/* 0x020400 */
  2.3851 +			kfree (megaCfg->scbList[i].sgList);	/* free sgList */
  2.3852 +#endif
  2.3853 +	}
  2.3854 +}
  2.3855 +
  2.3856 +/*----------------------------------------------
  2.3857 + * Get information about the card/driver
  2.3858 + *----------------------------------------------*/
  2.3859 +const char *megaraid_info (struct Scsi_Host *pSHost)
  2.3860 +{
  2.3861 +	static char buffer[512];
  2.3862 +	mega_host_config *megaCfg;
  2.3863 +
  2.3864 +	megaCfg = (mega_host_config *) pSHost->hostdata;
  2.3865 +
  2.3866 +	sprintf (buffer,
  2.3867 +		 "LSI Logic MegaRAID %s %d commands %d targs %d chans %d luns",
  2.3868 +		 megaCfg->fwVer, megaCfg->productInfo.MaxConcCmds,
  2.3869 +		 megaCfg->host->max_id-1, megaCfg->host->max_channel,
  2.3870 +		 megaCfg->host->max_lun);
  2.3871 +	return buffer;
  2.3872 +}
  2.3873 +
  2.3874 +/*-----------------------------------------------------------------
  2.3875 + * Perform a SCSI command
  2.3876 + * Mailbox area:
  2.3877 + *   00 01 command
  2.3878 + *   01 01 command id
  2.3879 + *   02 02 # of sectors
  2.3880 + *   04 04 logical bus address
  2.3881 + *   08 04 physical buffer address
  2.3882 + *   0C 01 logical drive #
  2.3883 + *   0D 01 length of scatter/gather list
  2.3884 + *   0E 01 reserved
  2.3885 + *   0F 01 mailbox busy
  2.3886 + *   10 01 numstatus byte
  2.3887 + *   11 01 status byte
  2.3888 + *-----------------------------------------------------------------*/
  2.3889 +int megaraid_queue (Scsi_Cmnd * SCpnt, void (*pktComp) (Scsi_Cmnd *))
  2.3890 +{
  2.3891 +	DRIVER_LOCK_T mega_host_config * megaCfg;
  2.3892 +	mega_scb *pScb;
  2.3893 +	char *user_area = NULL;
  2.3894 +
  2.3895 +	megaCfg = (mega_host_config *) SCpnt->host->hostdata;
  2.3896 +	DRIVER_LOCK (megaCfg);
  2.3897 +
  2.3898 +#if 0
  2.3899 +	if (!(megaCfg->flag & (1L << SCpnt->channel))) {
  2.3900 +		if (SCpnt->channel < megaCfg->productInfo.SCSIChanPresent)
  2.3901 +			printk ( KERN_NOTICE
  2.3902 +				"scsi%d: scanning channel %d for devices.\n",
  2.3903 +				megaCfg->host->host_no, SCpnt->channel);
  2.3904 +		else
  2.3905 +			printk ( KERN_NOTICE
  2.3906 +				"scsi%d: scanning virtual channel %d for logical drives.\n",
  2.3907 +				megaCfg->host->host_no,
  2.3908 +				SCpnt->channel-megaCfg->productInfo.SCSIChanPresent+1);
  2.3909 +
  2.3910 +		megaCfg->flag |= (1L << SCpnt->channel);
  2.3911 +	}
  2.3912 +#endif
  2.3913 +
  2.3914 +	SCpnt->scsi_done = pktComp;
  2.3915 +
  2.3916 +	if (mega_driver_ioctl (megaCfg, SCpnt))
  2.3917 +		return 0;
  2.3918 +
  2.3919 +	/* If driver in abort or reset.. cancel this command */
  2.3920 +	if (megaCfg->flag & IN_ABORT) {
  2.3921 +		SCpnt->result = (DID_ABORT << 16);
  2.3922 +		/* Add Scsi_Command to end of completed queue */
  2.3923 +		if (megaCfg->qCompletedH == NULL) {
  2.3924 +			megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
  2.3925 +		} else {
  2.3926 +			megaCfg->qCompletedT->host_scribble =
  2.3927 +			    (unsigned char *) SCpnt;
  2.3928 +			megaCfg->qCompletedT = SCpnt;
  2.3929 +		}
  2.3930 +		megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
  2.3931 +		megaCfg->qCcnt++;
  2.3932 +
  2.3933 +		DRIVER_UNLOCK (megaCfg);
  2.3934 +		return 0;
  2.3935 +	} else if (megaCfg->flag & IN_RESET) {
  2.3936 +		SCpnt->result = (DID_RESET << 16);
  2.3937 +		/* Add Scsi_Command to end of completed queue */
  2.3938 +		if (megaCfg->qCompletedH == NULL) {
  2.3939 +			megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
  2.3940 +		} else {
  2.3941 +			megaCfg->qCompletedT->host_scribble =
  2.3942 +			    (unsigned char *) SCpnt;
  2.3943 +			megaCfg->qCompletedT = SCpnt;
  2.3944 +		}
  2.3945 +		megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
  2.3946 +		megaCfg->qCcnt++;
  2.3947 +
  2.3948 +		DRIVER_UNLOCK (megaCfg);
  2.3949 +		return 0;
  2.3950 +	}
  2.3951 +
  2.3952 +	megaCfg->flag |= IN_QUEUE;
  2.3953 +	/* Allocate and build a SCB request */
  2.3954 +	if ((pScb = mega_build_cmd (megaCfg, SCpnt)) != NULL) {
  2.3955 +
  2.3956 +		/*
  2.3957 +		 * Check if the HBA is in quiescent state, e.g., during a delete
  2.3958 +		 * logical drive opertion. If it is, queue the commands in the
  2.3959 +		 * internal queue until the delete operation is complete.
  2.3960 +		 */
  2.3961 +		if( ! megaCfg->quiescent ) {
  2.3962 +			/* Add SCB to the head of the pending queue */
  2.3963 +			if (megaCfg->qPendingH == NULL) {
  2.3964 +				megaCfg->qPendingH = megaCfg->qPendingT = pScb;
  2.3965 +			} else {
  2.3966 +				megaCfg->qPendingT->next = pScb;
  2.3967 +				megaCfg->qPendingT = pScb;
  2.3968 +			}
  2.3969 +			megaCfg->qPendingT->next = NULL;
  2.3970 +			megaCfg->qPcnt++;
  2.3971 +
  2.3972 +			if (mega_runpendq (megaCfg) == -1) {
  2.3973 +				DRIVER_UNLOCK (megaCfg);
  2.3974 +				return 0;
  2.3975 +			}
  2.3976 +		}
  2.3977 +		else {
  2.3978 +			/* Add SCB to the internal queue */
  2.3979 +			if (megaCfg->int_qh == NULL) {
  2.3980 +				megaCfg->int_qh = megaCfg->int_qt = pScb;
  2.3981 +			} else {
  2.3982 +				megaCfg->int_qt->next = pScb;
  2.3983 +				megaCfg->int_qt = pScb;
  2.3984 +			}
  2.3985 +			megaCfg->int_qt->next = NULL;
  2.3986 +			megaCfg->int_qlen++;
  2.3987 +		}
  2.3988 +
  2.3989 +		if (pScb->SCpnt->cmnd[0] == M_RD_IOCTL_CMD_NEW) {
  2.3990 +#if XENO_KILLED
  2.3991 +			init_MUTEX_LOCKED (&pScb->ioctl_sem);
  2.3992 +#endif
  2.3993 +			spin_unlock_irq (&io_request_lock);
  2.3994 +#if XENO_KILLED
  2.3995 +			down (&pScb->ioctl_sem);
  2.3996 +#endif
  2.3997 +    		user_area = (char *)*((u32*)&pScb->SCpnt->cmnd[4]);
  2.3998 +			if (copy_to_user
  2.3999 +			    (user_area, pScb->buff_ptr, pScb->iDataSize)) {
  2.4000 +				printk
  2.4001 +				    ("megaraid: Error copying ioctl return value to user buffer.\n");
  2.4002 +				pScb->SCpnt->result = (DID_ERROR << 16);
  2.4003 +			}
  2.4004 +			spin_lock_irq (&io_request_lock);
  2.4005 +			DRIVER_LOCK (megaCfg);
  2.4006 +			kfree (pScb->buff_ptr);
  2.4007 +			pScb->buff_ptr = NULL;
  2.4008 +			mega_cmd_done (megaCfg, pScb, pScb->SCpnt->result);
  2.4009 +			mega_rundoneq (megaCfg);
  2.4010 +			mega_runpendq (megaCfg);
  2.4011 +			DRIVER_UNLOCK (megaCfg);
  2.4012 +		}
  2.4013 +
  2.4014 +		megaCfg->flag &= ~IN_QUEUE;
  2.4015 +
  2.4016 +	}
  2.4017 +
  2.4018 +	DRIVER_UNLOCK (megaCfg);
  2.4019 +	return 0;
  2.4020 +}
  2.4021 +
  2.4022 +/*----------------------------------------------------------------------
  2.4023 + * Issue a blocking command to the controller
  2.4024 + *----------------------------------------------------------------------*/
  2.4025 +#if XENO_KILLED
  2.4026 +volatile static int internal_done_flag = 0;
  2.4027 +volatile static int internal_done_errcode = 0;
  2.4028 +
  2.4029 +static DECLARE_WAIT_QUEUE_HEAD (internal_wait);
  2.4030 +
  2.4031 +static void internal_done (Scsi_Cmnd * SCpnt)
  2.4032 +{
  2.4033 +	internal_done_errcode = SCpnt->result;
  2.4034 +	internal_done_flag++;
  2.4035 +	wake_up (&internal_wait);
  2.4036 +}
  2.4037 +
  2.4038 +/* shouldn't be used, but included for completeness */
  2.4039 +
  2.4040 +int megaraid_command (Scsi_Cmnd * SCpnt)
  2.4041 +{
  2.4042 +	internal_done_flag = 0;
  2.4043 +
  2.4044 +	/* Queue command, and wait until it has completed */
  2.4045 +	megaraid_queue (SCpnt, internal_done);
  2.4046 +
  2.4047 +	while (!internal_done_flag) {
  2.4048 +		interruptible_sleep_on (&internal_wait);
  2.4049 +	}
  2.4050 +
  2.4051 +	return internal_done_errcode;
  2.4052 +}
  2.4053 +#endif
  2.4054 +
  2.4055 +/*---------------------------------------------------------------------
  2.4056 + * Abort a previous SCSI request
  2.4057 + *---------------------------------------------------------------------*/
  2.4058 +int megaraid_abort (Scsi_Cmnd * SCpnt)
  2.4059 +{
  2.4060 +	mega_host_config *megaCfg;
  2.4061 +	int rc;			/*, idx; */
  2.4062 +	mega_scb *pScb;
  2.4063 +
  2.4064 +	rc = SCSI_ABORT_NOT_RUNNING;
  2.4065 +
  2.4066 +	megaCfg = (mega_host_config *) SCpnt->host->hostdata;
  2.4067 +
  2.4068 +	megaCfg->flag |= IN_ABORT;
  2.4069 +
  2.4070 +	for (pScb = megaCfg->qPendingH; pScb; pScb = pScb->next) {
  2.4071 +		if (pScb->SCpnt == SCpnt) {
  2.4072 +			/* Found an aborting command */
  2.4073 +#if DEBUG
  2.4074 +			showMbox (pScb);
  2.4075 +#endif
  2.4076 +
  2.4077 +	/*
  2.4078 +	 * If the command is queued to be issued to the firmware, abort the scsi cmd,
  2.4079 +	 * If the command is already aborted in a previous call to the _abort entry
  2.4080 +	 *  point, return SCSI_ABORT_SNOOZE, suggesting a reset.
  2.4081 +	 * If the command is issued to the firmware, which might complete after
  2.4082 +	 *  some time, we will mark the scb as aborted, and return to the mid layer,
  2.4083 +	 *  that abort could not be done.
  2.4084 +	 *  In the ISR, when this command actually completes, we will perform a normal
  2.4085 +	 *  completion.
  2.4086 +	 *
  2.4087 +	 * Oct 27, 1999
  2.4088 +	 */
  2.4089 +
  2.4090 +			switch (pScb->state) {
  2.4091 +			case SCB_ABORTED:	/* Already aborted */
  2.4092 +				rc = SCSI_ABORT_SNOOZE;
  2.4093 +				break;
  2.4094 +			case SCB_ISSUED:	/* Waiting on ISR result */
  2.4095 +				rc = SCSI_ABORT_NOT_RUNNING;
  2.4096 +				pScb->state = SCB_ABORTED;
  2.4097 +				break;
  2.4098 +			case SCB_ACTIVE:	/* still on the pending queue */
  2.4099 +				mega_freeSCB (megaCfg, pScb);
  2.4100 +				SCpnt->result = (DID_ABORT << 16);
  2.4101 +				if (megaCfg->qCompletedH == NULL) {
  2.4102 +					megaCfg->qCompletedH =
  2.4103 +					    megaCfg->qCompletedT = SCpnt;
  2.4104 +				} else {
  2.4105 +					megaCfg->qCompletedT->host_scribble =
  2.4106 +					    (unsigned char *) SCpnt;
  2.4107 +					megaCfg->qCompletedT = SCpnt;
  2.4108 +				}
  2.4109 +				megaCfg->qCompletedT->host_scribble =
  2.4110 +				    (unsigned char *) NULL;
  2.4111 +				megaCfg->qCcnt++;
  2.4112 +				rc = SCSI_ABORT_SUCCESS;
  2.4113 +				break;
  2.4114 +			default:
  2.4115 +				printk
  2.4116 +				    ("megaraid_abort: unknown command state!!\n");
  2.4117 +				rc = SCSI_ABORT_NOT_RUNNING;
  2.4118 +				break;
  2.4119 +			}
  2.4120 +			break;
  2.4121 +		}
  2.4122 +	}
  2.4123 +
  2.4124 +	megaCfg->flag &= ~IN_ABORT;
  2.4125 +
  2.4126 +#if DEBUG
  2.4127 +	if (megaCfg->flag & IN_QUEUE)
  2.4128 +		printk ("ma:flag is in queue\n");
  2.4129 +	if (megaCfg->qCompletedH == NULL)
  2.4130 +		printk ("ma:qchead == null\n");
  2.4131 +#endif
  2.4132 +
  2.4133 +	/*
  2.4134 +	 * This is required here to complete any completed requests to be communicated
  2.4135 +	 * over to the mid layer.
  2.4136 +	 * Calling just mega_rundoneq() did not work.
  2.4137 +	 */
  2.4138 +	if (megaCfg->qCompletedH) {
  2.4139 +		SCpnt = megaCfg->qCompletedH;
  2.4140 +		megaCfg->qCompletedH = (Scsi_Cmnd *) SCpnt->host_scribble;
  2.4141 +		megaCfg->qCcnt--;
  2.4142 +
  2.4143 +		SCpnt->host_scribble = (unsigned char *) NULL;
  2.4144 +		/* Callback */
  2.4145 +		callDone (SCpnt);
  2.4146 +	}
  2.4147 +	mega_rundoneq (megaCfg);
  2.4148 +
  2.4149 +	return rc;
  2.4150 +}
  2.4151 +
  2.4152 +/*---------------------------------------------------------------------
  2.4153 + * Reset a previous SCSI request
  2.4154 + *---------------------------------------------------------------------*/
  2.4155 +
  2.4156 +int megaraid_reset (Scsi_Cmnd * SCpnt, unsigned int rstflags)
  2.4157 +{
  2.4158 +	mega_host_config *megaCfg;
  2.4159 +	int idx;
  2.4160 +	int rc;
  2.4161 +	mega_scb *pScb;
  2.4162 +
  2.4163 +	rc = SCSI_RESET_NOT_RUNNING;
  2.4164 +	megaCfg = (mega_host_config *) SCpnt->host->hostdata;
  2.4165 +
  2.4166 +	megaCfg->flag |= IN_RESET;
  2.4167 +
  2.4168 +	printk
  2.4169 +	    ("megaraid_RESET: %.08lx cmd=%.02x <c=%d.t=%d.l=%d>, flag = %x\n",
  2.4170 +	     SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel,
  2.4171 +	     SCpnt->target, SCpnt->lun, rstflags);
  2.4172 +
  2.4173 +	TRACE (("RESET: %.08lx %.02x <%d.%d.%d>\n",
  2.4174 +		SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel,
  2.4175 +		SCpnt->target, SCpnt->lun));
  2.4176 +
  2.4177 +	/*
  2.4178 +	 * Walk list of SCBs for any that are still outstanding
  2.4179 +	 */
  2.4180 +	for (idx = 0; idx < megaCfg->max_cmds; idx++) {
  2.4181 +		if (megaCfg->scbList[idx].state != SCB_FREE) {
  2.4182 +			SCpnt = megaCfg->scbList[idx].SCpnt;
  2.4183 +			pScb = &megaCfg->scbList[idx];
  2.4184 +			if (SCpnt != NULL) {
  2.4185 +				pScb->state = SCB_RESET;
  2.4186 +				break;
  2.4187 +			}
  2.4188 +		}
  2.4189 +	}
  2.4190 +
  2.4191 +	megaCfg->flag &= ~IN_RESET;
  2.4192 +
  2.4193 +	mega_rundoneq (megaCfg);
  2.4194 +	return rc;
  2.4195 +}
  2.4196 +
  2.4197 +#ifdef CONFIG_PROC_FS
  2.4198 +/* Following code handles /proc fs  */
  2.4199 +static int proc_printf (mega_host_config * megaCfg, const char *fmt, ...)
  2.4200 +{
  2.4201 +	va_list args;
  2.4202 +	int i;
  2.4203 +
  2.4204 +	if (megaCfg->procidx > PROCBUFSIZE)
  2.4205 +		return 0;
  2.4206 +
  2.4207 +	va_start (args, fmt);
  2.4208 +	i = vsprintf ((megaCfg->procbuf + megaCfg->procidx), fmt, args);
  2.4209 +	va_end (args);
  2.4210 +
  2.4211 +	megaCfg->procidx += i;
  2.4212 +	return i;
  2.4213 +}
  2.4214 +
  2.4215 +static int proc_read_config (char *page, char **start, off_t offset,
  2.4216 +		  int count, int *eof, void *data)
  2.4217 +{
  2.4218 +
  2.4219 +	mega_host_config *megaCfg = (mega_host_config *) data;
  2.4220 +
  2.4221 +	*start = page;
  2.4222 +
  2.4223 +	if (megaCfg->productInfo.ProductName[0] != 0)
  2.4224 +		proc_printf (megaCfg, "%s\n", megaCfg->productInfo.ProductName);
  2.4225 +
  2.4226 +	proc_printf (megaCfg, "Controller Type: ");
  2.4227 +
  2.4228 +	if (megaCfg->flag & BOARD_QUARTZ)
  2.4229 +		proc_printf (megaCfg, "438/466/467/471/493\n");
  2.4230 +	else
  2.4231 +		proc_printf (megaCfg, "418/428/434\n");
  2.4232 +
  2.4233 +	if (megaCfg->flag & BOARD_40LD)
  2.4234 +		proc_printf (megaCfg,
  2.4235 +			     "Controller Supports 40 Logical Drives\n");
  2.4236 +
  2.4237 +	if (megaCfg->flag & BOARD_64BIT)
  2.4238 +		proc_printf (megaCfg,
  2.4239 +			     "Controller / Driver uses 64 bit memory addressing\n");
  2.4240 +
  2.4241 +	proc_printf (megaCfg, "Base = %08x, Irq = %d, ", megaCfg->base,
  2.4242 +		     megaCfg->host->irq);
  2.4243 +
  2.4244 +	proc_printf (megaCfg, "Logical Drives = %d, Channels = %d\n",
  2.4245 +		     megaCfg->numldrv, megaCfg->productInfo.SCSIChanPresent);
  2.4246 +
  2.4247 +	proc_printf (megaCfg, "Version =%s:%s, DRAM = %dMb\n",
  2.4248 +		     megaCfg->fwVer, megaCfg->biosVer,
  2.4249 +		     megaCfg->productInfo.DramSize);
  2.4250 +
  2.4251 +	proc_printf (megaCfg,
  2.4252 +		     "Controller Queue Depth = %d, Driver Queue Depth = %d\n",
  2.4253 +		     megaCfg->productInfo.MaxConcCmds, megaCfg->max_cmds);
  2.4254 +	COPY_BACK;
  2.4255 +	return count;
  2.4256 +}
  2.4257 +
  2.4258 +static int proc_read_stat (char *page, char **start, off_t offset,
  2.4259 +		int count, int *eof, void *data)
  2.4260 +{
  2.4261 +	int i;
  2.4262 +	mega_host_config *megaCfg = (mega_host_config *) data;
  2.4263 +
  2.4264 +	*start = page;
  2.4265 +
  2.4266 +	proc_printf (megaCfg, "Statistical Information for this controller\n");
  2.4267 +	proc_printf (megaCfg, "Interrupts Collected = %lu\n",
  2.4268 +		     megaCfg->nInterrupts);
  2.4269 +
  2.4270 +	for (i = 0; i < megaCfg->numldrv; i++) {
  2.4271 +		proc_printf (megaCfg, "Logical Drive %d:\n", i);
  2.4272 +
  2.4273 +		proc_printf (megaCfg,
  2.4274 +			     "\tReads Issued = %lu, Writes Issued = %lu\n",
  2.4275 +			     megaCfg->nReads[i], megaCfg->nWrites[i]);
  2.4276 +
  2.4277 +		proc_printf (megaCfg,
  2.4278 +			     "\tSectors Read = %lu, Sectors Written = %lu\n\n",
  2.4279 +			     megaCfg->nReadBlocks[i], megaCfg->nWriteBlocks[i]);
  2.4280 +
  2.4281 +	}
  2.4282 +
  2.4283 +	COPY_BACK;
  2.4284 +	return count;
  2.4285 +}
  2.4286 +
  2.4287 +static int proc_read_status (char *page, char **start, off_t offset,
  2.4288 +		  int count, int *eof, void *data)
  2.4289 +{
  2.4290 +	mega_host_config *megaCfg = (mega_host_config *) data;
  2.4291 +	*start = page;
  2.4292 +
  2.4293 +	proc_printf (megaCfg, "TBD\n");
  2.4294 +	COPY_BACK;
  2.4295 +	return count;
  2.4296 +}
  2.4297 +
  2.4298 +static int proc_read_mbox (char *page, char **start, off_t offset,
  2.4299 +		int count, int *eof, void *data)
  2.4300 +{
  2.4301 +
  2.4302 +	mega_host_config *megaCfg = (mega_host_config *) data;
  2.4303 +	volatile mega_mailbox *mbox = megaCfg->mbox;
  2.4304 +
  2.4305 +	*start = page;
  2.4306 +
  2.4307 +	proc_printf (megaCfg, "Contents of Mail Box Structure\n");
  2.4308 +	proc_printf (megaCfg, "  Fw Command   = 0x%02x\n", mbox->cmd);
  2.4309 +	proc_printf (megaCfg, "  Cmd Sequence = 0x%02x\n", mbox->cmdid);
  2.4310 +	proc_printf (megaCfg, "  No of Sectors= %04d\n", mbox->numsectors);
  2.4311 +	proc_printf (megaCfg, "  LBA          = 0x%02x\n", mbox->lba);
  2.4312 +	proc_printf (megaCfg, "  DTA          = 0x%08x\n", mbox->xferaddr);
  2.4313 +	proc_printf (megaCfg, "  Logical Drive= 0x%02x\n", mbox->logdrv);
  2.4314 +	proc_printf (megaCfg, "  No of SG Elmt= 0x%02x\n", mbox->numsgelements);
  2.4315 +	proc_printf (megaCfg, "  Busy         = %01x\n", mbox->busy);
  2.4316 +	proc_printf (megaCfg, "  Status       = 0x%02x\n", mbox->status);
  2.4317 +
  2.4318 +	/* proc_printf(megaCfg, "Dump of MailBox\n");
  2.4319 +	for (i = 0; i < 16; i++)
  2.4320 +        	proc_printf(megaCfg, "%02x ",*(mbox + i));
  2.4321 +
  2.4322 +	proc_printf(megaCfg, "\n\nNumber of Status = %02d\n",mbox->numstatus);
  2.4323 +
  2.4324 +	for (i = 0; i < 46; i++) {
  2.4325 +        	proc_printf(megaCfg,"%02d ",*(mbox + 16 + i));
  2.4326 +        if (i%16)
  2.4327 +                proc_printf(megaCfg,"\n");
  2.4328 +	}
  2.4329 +
  2.4330 +	if (!mbox->numsgelements) {
  2.4331 +	        dta = phys_to_virt(mbox->xferaddr);
  2.4332 +	        for (i = 0; i < mbox->numsgelements; i++)
  2.4333 +	                if (dta) {
  2.4334 +	                        proc_printf(megaCfg,"Addr = %08x\n", (ulong)*(dta + i));                        proc_printf(megaCfg,"Length = %08x\n",
  2.4335 +	                                (ulong)*(dta + i + 4));
  2.4336 +	                }
  2.4337 +	}*/
  2.4338 +	COPY_BACK;
  2.4339 +	return count;
  2.4340 +}
  2.4341 +
  2.4342 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)	/*0x20300 */
  2.4343 +#define CREATE_READ_PROC(string, fxn) create_proc_read_entry(string, \
  2.4344 +                                         S_IRUSR | S_IFREG,\
  2.4345 +                                         controller_proc_dir_entry,\
  2.4346 +                                         fxn, megaCfg)
  2.4347 +#else
  2.4348 +#define CREATE_READ_PROC(string, fxn) create_proc_read_entry(string,S_IRUSR | S_IFREG, controller_proc_dir_entry, fxn, megaCfg)
  2.4349 +
  2.4350 +static struct proc_dir_entry *
  2.4351 +create_proc_read_entry (const char *string,
  2.4352 +			int mode,
  2.4353 +			struct proc_dir_entry *parent,
  2.4354 +			read_proc_t * fxn, mega_host_config * megaCfg)
  2.4355 +{
  2.4356 +	struct proc_dir_entry *temp = NULL;
  2.4357 +
  2.4358 +	temp = kmalloc (sizeof (struct proc_dir_entry), GFP_KERNEL);
  2.4359 +	if (!temp)
  2.4360 +		return NULL;
  2.4361 +	memset (temp, 0, sizeof (struct proc_dir_entry));
  2.4362 +
  2.4363 +	if ((temp->name = kmalloc (strlen (string) + 1, GFP_KERNEL)) == NULL) {
  2.4364 +		kfree (temp);
  2.4365 +		return NULL;
  2.4366 +	}
  2.4367 +
  2.4368 +	strcpy ((char *) temp->name, string);
  2.4369 +	temp->namelen = strlen (string);
  2.4370 +	temp->mode = mode; /*S_IFREG | S_IRUSR */ ;
  2.4371 +	temp->data = (void *) megaCfg;
  2.4372 +	temp->read_proc = fxn;
  2.4373 +	proc_register (parent, temp);
  2.4374 +	return temp;
  2.4375 +}
  2.4376 +#endif
  2.4377 +
  2.4378 +static void mega_create_proc_entry (int index, struct proc_dir_entry *parent)
  2.4379 +{
  2.4380 +	u_char string[64] = { 0 };
  2.4381 +	mega_host_config *megaCfg = megaCtlrs[index];
  2.4382 +	struct proc_dir_entry *controller_proc_dir_entry = NULL;
  2.4383 +
  2.4384 +	sprintf (string, "%d", index);
  2.4385 +
  2.4386 +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0)	/*0x20300 */
  2.4387 +	controller_proc_dir_entry =
  2.4388 +	    megaCfg->controller_proc_dir_entry = proc_mkdir (string, parent);
  2.4389 +#else
  2.4390 +	controller_proc_dir_entry =
  2.4391 +	    megaCfg->controller_proc_dir_entry =
  2.4392 +	    create_proc_entry (string, S_IFDIR | S_IRUGO | S_IXUGO, parent);
  2.4393 +#endif
  2.4394 +
  2.4395 +	if (!controller_proc_dir_entry)
  2.4396 +		printk ("\nmegaraid: proc_mkdir failed\n");
  2.4397 +	else {
  2.4398 +		megaCfg->proc_read =
  2.4399 +		    CREATE_READ_PROC ("config", proc_read_config);
  2.4400 +		megaCfg->proc_status =
  2.4401 +		    CREATE_READ_PROC ("status", proc_read_status);
  2.4402 +		megaCfg->proc_stat = CREATE_READ_PROC ("stat", proc_read_stat);
  2.4403 +		megaCfg->proc_mbox =
  2.4404 +		    CREATE_READ_PROC ("mailbox", proc_read_mbox);
  2.4405 +	}
  2.4406 +
  2.4407 +}
  2.4408 +#endif				/* CONFIG_PROC_FS */
  2.4409 +
  2.4410 +/*-------------------------------------------------------------
  2.4411 + * Return the disk geometry for a particular disk
  2.4412 + * Input:
  2.4413 + *   Disk *disk - Disk geometry
  2.4414 + *   kdev_t dev - Device node
  2.4415 + *   int *geom  - Returns geometry fields
  2.4416 + *     geom[0] = heads
  2.4417 + *     geom[1] = sectors
  2.4418 + *     geom[2] = cylinders
  2.4419 + *-------------------------------------------------------------*/
  2.4420 +int megaraid_biosparam (Disk * disk, kdev_t dev, int *geom)
  2.4421 +{
  2.4422 +	int heads, sectors, cylinders;
  2.4423 +	mega_host_config *megaCfg;
  2.4424 +
  2.4425 +	/* Get pointer to host config structure */
  2.4426 +	megaCfg = (mega_host_config *) disk->device->host->hostdata;
  2.4427 +
  2.4428 +	if( IS_RAID_CH(megaCfg, disk->device->channel)) {
  2.4429 +			/* Default heads (64) & sectors (32) */
  2.4430 +			heads = 64;
  2.4431 +			sectors = 32;
  2.4432 +			cylinders = disk->capacity / (heads * sectors);
  2.4433 +
  2.4434 +			/* Handle extended translation size for logical drives > 1Gb */
  2.4435 +			if (disk->capacity >= 0x200000) {
  2.4436 +				heads = 255;
  2.4437 +				sectors = 63;
  2.4438 +				cylinders = disk->capacity / (heads * sectors);
  2.4439 +			}
  2.4440 +
  2.4441 +			/* return result */
  2.4442 +			geom[0] = heads;
  2.4443 +			geom[1] = sectors;
  2.4444 +			geom[2] = cylinders;
  2.4445 +	}
  2.4446 +	else {
  2.4447 +		if( mega_partsize(disk, dev, geom) == 0 ) return 0;
  2.4448 +
  2.4449 +		printk(KERN_WARNING
  2.4450 +				"megaraid: invalid partition on this disk on channel %d\n",
  2.4451 +				disk->device->channel);
  2.4452 +
  2.4453 +		/* Default heads (64) & sectors (32) */
  2.4454 +		heads = 64;
  2.4455 +		sectors = 32;
  2.4456 +		cylinders = disk->capacity / (heads * sectors);
  2.4457 +
  2.4458 +		/* Handle extended translation size for logical drives > 1Gb */
  2.4459 +		if (disk->capacity >= 0x200000) {
  2.4460 +			heads = 255;
  2.4461 +			sectors = 63;
  2.4462 +			cylinders = disk->capacity / (heads * sectors);
  2.4463 +		}
  2.4464 +
  2.4465 +		/* return result */
  2.4466 +		geom[0] = heads;
  2.4467 +		geom[1] = sectors;
  2.4468 +		geom[2] = cylinders;
  2.4469 +	}
  2.4470 +
  2.4471 +	return 0;
  2.4472 +}
  2.4473 +
  2.4474 +/*
  2.4475 + * Function : static int mega_partsize(Disk * disk, kdev_t dev, int *geom)
  2.4476 + *
  2.4477 + * Purpose : to determine the BIOS mapping used to create the partition
  2.4478 + *			table, storing the results (cyls, hds, and secs) in geom
  2.4479 + *
  2.4480 + * Note:	Code is picked from scsicam.h
  2.4481 + *
  2.4482 + * Returns : -1 on failure, 0 on success.
  2.4483 + */
  2.4484 +static int
  2.4485 +mega_partsize(Disk * disk, kdev_t dev, int *geom)
  2.4486 +{
  2.4487 +#if XENO_KILLED
  2.4488 +	struct buffer_head *bh;
  2.4489 +	struct partition *p, *largest = NULL;
  2.4490 +	int i, largest_cyl;
  2.4491 +	int heads, cyls, sectors;
  2.4492 +	int capacity = disk->capacity;
  2.4493 +
  2.4494 +	int ma = MAJOR(dev);
  2.4495 +	int mi = (MINOR(dev) & ~0xf);
  2.4496 +
  2.4497 +	int block = 1024; 
  2.4498 +
  2.4499 +
  2.4500 +	if(blksize_size[ma])
  2.4501 +		block = blksize_size[ma][mi];
  2.4502 +		
  2.4503 +	if(!(bh = bread(MKDEV(ma,mi), 0, block)))
  2.4504 +		return -1;
  2.4505 +
  2.4506 +	if( *(unsigned short *)(bh->b_data + 510) == 0xAA55 ) {
  2.4507 +
  2.4508 +		for( largest_cyl = -1, p = (struct partition *)(0x1BE + bh->b_data),
  2.4509 +				i = 0; i < 4; ++i, ++p) {
  2.4510 +
  2.4511 +			if (!p->sys_ind) continue;
  2.4512 +
  2.4513 +			cyls = p->end_cyl + ((p->end_sector & 0xc0) << 2);
  2.4514 +
  2.4515 +			if(cyls >= largest_cyl) {
  2.4516 +				largest_cyl = cyls;
  2.4517 +				largest = p;
  2.4518 +			}
  2.4519 +		}
  2.4520 +	}
  2.4521 +
  2.4522 +	if (largest) {
  2.4523 +		heads = largest->end_head + 1;
  2.4524 +		sectors = largest->end_sector & 0x3f;
  2.4525 +
  2.4526 +		if (heads == 0 || sectors == 0) {
  2.4527 +			brelse(bh);
  2.4528 +			return -1;
  2.4529 +		}
  2.4530 +
  2.4531 +		cyls = capacity/(heads * sectors);
  2.4532 +
  2.4533 +		geom[0] = heads;
  2.4534 +		geom[1] = sectors;
  2.4535 +		geom[2] = cyls;
  2.4536 +
  2.4537 +		brelse(bh);
  2.4538 +		return 0;
  2.4539 +	}
  2.4540 +
  2.4541 +	brelse(bh);
  2.4542 +#endif
  2.4543 +	return -1;
  2.4544 +}
  2.4545 +
  2.4546 +
  2.4547 +/*
  2.4548 + * This routine will be called when the use has done a forced shutdown on the
  2.4549 + * system. Flush the Adapter cache, that's the most we can do.
  2.4550 + */
  2.4551 +static int megaraid_reboot_notify (struct notifier_block *this, unsigned long code,
  2.4552 +			void *unused)
  2.4553 +{
  2.4554 +	struct Scsi_Host *pSHost;
  2.4555 +	mega_host_config *megaCfg;
  2.4556 +	mega_mailbox *mbox;
  2.4557 +	u_char mboxData[16];
  2.4558 +	int i;
  2.4559 +
  2.4560 +	if (code == SYS_DOWN || code == SYS_HALT) {
  2.4561 +		for (i = 0; i < numCtlrs; i++) {
  2.4562 +			pSHost = megaCtlrs[i]->host;
  2.4563 +
  2.4564 +			megaCfg = (mega_host_config *) pSHost->hostdata;
  2.4565 +			mbox = (mega_mailbox *) mboxData;
  2.4566 +
  2.4567 +			/* Flush cache to disk */
  2.4568 +			memset (mbox, 0, 16);
  2.4569 +			mboxData[0] = 0xA;
  2.4570 +
  2.4571 +			/*
  2.4572 +			 * Free irq, otherwise extra interrupt is generated
  2.4573 +			 */
  2.4574 +			free_irq (megaCfg->host->irq, megaCfg);
  2.4575 +
  2.4576 +			/*
  2.4577 +			   * Issue a blocking (interrupts disabled) command to
  2.4578 +			   * the card
  2.4579 +			 */
  2.4580 +			megaIssueCmd (megaCfg, mboxData, NULL, 0);
  2.4581 +		}
  2.4582 +	}
  2.4583 +	return NOTIFY_DONE;
  2.4584 +}
  2.4585 +
  2.4586 +static int mega_init_scb (mega_host_config * megacfg)
  2.4587 +{
  2.4588 +	int idx;
  2.4589 +
  2.4590 +#if DEBUG
  2.4591 +	if (megacfg->max_cmds >= MAX_COMMANDS) {
  2.4592 +		printk ("megaraid:ctlr max cmds = %x : MAX_CMDS = %x",
  2.4593 +			megacfg->max_cmds, MAX_COMMANDS);
  2.4594 +	}
  2.4595 +#endif
  2.4596 +
  2.4597 +	for (idx = megacfg->max_cmds - 1; idx >= 0; idx--) {
  2.4598 +
  2.4599 +		megacfg->scbList[idx].idx = idx;
  2.4600 +
  2.4601 +		/*
  2.4602 +		 * ISR will make this flag zero to indicate the command has been
  2.4603 +		 * completed. This is only for user ioctl calls. Rest of the driver
  2.4604 +		 * and the mid-layer operations are not connected with this flag.
  2.4605 +		 */
  2.4606 +
  2.4607 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.4608 +		megacfg->scbList[idx].sgList =
  2.4609 +		    pci_alloc_consistent (megacfg->dev,
  2.4610 +					  sizeof (mega_64sglist) * MAX_SGLIST,
  2.4611 +					  &(megacfg->scbList[idx].
  2.4612 +					    dma_sghandle64));
  2.4613 +
  2.4614 +		megacfg->scbList[idx].sg64List =
  2.4615 +		    (mega_64sglist *) megacfg->scbList[idx].sgList;
  2.4616 +#else
  2.4617 +		megacfg->scbList[idx].sgList = kmalloc (sizeof (mega_sglist) * MAX_SGLIST, GFP_ATOMIC | GFP_DMA);
  2.4618 +#endif
  2.4619 +
  2.4620 +		if (megacfg->scbList[idx].sgList == NULL) {
  2.4621 +			printk (KERN_WARNING
  2.4622 +				"Can't allocate sglist for id %d\n", idx);
  2.4623 +			mega_freeSgList (megacfg);
  2.4624 +			return -1;
  2.4625 +		}
  2.4626 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.4627 +		megacfg->scbList[idx].pthru = pci_alloc_consistent (megacfg->dev,
  2.4628 +					  sizeof (mega_passthru),
  2.4629 +					  &(megacfg->scbList[idx].
  2.4630 +					    dma_passthruhandle64));
  2.4631 +
  2.4632 +		if (megacfg->scbList[idx].pthru == NULL) {
  2.4633 +			printk (KERN_WARNING
  2.4634 +				"Can't allocate passthru for id %d\n", idx);
  2.4635 +		}
  2.4636 +
  2.4637 +		megacfg->scbList[idx].epthru =
  2.4638 +			pci_alloc_consistent(
  2.4639 +				megacfg->dev, sizeof(mega_ext_passthru),
  2.4640 +				&(megacfg->scbList[idx].dma_ext_passthruhandle64)
  2.4641 +			);
  2.4642 +
  2.4643 +		if (megacfg->scbList[idx].epthru == NULL) {
  2.4644 +			printk (KERN_WARNING
  2.4645 +				"Can't allocate extended passthru for id %d\n", idx);
  2.4646 +		}
  2.4647 +		/* 
  2.4648 +		 * Allocate a 256 Byte Bounce Buffer for handling INQ/RD_CAPA 
  2.4649 +		 */
  2.4650 +		megacfg->scbList[idx].bounce_buffer = pci_alloc_consistent (megacfg->dev,
  2.4651 +					  256,
  2.4652 +					  &(megacfg->scbList[idx].
  2.4653 +					    dma_bounce_buffer));
  2.4654 +
  2.4655 +		if (!megacfg->scbList[idx].bounce_buffer)
  2.4656 +			printk
  2.4657 +			    ("megaraid: allocation for bounce buffer failed\n");
  2.4658 +
  2.4659 +		megacfg->scbList[idx].dma_type = M_RD_DMA_TYPE_NONE;
  2.4660 +#endif
  2.4661 +
  2.4662 +		if (idx < MAX_COMMANDS) {
  2.4663 +			/*
  2.4664 +			 * Link to free list
  2.4665 +			 * lock not required since we are loading the driver, so no
  2.4666 +			 * commands possible right now.
  2.4667 +			 */
  2.4668 +			enq_scb_freelist (megacfg, &megacfg->scbList[idx],
  2.4669 +					  NO_LOCK, INTR_ENB);
  2.4670 +
  2.4671 +		}
  2.4672 +	}
  2.4673 +
  2.4674 +	return 0;
  2.4675 +}
  2.4676 +
  2.4677 +/*
  2.4678 + * Enqueues a SCB
  2.4679 + */
  2.4680 +static void enq_scb_freelist (mega_host_config * megacfg, mega_scb * scb, int lock,
  2.4681 +		  int intr)
  2.4682 +{
  2.4683 +
  2.4684 +	if (lock == INTERNAL_LOCK || intr == INTR_DIS) {
  2.4685 +		if (intr == INTR_DIS)
  2.4686 +			spin_lock_irq (&megacfg->lock_free);
  2.4687 +		else
  2.4688 +			spin_lock (&megacfg->lock_free);
  2.4689 +	}
  2.4690 +
  2.4691 +	scb->state = SCB_FREE;
  2.4692 +	scb->SCpnt = NULL;
  2.4693 +
  2.4694 +	if (megacfg->qFreeH == (mega_scb *) NULL) {
  2.4695 +		megacfg->qFreeH = megacfg->qFreeT = scb;
  2.4696 +	} else {
  2.4697 +		megacfg->qFreeT->next = scb;
  2.4698 +		megacfg->qFreeT = scb;
  2.4699 +	}
  2.4700 +
  2.4701 +	megacfg->qFreeT->next = NULL;
  2.4702 +	megacfg->qFcnt++;
  2.4703 +
  2.4704 +	if (lock == INTERNAL_LOCK || intr == INTR_DIS) {
  2.4705 +		if (intr == INTR_DIS)
  2.4706 +			spin_unlock_irq (&megacfg->lock_free);
  2.4707 +		else
  2.4708 +			spin_unlock (&megacfg->lock_free);
  2.4709 +	}
  2.4710 +}
  2.4711 +
  2.4712 +/*
  2.4713 + * Routines for the character/ioctl interface to the driver
  2.4714 + */
  2.4715 +static int megadev_open (struct inode *inode, struct file *filep)
  2.4716 +{
  2.4717 +	MOD_INC_USE_COUNT;
  2.4718 +	return 0;		/* success */
  2.4719 +}
  2.4720 +
  2.4721 +static int megadev_ioctl_entry (struct inode *inode, struct file *filep,
  2.4722 +		     unsigned int cmd, unsigned long arg)
  2.4723 +{
  2.4724 +	int ret = -1;
  2.4725 +
  2.4726 +	/*
  2.4727 +	 * We do not allow parallel ioctls to the driver as of now.
  2.4728 +	 */
  2.4729 +#if XENO_KILLED // XXX JWS killed the locking!
  2.4730 +	down (&mimd_entry_mtx);
  2.4731 +	ret = megadev_ioctl (inode, filep, cmd, arg);
  2.4732 +	up (&mimd_entry_mtx);
  2.4733 +#else
  2.4734 +	ret = megadev_ioctl (inode, filep, cmd, arg);
  2.4735 +#endif
  2.4736 +
  2.4737 +	return ret;
  2.4738 +
  2.4739 +}
  2.4740 +
  2.4741 +static int megadev_ioctl (struct inode *inode, struct file *filep,
  2.4742 +	       unsigned int cmd, unsigned long arg)
  2.4743 +{
  2.4744 +	int adapno;
  2.4745 +	kdev_t dev;
  2.4746 +	u32 inlen;
  2.4747 +	struct uioctl_t ioc;
  2.4748 +	char *kvaddr = NULL;
  2.4749 +	int nadap = numCtlrs;
  2.4750 +	u8 opcode;
  2.4751 +	u32 outlen;
  2.4752 +	int ret;
  2.4753 +	u8 subopcode;
  2.4754 +	Scsi_Cmnd *scsicmd;
  2.4755 +	struct Scsi_Host *shpnt;
  2.4756 +	char *uaddr;
  2.4757 +	struct uioctl_t *uioc;
  2.4758 +	dma_addr_t	dma_addr;
  2.4759 +	u32		length;
  2.4760 +	mega_host_config *megacfg = NULL;
  2.4761 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)	/* 0x020400 */
  2.4762 +	struct pci_dev pdev;
  2.4763 +	struct pci_dev *pdevp = &pdev;
  2.4764 +#else
  2.4765 +	char *pdevp = NULL;
  2.4766 +#endif
  2.4767 +	IO_LOCK_T;
  2.4768 +
  2.4769 +	if (!inode || !(dev = inode->i_rdev))
  2.4770 +		return -EINVAL;
  2.4771 +
  2.4772 +	if (_IOC_TYPE (cmd) != MEGAIOC_MAGIC)
  2.4773 +		return (-EINVAL);
  2.4774 +
  2.4775 +	/*
  2.4776 +	 * Get the user ioctl structure
  2.4777 +	 */
  2.4778 +	ret = verify_area (VERIFY_WRITE, (char *) arg, sizeof (struct uioctl_t));
  2.4779 +
  2.4780 +	if (ret)
  2.4781 +		return ret;
  2.4782 +
  2.4783 +	if(copy_from_user (&ioc, (char *) arg, sizeof (struct uioctl_t)))
  2.4784 +		return -EFAULT;
  2.4785 +
  2.4786 +	/*
  2.4787 +	 * The first call the applications should make is to find out the
  2.4788 +	 * number of controllers in the system. The next logical call should
  2.4789 +	 * be for getting the list of controllers in the system as detected
  2.4790 +	 * by the driver.
  2.4791 +	 */
  2.4792 +
  2.4793 +	/*
  2.4794 +	 * Get the opcode and subopcode for the commands
  2.4795 +	 */
  2.4796 +	opcode = ioc.ui.fcs.opcode;
  2.4797 +	subopcode = ioc.ui.fcs.subopcode;
  2.4798 +
  2.4799 +	switch (opcode) {
  2.4800 +	case M_RD_DRIVER_IOCTL_INTERFACE:
  2.4801 +		switch (subopcode) {
  2.4802 +		case MEGAIOC_QDRVRVER:	/* Query driver version */
  2.4803 +			put_user (driver_ver, (u32 *) ioc.data);
  2.4804 +			return 0;
  2.4805 +
  2.4806 +		case MEGAIOC_QNADAP:	/* Get # of adapters */
  2.4807 +			put_user (nadap, (int *) ioc.data);
  2.4808 +			return nadap;
  2.4809 +
  2.4810 +		case MEGAIOC_QADAPINFO:	/* Get adapter information */
  2.4811 +			/*
  2.4812 +			 * which adapter?
  2.4813 +			 */
  2.4814 +			adapno = ioc.ui.fcs.adapno;
  2.4815 +
  2.4816 +			/*
  2.4817 +			 * The adapter numbers do not start with 0, at least in
  2.4818 +			 * the user space. This is just to make sure, 0 is not the
  2.4819 +			 * default value which will refer to adapter 1. So the
  2.4820 +			 * user needs to make use of macros MKADAP() and GETADAP()
  2.4821 +			 * (See megaraid.h) while making ioctl() call.
  2.4822 +			 */
  2.4823 +			adapno = GETADAP (adapno);
  2.4824 +
  2.4825 +			if (adapno >= numCtlrs)
  2.4826 +				return (-ENODEV);
  2.4827 +
  2.4828 +			ret = verify_area (VERIFY_WRITE,
  2.4829 +					   ioc.data,
  2.4830 +					   sizeof (struct mcontroller));
  2.4831 +			if (ret)
  2.4832 +				return ret;
  2.4833 +
  2.4834 +			/*
  2.4835 +			 * Copy struct mcontroller to user area
  2.4836 +			 */
  2.4837 +			if (copy_to_user (ioc.data,
  2.4838 +				      mcontroller + adapno,
  2.4839 +				      sizeof (struct mcontroller)))
  2.4840 +				      return -EFAULT;
  2.4841 +			return 0;
  2.4842 +
  2.4843 +		default:
  2.4844 +			return (-EINVAL);
  2.4845 +
  2.4846 +		}		/* inner switch */
  2.4847 +		break;
  2.4848 +
  2.4849 +	case M_RD_IOCTL_CMD_NEW:
  2.4850 +
  2.4851 +		/*
  2.4852 +		 * Deletion of logical drives is only handled in 0x80 commands
  2.4853 +		 */
  2.4854 +		if( ioc.mbox[0] == FC_DEL_LOGDRV && ioc.mbox[2] == OP_DEL_LOGDRV ) {
  2.4855 +			return -EINVAL;
  2.4856 +		}
  2.4857 +
  2.4858 +		/* which adapter?  */
  2.4859 +		adapno = ioc.ui.fcs.adapno;
  2.4860 +
  2.4861 +		/* See comment above: MEGAIOC_QADAPINFO */
  2.4862 +		adapno = GETADAP(adapno);
  2.4863 +
  2.4864 +		if (adapno >= numCtlrs)
  2.4865 +			return(-ENODEV);
  2.4866 +
  2.4867 +		length = ioc.ui.fcs.length;
  2.4868 +
  2.4869 +		/* Check for zero length buffer or very large buffers */
  2.4870 +		if( !length || length > 32*1024 )
  2.4871 +			return -EINVAL;
  2.4872 +
  2.4873 +		/* save the user address */
  2.4874 +		uaddr = ioc.ui.fcs.buffer;
  2.4875 +
  2.4876 +		/*
  2.4877 +		 * For M_RD_IOCTL_CMD_NEW commands, the fields outlen and inlen of
  2.4878 +		 * uioctl_t structure are treated as flags. If outlen is 1, the
  2.4879 +		 * data is transferred from the device and if inlen is 1, the data
  2.4880 +		 * is transferred to the device.
  2.4881 +		 */
  2.4882 +		outlen = ioc.outlen;
  2.4883 +		inlen = ioc.inlen;
  2.4884 +
  2.4885 +		if(outlen) {
  2.4886 +			ret = verify_area(VERIFY_WRITE, (char *)ioc.ui.fcs.buffer, length);
  2.4887 +			if (ret) return ret;
  2.4888 +		}
  2.4889 +		if(inlen) {
  2.4890 +			ret = verify_area(VERIFY_READ, (char *) ioc.ui.fcs.buffer, length);
  2.4891 +			if (ret) return ret;
  2.4892 +		}
  2.4893 +
  2.4894 +		/*
  2.4895 +		 * Find this host
  2.4896 +		 */
  2.4897 +		for( shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next ) {
  2.4898 +			if( shpnt->hostdata == (unsigned long *)megaCtlrs[adapno] ) {
  2.4899 +				megacfg = (mega_host_config *)shpnt->hostdata;
  2.4900 +				break;
  2.4901 +			}
  2.4902 +		}
  2.4903 +		if(shpnt == NULL)  return -ENODEV;
  2.4904 +
  2.4905 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.4906 +		scsicmd = (Scsi_Cmnd *)kmalloc(sizeof(Scsi_Cmnd), GFP_KERNEL|GFP_DMA);
  2.4907 +#else
  2.4908 +		scsicmd = (Scsi_Cmnd *)scsi_init_malloc(sizeof(Scsi_Cmnd),
  2.4909 +							  GFP_ATOMIC | GFP_DMA);
  2.4910 +#endif
  2.4911 +		if(scsicmd == NULL) return -ENOMEM;
  2.4912 +
  2.4913 +		memset(scsicmd, 0, sizeof(Scsi_Cmnd));
  2.4914 +		scsicmd->host = shpnt;
  2.4915 +
  2.4916 +		if( outlen || inlen ) {
  2.4917 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.4918 +			pdevp = &pdev;
  2.4919 +			memcpy(pdevp, megacfg->dev, sizeof(struct pci_dev));
  2.4920 +			pdevp->dma_mask = 0xffffffff;
  2.4921 +#else
  2.4922 +			pdevp = NULL;
  2.4923 +#endif
  2.4924 +			kvaddr = dma_alloc_consistent(pdevp, length, &dma_addr);
  2.4925 +
  2.4926 +			if( kvaddr == NULL ) {
  2.4927 +				printk(KERN_WARNING "megaraid:allocation failed\n");
  2.4928 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)	/*0x20400 */
  2.4929 +				kfree(scsicmd);
  2.4930 +#else
  2.4931 +				scsi_init_free((char *)scsicmd, sizeof(Scsi_Cmnd));
  2.4932 +#endif
  2.4933 +				return -ENOMEM;
  2.4934 +			}
  2.4935 +
  2.4936 +			ioc.ui.fcs.buffer = kvaddr;
  2.4937 +
  2.4938 +			if (inlen) {
  2.4939 +				/* copyin the user data */
  2.4940 +				copy_from_user(kvaddr, (char *)uaddr, length );
  2.4941 +			}
  2.4942 +		}
  2.4943 +
  2.4944 +		scsicmd->cmnd[0] = MEGADEVIOC;
  2.4945 +		scsicmd->request_buffer = (void *)&ioc;
  2.4946 +
  2.4947 +#if XENO_KILLED
  2.4948 +		init_MUTEX_LOCKED(&mimd_ioctl_sem);
  2.4949 +#endif
  2.4950 +
  2.4951 +		IO_LOCK;
  2.4952 +		megaraid_queue(scsicmd, megadev_ioctl_done);
  2.4953 +
  2.4954 +		IO_UNLOCK;
  2.4955 +#if XENO_KILLED
  2.4956 +		down(&mimd_ioctl_sem);
  2.4957 +#endif
  2.4958 +		if( !scsicmd->result && outlen ) {
  2.4959 +			if (copy_to_user(uaddr, kvaddr, length))
  2.4960 +				return -EFAULT;
  2.4961 +		}
  2.4962 +
  2.4963 +		/*
  2.4964 +		 * copyout the result
  2.4965 +		 */
  2.4966 +		uioc = (struct uioctl_t *)arg;
  2.4967 +
  2.4968 +		if( ioc.mbox[0] == MEGA_MBOXCMD_PASSTHRU ) {
  2.4969 +			put_user( scsicmd->result, &uioc->pthru.scsistatus );
  2.4970 +			if (copy_to_user( uioc->pthru.reqsensearea, scsicmd->sense_buffer,
  2.4971 +							  MAX_REQ_SENSE_LEN ));
  2.4972 +				ret= -EFAULT;
  2.4973 +		} else {
  2.4974 +			put_user(1, &uioc->mbox[16]);	/* numstatus */
  2.4975 +			/* status */
  2.4976 +			put_user (scsicmd->result, &uioc->mbox[17]);
  2.4977 +		}
  2.4978 +
  2.4979 +		if (kvaddr) {
  2.4980 +			dma_free_consistent(pdevp, length, kvaddr, dma_addr);
  2.4981 +		}
  2.4982 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)	/*0x20400 */
  2.4983 +		kfree (scsicmd);
  2.4984 +#else
  2.4985 +		scsi_init_free((char *)scsicmd, sizeof(Scsi_Cmnd));
  2.4986 +#endif
  2.4987 +
  2.4988 +		/* restore the user address */
  2.4989 +		ioc.ui.fcs.buffer = uaddr;
  2.4990 +
  2.4991 +		return ret;
  2.4992 +
  2.4993 +	case M_RD_IOCTL_CMD:
  2.4994 +		/* which adapter?  */
  2.4995 +		adapno = ioc.ui.fcs.adapno;
  2.4996 +
  2.4997 +		/* See comment above: MEGAIOC_QADAPINFO */
  2.4998 +		adapno = GETADAP (adapno);
  2.4999 +
  2.5000 +		if (adapno >= numCtlrs)
  2.5001 +			return (-ENODEV);
  2.5002 +
  2.5003 +		/* save the user address */
  2.5004 +		uaddr = ioc.data;
  2.5005 +		outlen = ioc.outlen;
  2.5006 +		inlen = ioc.inlen;
  2.5007 +
  2.5008 +		if ((outlen >= IOCTL_MAX_DATALEN) || (inlen >= IOCTL_MAX_DATALEN))
  2.5009 +			return (-EINVAL);
  2.5010 +
  2.5011 +		if (outlen) {
  2.5012 +			ret = verify_area (VERIFY_WRITE, ioc.data, outlen);
  2.5013 +			if (ret) return ret;
  2.5014 +		}
  2.5015 +		if (inlen) {
  2.5016 +			ret = verify_area (VERIFY_READ, ioc.data, inlen);
  2.5017 +			if (ret) return ret;
  2.5018 +		}
  2.5019 +
  2.5020 +		/*
  2.5021 +		 * Find this host
  2.5022 +		 */
  2.5023 +		for( shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next ) {
  2.5024 +			if( shpnt->hostdata == (unsigned long *)megaCtlrs[adapno] ) {
  2.5025 +				megacfg = (mega_host_config *)shpnt->hostdata;
  2.5026 +				break;
  2.5027 +			}
  2.5028 +		}
  2.5029 +		if(shpnt == NULL)  return -ENODEV;
  2.5030 +
  2.5031 +		/*
  2.5032 +		 * ioctls for deleting logical drives is a special case, so check
  2.5033 +		 * for it first
  2.5034 +		 */
  2.5035 +		if( ioc.mbox[0] == FC_DEL_LOGDRV && ioc.mbox[2] == OP_DEL_LOGDRV ) {
  2.5036 +
  2.5037 +			if( !megacfg->support_random_del ) {
  2.5038 +				printk("megaraid: logdrv delete on non supporting f/w.\n");
  2.5039 +				return -EINVAL;
  2.5040 +			}
  2.5041 +
  2.5042 +			uioc = (struct uioctl_t *)arg;
  2.5043 +
  2.5044 +			ret = mega_del_logdrv(megacfg, ioc.mbox[3]);
  2.5045 +
  2.5046 +			put_user(1, &uioc->mbox[16]);	/* numstatus */
  2.5047 +			put_user(ret, &uioc->mbox[17]);	/* status */
  2.5048 +
  2.5049 +			/* if deletion failed, let the user know by failing ioctl */
  2.5050 +			return ret;
  2.5051 +		}
  2.5052 +
  2.5053 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.5054 +		scsicmd = (Scsi_Cmnd *)kmalloc(sizeof(Scsi_Cmnd), GFP_KERNEL|GFP_DMA);
  2.5055 +#else
  2.5056 +		scsicmd = (Scsi_Cmnd *)scsi_init_malloc(sizeof(Scsi_Cmnd),
  2.5057 +							  GFP_ATOMIC | GFP_DMA);
  2.5058 +#endif
  2.5059 +		if(scsicmd == NULL) return -ENOMEM;
  2.5060 +
  2.5061 +		memset(scsicmd, 0, sizeof(Scsi_Cmnd));
  2.5062 +		scsicmd->host = shpnt;
  2.5063 +
  2.5064 +		if (outlen || inlen) {
  2.5065 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.5066 +			pdevp = &pdev;
  2.5067 +			memcpy(pdevp, megacfg->dev, sizeof(struct pci_dev));
  2.5068 +			pdevp->dma_mask = 0xffffffff;
  2.5069 +#else
  2.5070 +			pdevp = NULL;
  2.5071 +#endif
  2.5072 +			/*
  2.5073 +			 * Allocate a page of kernel space.
  2.5074 +			 */
  2.5075 +			kvaddr = dma_alloc_consistent(pdevp, PAGE_SIZE, &dma_addr);
  2.5076 +
  2.5077 +			if( kvaddr == NULL ) {
  2.5078 +				printk (KERN_WARNING "megaraid:allocation failed\n");
  2.5079 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)	/*0x20400 */
  2.5080 +				kfree(scsicmd);
  2.5081 +#else
  2.5082 +				scsi_init_free((char *)scsicmd, sizeof(Scsi_Cmnd));
  2.5083 +#endif
  2.5084 +				return -ENOMEM;
  2.5085 +			}
  2.5086 +
  2.5087 +			ioc.data = kvaddr;
  2.5088 +
  2.5089 +			if (inlen) {
  2.5090 +				if (ioc.mbox[0] == MEGA_MBOXCMD_PASSTHRU) {
  2.5091 +					/* copyin the user data */
  2.5092 +					copy_from_user (kvaddr, uaddr, ioc.pthru.dataxferlen);
  2.5093 +				} else {
  2.5094 +					copy_from_user (kvaddr, uaddr, inlen);
  2.5095 +				}
  2.5096 +			}
  2.5097 +		}
  2.5098 +
  2.5099 +		scsicmd->cmnd[0] = MEGADEVIOC;
  2.5100 +		scsicmd->request_buffer = (void *) &ioc;
  2.5101 +
  2.5102 +#if XENO_KILLED
  2.5103 +		init_MUTEX_LOCKED (&mimd_ioctl_sem);
  2.5104 +#endif
  2.5105 +
  2.5106 +		IO_LOCK;
  2.5107 +		megaraid_queue (scsicmd, megadev_ioctl_done);
  2.5108 +
  2.5109 +		IO_UNLOCK;
  2.5110 +#if XENO_KILLED
  2.5111 +		down (&mimd_ioctl_sem);
  2.5112 +#endif
  2.5113 +
  2.5114 +		if (!scsicmd->result && outlen) {
  2.5115 +			if (ioc.mbox[0] == MEGA_MBOXCMD_PASSTHRU) {
  2.5116 +				if (copy_to_user (uaddr, kvaddr, ioc.pthru.dataxferlen))	
  2.5117 +					ret = -EFAULT;
  2.5118 +			} else {
  2.5119 +				if (copy_to_user (uaddr, kvaddr, outlen)) 
  2.5120 +					ret = -EFAULT;
  2.5121 +			}
  2.5122 +		}
  2.5123 +
  2.5124 +		/*
  2.5125 +		 * copyout the result
  2.5126 +		 */
  2.5127 +		uioc = (struct uioctl_t *) arg;
  2.5128 +
  2.5129 +		if (ioc.mbox[0] == MEGA_MBOXCMD_PASSTHRU) {
  2.5130 +			put_user (scsicmd->result, &uioc->pthru.scsistatus);
  2.5131 +
  2.5132 +			/*
  2.5133 +			 * If scsicmd->result is 0x02 (CHECK CONDITION) then copy the
  2.5134 +			 * SCSI sense data into user area
  2.5135 +			 */
  2.5136 +			if (copy_to_user( uioc->pthru.reqsensearea, scsicmd->sense_buffer,
  2.5137 +							  MAX_REQ_SENSE_LEN ))
  2.5138 +				ret = -EFAULT;
  2.5139 +							
  2.5140 +		} else {
  2.5141 +			put_user (1, &uioc->mbox[16]);	/* numstatus */
  2.5142 +			put_user (scsicmd->result, &uioc->mbox[17]); /* status */
  2.5143 +		}
  2.5144 +
  2.5145 +		if (kvaddr) {
  2.5146 +			dma_free_consistent(pdevp, PAGE_SIZE, kvaddr, dma_addr );
  2.5147 +		}
  2.5148 +
  2.5149 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.5150 +		kfree (scsicmd);
  2.5151 +#else
  2.5152 +		scsi_init_free((char *)scsicmd, sizeof(Scsi_Cmnd));
  2.5153 +#endif
  2.5154 +
  2.5155 +		/* restore user pointer */
  2.5156 +		ioc.data = uaddr;
  2.5157 +
  2.5158 +		return ret;
  2.5159 +
  2.5160 +	default:
  2.5161 +		return (-EINVAL);
  2.5162 +
  2.5163 +	}/* Outer switch */
  2.5164 +
  2.5165 +	return 0;
  2.5166 +}
  2.5167 +
  2.5168 +static void
  2.5169 +megadev_ioctl_done(Scsi_Cmnd *sc)
  2.5170 +{
  2.5171 +#if XENO_KILLED
  2.5172 +	up (&mimd_ioctl_sem);
  2.5173 +#endif
  2.5174 +}
  2.5175 +
  2.5176 +static mega_scb *
  2.5177 +megadev_doioctl (mega_host_config * megacfg, Scsi_Cmnd * sc)
  2.5178 +{
  2.5179 +	u8 cmd;
  2.5180 +	struct uioctl_t *ioc = NULL;
  2.5181 +	mega_mailbox *mbox = NULL;
  2.5182 +	mega_ioctl_mbox *mboxioc = NULL;
  2.5183 +	struct mbox_passthru *mboxpthru = NULL;
  2.5184 +	mega_scb *scb = NULL;
  2.5185 +	mega_passthru *pthru = NULL;
  2.5186 +
  2.5187 +	if ((scb = mega_allocateSCB (megacfg, sc)) == NULL) {
  2.5188 +		sc->result = (DID_ERROR << 16);
  2.5189 +		callDone (sc);
  2.5190 +		return NULL;
  2.5191 +	}
  2.5192 +
  2.5193 +	ioc = (struct uioctl_t *) sc->request_buffer;
  2.5194 +
  2.5195 +	memcpy (scb->mboxData, ioc->mbox, sizeof (scb->mboxData));
  2.5196 +
  2.5197 +	/* The generic mailbox */
  2.5198 +	mbox = (mega_mailbox *) ioc->mbox;
  2.5199 +
  2.5200 +	/*
  2.5201 +	 * Get the user command
  2.5202 +	 */
  2.5203 +	cmd = ioc->mbox[0];
  2.5204 +
  2.5205 +	switch (cmd) {
  2.5206 +	case MEGA_MBOXCMD_PASSTHRU:
  2.5207 +		/*
  2.5208 +		   * prepare the SCB with information from the user ioctl structure
  2.5209 +		 */
  2.5210 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.5211 +		pthru = scb->pthru;
  2.5212 +#else
  2.5213 +		pthru = &scb->pthru;
  2.5214 +#endif
  2.5215 +		memcpy (pthru, &ioc->pthru, sizeof (mega_passthru));
  2.5216 +		mboxpthru = (struct mbox_passthru *) scb->mboxData;
  2.5217 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.5218 +		if (megacfg->flag & BOARD_64BIT) {
  2.5219 +			/* This is just a sample with one element 
  2.5220 +			   * This if executes onlu on 2.4 kernels
  2.5221 +			 */
  2.5222 +			mboxpthru->dataxferaddr = scb->dma_passthruhandle64;
  2.5223 +			scb->sg64List[0].address =
  2.5224 +			    pci_map_single (megacfg->dev,
  2.5225 +					    ioc->data,
  2.5226 +					    4096, PCI_DMA_BIDIRECTIONAL);
  2.5227 +			scb->sg64List[0].length = 4096;	// TODO: Check this
  2.5228 +			pthru->dataxferaddr = scb->dma_sghandle64;
  2.5229 +			pthru->numsgelements = 1;
  2.5230 +			mboxpthru->cmd = MEGA_MBOXCMD_PASSTHRU64;
  2.5231 +		} else {
  2.5232 +			mboxpthru->dataxferaddr = scb->dma_passthruhandle64;
  2.5233 +			pthru->dataxferaddr =
  2.5234 +			    pci_map_single (megacfg->dev,
  2.5235 +					    ioc->data,
  2.5236 +					    4096, PCI_DMA_BIDIRECTIONAL);
  2.5237 +			pthru->numsgelements = 0;
  2.5238 +		}
  2.5239 +
  2.5240 +#else
  2.5241 +		{
  2.5242 +			mboxpthru->dataxferaddr = virt_to_bus (&scb->pthru);
  2.5243 +			pthru->dataxferaddr = virt_to_bus (ioc->data);
  2.5244 +			pthru->numsgelements = 0;
  2.5245 +		}
  2.5246 +#endif
  2.5247 +
  2.5248 +		pthru->reqsenselen = 14;
  2.5249 +		break;
  2.5250 +
  2.5251 +	default:		/* Normal command */
  2.5252 +		mboxioc = (mega_ioctl_mbox *) scb->mboxData;
  2.5253 +
  2.5254 +		if (ioc->ui.fcs.opcode == M_RD_IOCTL_CMD_NEW) {
  2.5255 +			scb->buff_ptr = ioc->ui.fcs.buffer;
  2.5256 +			scb->iDataSize = ioc->ui.fcs.length;
  2.5257 +		} else {
  2.5258 +			scb->buff_ptr = ioc->data;
  2.5259 +			scb->iDataSize = 4096;	// TODO:check it
  2.5260 +		}
  2.5261 +
  2.5262 +		set_mbox_xfer_addr (megacfg, scb, mboxioc, FROMTO_DEVICE);
  2.5263 +		mboxioc->numsgelements = 0;
  2.5264 +		break;
  2.5265 +	}
  2.5266 +
  2.5267 +	return scb;
  2.5268 +}
  2.5269 +
  2.5270 +static int
  2.5271 +megadev_close (struct inode *inode, struct file *filep)
  2.5272 +{
  2.5273 +#ifdef MODULE
  2.5274 +	MOD_DEC_USE_COUNT;
  2.5275 +#endif
  2.5276 +	return 0;
  2.5277 +}
  2.5278 +
  2.5279 +
  2.5280 +static int
  2.5281 +mega_support_ext_cdb(mega_host_config *this_hba)
  2.5282 +{
  2.5283 +	mega_mailbox *mboxpnt;
  2.5284 +	unsigned char mbox[16];
  2.5285 +	int ret;
  2.5286 +
  2.5287 +	mboxpnt = (mega_mailbox *) mbox;
  2.5288 +
  2.5289 +	memset(mbox, 0, sizeof (mbox));
  2.5290 +	/*
  2.5291 +	 * issue command to find out if controller supports extended CDBs.
  2.5292 +	 */
  2.5293 +	mbox[0] = 0xA4;
  2.5294 +	mbox[2] = 0x16;
  2.5295 +
  2.5296 +	ret = megaIssueCmd(this_hba, mbox, NULL, 0);
  2.5297 +
  2.5298 +	return !ret;
  2.5299 +}
  2.5300 +
  2.5301 +
  2.5302 +/*
  2.5303 + * Find out if this controller supports random deletion and addition of
  2.5304 + * logical drives
  2.5305 + */
  2.5306 +static int
  2.5307 +mega_support_random_del(mega_host_config *this_hba)
  2.5308 +{
  2.5309 +#if XENO_KILLED
  2.5310 +	mega_mailbox *mboxpnt;
  2.5311 +	unsigned char mbox[16];
  2.5312 +	int ret;
  2.5313 +
  2.5314 +	mboxpnt = (mega_mailbox *)mbox;
  2.5315 +
  2.5316 +	memset(mbox, 0, sizeof(mbox));
  2.5317 +
  2.5318 +	/*
  2.5319 +	 * issue command
  2.5320 +	 */
  2.5321 +	mbox[0] = FC_DEL_LOGDRV;
  2.5322 +	mbox[2] = OP_SUP_DEL_LOGDRV;
  2.5323 +
  2.5324 +	ret = megaIssueCmd(this_hba, mbox, NULL, 0);
  2.5325 +
  2.5326 +	return !ret;
  2.5327 +#endif
  2.5328 +	return 0; // no support for random deletions
  2.5329 +}
  2.5330 +
  2.5331 +static int
  2.5332 +mega_del_logdrv(mega_host_config *this_hba, int logdrv)
  2.5333 +{
  2.5334 +  return -ENOSYS;
  2.5335 +#if XENO_KILLED
  2.5336 +	int		rval;
  2.5337 +	IO_LOCK_T;
  2.5338 +	DECLARE_WAIT_QUEUE_HEAD(wq);
  2.5339 +	mega_scb	*scbp;
  2.5340 +
  2.5341 +	/*
  2.5342 +	 * Stop sending commands to the controller, queue them internally.
  2.5343 +	 * When deletion is complete, ISR will flush the queue.
  2.5344 +	 */
  2.5345 +	IO_LOCK;
  2.5346 +	this_hba->quiescent = 1;
  2.5347 +	IO_UNLOCK;
  2.5348 +
  2.5349 +	while( this_hba->qPcnt ) {
  2.5350 +			sleep_on_timeout( &wq, 1*HZ );	/* sleep for 1s */
  2.5351 +	}
  2.5352 +	rval = mega_do_del_logdrv(this_hba, logdrv);
  2.5353 +
  2.5354 +	IO_LOCK;
  2.5355 +	/*
  2.5356 +	 * Attach the internal queue to the pending queue
  2.5357 +	 */
  2.5358 +	if( this_hba->qPendingH == NULL ) {
  2.5359 +		/*
  2.5360 +		 * If pending queue head is null, make internal queue as
  2.5361 +		 * pending queue
  2.5362 +		 */
  2.5363 +		this_hba->qPendingH = this_hba->int_qh;
  2.5364 +		this_hba->qPendingT = this_hba->int_qt;
  2.5365 +		this_hba->qPcnt = this_hba->int_qlen;
  2.5366 +	}
  2.5367 +	else {
  2.5368 +		/*
  2.5369 +		 * Append pending queue to internal queue
  2.5370 +		 */
  2.5371 +		if( this_hba->int_qt ) {
  2.5372 +			this_hba->int_qt->next = this_hba->qPendingH;
  2.5373 +
  2.5374 +			this_hba->qPendingH = this_hba->int_qh;
  2.5375 +			this_hba->qPcnt += this_hba->int_qlen;
  2.5376 +		}
  2.5377 +	}
  2.5378 +
  2.5379 +	this_hba->int_qh = this_hba->int_qt = NULL;
  2.5380 +	this_hba->int_qlen = 0;
  2.5381 +
  2.5382 +	/*
  2.5383 +	 * If delete operation was successful, add 0x80 to the logical drive
  2.5384 +	 * ids for commands in the pending queue.
  2.5385 +	 */
  2.5386 +	if( this_hba->read_ldidmap) {
  2.5387 +		for( scbp = this_hba->qPendingH; scbp; scbp = scbp->next ) {
  2.5388 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.5389 +			if( scbp->pthru->logdrv < 0x80 )
  2.5390 +				scbp->pthru->logdrv += 0x80;
  2.5391 +#else
  2.5392 +			if( scbp->pthru.logdrv < 0x80 )
  2.5393 +				scbp->pthru.logdrv += 0x80;
  2.5394 +#endif
  2.5395 +		}
  2.5396 +	}
  2.5397 +	this_hba->quiescent = 0;
  2.5398 +
  2.5399 +	IO_UNLOCK;
  2.5400 +
  2.5401 +	return rval;
  2.5402 +#endif
  2.5403 +}
  2.5404 +
  2.5405 +
  2.5406 +static int
  2.5407 +mega_do_del_logdrv(mega_host_config *this_hba, int logdrv)
  2.5408 +{
  2.5409 +	mega_mailbox *mboxpnt;
  2.5410 +	unsigned char mbox[16];
  2.5411 +	int rval;
  2.5412 +
  2.5413 +	mboxpnt = (mega_mailbox *)mbox;
  2.5414 +
  2.5415 +	memset(mbox, 0, sizeof(mbox));
  2.5416 +
  2.5417 +	mbox[0] = FC_DEL_LOGDRV;
  2.5418 +	mbox[2] = OP_DEL_LOGDRV;
  2.5419 +	mbox[3] = logdrv;
  2.5420 +
  2.5421 +	rval = megaIssueCmd(this_hba, mbox, NULL, 0);
  2.5422 +
  2.5423 +	/* log this event */
  2.5424 +	if( rval != 0 ) {
  2.5425 +		printk("megaraid: Attempt to delete logical drive %d failed.",
  2.5426 +				logdrv);
  2.5427 +		return rval;
  2.5428 +	}
  2.5429 +
  2.5430 +	printk("megaraid: logical drive %d deleted.\n", logdrv);
  2.5431 +
  2.5432 +	/*
  2.5433 +	 * After deleting first logical drive, the logical drives must be
  2.5434 +	 * addressed by adding 0x80 to the logical drive id.
  2.5435 +	 */
  2.5436 +	this_hba->read_ldidmap = 1;
  2.5437 +
  2.5438 +	return rval;
  2.5439 +}
  2.5440 +
  2.5441 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
  2.5442 +void *
  2.5443 +dma_alloc_consistent(void *dev, size_t size, dma_addr_t *dma_addr)
  2.5444 +{
  2.5445 +	void	*_tv;
  2.5446 +	int		npages;
  2.5447 +	int		order = 0;
  2.5448 +
  2.5449 +	/*
  2.5450 +	 * How many pages application needs
  2.5451 +	 */
  2.5452 +	npages = size / PAGE_SIZE;
  2.5453 +
  2.5454 +	/* Do we need one more page */
  2.5455 +	if(size % PAGE_SIZE)
  2.5456 +		npages++;
  2.5457 +
  2.5458 +	order = mega_get_order(npages);
  2.5459 +
  2.5460 +	_tv = (void *)__get_free_pages(GFP_DMA, order);
  2.5461 +
  2.5462 +	if( _tv != NULL ) {
  2.5463 +		memset(_tv, 0, size);
  2.5464 +		*(dma_addr) = virt_to_bus(_tv);
  2.5465 +	}
  2.5466 +
  2.5467 +	return _tv;
  2.5468 +}
  2.5469 +
  2.5470 +/*
  2.5471 + * int mega_get_order(int)
  2.5472 + *
  2.5473 + * returns the order to be used as 2nd argument to __get_free_pages() - which
  2.5474 + * return pages equal to pow(2, order) - AM
  2.5475 + */
  2.5476 +int
  2.5477 +mega_get_order(int n)
  2.5478 +{
  2.5479 +	int		i = 0;
  2.5480 +
  2.5481 +	while( pow_2(i++) < n )
  2.5482 +		; /* null statement */
  2.5483 +
  2.5484 +	return i-1;
  2.5485 +}
  2.5486 +
  2.5487 +/*
  2.5488 + * int pow_2(int)
  2.5489 + *
  2.5490 + * calculates pow(2, i)
  2.5491 + */
  2.5492 +int
  2.5493 +pow_2(int i)
  2.5494 +{
  2.5495 +	unsigned int	v = 1;
  2.5496 +	
  2.5497 +	while(i--)
  2.5498 +		v <<= 1;
  2.5499 +
  2.5500 +	return v;
  2.5501 +}
  2.5502 +
  2.5503 +void
  2.5504 +dma_free_consistent(void *dev, size_t size, void *vaddr, dma_addr_t dma_addr)
  2.5505 +{
  2.5506 +	int		npages;
  2.5507 +	int		order = 0;
  2.5508 +
  2.5509 +	npages = size / PAGE_SIZE;
  2.5510 +
  2.5511 +	if(size % PAGE_SIZE)
  2.5512 +		npages++;
  2.5513 +
  2.5514 +	if (npages == 1)
  2.5515 +		order = 0;
  2.5516 +	else if (npages == 2)
  2.5517 +		order = 1;
  2.5518 +	else if (npages <= 4)
  2.5519 +		order = 2;
  2.5520 +	else
  2.5521 +		order = 3;
  2.5522 +
  2.5523 +	free_pages((unsigned long)vaddr, order);
  2.5524 +
  2.5525 +}
  2.5526 +#endif
  2.5527 +
  2.5528 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
  2.5529 +static
  2.5530 +#endif				/* LINUX VERSION 2.4.XX */
  2.5531 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) || defined(MODULE)
  2.5532 +Scsi_Host_Template driver_template = MEGARAID;
  2.5533 +
  2.5534 +#include "scsi_module.c.inc"
  2.5535 +#endif				/* LINUX VERSION 2.4.XX || MODULE */
  2.5536 +
  2.5537 +/* vi: set ts=4: */
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/xen/drivers/scsi/megaraid.h	Mon Mar 31 11:34:23 2003 +0000
     3.3 @@ -0,0 +1,1040 @@
     3.4 +#ifndef __MEGARAID_H__
     3.5 +#define __MEGARAID_H__
     3.6 +
     3.7 +#include <xeno/version.h>
     3.8 +
     3.9 +/*
    3.10 + * For state flag. Do not use LSB(8 bits) which are
    3.11 + * reserved for storing info about channels.
    3.12 + */
    3.13 +#define IN_ISR		  	0x80000000L
    3.14 +#define IN_ABORT		0x40000000L
    3.15 +#define IN_RESET		0x20000000L
    3.16 +#define IN_QUEUE		0x10000000L
    3.17 +#define BOARD_QUARTZ	0x08000000L
    3.18 +#define BOARD_40LD	   	0x04000000L
    3.19 +#define BOARD_64BIT		0x02000000L
    3.20 +
    3.21 +#define SCB_FREE     0x0
    3.22 +#define SCB_ACTIVE   0x1
    3.23 +#define SCB_WAITQ    0x2
    3.24 +#define SCB_ISSUED   0x3
    3.25 +#define SCB_COMPLETE 0x4
    3.26 +#define SCB_ABORTED  0x5
    3.27 +#define SCB_RESET    0x6
    3.28 +
    3.29 +#define M_RD_CRLFSTR 			"\n"
    3.30 +#define M_RD_IOCTL_CMD			0x80
    3.31 +#define M_RD_IOCTL_CMD_NEW		0x81
    3.32 +#define M_RD_DRIVER_IOCTL_INTERFACE	0x82
    3.33 +
    3.34 +#define MEGARAID_VERSION "v1.18d (Release Date: Wed Aug  7 18:51:51 EDT 2002)\n"
    3.35 +
    3.36 +#define MEGARAID_IOCTL_VERSION 	114
    3.37 +
    3.38 +/* Methods */
    3.39 +#define GET_DRIVER_INFO 		0x1
    3.40 +
    3.41 +#define MEGA_CMD_TIMEOUT		10
    3.42 +
    3.43 +/* Feel free to fiddle with these.. max values are:
    3.44 +   SGLIST     0..26
    3.45 +   COMMANDS   0..253
    3.46 +   CMDPERLUN  0..63
    3.47 +*/
    3.48 +
    3.49 +#define MAX_SGLIST	      	0x1A
    3.50 +#define MAX_COMMANDS	    	127
    3.51 +#define MAX_CMD_PER_LUN	 	63
    3.52 +#define MAX_FIRMWARE_STATUS     46
    3.53 +
    3.54 +#define MAX_LOGICAL_DRIVES      8
    3.55 +#define MAX_CHANNEL	     	5
    3.56 +#define MAX_TARGET	      	15
    3.57 +#define MAX_PHYSICAL_DRIVES     MAX_CHANNEL*MAX_TARGET
    3.58 +
    3.59 +#define INQUIRY_DATA_SIZE       0x24
    3.60 +#define MAX_CDB_LEN	     		0x0A
    3.61 +#define MAX_REQ_SENSE_LEN       0x20
    3.62 +
    3.63 +#define INTR_VALID	      	0x40
    3.64 +
    3.65 +/* Direction Macros for MBOX Data direction */
    3.66 +#define TO_DEVICE		0x0
    3.67 +#define FROM_DEVICE		0x1
    3.68 +#define FROMTO_DEVICE		0x2
    3.69 +
    3.70 +/* Mailbox commands */
    3.71 +#define MEGA_MBOXCMD_LREAD		0x01
    3.72 +#define MEGA_MBOXCMD_LWRITE		0x02
    3.73 +#define MEGA_MBOXCMD_LREAD64		0xA7
    3.74 +#define MEGA_MBOXCMD_LWRITE64		0xA8
    3.75 +#define MEGA_MBOXCMD_PASSTHRU		0x03
    3.76 +#define MEGA_MBOXCMD_EXTPASSTHRU	0xE3
    3.77 +#define MEGA_MBOXCMD_PASSTHRU64		0xC3
    3.78 +#define MEGA_MBOXCMD_ADAPTERINQ		0x05
    3.79 +
    3.80 +
    3.81 +/* Offsets into Mailbox */
    3.82 +#define COMMAND_PORT       	0x00
    3.83 +#define COMMAND_ID_PORT    	0x01
    3.84 +#define SG_LIST_PORT0      	0x08
    3.85 +#define SG_LIST_PORT1      	0x09
    3.86 +#define SG_LIST_PORT2      	0x0a
    3.87 +#define SG_LIST_PORT3      	0x0b
    3.88 +#define SG_ELEMENT_PORT    	0x0d
    3.89 +#define NO_FIRED_PORT      	0x0f
    3.90 +
    3.91 +/* I/O Port offsets */
    3.92 +#define I_CMD_PORT	 	0x00
    3.93 +#define I_ACK_PORT	 	0x00
    3.94 +#define I_TOGGLE_PORT      	0x01
    3.95 +#define INTR_PORT	  	0x0a
    3.96 +
    3.97 +#define MAILBOX_SIZE       	(sizeof(mega_mailbox)-16)
    3.98 +#define MBOX_BUSY_PORT     	0x00
    3.99 +#define MBOX_PORT0	 	0x04
   3.100 +#define MBOX_PORT1	 	0x05
   3.101 +#define MBOX_PORT2	 	0x06
   3.102 +#define MBOX_PORT3	 	0x07
   3.103 +#define ENABLE_MBOX_REGION 	0x0B
   3.104 +
   3.105 +/* I/O Port Values */
   3.106 +#define ISSUE_BYTE	 	0x10
   3.107 +#define ACK_BYTE	   	0x08
   3.108 +#define ENABLE_INTR_BYTE   	0xc0
   3.109 +#define DISABLE_INTR_BYTE  	0x00
   3.110 +#define VALID_INTR_BYTE    	0x40
   3.111 +#define MBOX_BUSY_BYTE     	0x10
   3.112 +#define ENABLE_MBOX_BYTE   	0x00
   3.113 +
   3.114 +/* Setup some port macros here */
   3.115 +#define WRITE_MAILBOX(base,offset,value)   	*(base+offset)=value
   3.116 +#define READ_MAILBOX(base,offset)		*(base+offset)
   3.117 +
   3.118 +#define WRITE_PORT(base,offset,value)      	outb_p(value,base+offset)
   3.119 +#define READ_PORT(base,offset)	     		inb_p(base+offset)
   3.120 +
   3.121 +#define ISSUE_COMMAND(base)	WRITE_PORT(base,I_CMD_PORT,ISSUE_BYTE)
   3.122 +#define CLEAR_INTR(base)	WRITE_PORT(base,I_ACK_PORT,ACK_BYTE)
   3.123 +#define ENABLE_INTR(base)	WRITE_PORT(base,I_TOGGLE_PORT,ENABLE_INTR_BYTE)
   3.124 +#define DISABLE_INTR(base)	WRITE_PORT(base,I_TOGGLE_PORT,DISABLE_INTR_BYTE)
   3.125 +
   3.126 +#ifndef PCI_VENDOR_ID_LSI_LOGIC
   3.127 +#define PCI_VENDOR_ID_LSI_LOGIC		0x1000
   3.128 +#endif
   3.129 +
   3.130 +/* Define AMI's PCI codes */
   3.131 +#ifndef PCI_VENDOR_ID_AMI
   3.132 +#define PCI_VENDOR_ID_AMI		0x101E
   3.133 +#endif
   3.134 +
   3.135 +#ifndef PCI_DEVICE_ID_AMI_MEGARAID
   3.136 +#define PCI_DEVICE_ID_AMI_MEGARAID	0x9010
   3.137 +#endif
   3.138 +
   3.139 +#ifndef PCI_DEVICE_ID_AMI_MEGARAID2
   3.140 +#define PCI_DEVICE_ID_AMI_MEGARAID2	0x9060
   3.141 +#endif
   3.142 +
   3.143 +#ifndef PCI_DEVICE_ID_AMI_MEGARAID3
   3.144 +#define PCI_DEVICE_ID_AMI_MEGARAID3	0x1960
   3.145 +#endif
   3.146 +
   3.147 +#define PCI_VENDOR_ID_DISCOVERY		0x1028
   3.148 +#define PCI_DEVICE_ID_DISCOVERY		0x000E
   3.149 +
   3.150 +#define PCI_VENDOR_ID_PERC4_DI_YSTONE	0x1028
   3.151 +#define PCI_DEVICE_ID_PERC4_DI_YSTONE	0x000F
   3.152 +
   3.153 +#define PCI_VENDOR_ID_PERC4_QC_VERDE	0x1000
   3.154 +#define PCI_DEVICE_ID_PERC4_QC_VERDE	0x0407
   3.155 +
   3.156 +/* Special Adapter Commands */
   3.157 +#define FW_FIRE_WRITE   	0x2C
   3.158 +#define FW_FIRE_FLASH   	0x2D
   3.159 +
   3.160 +#define FC_NEW_CONFIG	   		0xA1
   3.161 +#define DCMD_FC_CMD			0xA1
   3.162 +#define DCMD_FC_PROCEED	     		0x02
   3.163 +#define DCMD_DELETE_LOGDRV	  	0x03
   3.164 +#define DCMD_FC_READ_NVRAM_CONFIG   	0x04
   3.165 +#define DCMD_FC_READ_NVRAM_CONFIG_64   	0xC0
   3.166 +#define DCMD_FC_READ_FINAL_CONFIG   	0x05
   3.167 +#define DCMD_GET_DISK_CONFIG		0x06
   3.168 +#define DCMD_GET_DISK_CONFIG_64		0xC2
   3.169 +#define DCMD_CHANGE_LDNO	    	0x07
   3.170 +#define DCMD_COMPACT_CONFIG	 	0x08
   3.171 +#define DCMD_DELETE_DRIVEGROUP      	0x09
   3.172 +#define DCMD_GET_LOOPID_INFO		0x0A
   3.173 +#define DCMD_CHANGE_LOOPID	  	0x0B
   3.174 +#define DCMD_GET_NUM_SCSI_CHANS     	0x0C
   3.175 +#define DCMD_WRITE_CONFIG	   	0x0D
   3.176 +#define DCMD_WRITE_CONFIG_64   		0xC1
   3.177 +
   3.178 +#define NC_SUBOP_PRODUCT_INFO       	0x0E
   3.179 +#define NC_SUBOP_ENQUIRY3	   	0x0F
   3.180 +#define ENQ3_GET_SOLICITED_NOTIFY_ONLY  0x01
   3.181 +#define ENQ3_GET_SOLICITED_FULL	 	0x02
   3.182 +#define ENQ3_GET_UNSOLICITED	    	0x03
   3.183 +
   3.184 +#define PCI_CONF_BASE_ADDR_OFFSET  	0x10
   3.185 +#define PCI_CONF_IRQ_OFFSET		0x3c
   3.186 +#define PCI_CONF_AMISIG	    		0xa0
   3.187 +#define PCI_CONF_AMISIG64		0xa4
   3.188 +
   3.189 +/* Sub-System Vendor ID sorted on alphabetical order*/
   3.190 +#define LSI_SUBSYS_ID                  0x1000
   3.191 +#define	AMI_SUBSYS_ID			0x101E
   3.192 +#define DELL_SUBSYS_ID			0x1028
   3.193 +#define	HP_SUBSYS_ID			0x103C
   3.194 +
   3.195 +#define AMI_SIGNATURE	      		0x3344
   3.196 +#define AMI_SIGNATURE_471	  	0xCCCC
   3.197 +#define AMI_64BIT_SIGNATURE		0x0299
   3.198 +
   3.199 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0)	/*0x20100 */
   3.200 +#define MEGARAID \
   3.201 +  { NULL,			      	/* Next				*/\
   3.202 +    NULL,			        /* Usage Count Pointer		*/\
   3.203 +    NULL,			       	/* proc Directory Entry		*/\
   3.204 +    megaraid_proc_info,		 	/* proc Info Function		*/\
   3.205 +    "MegaRAID",			 	/* Driver Name			*/\
   3.206 +    megaraid_detect,		    	/* Detect Host Adapter		*/\
   3.207 +    megaraid_release,		   	/* Release Host Adapter		*/\
   3.208 +    megaraid_info,		      	/* Driver Info Function		*/\
   3.209 +    megaraid_command,		   	/* Command Function		*/\
   3.210 +    megaraid_queue,		     	/* Queue Command Function	*/\
   3.211 +    megaraid_abort,		     	/* Abort Command Function	*/\
   3.212 +    megaraid_reset,		     	/* Reset Command Function	*/\
   3.213 +    NULL,			       	/* Slave Attach Function	*/\
   3.214 +    megaraid_biosparam,		 	/* Disk BIOS Parameters		*/\
   3.215 +    MAX_COMMANDS,		       	/* # of cmds that can be\
   3.216 +					outstanding at any time		*/\
   3.217 +    7,				  	/* HBA Target ID		*/\
   3.218 +    MAX_SGLIST,			 	/* Scatter/Gather Table Size	*/\
   3.219 +    MAX_CMD_PER_LUN,		    	/* SCSI Commands per LUN	*/\
   3.220 +    0,				  	/* Present			*/\
   3.221 +    0,				  	/* Default Unchecked ISA DMA	*/\
   3.222 +    ENABLE_CLUSTERING }			/* Enable Clustering		*/
   3.223 +#else
   3.224 +#define MEGARAID \
   3.225 +  {\
   3.226 +    name:	    	"MegaRAID",		/* Driver Name			*/\
   3.227 +    detect:		megaraid_detect,	/* Detect Host Adapter		*/\
   3.228 +    release:	  	megaraid_release,	/* Release Host Adapter		*/\
   3.229 +    info:	     	megaraid_info,	   	/* Driver Info Function		*/\
   3.230 +    command:            NULL, /* XEN KILLED */\
   3.231 +    queuecommand:  	megaraid_queue,		/* Queue Command Function	*/\
   3.232 +    abort:	    	megaraid_abort,	  	/* Abort Command Function	*/\
   3.233 +    reset:	    	megaraid_reset,	  	/* Reset Command Function	*/\
   3.234 +    bios_param:     	megaraid_biosparam, 	/* Disk BIOS Parameters		*/\
   3.235 +    can_queue:		MAX_COMMANDS,	    	/* Can Queue			*/\
   3.236 +    this_id:	  	7,		       	/* HBA Target ID		*/\
   3.237 +    sg_tablesize:   	MAX_SGLIST,	  	/* Scatter/Gather Table Size	*/\
   3.238 +    cmd_per_lun:    	MAX_CMD_PER_LUN,	/* SCSI Commands per LUN	*/\
   3.239 +    present:	  	0,		       	/* Present			*/\
   3.240 +    unchecked_isa_dma:	0,		       	/* Default Unchecked ISA DMA	*/\
   3.241 +    use_clustering:   	ENABLE_CLUSTERING, 	/* Enable Clustering		*/\
   3.242 +  }
   3.243 +#endif
   3.244 +// XENO: REMOVED     command:	  	megaraid_command,	/* Command Function		*/
   3.245 +// XENO: REMOVED     proc_info:		megaraid_proc_info,     /* /proc driver info		*/
   3.246 +// XENO: REMOVED	highmem_io:		1, /* enable HIGHMEM I/O */ 
   3.247 +
   3.248 +
   3.249 +/***********************************************************************
   3.250 + * Structure Declarations for the Firmware supporting 40 Logical Drives
   3.251 + * and 256 Physical Drives.
   3.252 + ***********************************************************************/
   3.253 +
   3.254 +#define FC_MAX_LOGICAL_DRIVES       	40
   3.255 +#define FC_MAX_LOG_DEVICES	  	FC_MAX_LOGICAL_DRIVES
   3.256 +#define FC_MAX_SPAN_DEPTH	   	8
   3.257 +#define FC_MAX_ROW_SIZE	     		32
   3.258 +
   3.259 +#define FC_MAX_CHANNELS	     		16
   3.260 +#define FC_MAX_TARGETS_PER_CHANNEL  	16
   3.261 +#define FC_MAX_PHYSICAL_DEVICES     	256
   3.262 +
   3.263 +/********************************************
   3.264 + * PRODUCT_INFO
   3.265 + ********************************************/
   3.266 +
   3.267 +#define SIG_40LOG_32STR_8SPN  0x00282008
   3.268 +
   3.269 +/*
   3.270 + * Utilities declare this strcture size as 1024 bytes. So more fields can
   3.271 + * be added in future.
   3.272 + */
   3.273 +
   3.274 +struct MRaidProductInfo {
   3.275 +	u32 DataSize;		/* current size in bytes (not including resvd) */
   3.276 +	u32 ConfigSignature;
   3.277 +	/* Current value is 0x00282008
   3.278 +	 * 0x28=MAX_LOGICAL_DRIVES,
   3.279 +	 * 0x20=Number of stripes and
   3.280 +	 * 0x08=Number of spans */
   3.281 +	u8 FwVer[16];		/* printable ASCI string */
   3.282 +	u8 BiosVer[16];		/* printable ASCI string */
   3.283 +	u8 ProductName[80];	/* printable ASCI string */
   3.284 +
   3.285 +	u8 MaxConcCmds;		/* Max. concurrent commands supported */
   3.286 +	u8 SCSIChanPresent;	/* Number of SCSI Channels detected */
   3.287 +	u8 FCLoopPresent;	/* Number of Fibre Loops detected */
   3.288 +	u8 memType;		/* EDO, FPM, SDRAM etc */
   3.289 +
   3.290 +	u32 signature;
   3.291 +	u16 DramSize;		/* In terms of MB */
   3.292 +	u16 subSystemID;
   3.293 +
   3.294 +	u16 subSystemVendorID;
   3.295 +	u8 numNotifyCounters;
   3.296 +	u8 pad1k[889];		/* 135 + 889 resvd = 1024 total size */
   3.297 +} __attribute__ ((packed));
   3.298 +typedef struct MRaidProductInfo megaRaidProductInfo;
   3.299 +
   3.300 +/********************************************
   3.301 + * Standard ENQUIRY
   3.302 + ********************************************/
   3.303 +struct FC_ADP_INFO {
   3.304 +	u8 MaxConcCmds;		/* Max. concurrent commands supported. */
   3.305 +	u8 RbldRate;		/* Rebuild Rate. Varies from 0%-100% */
   3.306 +	u8 MaxTargPerChan;	/* Max. Targets supported per chan. */
   3.307 +	u8 ChanPresent;		/* No. of Chans present on this adapter. */
   3.308 +	u8 FwVer[4];		/* Firmware version. */
   3.309 +	u16 AgeOfFlash;		/* No. of times FW has been downloaded. */
   3.310 +	u8 ChipSetValue;	/* Contents of 0xC0000832 */
   3.311 +	u8 DramSize;		/* In terms of MB */
   3.312 +	u8 CacheFlushInterval;	/* In terms of Seconds */
   3.313 +	u8 BiosVersion[4];
   3.314 +	u8 BoardType;
   3.315 +	u8 sense_alert;
   3.316 +	u8 write_config_count;	/* Increase with evry configuration change */
   3.317 +	u8 drive_inserted_count;/* Increase with every drive inserted */
   3.318 +	u8 inserted_drive;	/* Channel: Id of inserted drive */
   3.319 +	u8 battery_status;
   3.320 +	/*
   3.321 +	   BIT 0 : battery module missing
   3.322 +	   BIT 1 : VBAD
   3.323 +	   BIT 2 : temp high
   3.324 +	   BIT 3 : battery pack missing
   3.325 +	   BIT 4,5 : 00 - charge complete
   3.326 +	   01 - fast charge in prog
   3.327 +	   10 - fast charge fail
   3.328 +	   11 - undefined
   3.329 +	   BIt 6 : counter > 1000
   3.330 +	   Bit 7 : undefined
   3.331 +	 */
   3.332 +	u8 dec_fault_bus_info;	/* was resvd */
   3.333 +} __attribute__ ((packed));
   3.334 +
   3.335 +struct FC_LDRV_INFO {
   3.336 +	u8 NumLDrv;		/* No. of Log. Drvs configured. */
   3.337 +	u8 recon_state[FC_MAX_LOGICAL_DRIVES / 8];
   3.338 +	/* bit field for State of reconstruct */
   3.339 +	u16 LDrvOpStatus[FC_MAX_LOGICAL_DRIVES / 8];
   3.340 +	/* bit field Status of Long Operations. */
   3.341 +
   3.342 +	u32 LDrvSize[FC_MAX_LOGICAL_DRIVES];	/* Size of each log. Drv. */
   3.343 +	u8 LDrvProp[FC_MAX_LOGICAL_DRIVES];
   3.344 +	u8 LDrvState[FC_MAX_LOGICAL_DRIVES];	/* State of Logical Drives. */
   3.345 +} __attribute__ ((packed));
   3.346 +
   3.347 +#define PREVSTAT_MASK   0xf0
   3.348 +#define CURRSTAT_MASK   0x0f
   3.349 +
   3.350 +struct FC_PDRV_INFO {
   3.351 +	u8 PDrvState[FC_MAX_PHYSICAL_DEVICES];	/* State of Phys Drvs. */
   3.352 +} __attribute__ ((packed));
   3.353 +
   3.354 +struct FC_AdapterInq {
   3.355 +	struct FC_ADP_INFO AdpInfo;
   3.356 +	struct FC_LDRV_INFO LogdrvInfo;
   3.357 +	struct FC_PDRV_INFO PhysdrvInfo;
   3.358 +} __attribute__ ((packed));
   3.359 +
   3.360 +typedef struct FC_AdapterInq mega_RAIDINQ_FC;
   3.361 +
   3.362 +/********************************************
   3.363 + * NOTIFICATION
   3.364 + ********************************************/
   3.365 +
   3.366 +#define MAX_NOTIFY_SIZE     0x80
   3.367 +#define CUR_NOTIFY_SIZE     sizeof(struct MegaRAID_Notify)
   3.368 +
   3.369 +/*
   3.370 + * Utilities declare this strcture size as ?? bytes. So more fields can
   3.371 + * be added in future.
   3.372 + */
   3.373 +struct MegaRAID_Notify {
   3.374 +	u32 globalCounter;	/* Any change increments this counter */
   3.375 +
   3.376 +	u8 paramCounter;	/* Indicates any params changed  */
   3.377 +	u8 paramId;		/* Param modified - defined below */
   3.378 +	u16 paramVal;		/* New val of last param modified */
   3.379 +
   3.380 +	u8 writeConfigCounter;	/* write config occurred */
   3.381 +	u8 writeConfigRsvd[3];
   3.382 +
   3.383 +	u8 ldrvOpCounter;	/* Indicates ldrv op started/completed */
   3.384 +	u8 ldrvOpId;		/* ldrv num */
   3.385 +	u8 ldrvOpCmd;		/* ldrv operation - defined below */
   3.386 +	u8 ldrvOpStatus;	/* status of the operation */
   3.387 +
   3.388 +	u8 ldrvStateCounter;	/* Indicates change of ldrv state */
   3.389 +	u8 ldrvStateId;		/* ldrv num */
   3.390 +	u8 ldrvStateNew;	/* New state */
   3.391 +	u8 ldrvStateOld;	/* old state */
   3.392 +
   3.393 +	u8 pdrvStateCounter;	/* Indicates change of ldrv state */
   3.394 +	u8 pdrvStateId;		/* pdrv id */
   3.395 +	u8 pdrvStateNew;	/* New state */
   3.396 +	u8 pdrvStateOld;	/* old state */
   3.397 +
   3.398 +	u8 pdrvFmtCounter;	/* Indicates pdrv format started/over */
   3.399 +	u8 pdrvFmtId;		/* pdrv id */
   3.400 +	u8 pdrvFmtVal;		/* format started/over */
   3.401 +	u8 pdrvFmtRsvd;
   3.402 +
   3.403 +	u8 targXferCounter;	/* Indicates SCSI-2 Xfer rate change */
   3.404 +	u8 targXferId;		/* pdrv Id  */
   3.405 +	u8 targXferVal;		/* new Xfer params of last pdrv */
   3.406 +	u8 targXferRsvd;
   3.407 +
   3.408 +	u8 fcLoopIdChgCounter;	/* Indicates loopid changed */
   3.409 +	u8 fcLoopIdPdrvId;	/* pdrv id */
   3.410 +	u8 fcLoopId0;		/* loopid on fc loop 0 */
   3.411 +	u8 fcLoopId1;		/* loopid on fc loop 1 */
   3.412 +
   3.413 +	u8 fcLoopStateCounter;	/* Indicates loop state changed */
   3.414 +	u8 fcLoopState0;	/* state of fc loop 0 */
   3.415 +	u8 fcLoopState1;	/* state of fc loop 1 */
   3.416 +	u8 fcLoopStateRsvd;
   3.417 +} __attribute__ ((packed));
   3.418 +
   3.419 +/********************************************
   3.420 + * PARAM IDs in Notify struct
   3.421 + ********************************************/
   3.422 +#define PARAM_RBLD_RATE		 0x01
   3.423 +    /*--------------------------------------
   3.424 +     * Param val =
   3.425 +     *      byte 0: new rbld rate
   3.426 +     *--------------------------------------*/
   3.427 +#define PARAM_CACHE_FLUSH_INTERVAL      0x02
   3.428 +    /*--------------------------------------
   3.429 +     * Param val =
   3.430 +     *      byte 0: new cache flush interval
   3.431 +     *--------------------------------------*/
   3.432 +#define PARAM_SENSE_ALERT	       0x03
   3.433 +    /*--------------------------------------
   3.434 +     * Param val =
   3.435 +     *      byte 0: last pdrv id causing chkcond
   3.436 +     *--------------------------------------*/
   3.437 +#define PARAM_DRIVE_INSERTED	    0x04
   3.438 +    /*--------------------------------------
   3.439 +     * Param val =
   3.440 +     *      byte 0: last pdrv id inserted
   3.441 +     *--------------------------------------*/
   3.442 +#define PARAM_BATTERY_STATUS	    0x05
   3.443 +    /*--------------------------------------
   3.444 +     * Param val =
   3.445 +     *      byte 0: battery status
   3.446 +     *--------------------------------------*/
   3.447 +
   3.448 +/********************************************
   3.449 + * Ldrv operation cmd in Notify struct
   3.450 + ********************************************/
   3.451 +#define LDRV_CMD_CHKCONSISTANCY	 0x01
   3.452 +#define LDRV_CMD_INITIALIZE	 0x02
   3.453 +#define LDRV_CMD_RECONSTRUCTION	 0x03
   3.454 +
   3.455 +/********************************************
   3.456 + * Ldrv operation status in Notify struct
   3.457 + ********************************************/
   3.458 +#define LDRV_OP_SUCCESS		 0x00
   3.459 +#define LDRV_OP_FAILED		 0x01
   3.460 +#define LDRV_OP_ABORTED		 0x02
   3.461 +#define LDRV_OP_CORRECTED	 0x03
   3.462 +#define LDRV_OP_STARTED		 0x04
   3.463 +
   3.464 +/********************************************
   3.465 + * Raid Logical drive states.
   3.466 + ********************************************/
   3.467 +#define     RDRV_OFFLINE	0
   3.468 +#define     RDRV_DEGRADED	1
   3.469 +#define     RDRV_OPTIMAL	2
   3.470 +#define     RDRV_DELETED	3
   3.471 +
   3.472 +/*******************************************
   3.473 + * Physical drive states.
   3.474 + *******************************************/
   3.475 +#define     PDRV_UNCNF		0
   3.476 +#define     PDRV_ONLINE		3
   3.477 +#define     PDRV_FAILED		4
   3.478 +#define     PDRV_RBLD		5
   3.479 +
   3.480 +/*******************************************
   3.481 + * Formal val in Notify struct
   3.482 + *******************************************/
   3.483 +#define PDRV_FMT_START		0x01
   3.484 +#define PDRV_FMT_OVER		0x02
   3.485 +
   3.486 +/********************************************
   3.487 + * FC Loop State in Notify Struct
   3.488 + ********************************************/
   3.489 +#define ENQ_FCLOOP_FAILED	0
   3.490 +#define ENQ_FCLOOP_ACTIVE	1
   3.491 +#define ENQ_FCLOOP_TRANSIENT	2
   3.492 +
   3.493 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
   3.494 +#define M_RD_DMA_TYPE_NONE	      	0xFFFF
   3.495 +#define M_RD_PTHRU_WITH_BULK_DATA   	0x0001
   3.496 +#define M_RD_PTHRU_WITH_SGLIST	  	0x0002
   3.497 +#define M_RD_BULK_DATA_ONLY	     	0x0004
   3.498 +#define M_RD_SGLIST_ONLY		0x0008
   3.499 +#define M_RD_EPTHRU_WITH_BULK_DATA   	0x0010
   3.500 +#endif
   3.501 +/********************************************
   3.502 + * ENQUIRY3
   3.503 + ********************************************/
   3.504 +/*
   3.505 + * Utilities declare this strcture size as 1024 bytes. So more fields can
   3.506 + * be added in future.
   3.507 + */
   3.508 +struct MegaRAID_Enquiry3 {
   3.509 +	u32 dataSize;		/* current size in bytes (not including resvd) */
   3.510 +
   3.511 +	struct MegaRAID_Notify notify;
   3.512 +
   3.513 +	u8 notifyRsvd[MAX_NOTIFY_SIZE - CUR_NOTIFY_SIZE];
   3.514 +
   3.515 +	u8 rbldRate;		/* Rebuild rate (0% - 100%) */
   3.516 +	u8 cacheFlushInterval;	/* In terms of Seconds */
   3.517 +	u8 senseAlert;
   3.518 +	u8 driveInsertedCount;	/* drive insertion count */
   3.519 +
   3.520 +	u8 batteryStatus;
   3.521 +	u8 numLDrv;		/* No. of Log Drives configured */
   3.522 +	u8 reconState[FC_MAX_LOGICAL_DRIVES / 8];	/* State of reconstruct */
   3.523 +	u16 lDrvOpStatus[FC_MAX_LOGICAL_DRIVES / 8];	/* log. Drv Status */
   3.524 +
   3.525 +	u32 lDrvSize[FC_MAX_LOGICAL_DRIVES];	/* Size of each log. Drv */
   3.526 +	u8 lDrvProp[FC_MAX_LOGICAL_DRIVES];
   3.527 +	u8 lDrvState[FC_MAX_LOGICAL_DRIVES];	/* State of Logical Drives */
   3.528 +	u8 pDrvState[FC_MAX_PHYSICAL_DEVICES];	/* State of Phys. Drvs. */
   3.529 +	u16 physDrvFormat[FC_MAX_PHYSICAL_DEVICES / 16];
   3.530 +
   3.531 +	u8 targXfer[80];	/* phys device transfer rate */
   3.532 +	u8 pad1k[263];		/* 761 + 263reserved = 1024 bytes total size */
   3.533 +} __attribute__ ((packed));
   3.534 +typedef struct MegaRAID_Enquiry3 mega_Enquiry3;
   3.535 +
   3.536 +/* Structures */
   3.537 +typedef struct _mega_ADP_INFO {
   3.538 +	u8 MaxConcCmds;
   3.539 +	u8 RbldRate;
   3.540 +	u8 MaxTargPerChan;
   3.541 +	u8 ChanPresent;
   3.542 +	u8 FwVer[4];
   3.543 +	u16 AgeOfFlash;
   3.544 +	u8 ChipSetValue;
   3.545 +	u8 DramSize;
   3.546 +	u8 CacheFlushInterval;
   3.547 +	u8 BiosVer[4];
   3.548 +	u8 resvd[7];
   3.549 +} mega_ADP_INFO;
   3.550 +
   3.551 +typedef struct _mega_LDRV_INFO {
   3.552 +	u8 NumLDrv;
   3.553 +	u8 resvd[3];
   3.554 +	u32 LDrvSize[MAX_LOGICAL_DRIVES];
   3.555 +	u8 LDrvProp[MAX_LOGICAL_DRIVES];
   3.556 +	u8 LDrvState[MAX_LOGICAL_DRIVES];
   3.557 +} mega_LDRV_INFO;
   3.558 +
   3.559 +typedef struct _mega_PDRV_INFO {
   3.560 +	u8 PDrvState[MAX_PHYSICAL_DRIVES];
   3.561 +	u8 resvd;
   3.562 +} mega_PDRV_INFO;
   3.563 +
   3.564 +/* RAID inquiry: Mailbox command 0x5*/
   3.565 +typedef struct _mega_RAIDINQ {
   3.566 +	mega_ADP_INFO AdpInfo;
   3.567 +	mega_LDRV_INFO LogdrvInfo;
   3.568 +	mega_PDRV_INFO PhysdrvInfo;
   3.569 +} mega_RAIDINQ;
   3.570 +
   3.571 +/* Passthrough command: Mailbox command 0x3*/
   3.572 +typedef struct mega_passthru {
   3.573 +	u8 timeout:3;		/* 0=6sec/1=60sec/2=10min/3=3hrs */
   3.574 +	u8 ars:1;
   3.575 +	u8 reserved:3;
   3.576 +	u8 islogical:1;
   3.577 +	u8 logdrv;		/* if islogical == 1 */
   3.578 +	u8 channel;		/* if islogical == 0 */
   3.579 +	u8 target;		/* if islogical == 0 */
   3.580 +	u8 queuetag;		/* unused */
   3.581 +	u8 queueaction;		/* unused */
   3.582 +	u8 cdb[MAX_CDB_LEN];
   3.583 +	u8 cdblen;
   3.584 +	u8 reqsenselen;
   3.585 +	u8 reqsensearea[MAX_REQ_SENSE_LEN];
   3.586 +	u8 numsgelements;
   3.587 +	u8 scsistatus;
   3.588 +	u32 dataxferaddr;
   3.589 +	u32 dataxferlen;
   3.590 +} mega_passthru;
   3.591 +
   3.592 +/*
   3.593 + * Extended passthru: support CDB > 10 bytes
   3.594 + */
   3.595 +typedef struct {
   3.596 +	u8 timeout:3;		/* 0=6sec/1=60sec/2=10min/3=3hrs */
   3.597 +	u8 ars:1;
   3.598 +	u8 rsvd1:1;
   3.599 +	u8 cd_rom:1;
   3.600 +	u8 rsvd2:1;
   3.601 +	u8 islogical:1;
   3.602 +
   3.603 +	u8 logdrv;		/* if islogical == 1 */
   3.604 +	u8 channel;		/* if islogical == 0 */
   3.605 +	u8 target;		/* if islogical == 0 */
   3.606 +
   3.607 +	u8 queuetag;		/* unused */
   3.608 +	u8 queueaction;		/* unused */
   3.609 +
   3.610 +	u8 cdblen;
   3.611 +	u8 rsvd3;
   3.612 +	u8 cdb[16];
   3.613 +
   3.614 +	u8 numsgelements;
   3.615 +	u8 status;
   3.616 +	u8 reqsenselen;
   3.617 +	u8 reqsensearea[MAX_REQ_SENSE_LEN];
   3.618 +	u8 rsvd4;
   3.619 +
   3.620 +	u32 dataxferaddr;
   3.621 +	u32 dataxferlen;
   3.622 +}mega_ext_passthru;
   3.623 +
   3.624 +struct _mega_mailbox {
   3.625 +	/* 0x0 */ u8 cmd;
   3.626 +	/* 0x1 */ u8 cmdid;
   3.627 +	/* 0x2 */ u16 numsectors;
   3.628 +	/* 0x4 */ u32 lba;
   3.629 +	/* 0x8 */ u32 xferaddr;
   3.630 +	/* 0xC */ u8 logdrv;
   3.631 +	/* 0xD */ u8 numsgelements;
   3.632 +	/* 0xE */ u8 resvd;
   3.633 +	/* 0xF */ u8 busy;
   3.634 +	/* 0x10 */ u8 numstatus;
   3.635 +	/* 0x11 */ u8 status;
   3.636 +	/* 0x12 */ u8 completed[46];
   3.637 +	volatile u8 mraid_poll;
   3.638 +	volatile u8 mraid_ack;
   3.639 +	u8 pad[16];		/* for alignment purposes */
   3.640 +} __attribute__ ((packed));
   3.641 +typedef struct _mega_mailbox mega_mailbox;
   3.642 +
   3.643 +typedef struct {
   3.644 +	u32 xferSegment_lo;
   3.645 +	u32 xferSegment_hi;
   3.646 +	mega_mailbox mailbox;
   3.647 +} mega_mailbox64;
   3.648 +
   3.649 +typedef struct _mega_ioctl_mbox {
   3.650 +	/* 0x0 */ u8 cmd;
   3.651 +	/* 0x1 */ u8 cmdid;
   3.652 +	/* 0x2 */ u8 channel;
   3.653 +	/* 0x3 */ u8 param;
   3.654 +	/* 0x4 */ u8 pad[4];
   3.655 +	/* 0x8 */ u32 xferaddr;
   3.656 +	/* 0xC */ u8 logdrv;
   3.657 +	/* 0xD */ u8 numsgelements;
   3.658 +	/* 0xE */ u8 resvd;
   3.659 +	/* 0xF */ u8 busy;
   3.660 +	/* 0x10 */ u8 numstatus;
   3.661 +	/* 0x11 */ u8 status;
   3.662 +	/* 0x12 */ u8 completed[46];
   3.663 +	u8 mraid_poll;
   3.664 +	u8 mraid_ack;
   3.665 +	u8 malign[16];
   3.666 +} mega_ioctl_mbox;
   3.667 +
   3.668 +typedef struct _mega_64sglist32 {
   3.669 +	u64 address;
   3.670 +	u32 length;
   3.671 +} __attribute__ ((packed)) mega_64sglist;
   3.672 +
   3.673 +typedef struct _mega_sglist {
   3.674 +	u32 address;
   3.675 +	u32 length;
   3.676 +} mega_sglist;
   3.677 +
   3.678 +/* Queued command data */
   3.679 +typedef struct _mega_scb mega_scb;
   3.680 +
   3.681 +struct _mega_scb {
   3.682 +	int idx;
   3.683 +	u32 state;
   3.684 +	u32 isrcount;
   3.685 +	u8 mboxData[16];
   3.686 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
   3.687 +	u32 dma_type;
   3.688 +	dma_addr_t dma_h_bulkdata;	/*Dma handle for bulk data transfter */
   3.689 +	u32 dma_direction;	/*Dma direction */
   3.690 +	dma_addr_t dma_h_sgdata;	/*Dma handle for the sglist structure */
   3.691 +	dma_addr_t dma_h_sglist[MAX_SGLIST];	/*Dma handle for all SGL elements */
   3.692 +	u8 sglist_count;
   3.693 +	dma_addr_t dma_sghandle64;
   3.694 +	dma_addr_t dma_passthruhandle64;
   3.695 +	dma_addr_t dma_ext_passthruhandle64;
   3.696 +	dma_addr_t dma_bounce_buffer;
   3.697 +	u8 *bounce_buffer;
   3.698 +#endif
   3.699 +
   3.700 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
   3.701 +	mega_passthru *pthru;
   3.702 +	mega_ext_passthru *epthru;
   3.703 +#else
   3.704 +	mega_passthru pthru;
   3.705 +	mega_ext_passthru epthru;
   3.706 +#endif
   3.707 +
   3.708 +	Scsi_Cmnd *SCpnt;
   3.709 +	mega_sglist *sgList;
   3.710 +	mega_64sglist *sg64List;
   3.711 +#if 0
   3.712 +	struct semaphore ioctl_sem;
   3.713 +#endif
   3.714 +	void *buff_ptr;
   3.715 +	u32 iDataSize;
   3.716 +	mega_scb *next;
   3.717 +};
   3.718 +
   3.719 +/* internal locking by the queue manipulting routines */
   3.720 +#define INTERNAL_LOCK   0
   3.721 +/* external locking by the queue manipulting routines */
   3.722 +#define EXTERNAL_LOCK   1
   3.723 +#define NO_LOCK		2
   3.724 +#define INTR_ENB	0	/* do not disable interrupt while manipulating */
   3.725 +#define INTR_DIS	1	/* disable interrupt while manipulating */
   3.726 +
   3.727 +#define NVIRT_CHAN		4	/* # of virtual channels to represent 60 logical
   3.728 +							drives */
   3.729 +
   3.730 +/* Per-controller data */
   3.731 +typedef struct _mega_host_config {
   3.732 +	u8 numldrv;
   3.733 +	u32 flag;
   3.734 +
   3.735 +#ifdef __LP64__
   3.736 +	u64 base;
   3.737 +#else
   3.738 +	u32 base;
   3.739 +#endif
   3.740 +
   3.741 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
   3.742 +	dma_addr_t dma_handle64, adjdmahandle64;
   3.743 +	struct pci_dev *dev;
   3.744 +#endif
   3.745 +
   3.746 +	mega_scb *qFreeH;
   3.747 +	mega_scb *qFreeT;
   3.748 +	spinlock_t lock_free;
   3.749 +
   3.750 +	mega_scb *qPendingH;
   3.751 +	mega_scb *qPendingT;
   3.752 +	spinlock_t lock_pend;
   3.753 +
   3.754 +	Scsi_Cmnd *qCompletedH;
   3.755 +	Scsi_Cmnd *qCompletedT;
   3.756 +	spinlock_t lock_scsicmd;
   3.757 +
   3.758 +	u32 qFcnt;
   3.759 +	u32 qPcnt;
   3.760 +	u32 qCcnt;
   3.761 +
   3.762 +	unsigned long nReads[FC_MAX_LOGICAL_DRIVES];
   3.763 +	unsigned long nReadBlocks[FC_MAX_LOGICAL_DRIVES];
   3.764 +	unsigned long nWrites[FC_MAX_LOGICAL_DRIVES];
   3.765 +	unsigned long nWriteBlocks[FC_MAX_LOGICAL_DRIVES];
   3.766 +	unsigned long nInterrupts;
   3.767 +	/* Host adapter parameters */
   3.768 +	u8 fwVer[7];
   3.769 +	u8 biosVer[7];
   3.770 +
   3.771 +	struct Scsi_Host *host;
   3.772 +
   3.773 +	volatile mega_mailbox64 *mbox64;	/* ptr to beginning of 64-bit mailbox */
   3.774 +	volatile mega_mailbox *mbox;	/* ptr to beginning of standard mailbox */
   3.775 +
   3.776 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
   3.777 +/* ptr to beginning of standard mailbox */
   3.778 +	volatile mega_mailbox64 *mailbox64ptr;
   3.779 +#else
   3.780 +	volatile mega_mailbox64 mailbox64;
   3.781 +#endif
   3.782 +
   3.783 +	volatile u8 mega_buffer[2 * 1024L];
   3.784 +	volatile megaRaidProductInfo productInfo;
   3.785 +
   3.786 +	u8 max_cmds;
   3.787 +	mega_scb scbList[MAX_COMMANDS];
   3.788 +
   3.789 +#if XENO_KILLED
   3.790 +#define PROCBUFSIZE 4096
   3.791 +	char procbuf[PROCBUFSIZE];
   3.792 +	int procidx;
   3.793 +	struct proc_dir_entry *controller_proc_dir_entry;
   3.794 +	struct proc_dir_entry *proc_read, *proc_stat, *proc_status, *proc_mbox;
   3.795 +#endif
   3.796 +
   3.797 +	int		support_ext_cdb;
   3.798 +
   3.799 +	u8		boot_ldrv_enabled;	/* boot from logical drive */
   3.800 +	u8		boot_ldrv;			/* boot logical drive */
   3.801 +	u8		boot_pdrv_enabled;	/* boot from physical drive */
   3.802 +	u8		boot_pdrv_ch;		/* boot physical drive channel */
   3.803 +	u8		boot_pdrv_tgt;		/* boot physical drive target */
   3.804 +
   3.805 +	int		support_random_del;	/* Do we support random deletion of logdrvs */
   3.806 +	int		read_ldidmap;	/* set after logical drive deltion. The logical
   3.807 +								drive number must be read from the map */
   3.808 +	int		quiescent;	/* a stage reached when delete logical drive needs to
   3.809 +						   be done. Stop sending requests to the hba till
   3.810 +						   delete operation is completed */
   3.811 +
   3.812 +	mega_scb	*int_qh;	/* commands are queued in the internal queue */
   3.813 +	mega_scb	*int_qt;	/* while the hba is quiescent */
   3.814 +	int			int_qlen;
   3.815 +	char		logdrv_chan[MAX_CHANNEL+NVIRT_CHAN]; /* logical drive are on
   3.816 +														 what channels. */
   3.817 +	int			mega_ch_class;
   3.818 +} mega_host_config;
   3.819 +
   3.820 +typedef struct _driver_info {
   3.821 +	int size;
   3.822 +	ulong version;
   3.823 +} mega_driver_info;
   3.824 +
   3.825 +/*
   3.826 + * User ioctl structure.
   3.827 + * This structure will be used for Traditional Method ioctl interface
   3.828 + * commands (M_RD_IOCTL_CMD),Alternate Buffer Method (M_RD_IOCTL_CMD_NEW) 
   3.829 + * ioctl commands and the Driver ioctls(M_RD_DRIVER_IOCTL_INTERFACE).
   3.830 + * The Driver ioctl interface handles the commands at
   3.831 + * the driver level, without being sent to the card.
   3.832 + */
   3.833 +#define MEGADEVIOC      0x84
   3.834 +
   3.835 +/* system call imposed limit. Change accordingly */
   3.836 +#define IOCTL_MAX_DATALEN       4096
   3.837 +
   3.838 +#pragma pack(1)
   3.839 +struct uioctl_t {
   3.840 +	u32 inlen;
   3.841 +	u32 outlen;
   3.842 +	union {
   3.843 +		u8 fca[16];
   3.844 +		struct {
   3.845 +			u8 opcode;
   3.846 +			u8 subopcode;
   3.847 +			u16 adapno;
   3.848 +#if BITS_PER_LONG == 32
   3.849 +			u8 *buffer;
   3.850 +			u8 pad[4];
   3.851 +#endif
   3.852 +#if BITS_PER_LONG == 64
   3.853 +			u8 *buffer;
   3.854 +#endif
   3.855 +			u32 length;
   3.856 +		} fcs;
   3.857 +	} ui;
   3.858 +	u8 mbox[18];		/* 16 bytes + 2 status bytes */
   3.859 +	mega_passthru pthru;
   3.860 +#if BITS_PER_LONG == 32
   3.861 +	char *data;		/* buffer <= 4096 for 0x80 commands */
   3.862 +	char pad[4];
   3.863 +#endif
   3.864 +#if BITS_PER_LONG == 64
   3.865 +	char *data;
   3.866 +#endif
   3.867 +};
   3.868 +#pragma pack()
   3.869 +
   3.870 +/*
   3.871 + * struct mcontroller is used to pass information about the controllers in the
   3.872 + * system. Its upto the application how to use the information. We are passing
   3.873 + * as much info about the cards as possible and useful. Before issuing the
   3.874 + * call to find information about the cards, the applicaiton needs to issue a
   3.875 + * ioctl first to find out the number of controllers in the system.
   3.876 + */
   3.877 +#define MAX_CONTROLLERS 32
   3.878 +
   3.879 +struct mcontroller {
   3.880 +	u64 base;
   3.881 +	u8 irq;
   3.882 +	u8 numldrv;
   3.883 +	u8 pcibus;
   3.884 +	u16 pcidev;
   3.885 +	u8 pcifun;
   3.886 +	u16 pciid;
   3.887 +	u16 pcivendor;
   3.888 +	u8 pcislot;
   3.889 +	u32 uid;
   3.890 +};
   3.891 +
   3.892 +struct mbox_passthru {
   3.893 +	u8 cmd;
   3.894 +	u8 cmdid;
   3.895 +	u16 pad1;
   3.896 +	u32 pad2;
   3.897 +	u32 dataxferaddr;
   3.898 +	u8 pad3;
   3.899 +	u8 pad4;
   3.900 +	u8 rsvd;
   3.901 +	u8 mboxbusy;
   3.902 +	u8 nstatus;
   3.903 +	u8 status;
   3.904 +};
   3.905 +
   3.906 +/*
   3.907 + * Defines for Driver IOCTL interface, Op-code:M_RD_DRIVER_IOCTL_INTERFACE
   3.908 + */
   3.909 +#define MEGAIOC_MAGIC  	'm'
   3.910 +#define MEGAIOCCMD     	_IOWR(MEGAIOC_MAGIC, 0)	/* Mega IOCTL command */
   3.911 +
   3.912 +#define MEGAIOC_QNADAP		'm'	/* Query # of adapters */
   3.913 +#define MEGAIOC_QDRVRVER	'e'	/* Query driver version */
   3.914 +#define MEGAIOC_QADAPINFO   	'g'	/* Query adapter information */
   3.915 +#define MKADAP(adapno)	  	(MEGAIOC_MAGIC << 8 | (adapno) )
   3.916 +#define GETADAP(mkadap)	 	( (mkadap) ^ MEGAIOC_MAGIC << 8 )
   3.917 +
   3.918 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)	/*0x20300 */
   3.919 +extern struct proc_dir_entry proc_scsi_megaraid;
   3.920 +#endif
   3.921 +
   3.922 +/* For Host Re-Ordering */
   3.923 +#define MAX_CONTROLLERS	32
   3.924 +
   3.925 +struct mega_hbas {
   3.926 +	int is_bios_enabled;
   3.927 +	mega_host_config *hostdata_addr;
   3.928 +};
   3.929 +
   3.930 +#define		IS_BIOS_ENABLED		0x62
   3.931 +#define		GET_BIOS		0x01
   3.932 +#define		CHNL_CLASS		0xA9
   3.933 +#define		GET_CHNL_CLASS	0x00
   3.934 +#define		SET_CHNL_CLASS	0x01
   3.935 +#define		CH_RAID			0x01
   3.936 +#define		CH_SCSI			0x00
   3.937 +
   3.938 +
   3.939 +#define BIOS_PVT_DATA		0x40
   3.940 +#define GET_BIOS_PVT_DATA	0x00
   3.941 +
   3.942 +#pragma pack(1)
   3.943 +struct private_bios_data {
   3.944 +	u8		geometry:4;		/*
   3.945 +							 * bits 0-3 - BIOS geometry
   3.946 +							 * 0x0001 - 1GB
   3.947 +							 * 0x0010 - 2GB
   3.948 +							 * 0x1000 - 8GB
   3.949 +							 * Others values are invalid
   3.950 +							 */
   3.951 +	u8		unused:4;		/* bits 4-7 are unused */
   3.952 +	u8		boot_drv;		/*
   3.953 +							 * logical/physical drive set as boot drive
   3.954 +							 * 0..7 - for 8LD cards
   3.955 +							 * 0..39 - for 40LD cards
   3.956 +							 */
   3.957 +	u8		rsvd[12];
   3.958 +	u16		cksum;			/* 0-(sum of first 13 bytes of this structure) */
   3.959 +};
   3.960 +#pragma pack()
   3.961 +
   3.962 +/*
   3.963 + * Command for random deletion of logical drives
   3.964 + */
   3.965 +#define	FC_DEL_LOGDRV		0xA4	/* f/w command */
   3.966 +#define	OP_SUP_DEL_LOGDRV	0x2A	/* is feature supported */
   3.967 +#define OP_GET_LDID_MAP		0x18	/* get logdrv id and logdrv number map */
   3.968 +#define OP_DEL_LOGDRV		0x1C	/* delete logical drive */
   3.969 +
   3.970 +/*================================================================
   3.971 + *
   3.972 + *                    Function prototypes
   3.973 + *
   3.974 + *================================================================
   3.975 + */
   3.976 +const char *megaraid_info (struct Scsi_Host *);
   3.977 +int megaraid_detect (Scsi_Host_Template *);
   3.978 +int megaraid_release (struct Scsi_Host *);
   3.979 +int megaraid_command (Scsi_Cmnd *);
   3.980 +int megaraid_abort (Scsi_Cmnd *);
   3.981 +int megaraid_reset (Scsi_Cmnd *, unsigned int);
   3.982 +int megaraid_queue (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
   3.983 +int megaraid_biosparam (Disk *, kdev_t, int *);
   3.984 +#if 0
   3.985 +int megaraid_proc_info (char *buffer, char **start, off_t offset,
   3.986 +			int length, int hostno, int inout);
   3.987 +#endif
   3.988 +static int megaIssueCmd (mega_host_config * megaCfg, u_char * mboxData,
   3.989 +			 mega_scb * scb, int intr);
   3.990 +static int mega_build_sglist (mega_host_config * megaCfg, mega_scb * scb,
   3.991 +			      u32 * buffer, u32 * length);
   3.992 +static int mega_busyWaitMbox (mega_host_config *);
   3.993 +static int mega_runpendq (mega_host_config *);
   3.994 +static void mega_rundoneq (mega_host_config *);
   3.995 +static void mega_cmd_done (mega_host_config *, mega_scb *, int);
   3.996 +static inline void mega_freeSgList (mega_host_config * megaCfg);
   3.997 +static void mega_Convert8ldTo40ld (mega_RAIDINQ * inquiry,
   3.998 +				   mega_Enquiry3 * enquiry3,
   3.999 +				   megaRaidProductInfo * productInfo);
  3.1000 +
  3.1001 +static int megaraid_reboot_notify (struct notifier_block *,
  3.1002 +				   unsigned long, void *);
  3.1003 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)  
  3.1004 +static mega_scb *mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt);
  3.1005 +static void mega_build_kernel_sg (char *barea, ulong xfersize, mega_scb * pScb,
  3.1006 +			   mega_ioctl_mbox * mbox);
  3.1007 +#endif
  3.1008 +
  3.1009 +static int megadev_open (struct inode *, struct file *);
  3.1010 +static int megadev_ioctl_entry (struct inode *, struct file *,
  3.1011 +				unsigned int, unsigned long);
  3.1012 +static int megadev_ioctl (struct inode *, struct file *,
  3.1013 +			  unsigned int, unsigned long);
  3.1014 +static mega_scb *megadev_doioctl (mega_host_config *, Scsi_Cmnd *);
  3.1015 +static int megadev_close (struct inode *, struct file *);
  3.1016 +static void megadev_ioctl_done (Scsi_Cmnd *);
  3.1017 +static int mega_init_scb (mega_host_config *);
  3.1018 +static void enq_scb_freelist (mega_host_config *, mega_scb *,
  3.1019 +			      int lock, int intr);
  3.1020 +
  3.1021 +static int mega_is_bios_enabled (mega_host_config *);
  3.1022 +static void mega_reorder_hosts (void);
  3.1023 +static void mega_swap_hosts (struct Scsi_Host *, struct Scsi_Host *);
  3.1024 +
  3.1025 +#if 0
  3.1026 +static void mega_create_proc_entry (int index, struct proc_dir_entry *);
  3.1027 +#endif
  3.1028 +static int mega_support_ext_cdb(mega_host_config *);
  3.1029 +static mega_passthru* mega_prepare_passthru(mega_host_config *, mega_scb *,
  3.1030 +		Scsi_Cmnd *, int, int);
  3.1031 +static mega_ext_passthru* mega_prepare_extpassthru(mega_host_config *,
  3.1032 +		mega_scb *, Scsi_Cmnd *, int, int);
  3.1033 +static void mega_enum_raid_scsi(mega_host_config *);
  3.1034 +static int mega_partsize(Disk *, kdev_t, int *);
  3.1035 +static void mega_get_boot_drv(mega_host_config *);
  3.1036 +static int mega_get_ldrv_num(mega_host_config *, Scsi_Cmnd *, int);
  3.1037 +static int mega_support_random_del(mega_host_config *);
  3.1038 +static int mega_del_logdrv(mega_host_config *, int);
  3.1039 +static int mega_do_del_logdrv(mega_host_config *, int);
  3.1040 +
  3.1041 +#endif
  3.1042 +
  3.1043 +/* vi: set ts=4: */
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/xen/include/xeno/version.h	Mon Mar 31 11:34:23 2003 +0000
     4.3 @@ -0,0 +1,2 @@
     4.4 +#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
     4.5 +#define LINUX_VERSION_CODE KERNEL_VERSION(2,4,21)