| File: | obj-scan-build/../linux/src/drivers/scsi/u14-34f.c |
| Location: | line 763, column 10 |
| Description: | Array subscript is undefined |
| 1 | /* | |||
| 2 | * u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters. | |||
| 3 | * | |||
| 4 | * 26 Jul 1998 Rev. 4.33 for linux 2.0.35 and 2.1.111 | |||
| 5 | * Added command line option (et:[y|n]) to use the existing | |||
| 6 | * translation (returned by scsicam_bios_param) as disk geometry. | |||
| 7 | * The default is et:n, which uses the disk geometry jumpered | |||
| 8 | * on the board. | |||
| 9 | * The default value et:n is compatible with all previous revisions | |||
| 10 | * of this driver. | |||
| 11 | * | |||
| 12 | * 28 May 1998 Rev. 4.32 for linux 2.0.33 and 2.1.104 | |||
| 13 | * Increased busy timeout from 10 msec. to 200 msec. while | |||
| 14 | * processing interrupts. | |||
| 15 | * | |||
| 16 | * 18 May 1998 Rev. 4.31 for linux 2.0.33 and 2.1.102 | |||
| 17 | * Improved abort handling during the eh recovery process. | |||
| 18 | * | |||
| 19 | * 13 May 1998 Rev. 4.30 for linux 2.0.33 and 2.1.101 | |||
| 20 | * The driver is now fully SMP safe, including the | |||
| 21 | * abort and reset routines. | |||
| 22 | * Added command line options (eh:[y|n]) to choose between | |||
| 23 | * new_eh_code and the old scsi code. | |||
| 24 | * If linux version >= 2.1.101 the default is eh:y, while the eh | |||
| 25 | * option is ignored for previous releases and the old scsi code | |||
| 26 | * is used. | |||
| 27 | * | |||
| 28 | * 18 Apr 1998 Rev. 4.20 for linux 2.0.33 and 2.1.97 | |||
| 29 | * Reworked interrupt handler. | |||
| 30 | * | |||
| 31 | * 11 Apr 1998 rev. 4.05 for linux 2.0.33 and 2.1.95 | |||
| 32 | * Major reliability improvement: when a batch with overlapping | |||
| 33 | * requests is detected, requests are queued one at a time | |||
| 34 | * eliminating any possible board or drive reordering. | |||
| 35 | * | |||
| 36 | * 10 Apr 1998 rev. 4.04 for linux 2.0.33 and 2.1.95 | |||
| 37 | * Improved SMP support (if linux version >= 2.1.95). | |||
| 38 | * | |||
| 39 | * 9 Apr 1998 rev. 4.03 for linux 2.0.33 and 2.1.94 | |||
| 40 | * Performance improvement: when sequential i/o is detected, | |||
| 41 | * always use direct sort instead of reverse sort. | |||
| 42 | * | |||
| 43 | * 4 Apr 1998 rev. 4.02 for linux 2.0.33 and 2.1.92 | |||
| 44 | * io_port is now unsigned long. | |||
| 45 | * | |||
| 46 | * 17 Mar 1998 rev. 4.01 for linux 2.0.33 and 2.1.88 | |||
| 47 | * Use new scsi error handling code (if linux version >= 2.1.88). | |||
| 48 | * Use new interrupt code. | |||
| 49 | * | |||
| 50 | * 12 Sep 1997 rev. 3.11 for linux 2.0.30 and 2.1.55 | |||
| 51 | * Use of udelay inside the wait loops to avoid timeout | |||
| 52 | * problems with fast cpus. | |||
| 53 | * Removed check about useless calls to the interrupt service | |||
| 54 | * routine (reported on SMP systems only). | |||
| 55 | * At initialization time "sorted/unsorted" is displayed instead | |||
| 56 | * of "linked/unlinked" to reinforce the fact that "linking" is | |||
| 57 | * nothing but "elevator sorting" in the actual implementation. | |||
| 58 | * | |||
| 59 | * 17 May 1997 rev. 3.10 for linux 2.0.30 and 2.1.38 | |||
| 60 | * Use of serial_number_at_timeout in abort and reset processing. | |||
| 61 | * Use of the __initfunc and __initdata macro in setup code. | |||
| 62 | * Minor cleanups in the list_statistics code. | |||
| 63 | * | |||
| 64 | * 24 Feb 1997 rev. 3.00 for linux 2.0.29 and 2.1.26 | |||
| 65 | * When loading as a module, parameter passing is now supported | |||
| 66 | * both in 2.0 and in 2.1 style. | |||
| 67 | * Fixed data transfer direction for some SCSI opcodes. | |||
| 68 | * Immediate acknowledge to request sense commands. | |||
| 69 | * Linked commands to each disk device are now reordered by elevator | |||
| 70 | * sorting. Rare cases in which reordering of write requests could | |||
| 71 | * cause wrong results are managed. | |||
| 72 | * | |||
| 73 | * 18 Jan 1997 rev. 2.60 for linux 2.1.21 and 2.0.28 | |||
| 74 | * Added command line options to enable/disable linked commands | |||
| 75 | * (lc:[y|n]), old firmware support (of:[y|n]) and to set the max | |||
| 76 | * queue depth (mq:xx). Default is "u14-34f=lc:n,of:n,mq:8". | |||
| 77 | * Improved command linking. | |||
| 78 | * | |||
| 79 | * 8 Jan 1997 rev. 2.50 for linux 2.1.20 and 2.0.27 | |||
| 80 | * Added linked command support. | |||
| 81 | * | |||
| 82 | * 3 Dec 1996 rev. 2.40 for linux 2.1.14 and 2.0.27 | |||
| 83 | * Added queue depth adjustment. | |||
| 84 | * | |||
| 85 | * 22 Nov 1996 rev. 2.30 for linux 2.1.12 and 2.0.26 | |||
| 86 | * The list of i/o ports to be probed can be overwritten by the | |||
| 87 | * "u14-34f=port0,port1,...." boot command line option. | |||
| 88 | * Scatter/gather lists are now allocated by a number of kmalloc | |||
| 89 | * calls, in order to avoid the previous size limit of 64Kb. | |||
| 90 | * | |||
| 91 | * 16 Nov 1996 rev. 2.20 for linux 2.1.10 and 2.0.25 | |||
| 92 | * Added multichannel support. | |||
| 93 | * | |||
| 94 | * 27 Sep 1996 rev. 2.12 for linux 2.1.0 | |||
| 95 | * Portability cleanups (virtual/bus addressing, little/big endian | |||
| 96 | * support). | |||
| 97 | * | |||
| 98 | * 09 Jul 1996 rev. 2.11 for linux 2.0.4 | |||
| 99 | * "Data over/under-run" no longer implies a redo on all targets. | |||
| 100 | * Number of internal retries is now limited. | |||
| 101 | * | |||
| 102 | * 16 Apr 1996 rev. 2.10 for linux 1.3.90 | |||
| 103 | * New argument "reset_flags" to the reset routine. | |||
| 104 | * | |||
| 105 | * 21 Jul 1995 rev. 2.02 for linux 1.3.11 | |||
| 106 | * Fixed Data Transfer Direction for some SCSI commands. | |||
| 107 | * | |||
| 108 | * 13 Jun 1995 rev. 2.01 for linux 1.2.10 | |||
| 109 | * HAVE_OLD_UX4F_FIRMWARE should be defined for U34F boards when | |||
| 110 | * the firmware prom is not the latest one (28008-006). | |||
| 111 | * | |||
| 112 | * 11 Mar 1995 rev. 2.00 for linux 1.2.0 | |||
| 113 | * Fixed a bug which prevented media change detection for removable | |||
| 114 | * disk drives. | |||
| 115 | * | |||
| 116 | * 23 Feb 1995 rev. 1.18 for linux 1.1.94 | |||
| 117 | * Added a check for scsi_register returning NULL. | |||
| 118 | * | |||
| 119 | * 11 Feb 1995 rev. 1.17 for linux 1.1.91 | |||
| 120 | * U14F qualified to run with 32 sglists. | |||
| 121 | * Now DEBUG_RESET is disabled by default. | |||
| 122 | * | |||
| 123 | * 9 Feb 1995 rev. 1.16 for linux 1.1.90 | |||
| 124 | * Use host->wish_block instead of host->block. | |||
| 125 | * | |||
| 126 | * 8 Feb 1995 rev. 1.15 for linux 1.1.89 | |||
| 127 | * Cleared target_time_out counter while performing a reset. | |||
| 128 | * | |||
| 129 | * 28 Jan 1995 rev. 1.14 for linux 1.1.86 | |||
| 130 | * Added module support. | |||
| 131 | * Log and do a retry when a disk drive returns a target status | |||
| 132 | * different from zero on a recovered error. | |||
| 133 | * Auto detects if U14F boards have an old firmware revision. | |||
| 134 | * Max number of scatter/gather lists set to 16 for all boards | |||
| 135 | * (most installation run fine using 33 sglists, while other | |||
| 136 | * has problems when using more then 16). | |||
| 137 | * | |||
| 138 | * 16 Jan 1995 rev. 1.13 for linux 1.1.81 | |||
| 139 | * Display a message if check_region detects a port address | |||
| 140 | * already in use. | |||
| 141 | * | |||
| 142 | * 15 Dec 1994 rev. 1.12 for linux 1.1.74 | |||
| 143 | * The host->block flag is set for all the detected ISA boards. | |||
| 144 | * | |||
| 145 | * 30 Nov 1994 rev. 1.11 for linux 1.1.68 | |||
| 146 | * Redo i/o on target status CHECK_CONDITION for TYPE_DISK only. | |||
| 147 | * Added optional support for using a single board at a time. | |||
| 148 | * | |||
| 149 | * 14 Nov 1994 rev. 1.10 for linux 1.1.63 | |||
| 150 | * | |||
| 151 | * 28 Oct 1994 rev. 1.09 for linux 1.1.58 Final BETA release. | |||
| 152 | * 16 Jul 1994 rev. 1.00 for linux 1.1.29 Initial ALPHA release. | |||
| 153 | * | |||
| 154 | * This driver is a total replacement of the original UltraStor | |||
| 155 | * scsi driver, but it supports ONLY the 14F and 34F boards. | |||
| 156 | * It can be configured in the same kernel in which the original | |||
| 157 | * ultrastor driver is configured to allow the original U24F | |||
| 158 | * support. | |||
| 159 | * | |||
| 160 | * Multiple U14F and/or U34F host adapters are supported. | |||
| 161 | * | |||
| 162 | * Copyright (C) 1994-1998 Dario Ballabio (dario@milano.europe.dg.com) | |||
| 163 | * | |||
| 164 | * Redistribution and use in source and binary forms, with or without | |||
| 165 | * modification, are permitted provided that redistributions of source | |||
| 166 | * code retain the above copyright notice and this comment without | |||
| 167 | * modification. | |||
| 168 | * | |||
| 169 | * WARNING: if your 14/34F board has an old firmware revision (see below) | |||
| 170 | * you must change "#undef" into "#define" in the following | |||
| 171 | * statement. | |||
| 172 | */ | |||
| 173 | #undef HAVE_OLD_UX4F_FIRMWARE | |||
| 174 | /* | |||
| 175 | * The UltraStor 14F, 24F, and 34F are a family of intelligent, high | |||
| 176 | * performance SCSI-2 host adapters. | |||
| 177 | * Here is the scoop on the various models: | |||
| 178 | * | |||
| 179 | * 14F - ISA first-party DMA HA with floppy support and WD1003 emulation. | |||
| 180 | * 24F - EISA Bus Master HA with floppy support and WD1003 emulation. | |||
| 181 | * 34F - VESA Local-Bus Bus Master HA (no WD1003 emulation). | |||
| 182 | * | |||
| 183 | * This code has been tested with up to two U14F boards, using both | |||
| 184 | * firmware 28004-005/38004-004 (BIOS rev. 2.00) and the latest firmware | |||
| 185 | * 28004-006/38004-005 (BIOS rev. 2.01). | |||
| 186 | * | |||
| 187 | * The latest firmware is required in order to get reliable operations when | |||
| 188 | * clustering is enabled. ENABLE_CLUSTERING provides a performance increase | |||
| 189 | * up to 50% on sequential access. | |||
| 190 | * | |||
| 191 | * Since the Scsi_Host_Template structure is shared among all 14F and 34F, | |||
| 192 | * the last setting of use_clustering is in effect for all of these boards. | |||
| 193 | * | |||
| 194 | * Here a sample configuration using two U14F boards: | |||
| 195 | * | |||
| 196 | U14F0: ISA 0x330, BIOS 0xc8000, IRQ 11, DMA 5, SG 32, MB 16, of:n, lc:y, mq:8. | |||
| 197 | U14F1: ISA 0x340, BIOS 0x00000, IRQ 10, DMA 6, SG 32, MB 16, of:n, lc:y, mq:8. | |||
| 198 | * | |||
| 199 | * The boot controller must have its BIOS enabled, while other boards can | |||
| 200 | * have their BIOS disabled, or enabled to an higher address. | |||
| 201 | * Boards are named Ux4F0, Ux4F1..., according to the port address order in | |||
| 202 | * the io_port[] array. | |||
| 203 | * | |||
| 204 | * The following facts are based on real testing results (not on | |||
| 205 | * documentation) on the above U14F board. | |||
| 206 | * | |||
| 207 | * - The U14F board should be jumpered for bus on time less or equal to 7 | |||
| 208 | * microseconds, while the default is 11 microseconds. This is order to | |||
| 209 | * get acceptable performance while using floppy drive and hard disk | |||
| 210 | * together. The jumpering for 7 microseconds is: JP13 pin 15-16, | |||
| 211 | * JP14 pin 7-8 and pin 9-10. | |||
| 212 | * The reduction has a little impact on scsi performance. | |||
| 213 | * | |||
| 214 | * - If scsi bus length exceeds 3m., the scsi bus speed needs to be reduced | |||
| 215 | * from 10Mhz to 5Mhz (do this by inserting a jumper on JP13 pin 7-8). | |||
| 216 | * | |||
| 217 | * - If U14F on board firmware is older than 28004-006/38004-005, | |||
| 218 | * the U14F board is unable to provide reliable operations if the scsi | |||
| 219 | * request length exceeds 16Kbyte. When this length is exceeded the | |||
| 220 | * behavior is: | |||
| 221 | * - adapter_status equal 0x96 or 0xa3 or 0x93 or 0x94; | |||
| 222 | * - adapter_status equal 0 and target_status equal 2 on for all targets | |||
| 223 | * in the next operation following the reset. | |||
| 224 | * This sequence takes a long time (>3 seconds), so in the meantime | |||
| 225 | * the SD_TIMEOUT in sd.c could expire giving rise to scsi aborts | |||
| 226 | * (SD_TIMEOUT has been increased from 3 to 6 seconds in 1.1.31). | |||
| 227 | * Because of this I had to DISABLE_CLUSTERING and to work around the | |||
| 228 | * bus reset in the interrupt service routine, returning DID_BUS_BUSY | |||
| 229 | * so that the operations are retried without complains from the scsi.c | |||
| 230 | * code. | |||
| 231 | * Any reset of the scsi bus is going to kill tape operations, since | |||
| 232 | * no retry is allowed for tapes. Bus resets are more likely when the | |||
| 233 | * scsi bus is under heavy load. | |||
| 234 | * Requests using scatter/gather have a maximum length of 16 x 1024 bytes | |||
| 235 | * when DISABLE_CLUSTERING is in effect, but unscattered requests could be | |||
| 236 | * larger than 16Kbyte. | |||
| 237 | * | |||
| 238 | * The new firmware has fixed all the above problems. | |||
| 239 | * | |||
| 240 | * For U34F boards the latest bios prom is 38008-002 (BIOS rev. 2.01), | |||
| 241 | * the latest firmware prom is 28008-006. Older firmware 28008-005 has | |||
| 242 | * problems when using more then 16 scatter/gather lists. | |||
| 243 | * | |||
| 244 | * The list of i/o ports to be probed can be totally replaced by the | |||
| 245 | * boot command line option: "u14-34f=port0,port1,port2,...", where the | |||
| 246 | * port0, port1... arguments are ISA/VESA addresses to be probed. | |||
| 247 | * For example using "u14-34f=0x230,0x340", the driver probes only the two | |||
| 248 | * addresses 0x230 and 0x340 in this order; "u14-34f=0" totally disables | |||
| 249 | * this driver. | |||
| 250 | * | |||
| 251 | * After the optional list of detection probes, other possible command line | |||
| 252 | * options are: | |||
| 253 | * | |||
| 254 | * eh:y use new scsi code (linux 2.2 only); | |||
| 255 | * eh:n use old scsi code; | |||
| 256 | * et:y use disk geometry returned by scsicam_bios_param; | |||
| 257 | * et:n use disk geometry jumpered on the board; | |||
| 258 | * lc:y enables linked commands; | |||
| 259 | * lc:n disables linked commands; | |||
| 260 | * of:y enables old firmware support; | |||
| 261 | * of:n disables old firmware support; | |||
| 262 | * mq:xx set the max queue depth to the value xx (2 <= xx <= 8). | |||
| 263 | * | |||
| 264 | * The default value is: "u14-34f=lc:n,of:n,mq:8,et:n". | |||
| 265 | * An example using the list of detection probes could be: | |||
| 266 | * "u14-34f=0x230,0x340,lc:y,of:n,mq:4,eh:n,et:n". | |||
| 267 | * | |||
| 268 | * When loading as a module, parameters can be specified as well. | |||
| 269 | * The above example would be (use 1 in place of y and 0 in place of n): | |||
| 270 | * | |||
| 271 | * modprobe u14-34f io_port=0x230,0x340 linked_comm=1 have_old_firmware=0 \ | |||
| 272 | * max_queue_depth=4 use_new_eh_code=0 ext_tran=0 | |||
| 273 | * | |||
| 274 | * ---------------------------------------------------------------------------- | |||
| 275 | * In this implementation, linked commands are designed to work with any DISK | |||
| 276 | * or CD-ROM, since this linking has only the intent of clustering (time-wise) | |||
| 277 | * and reordering by elevator sorting commands directed to each device, | |||
| 278 | * without any relation with the actual SCSI protocol between the controller | |||
| 279 | * and the device. | |||
| 280 | * If Q is the queue depth reported at boot time for each device (also named | |||
| 281 | * cmds/lun) and Q > 2, whenever there is already an active command to the | |||
| 282 | * device all other commands to the same device (up to Q-1) are kept waiting | |||
| 283 | * in the elevator sorting queue. When the active command completes, the | |||
| 284 | * commands in this queue are sorted by sector address. The sort is chosen | |||
| 285 | * between increasing or decreasing by minimizing the seek distance between | |||
| 286 | * the sector of the commands just completed and the sector of the first | |||
| 287 | * command in the list to be sorted. | |||
| 288 | * Trivial math assures that the unsorted average seek distance when doing | |||
| 289 | * random seeks over S sectors is S/3. | |||
| 290 | * When (Q-1) requests are uniformly distributed over S sectors, the average | |||
| 291 | * distance between two adjacent requests is S/((Q-1) + 1), so the sorted | |||
| 292 | * average seek distance for (Q-1) random requests over S sectors is S/Q. | |||
| 293 | * The elevator sorting hence divides the seek distance by a factor Q/3. | |||
| 294 | * The above pure geometric remarks are valid in all cases and the | |||
| 295 | * driver effectively reduces the seek distance by the predicted factor | |||
| 296 | * when there are Q concurrent read i/o operations on the device, but this | |||
| 297 | * does not necessarily results in a noticeable performance improvement: | |||
| 298 | * your mileage may vary.... | |||
| 299 | * | |||
| 300 | * Note: command reordering inside a batch of queued commands could cause | |||
| 301 | * wrong results only if there is at least one write request and the | |||
| 302 | * intersection (sector-wise) of all requests is not empty. | |||
| 303 | * When the driver detects a batch including overlapping requests | |||
| 304 | * (a really rare event) strict serial (pid) order is enforced. | |||
| 305 | * ---------------------------------------------------------------------------- | |||
| 306 | * | |||
| 307 | * The boards are named Ux4F0, Ux4F1,... according to the detection order. | |||
| 308 | * | |||
| 309 | * In order to support multiple ISA boards in a reliable way, | |||
| 310 | * the driver sets host->wish_block = TRUE for all ISA boards. | |||
| 311 | */ | |||
| 312 | ||||
| 313 | #include <linux/version.h> | |||
| 314 | ||||
| 315 | #define LinuxVersionCode(v, p, s)(((v)<<16)+((p)<<8)+(s)) (((v)<<16)+((p)<<8)+(s)) | |||
| 316 | #define MAX_INT_PARAM10 10 | |||
| 317 | ||||
| 318 | #if defined(MODULE) | |||
| 319 | #include <linux/module.h> | |||
| 320 | ||||
| 321 | #if LINUX_VERSION_CODE131108 >= LinuxVersionCode(2,1,26)(((2)<<16)+((1)<<8)+(26)) | |||
| 322 | MODULE_PARM(io_port, "1-" __MODULE_STRING(MAX_INT_PARAM10) "i"); | |||
| 323 | MODULE_PARM(linked_comm, "i"); | |||
| 324 | MODULE_PARM(have_old_firmware, "i"); | |||
| 325 | MODULE_PARM(link_statistics, "i"); | |||
| 326 | MODULE_PARM(max_queue_depth, "i"); | |||
| 327 | MODULE_PARM(use_new_eh_code, "i"); | |||
| 328 | MODULE_PARM(ext_tran, "i"); | |||
| 329 | MODULE_AUTHOR("Dario Ballabio"); | |||
| 330 | #endif | |||
| 331 | ||||
| 332 | #endif | |||
| 333 | ||||
| 334 | #include <linux/string.h> | |||
| 335 | #include <linux/sched.h> | |||
| 336 | #include <linux/kernel.h> | |||
| 337 | #include <linux/ioport.h> | |||
| 338 | #include <linux/delay.h> | |||
| 339 | #include <asm/io.h> | |||
| 340 | #include <asm/system.h> | |||
| 341 | #include <asm/byteorder.h> | |||
| 342 | #include <linux/proc_fs.h> | |||
| 343 | #include <linux/blk.h> | |||
| 344 | #include "scsi.h" | |||
| 345 | #include "hosts.h" | |||
| 346 | #include "sd.h" | |||
| 347 | #include <asm/dma.h> | |||
| 348 | #include <asm/irq.h> | |||
| 349 | #include "u14-34f.h" | |||
| 350 | #include <linux/stat.h> | |||
| 351 | #include <linux/config.h> | |||
| 352 | ||||
| 353 | #if LINUX_VERSION_CODE131108 >= LinuxVersionCode(2,1,36)(((2)<<16)+((1)<<8)+(36)) | |||
| 354 | #include <linux/init.h> | |||
| 355 | #else | |||
| 356 | #define __initfunc(A)A A | |||
| 357 | #define __initdata | |||
| 358 | #define __init | |||
| 359 | #endif | |||
| 360 | ||||
| 361 | #if LINUX_VERSION_CODE131108 >= LinuxVersionCode(2,1,101)(((2)<<16)+((1)<<8)+(101)) | |||
| 362 | #include <asm/spinlock.h> | |||
| 363 | #define IRQ_FLAGSunsigned long irq_flags; | |||
| 364 | #define IRQ_LOCK__asm__ __volatile__ ("cli": : :"memory"); | |||
| 365 | #define IRQ_LOCK_SAVEdo {__asm__ __volatile__("pushf ; pop %0" : "=r" (irq_flags): :"memory"); __asm__ __volatile__ ("cli": : :"memory");} while (0); | |||
| 366 | #define IRQ_UNLOCK__asm__ __volatile__ ("sti": : :"memory"); | |||
| 367 | #define IRQ_UNLOCK_RESTOREdo {__asm__ __volatile__("push %0 ; popf": :"g" (irq_flags):"memory" );} while (0); | |||
| 368 | #define SPIN_FLAGS unsigned long spin_flags; | |||
| 369 | #define SPIN_LOCK spin_lock_irq(&io_request_lock); | |||
| 370 | #define SPIN_LOCK_SAVE spin_lock_irqsave(&io_request_lock, spin_flags); | |||
| 371 | #define SPIN_UNLOCK spin_unlock_irq(&io_request_lock); | |||
| 372 | #define SPIN_UNLOCK_RESTORE \ | |||
| 373 | spin_unlock_irqrestore(&io_request_lock, spin_flags); | |||
| 374 | static int use_new_eh_code = TRUE1; | |||
| 375 | #else | |||
| 376 | #define IRQ_FLAGSunsigned long irq_flags; unsigned long irq_flags; | |||
| 377 | #define IRQ_LOCK__asm__ __volatile__ ("cli": : :"memory"); cli()__asm__ __volatile__ ("cli": : :"memory"); | |||
| 378 | #define IRQ_LOCK_SAVEdo {__asm__ __volatile__("pushf ; pop %0" : "=r" (irq_flags): :"memory"); __asm__ __volatile__ ("cli": : :"memory");} while (0); do {save_flags(irq_flags)__asm__ __volatile__("pushf ; pop %0" : "=r" (irq_flags): :"memory" ); cli()__asm__ __volatile__ ("cli": : :"memory");} while (0); | |||
| 379 | #define IRQ_UNLOCK__asm__ __volatile__ ("sti": : :"memory"); sti()__asm__ __volatile__ ("sti": : :"memory"); | |||
| 380 | #define IRQ_UNLOCK_RESTOREdo {__asm__ __volatile__("push %0 ; popf": :"g" (irq_flags):"memory" );} while (0); do {restore_flags(irq_flags)__asm__ __volatile__("push %0 ; popf": :"g" (irq_flags):"memory" );} while (0); | |||
| 381 | #define SPIN_FLAGS | |||
| 382 | #define SPIN_LOCK | |||
| 383 | #define SPIN_LOCK_SAVE | |||
| 384 | #define SPIN_UNLOCK | |||
| 385 | #define SPIN_UNLOCK_RESTORE | |||
| 386 | static int use_new_eh_code = FALSE0; | |||
| 387 | #endif | |||
| 388 | ||||
| 389 | struct proc_dir_entry proc_scsi_u14_34f = { | |||
| 390 | PROC_SCSI_U14_34F, 6, "u14_34f", | |||
| 391 | S_IFDIR0040000 | S_IRUGO(00400|00040|00004) | S_IXUGO(00100|00010|00001), 2 | |||
| 392 | }; | |||
| 393 | ||||
| 394 | /* Values for the PRODUCT_ID ports for the 14/34F */ | |||
| 395 | #define PRODUCT_ID10x56 0x56 | |||
| 396 | #define PRODUCT_ID20x40 0x40 /* NOTE: Only upper nibble is used */ | |||
| 397 | ||||
| 398 | /* Subversion values */ | |||
| 399 | #define ISA0 0 | |||
| 400 | #define ESA1 1 | |||
| 401 | ||||
| 402 | #define OP_HOST_ADAPTER0x1 0x1 | |||
| 403 | #define OP_SCSI0x2 0x2 | |||
| 404 | #define OP_RESET0x4 0x4 | |||
| 405 | #define DTD_SCSI0x0 0x0 | |||
| 406 | #define DTD_IN0x1 0x1 | |||
| 407 | #define DTD_OUT0x2 0x2 | |||
| 408 | #define DTD_NONE0x3 0x3 | |||
| 409 | #define HA_CMD_INQUIRY0x1 0x1 | |||
| 410 | #define HA_CMD_SELF_DIAG0x2 0x2 | |||
| 411 | #define HA_CMD_READ_BUFF0x3 0x3 | |||
| 412 | #define HA_CMD_WRITE_BUFF0x4 0x4 | |||
| 413 | ||||
| 414 | #undef DEBUG_LINKED_COMMANDS | |||
| 415 | #undef DEBUG_DETECT | |||
| 416 | #undef DEBUG_INTERRUPT | |||
| 417 | #undef DEBUG_RESET | |||
| 418 | #undef DEBUG_GENERATE_ERRORS | |||
| 419 | #undef DEBUG_GENERATE_ABORTS | |||
| 420 | #undef DEBUG_GEOMETRY | |||
| 421 | ||||
| 422 | #define MAX_ISA3 3 | |||
| 423 | #define MAX_VESA1 1 | |||
| 424 | #define MAX_EISA0 0 | |||
| 425 | #define MAX_PCI0 0 | |||
| 426 | #define MAX_BOARDS(3 + 1 + 0 + 0) (MAX_ISA3 + MAX_VESA1 + MAX_EISA0 + MAX_PCI0) | |||
| 427 | #define MAX_CHANNEL1 1 | |||
| 428 | #define MAX_LUN8 8 | |||
| 429 | #define MAX_TARGET8 8 | |||
| 430 | #define MAX_MAILBOXES16 16 | |||
| 431 | #define MAX_SGLIST32 32 | |||
| 432 | #define MAX_SAFE_SGLIST16 16 | |||
| 433 | #define MAX_INTERNAL_RETRIES64 64 | |||
| 434 | #define MAX_CMD_PER_LUN2 2 | |||
| 435 | #define MAX_TAGGED_CMD_PER_LUN(16 - 2) (MAX_MAILBOXES16 - MAX_CMD_PER_LUN2) | |||
| 436 | ||||
| 437 | #define SKIP(~0UL) ULONG_MAX(~0UL) | |||
| 438 | #define FALSE0 0 | |||
| 439 | #define TRUE1 1 | |||
| 440 | #define FREE0 0 | |||
| 441 | #define IN_USE1 1 | |||
| 442 | #define LOCKED2 2 | |||
| 443 | #define IN_RESET3 3 | |||
| 444 | #define IGNORE4 4 | |||
| 445 | #define READY5 5 | |||
| 446 | #define ABORTING6 6 | |||
| 447 | #define NO_DMA0xff 0xff | |||
| 448 | #define MAXLOOP10000 10000 | |||
| 449 | ||||
| 450 | #define REG_LCL_MASK0 0 | |||
| 451 | #define REG_LCL_INTR1 1 | |||
| 452 | #define REG_SYS_MASK2 2 | |||
| 453 | #define REG_SYS_INTR3 3 | |||
| 454 | #define REG_PRODUCT_ID14 4 | |||
| 455 | #define REG_PRODUCT_ID25 5 | |||
| 456 | #define REG_CONFIG16 6 | |||
| 457 | #define REG_CONFIG27 7 | |||
| 458 | #define REG_OGM8 8 | |||
| 459 | #define REG_ICM12 12 | |||
| 460 | #define REGION_SIZE13 13 | |||
| 461 | #define BSY_ASSERTED0x01 0x01 | |||
| 462 | #define IRQ_ASSERTED0x01 0x01 | |||
| 463 | #define CMD_RESET0xc0 0xc0 | |||
| 464 | #define CMD_OGM_INTR0x01 0x01 | |||
| 465 | #define CMD_CLR_INTR0x01 0x01 | |||
| 466 | #define CMD_ENA_INTR0x81 0x81 | |||
| 467 | #define ASOK0x00 0x00 | |||
| 468 | #define ASST0x91 0x91 | |||
| 469 | ||||
| 470 | #define ARRAY_SIZE(arr)(sizeof (arr) / sizeof (arr)[0]) (sizeof (arr) / sizeof (arr)[0]) | |||
| 471 | #define YESNO(a)((a) ? 'y' : 'n') ((a) ? 'y' : 'n') | |||
| 472 | #define TLDEV(type)((type) == 0x00 || (type) == 0x05) ((type) == TYPE_DISK0x00 || (type) == TYPE_ROM0x05) | |||
| 473 | ||||
| 474 | #define PACKED__attribute__((packed)) __attribute__((packed)) | |||
| 475 | ||||
| 476 | struct sg_list { | |||
| 477 | unsigned int address; /* Segment Address */ | |||
| 478 | unsigned int num_bytes; /* Segment Length */ | |||
| 479 | }; | |||
| 480 | ||||
| 481 | /* MailBox SCSI Command Packet */ | |||
| 482 | struct mscp { | |||
| 483 | unsigned char opcode: 3; /* type of command */ | |||
| 484 | unsigned char xdir: 2; /* data transfer direction */ | |||
| 485 | unsigned char dcn: 1; /* disable disconnect */ | |||
| 486 | unsigned char ca: 1; /* use cache (if available) */ | |||
| 487 | unsigned char sg: 1; /* scatter/gather operation */ | |||
| 488 | unsigned char target: 3; /* SCSI target id */ | |||
| 489 | unsigned char channel: 2; /* SCSI channel number */ | |||
| 490 | unsigned char lun: 3; /* SCSI logical unit number */ | |||
| 491 | unsigned int data_address PACKED__attribute__((packed)); /* transfer data pointer */ | |||
| 492 | unsigned int data_len PACKED__attribute__((packed)); /* length in bytes */ | |||
| 493 | unsigned int link_address PACKED__attribute__((packed)); /* for linking command chains */ | |||
| 494 | unsigned char clink_id; /* identifies command in chain */ | |||
| 495 | unsigned char use_sg; /* (if sg is set) 8 bytes per list */ | |||
| 496 | unsigned char sense_len; | |||
| 497 | unsigned char scsi_cdbs_len; /* 6, 10, or 12 */ | |||
| 498 | unsigned char scsi_cdbs[12]; /* SCSI commands */ | |||
| 499 | unsigned char adapter_status; /* non-zero indicates HA error */ | |||
| 500 | unsigned char target_status; /* non-zero indicates target error */ | |||
| 501 | unsigned int sense_addr PACKED__attribute__((packed)); | |||
| 502 | Scsi_Cmnd *SCpnt; | |||
| 503 | unsigned int index; /* cp index */ | |||
| 504 | struct sg_list *sglist; | |||
| 505 | }; | |||
| 506 | ||||
| 507 | struct hostdata { | |||
| 508 | struct mscp cp[MAX_MAILBOXES16]; /* Mailboxes for this board */ | |||
| 509 | unsigned int cp_stat[MAX_MAILBOXES16]; /* FREE, IN_USE, LOCKED, IN_RESET */ | |||
| 510 | unsigned int last_cp_used; /* Index of last mailbox used */ | |||
| 511 | unsigned int iocount; /* Total i/o done for this board */ | |||
| 512 | int board_number; /* Number of this board */ | |||
| 513 | char board_name[16]; /* Name of this board */ | |||
| 514 | char board_id[256]; /* data from INQUIRY on this board */ | |||
| 515 | int in_reset; /* True if board is doing a reset */ | |||
| 516 | int target_to[MAX_TARGET8][MAX_CHANNEL1]; /* N. of timeout errors on target */ | |||
| 517 | int target_redo[MAX_TARGET8][MAX_CHANNEL1]; /* If TRUE redo i/o on target */ | |||
| 518 | unsigned int retries; /* Number of internal retries */ | |||
| 519 | unsigned long last_retried_pid; /* Pid of last retried command */ | |||
| 520 | unsigned char subversion; /* Bus type, either ISA or ESA */ | |||
| 521 | unsigned char heads; | |||
| 522 | unsigned char sectors; | |||
| 523 | ||||
| 524 | /* slot != 0 for the U24F, slot == 0 for both the U14F and U34F */ | |||
| 525 | unsigned char slot; | |||
| 526 | }; | |||
| 527 | ||||
| 528 | static struct Scsi_Host *sh[MAX_BOARDS(3 + 1 + 0 + 0) + 1]; | |||
| 529 | static const char *driver_name = "Ux4F"; | |||
| 530 | static char sha[MAX_BOARDS(3 + 1 + 0 + 0)]; | |||
| 531 | ||||
| 532 | /* Initialize num_boards so that ihdlr can work while detect is in progress */ | |||
| 533 | static unsigned int num_boards = MAX_BOARDS(3 + 1 + 0 + 0); | |||
| 534 | ||||
| 535 | static unsigned long io_port[] __initdata = { | |||
| 536 | ||||
| 537 | /* Space for MAX_INT_PARAM ports usable while loading as a module */ | |||
| 538 | SKIP(~0UL), SKIP(~0UL), SKIP(~0UL), SKIP(~0UL), SKIP(~0UL), SKIP(~0UL), SKIP(~0UL), SKIP(~0UL), | |||
| 539 | SKIP(~0UL), SKIP(~0UL), | |||
| 540 | ||||
| 541 | /* Possible ISA/VESA ports */ | |||
| 542 | 0x330, 0x340, 0x230, 0x240, 0x210, 0x130, 0x140, | |||
| 543 | ||||
| 544 | /* End of list */ | |||
| 545 | 0x0 | |||
| 546 | }; | |||
| 547 | ||||
| 548 | #define HD(board)((struct hostdata *) &sh[board]->hostdata) ((struct hostdata *) &sh[board]->hostdata) | |||
| 549 | #define BN(board)(((struct hostdata *) &sh[board]->hostdata)->board_name ) (HD(board)((struct hostdata *) &sh[board]->hostdata)->board_name) | |||
| 550 | ||||
| 551 | #define SWAP_BYTE(x)((unsigned long)( (((unsigned long)(x) & 0x000000ffU) << 24) | (((unsigned long)(x) & 0x0000ff00U) << 8) | ( ((unsigned long)(x) & 0x00ff0000U) >> 8) | (((unsigned long)(x) & 0xff000000U) >> 24))) ((unsigned long)( \ | |||
| 552 | (((unsigned long)(x) & 0x000000ffU) << 24) | \ | |||
| 553 | (((unsigned long)(x) & 0x0000ff00U) << 8) | \ | |||
| 554 | (((unsigned long)(x) & 0x00ff0000U) >> 8) | \ | |||
| 555 | (((unsigned long)(x) & 0xff000000U) >> 24))) | |||
| 556 | ||||
| 557 | #if defined(__BIG_ENDIAN) | |||
| 558 | #define H2DEV(x)(x) SWAP_BYTE(x)((unsigned long)( (((unsigned long)(x) & 0x000000ffU) << 24) | (((unsigned long)(x) & 0x0000ff00U) << 8) | ( ((unsigned long)(x) & 0x00ff0000U) >> 8) | (((unsigned long)(x) & 0xff000000U) >> 24))) | |||
| 559 | #else | |||
| 560 | #define H2DEV(x)(x) (x) | |||
| 561 | #endif | |||
| 562 | ||||
| 563 | #define DEV2H(x)(x) H2DEV(x)(x) | |||
| 564 | #define V2DEV(addr)((addr) ? (virt_to_phys((void *)addr)) : 0) ((addr) ? H2DEV(virt_to_bus((void *)addr))(virt_to_phys((void *)addr)) : 0) | |||
| 565 | #define DEV2V(addr)((addr) ? (phys_to_virt((unsigned long)addr)) : 0) ((addr) ? DEV2H(bus_to_virt((unsigned long)addr))(phys_to_virt((unsigned long)addr)) : 0) | |||
| 566 | ||||
| 567 | static void do_interrupt_handler(int, void *, struct pt_regs *); | |||
| 568 | static void flush_dev(Scsi_Device *, unsigned long, unsigned int, unsigned int); | |||
| 569 | static int do_trace = FALSE0; | |||
| 570 | static int setup_done = FALSE0; | |||
| 571 | static int link_statistics = 0; | |||
| 572 | static int ext_tran = FALSE0; | |||
| 573 | ||||
| 574 | #if defined(HAVE_OLD_UX4F_FIRMWARE) | |||
| 575 | static int have_old_firmware = TRUE1; | |||
| 576 | #else | |||
| 577 | static int have_old_firmware = FALSE0; | |||
| 578 | #endif | |||
| 579 | ||||
| 580 | #if defined(CONFIG_SCSI_U14_34F_LINKED_COMMANDS) | |||
| 581 | static int linked_comm = TRUE1; | |||
| 582 | #else | |||
| 583 | static int linked_comm = FALSE0; | |||
| 584 | #endif | |||
| 585 | ||||
| 586 | #if defined(CONFIG_SCSI_U14_34F_MAX_TAGS) | |||
| 587 | static int max_queue_depth = CONFIG_SCSI_U14_34F_MAX_TAGS; | |||
| 588 | #else | |||
| 589 | static int max_queue_depth = MAX_CMD_PER_LUN2; | |||
| 590 | #endif | |||
| 591 | ||||
| 592 | static void select_queue_depths(struct Scsi_Host *host, Scsi_Device *devlist) { | |||
| 593 | Scsi_Device *dev; | |||
| 594 | int j, ntag = 0, nuntag = 0, tqd, utqd; | |||
| 595 | IRQ_FLAGSunsigned long irq_flags; | |||
| 596 | ||||
| 597 | IRQ_LOCK_SAVEdo {__asm__ __volatile__("pushf ; pop %0" : "=r" (irq_flags): :"memory"); __asm__ __volatile__ ("cli": : :"memory");} while (0); | |||
| 598 | j = ((struct hostdata *) host->hostdata)->board_number; | |||
| 599 | ||||
| 600 | for(dev = devlist; dev; dev = dev->next) { | |||
| 601 | ||||
| 602 | if (dev->host != host) continue; | |||
| 603 | ||||
| 604 | if (TLDEV(dev->type)((dev->type) == 0x00 || (dev->type) == 0x05) && (dev->tagged_supported || linked_comm)) | |||
| 605 | ntag++; | |||
| 606 | else | |||
| 607 | nuntag++; | |||
| 608 | } | |||
| 609 | ||||
| 610 | utqd = MAX_CMD_PER_LUN2; | |||
| 611 | ||||
| 612 | tqd = (host->can_queue - utqd * nuntag) / (ntag ? ntag : 1); | |||
| 613 | ||||
| 614 | if (tqd > max_queue_depth) tqd = max_queue_depth; | |||
| 615 | ||||
| 616 | if (tqd < MAX_CMD_PER_LUN2) tqd = MAX_CMD_PER_LUN2; | |||
| 617 | ||||
| 618 | for(dev = devlist; dev; dev = dev->next) { | |||
| 619 | char *tag_suffix = "", *link_suffix = ""; | |||
| 620 | ||||
| 621 | if (dev->host != host) continue; | |||
| 622 | ||||
| 623 | if (TLDEV(dev->type)((dev->type) == 0x00 || (dev->type) == 0x05) && (dev->tagged_supported || linked_comm)) | |||
| 624 | dev->queue_depth = tqd; | |||
| 625 | else | |||
| 626 | dev->queue_depth = utqd; | |||
| 627 | ||||
| 628 | if (TLDEV(dev->type)((dev->type) == 0x00 || (dev->type) == 0x05)) { | |||
| 629 | if (linked_comm && dev->queue_depth > 2) | |||
| 630 | link_suffix = ", sorted"; | |||
| 631 | else | |||
| 632 | link_suffix = ", unsorted"; | |||
| 633 | } | |||
| 634 | ||||
| 635 | if (dev->tagged_supported && TLDEV(dev->type)((dev->type) == 0x00 || (dev->type) == 0x05) && dev->tagged_queue) | |||
| 636 | tag_suffix = ", tagged"; | |||
| 637 | else if (dev->tagged_supported && TLDEV(dev->type)((dev->type) == 0x00 || (dev->type) == 0x05)) | |||
| 638 | tag_suffix = ", untagged"; | |||
| 639 | ||||
| 640 | printk("%s: scsi%d, channel %d, id %d, lun %d, cmds/lun %d%s%s.\n", | |||
| 641 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), host->host_no, dev->channel, dev->id, dev->lun, | |||
| 642 | dev->queue_depth, link_suffix, tag_suffix); | |||
| 643 | } | |||
| 644 | ||||
| 645 | IRQ_UNLOCK_RESTOREdo {__asm__ __volatile__("push %0 ; popf": :"g" (irq_flags):"memory" );} while (0); | |||
| 646 | return; | |||
| 647 | } | |||
| 648 | ||||
| 649 | static inlineinline __attribute__((always_inline)) int wait_on_busy(unsigned long iobase, unsigned int loop) { | |||
| 650 | ||||
| 651 | while (inb(iobase + REG_LCL_INTR)((__builtin_constant_p((iobase + 1)) && (iobase + 1) < 256) ? __inbc(iobase + 1) : __inb(iobase + 1)) & BSY_ASSERTED0x01) { | |||
| 652 | udelay(1L)(__builtin_constant_p(1L) ? __const_udelay((1L) * 0x10c6ul) : __udelay(1L)); | |||
| 653 | if (--loop == 0) return TRUE1; | |||
| 654 | } | |||
| 655 | ||||
| 656 | return FALSE0; | |||
| 657 | } | |||
| 658 | ||||
| 659 | static int board_inquiry(unsigned int j) { | |||
| 660 | struct mscp *cpp; | |||
| 661 | unsigned int time, limit = 0; | |||
| 662 | ||||
| 663 | cpp = &HD(j)((struct hostdata *) &sh[j]->hostdata)->cp[0]; | |||
| 664 | memset(cpp, 0, sizeof(struct mscp))(__builtin_constant_p(0) ? (__builtin_constant_p((sizeof(struct mscp))) ? __constant_c_and_count_memset(((cpp)),((0x01010101UL *(unsigned char)(0))),((sizeof(struct mscp)))) : __constant_c_memset (((cpp)),((0x01010101UL*(unsigned char)(0))),((sizeof(struct mscp ))))) : (__builtin_constant_p((sizeof(struct mscp))) ? __memset_generic ((((cpp))),(((0))),(((sizeof(struct mscp))))) : __memset_generic (((cpp)),((0)),((sizeof(struct mscp)))))); | |||
| 665 | cpp->opcode = OP_HOST_ADAPTER0x1; | |||
| 666 | cpp->xdir = DTD_IN0x1; | |||
| 667 | cpp->data_address = V2DEV(HD(j)->board_id)((((struct hostdata *) &sh[j]->hostdata)->board_id) ? (virt_to_phys((void *)((struct hostdata *) &sh[j]-> hostdata)->board_id)) : 0); | |||
| 668 | cpp->data_len = H2DEV(sizeof(HD(j)->board_id))(sizeof(((struct hostdata *) &sh[j]->hostdata)->board_id )); | |||
| 669 | cpp->scsi_cdbs_len = 6; | |||
| 670 | cpp->scsi_cdbs[0] = HA_CMD_INQUIRY0x1; | |||
| 671 | ||||
| 672 | if (wait_on_busy(sh[j]->io_port, MAXLOOP10000)) { | |||
| 673 | printk("%s: board_inquiry, adapter busy.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name )); | |||
| 674 | return TRUE1; | |||
| 675 | } | |||
| 676 | ||||
| 677 | HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[0] = IGNORE4; | |||
| 678 | ||||
| 679 | /* Clear the interrupt indication */ | |||
| 680 | outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR)((__builtin_constant_p((sh[j]->io_port + 3)) && (sh [j]->io_port + 3) < 256) ? __outbc((0x01),(sh[j]->io_port + 3)) : __outb((0x01),(sh[j]->io_port + 3))); | |||
| 681 | ||||
| 682 | /* Store pointer in OGM address bytes */ | |||
| 683 | outl(V2DEV(cpp), sh[j]->io_port + REG_OGM)((__builtin_constant_p((sh[j]->io_port + 8)) && (sh [j]->io_port + 8) < 256) ? __outlc((((cpp) ? (virt_to_phys ((void *)cpp)) : 0)),(sh[j]->io_port + 8)) : __outl((((cpp ) ? (virt_to_phys((void *)cpp)) : 0)),(sh[j]->io_port + 8) )); | |||
| 684 | ||||
| 685 | /* Issue OGM interrupt */ | |||
| 686 | outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR)((__builtin_constant_p((sh[j]->io_port + 1)) && (sh [j]->io_port + 1) < 256) ? __outbc((0x01),(sh[j]->io_port + 1)) : __outb((0x01),(sh[j]->io_port + 1))); | |||
| 687 | ||||
| 688 | SPIN_UNLOCK | |||
| 689 | IRQ_UNLOCK__asm__ __volatile__ ("sti": : :"memory"); | |||
| 690 | time = jiffies; | |||
| 691 | while ((jiffies - time) < HZ100 && limit++ < 20000) udelay(100L)(__builtin_constant_p(100L) ? __const_udelay((100L) * 0x10c6ul ) : __udelay(100L)); | |||
| 692 | IRQ_LOCK__asm__ __volatile__ ("cli": : :"memory"); | |||
| 693 | SPIN_LOCK | |||
| 694 | ||||
| 695 | if (cpp->adapter_status || HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[0] != FREE0) { | |||
| 696 | HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[0] = FREE0; | |||
| 697 | printk("%s: board_inquiry, err 0x%x.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), cpp->adapter_status); | |||
| 698 | return TRUE1; | |||
| 699 | } | |||
| 700 | ||||
| 701 | return FALSE0; | |||
| 702 | } | |||
| 703 | ||||
| 704 | __initfunc (static inline int port_detect \static inline __attribute__((always_inline)) int port_detect ( unsigned long port_base, unsigned int j, Scsi_Host_Template * tpnt) | |||
| 705 | (unsigned long port_base, unsigned int j, Scsi_Host_Template *tpnt))static inline __attribute__((always_inline)) int port_detect ( unsigned long port_base, unsigned int j, Scsi_Host_Template * tpnt) { | |||
| 706 | unsigned char irq, dma_channel, subversion, i; | |||
| 707 | unsigned char in_byte; | |||
| 708 | char *bus_type, dma_name[16]; | |||
| 709 | ||||
| 710 | /* Allowed BIOS base addresses (NULL indicates reserved) */ | |||
| 711 | void *bios_segment_table[8] = { | |||
| 712 | NULL((void *) 0), | |||
| 713 | (void *) 0xc4000, (void *) 0xc8000, (void *) 0xcc000, (void *) 0xd0000, | |||
| 714 | (void *) 0xd4000, (void *) 0xd8000, (void *) 0xdc000 | |||
| 715 | }; | |||
| 716 | ||||
| 717 | /* Allowed IRQs */ | |||
| 718 | unsigned char interrupt_table[4] = { 15, 14, 11, 10 }; | |||
| 719 | ||||
| 720 | /* Allowed DMA channels for ISA (0 indicates reserved) */ | |||
| 721 | unsigned char dma_channel_table[4] = { 5, 6, 7, 0 }; | |||
| 722 | ||||
| 723 | /* Head/sector mappings */ | |||
| 724 | struct { | |||
| 725 | unsigned char heads; | |||
| 726 | unsigned char sectors; | |||
| 727 | } mapping_table[4] = { | |||
| 728 | { 16, 63 }, { 64, 32 }, { 64, 63 }, { 64, 32 } | |||
| 729 | }; | |||
| 730 | ||||
| 731 | struct config_1 { | |||
| 732 | unsigned char bios_segment: 3; | |||
| 733 | unsigned char removable_disks_as_fixed: 1; | |||
| 734 | unsigned char interrupt: 2; | |||
| 735 | unsigned char dma_channel: 2; | |||
| 736 | } config_1; | |||
| 737 | ||||
| 738 | struct config_2 { | |||
| 739 | unsigned char ha_scsi_id: 3; | |||
| 740 | unsigned char mapping_mode: 2; | |||
| 741 | unsigned char bios_drive_number: 1; | |||
| 742 | unsigned char tfr_port: 2; | |||
| 743 | } config_2; | |||
| 744 | ||||
| 745 | char name[16]; | |||
| 746 | ||||
| 747 | sprintflinux_sprintf(name, "%s%d", driver_name, j); | |||
| 748 | ||||
| 749 | if(check_region(port_base, REGION_SIZE13)) { | |||
| ||||
| 750 | printk("%s: address 0x%03lx in use, skipping probe.\n", name, port_base); | |||
| 751 | return FALSE0; | |||
| 752 | } | |||
| 753 | ||||
| 754 | if (inb(port_base + REG_PRODUCT_ID1)((__builtin_constant_p((port_base + 4)) && (port_base + 4) < 256) ? __inbc(port_base + 4) : __inb(port_base + 4 )) != PRODUCT_ID10x56) return FALSE0; | |||
| 755 | ||||
| 756 | in_byte = inb(port_base + REG_PRODUCT_ID2)((__builtin_constant_p((port_base + 5)) && (port_base + 5) < 256) ? __inbc(port_base + 5) : __inb(port_base + 5 )); | |||
| 757 | ||||
| 758 | if ((in_byte & 0xf0) != PRODUCT_ID20x40) return FALSE0; | |||
| 759 | ||||
| 760 | *(char *)&config_1 = inb(port_base + REG_CONFIG1)((__builtin_constant_p((port_base + 6)) && (port_base + 6) < 256) ? __inbc(port_base + 6) : __inb(port_base + 6 )); | |||
| 761 | *(char *)&config_2 = inb(port_base + REG_CONFIG2)((__builtin_constant_p((port_base + 7)) && (port_base + 7) < 256) ? __inbc(port_base + 7) : __inb(port_base + 7 )); | |||
| 762 | ||||
| 763 | irq = interrupt_table[config_1.interrupt]; | |||
| ||||
| 764 | dma_channel = dma_channel_table[config_1.dma_channel]; | |||
| 765 | subversion = (in_byte & 0x0f); | |||
| 766 | ||||
| 767 | /* Board detected, allocate its IRQ */ | |||
| 768 | if (request_irq(irq, do_interrupt_handler, | |||
| 769 | SA_INTERRUPT0x20000000 | ((subversion == ESA1) ? SA_SHIRQ0x04000000 : 0), | |||
| 770 | driver_name, (void *) &sha[j])) { | |||
| 771 | printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq); | |||
| 772 | return FALSE0; | |||
| 773 | } | |||
| 774 | ||||
| 775 | if (subversion == ISA0 && request_dma(dma_channel, driver_name)) { | |||
| 776 | printk("%s: unable to allocate DMA channel %u, detaching.\n", | |||
| 777 | name, dma_channel); | |||
| 778 | free_irq(irq, &sha[j]); | |||
| 779 | return FALSE0; | |||
| 780 | } | |||
| 781 | ||||
| 782 | if (have_old_firmware) tpnt->use_clustering = DISABLE_CLUSTERING0; | |||
| 783 | ||||
| 784 | #if LINUX_VERSION_CODE131108 >= LinuxVersionCode(2,1,101)(((2)<<16)+((1)<<8)+(101)) | |||
| 785 | tpnt->use_new_eh_code = use_new_eh_code; | |||
| 786 | #else | |||
| 787 | use_new_eh_code = FALSE0; | |||
| 788 | #endif | |||
| 789 | ||||
| 790 | sh[j] = scsi_register(tpnt, sizeof(struct hostdata)); | |||
| 791 | ||||
| 792 | if (sh[j] == NULL((void *) 0)) { | |||
| 793 | printk("%s: unable to register host, detaching.\n", name); | |||
| 794 | ||||
| 795 | free_irq(irq, &sha[j]); | |||
| 796 | ||||
| 797 | if (subversion == ISA0) free_dma(dma_channel); | |||
| 798 | ||||
| 799 | return FALSE0; | |||
| 800 | } | |||
| 801 | ||||
| 802 | sh[j]->io_port = port_base; | |||
| 803 | sh[j]->unique_id = port_base; | |||
| 804 | sh[j]->n_io_port = REGION_SIZE13; | |||
| 805 | sh[j]->base = bios_segment_table[config_1.bios_segment]; | |||
| 806 | sh[j]->irq = irq; | |||
| 807 | sh[j]->sg_tablesize = MAX_SGLIST32; | |||
| 808 | sh[j]->this_id = config_2.ha_scsi_id; | |||
| 809 | sh[j]->can_queue = MAX_MAILBOXES16; | |||
| 810 | sh[j]->cmd_per_lun = MAX_CMD_PER_LUN2; | |||
| 811 | sh[j]->select_queue_depths = select_queue_depths; | |||
| 812 | ||||
| 813 | #if defined(DEBUG_DETECT) | |||
| 814 | { | |||
| 815 | unsigned char sys_mask, lcl_mask; | |||
| 816 | ||||
| 817 | sys_mask = inb(sh[j]->io_port + REG_SYS_MASK)((__builtin_constant_p((sh[j]->io_port + 2)) && (sh [j]->io_port + 2) < 256) ? __inbc(sh[j]->io_port + 2 ) : __inb(sh[j]->io_port + 2)); | |||
| 818 | lcl_mask = inb(sh[j]->io_port + REG_LCL_MASK)((__builtin_constant_p((sh[j]->io_port + 0)) && (sh [j]->io_port + 0) < 256) ? __inbc(sh[j]->io_port + 0 ) : __inb(sh[j]->io_port + 0)); | |||
| 819 | printk("SYS_MASK 0x%x, LCL_MASK 0x%x.\n", sys_mask, lcl_mask); | |||
| 820 | } | |||
| 821 | #endif | |||
| 822 | ||||
| 823 | /* Probably a bogus host scsi id, set it to the dummy value */ | |||
| 824 | if (sh[j]->this_id == 0) sh[j]->this_id = -1; | |||
| 825 | ||||
| 826 | /* If BIOS is disabled, force enable interrupts */ | |||
| 827 | if (sh[j]->base == 0) outb(CMD_ENA_INTR, sh[j]->io_port + REG_SYS_MASK)((__builtin_constant_p((sh[j]->io_port + 2)) && (sh [j]->io_port + 2) < 256) ? __outbc((0x81),(sh[j]->io_port + 2)) : __outb((0x81),(sh[j]->io_port + 2))); | |||
| 828 | ||||
| 829 | /* Register the I/O space that we use */ | |||
| 830 | request_region(sh[j]->io_port, sh[j]->n_io_port, driver_name); | |||
| 831 | ||||
| 832 | memset(HD(j), 0, sizeof(struct hostdata))(__builtin_constant_p(0) ? (__builtin_constant_p((sizeof(struct hostdata))) ? __constant_c_and_count_memset(((((struct hostdata *) &sh[j]->hostdata))),((0x01010101UL*(unsigned char) (0))),((sizeof(struct hostdata)))) : __constant_c_memset((((( struct hostdata *) &sh[j]->hostdata))),((0x01010101UL* (unsigned char)(0))),((sizeof(struct hostdata))))) : (__builtin_constant_p ((sizeof(struct hostdata))) ? __memset_generic((((((struct hostdata *) &sh[j]->hostdata)))),(((0))),(((sizeof(struct hostdata ))))) : __memset_generic(((((struct hostdata *) &sh[j]-> hostdata))),((0)),((sizeof(struct hostdata)))))); | |||
| 833 | HD(j)((struct hostdata *) &sh[j]->hostdata)->heads = mapping_table[config_2.mapping_mode].heads; | |||
| 834 | HD(j)((struct hostdata *) &sh[j]->hostdata)->sectors = mapping_table[config_2.mapping_mode].sectors; | |||
| 835 | HD(j)((struct hostdata *) &sh[j]->hostdata)->subversion = subversion; | |||
| 836 | HD(j)((struct hostdata *) &sh[j]->hostdata)->board_number = j; | |||
| 837 | ||||
| 838 | if (have_old_firmware) sh[j]->sg_tablesize = MAX_SAFE_SGLIST16; | |||
| 839 | ||||
| 840 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->subversion == ESA1) { | |||
| 841 | sh[j]->unchecked_isa_dma = FALSE0; | |||
| 842 | sh[j]->dma_channel = NO_DMA0xff; | |||
| 843 | sprintflinux_sprintf(BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), "U34F%d", j); | |||
| 844 | bus_type = "VESA"; | |||
| 845 | } | |||
| 846 | else { | |||
| 847 | sh[j]->wish_block = TRUE1; | |||
| 848 | sh[j]->unchecked_isa_dma = TRUE1; | |||
| 849 | disable_dma(dma_channel); | |||
| 850 | clear_dma_ff(dma_channel); | |||
| 851 | set_dma_mode(dma_channel, DMA_MODE_CASCADE0xC0); | |||
| 852 | enable_dma(dma_channel); | |||
| 853 | sh[j]->dma_channel = dma_channel; | |||
| 854 | sprintflinux_sprintf(BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), "U14F%d", j); | |||
| 855 | bus_type = "ISA"; | |||
| 856 | } | |||
| 857 | ||||
| 858 | sh[j]->max_channel = MAX_CHANNEL1 - 1; | |||
| 859 | sh[j]->max_id = MAX_TARGET8; | |||
| 860 | sh[j]->max_lun = MAX_LUN8; | |||
| 861 | ||||
| 862 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->subversion == ISA0 && !board_inquiry(j)) { | |||
| 863 | HD(j)((struct hostdata *) &sh[j]->hostdata)->board_id[40] = 0; | |||
| 864 | ||||
| 865 | if (strcmp(&HD(j)((struct hostdata *) &sh[j]->hostdata)->board_id[32], "06000600")) { | |||
| 866 | printk("%s: %s.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), &HD(j)((struct hostdata *) &sh[j]->hostdata)->board_id[8]); | |||
| 867 | printk("%s: firmware %s is outdated, FW PROM should be 28004-006.\n", | |||
| 868 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), &HD(j)((struct hostdata *) &sh[j]->hostdata)->board_id[32]); | |||
| 869 | sh[j]->hostt->use_clustering = DISABLE_CLUSTERING0; | |||
| 870 | sh[j]->sg_tablesize = MAX_SAFE_SGLIST16; | |||
| 871 | } | |||
| 872 | } | |||
| 873 | ||||
| 874 | if (dma_channel == NO_DMA0xff) sprintflinux_sprintf(dma_name, "%s", "BMST"); | |||
| 875 | else sprintflinux_sprintf(dma_name, "DMA %u", dma_channel); | |||
| 876 | ||||
| 877 | for (i = 0; i < sh[j]->can_queue; i++) | |||
| 878 | if (! ((&HD(j)((struct hostdata *) &sh[j]->hostdata)->cp[i])->sglist = kmalloclinux_kmalloc( | |||
| 879 | sh[j]->sg_tablesize * sizeof(struct sg_list), | |||
| 880 | (sh[j]->unchecked_isa_dma ? GFP_DMA0x80 : 0) | GFP_ATOMIC0x01))) { | |||
| 881 | printk("%s: kmalloc SGlist failed, mbox %d, detaching.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i); | |||
| 882 | u14_34f_release(sh[j]); | |||
| 883 | return FALSE0; | |||
| 884 | } | |||
| 885 | ||||
| 886 | if (max_queue_depth > MAX_TAGGED_CMD_PER_LUN(16 - 2)) | |||
| 887 | max_queue_depth = MAX_TAGGED_CMD_PER_LUN(16 - 2); | |||
| 888 | ||||
| 889 | if (max_queue_depth < MAX_CMD_PER_LUN2) max_queue_depth = MAX_CMD_PER_LUN2; | |||
| 890 | ||||
| 891 | if (j == 0) { | |||
| 892 | printk("UltraStor 14F/34F: Copyright (C) 1994-1998 Dario Ballabio.\n"); | |||
| 893 | printk("%s config options -> of:%c, lc:%c, mq:%d, eh:%c, et:%c.\n", | |||
| 894 | driver_name, YESNO(have_old_firmware)((have_old_firmware) ? 'y' : 'n'), YESNO(linked_comm)((linked_comm) ? 'y' : 'n'), | |||
| 895 | max_queue_depth, YESNO(use_new_eh_code)((use_new_eh_code) ? 'y' : 'n'), YESNO(ext_tran)((ext_tran) ? 'y' : 'n')); | |||
| 896 | } | |||
| 897 | ||||
| 898 | printk("%s: %s 0x%03lx, BIOS 0x%05x, IRQ %u, %s, SG %d, MB %d.\n", | |||
| 899 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), bus_type, (unsigned long)sh[j]->io_port, (int)sh[j]->base, | |||
| 900 | sh[j]->irq, dma_name, sh[j]->sg_tablesize, sh[j]->can_queue); | |||
| 901 | ||||
| 902 | if (sh[j]->max_id > 8 || sh[j]->max_lun > 8) | |||
| 903 | printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n", | |||
| 904 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), sh[j]->max_id, sh[j]->max_lun); | |||
| 905 | ||||
| 906 | for (i = 0; i <= sh[j]->max_channel; i++) | |||
| 907 | printk("%s: SCSI channel %u enabled, host target ID %d.\n", | |||
| 908 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i, sh[j]->this_id); | |||
| 909 | ||||
| 910 | return TRUE1; | |||
| 911 | } | |||
| 912 | ||||
| 913 | __initfunc (void u14_34f_setup(char *str, int *ints))void u14_34f_setup(char *str, int *ints) { | |||
| 914 | int i, argc = ints[0]; | |||
| 915 | char *cur = str, *pc; | |||
| 916 | ||||
| 917 | if (argc > 0) { | |||
| 918 | ||||
| 919 | if (argc > MAX_INT_PARAM10) argc = MAX_INT_PARAM10; | |||
| 920 | ||||
| 921 | for (i = 0; i < argc; i++) io_port[i] = ints[i + 1]; | |||
| 922 | ||||
| 923 | io_port[i] = 0; | |||
| 924 | setup_done = TRUE1; | |||
| 925 | } | |||
| 926 | ||||
| 927 | while (cur && (pc = strchr(cur, ':'))) { | |||
| 928 | int val = 0, c = *++pc; | |||
| 929 | ||||
| 930 | if (c == 'n' || c == 'N') val = FALSE0; | |||
| 931 | else if (c == 'y' || c == 'Y') val = TRUE1; | |||
| 932 | else val = (int) simple_strtoul(pc, NULL((void *) 0), 0); | |||
| 933 | ||||
| 934 | if (!strncmp(cur, "lc:", 3)) linked_comm = val; | |||
| 935 | else if (!strncmp(cur, "of:", 3)) have_old_firmware = val; | |||
| 936 | else if (!strncmp(cur, "mq:", 3)) max_queue_depth = val; | |||
| 937 | else if (!strncmp(cur, "ls:", 3)) link_statistics = val; | |||
| 938 | else if (!strncmp(cur, "eh:", 3)) use_new_eh_code = val; | |||
| 939 | else if (!strncmp(cur, "et:", 3)) ext_tran = val; | |||
| 940 | ||||
| 941 | if ((cur = strchr(cur, ','))) ++cur; | |||
| 942 | } | |||
| 943 | ||||
| 944 | return; | |||
| 945 | } | |||
| 946 | ||||
| 947 | __initfunc (int u14_34f_detect(Scsi_Host_Template *tpnt))int u14_34f_detect(Scsi_Host_Template *tpnt) { | |||
| 948 | unsigned int j = 0, k; | |||
| 949 | IRQ_FLAGSunsigned long irq_flags; | |||
| 950 | ||||
| 951 | IRQ_LOCK_SAVEdo {__asm__ __volatile__("pushf ; pop %0" : "=r" (irq_flags): :"memory"); __asm__ __volatile__ ("cli": : :"memory");} while (0); | |||
| 952 | tpnt->proc_dir = &proc_scsi_u14_34f; | |||
| 953 | ||||
| 954 | #if defined(MODULE) | |||
| 955 | /* io_port could have been modified when loading as a module */ | |||
| 956 | if(io_port[0] != SKIP(~0UL)) { | |||
| 957 | setup_done = TRUE1; | |||
| 958 | io_port[MAX_INT_PARAM10] = 0; | |||
| 959 | } | |||
| 960 | #endif | |||
| 961 | ||||
| 962 | for (k = 0; k < MAX_BOARDS(3 + 1 + 0 + 0) + 1; k++) sh[k] = NULL((void *) 0); | |||
| 963 | ||||
| 964 | for (k = 0; io_port[k]; k++) { | |||
| 965 | ||||
| 966 | if (io_port[k] == SKIP(~0UL)) continue; | |||
| 967 | ||||
| 968 | if (j < MAX_BOARDS(3 + 1 + 0 + 0) && port_detect(io_port[k], j, tpnt)) j++; | |||
| 969 | } | |||
| 970 | ||||
| 971 | num_boards = j; | |||
| 972 | IRQ_UNLOCK_RESTOREdo {__asm__ __volatile__("push %0 ; popf": :"g" (irq_flags):"memory" );} while (0); | |||
| 973 | return j; | |||
| 974 | } | |||
| 975 | ||||
| 976 | static inlineinline __attribute__((always_inline)) void build_sg_list(struct mscp *cpp, Scsi_Cmnd *SCpnt) { | |||
| 977 | unsigned int k, data_len = 0; | |||
| 978 | struct scatterlist *sgpnt; | |||
| 979 | ||||
| 980 | sgpnt = (struct scatterlist *) SCpnt->request_buffer; | |||
| 981 | ||||
| 982 | for (k = 0; k < SCpnt->use_sg; k++) { | |||
| 983 | cpp->sglist[k].address = V2DEV(sgpnt[k].address)((sgpnt[k].address) ? (virt_to_phys((void *)sgpnt[k].address) ) : 0); | |||
| 984 | cpp->sglist[k].num_bytes = H2DEV(sgpnt[k].length)(sgpnt[k].length); | |||
| 985 | data_len += sgpnt[k].length; | |||
| 986 | } | |||
| 987 | ||||
| 988 | cpp->use_sg = SCpnt->use_sg; | |||
| 989 | cpp->data_address = V2DEV(cpp->sglist)((cpp->sglist) ? (virt_to_phys((void *)cpp->sglist)) : 0 ); | |||
| 990 | cpp->data_len = H2DEV(data_len)(data_len); | |||
| 991 | } | |||
| 992 | ||||
| 993 | static inlineinline __attribute__((always_inline)) int do_qcomm(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { | |||
| 994 | unsigned int i, j, k; | |||
| 995 | struct mscp *cpp; | |||
| 996 | ||||
| 997 | static const unsigned char data_out_cmds[] = { | |||
| 998 | 0x0a, 0x2a, 0x15, 0x55, 0x04, 0x07, 0x18, 0x1d, 0x24, 0x2e, | |||
| 999 | 0x30, 0x31, 0x32, 0x38, 0x39, 0x3a, 0x3b, 0x3d, 0x3f, 0x40, | |||
| 1000 | 0x41, 0x4c, 0xaa, 0xae, 0xb0, 0xb1, 0xb2, 0xb6, 0xea, 0x1b | |||
| 1001 | }; | |||
| 1002 | ||||
| 1003 | static const unsigned char data_none_cmds[] = { | |||
| 1004 | 0x01, 0x0b, 0x10, 0x11, 0x13, 0x16, 0x17, 0x19, 0x2b, 0x1e, | |||
| 1005 | 0x2c, 0xac, 0x2f, 0xaf, 0x33, 0xb3, 0x35, 0x36, 0x45, 0x47, | |||
| 1006 | 0x48, 0x49, 0xa9, 0x4b, 0xa5, 0xa6, 0xb5 | |||
| 1007 | }; | |||
| 1008 | ||||
| 1009 | /* j is the board number */ | |||
| 1010 | j = ((struct hostdata *) SCpnt->host->hostdata)->board_number; | |||
| 1011 | ||||
| 1012 | if (SCpnt->host_scribble) | |||
| 1013 | panic("%s: qcomm, pid %ld, SCpnt %p already active.\n", | |||
| 1014 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), SCpnt->pid, SCpnt); | |||
| 1015 | ||||
| 1016 | /* i is the mailbox number, look for the first free mailbox | |||
| 1017 | starting from last_cp_used */ | |||
| 1018 | i = HD(j)((struct hostdata *) &sh[j]->hostdata)->last_cp_used + 1; | |||
| 1019 | ||||
| 1020 | for (k = 0; k < sh[j]->can_queue; k++, i++) { | |||
| 1021 | ||||
| 1022 | if (i >= sh[j]->can_queue) i = 0; | |||
| 1023 | ||||
| 1024 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == FREE0) { | |||
| 1025 | HD(j)((struct hostdata *) &sh[j]->hostdata)->last_cp_used = i; | |||
| 1026 | break; | |||
| 1027 | } | |||
| 1028 | } | |||
| 1029 | ||||
| 1030 | if (k == sh[j]->can_queue) { | |||
| 1031 | printk("%s: qcomm, no free mailbox.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name )); | |||
| 1032 | return 1; | |||
| 1033 | } | |||
| 1034 | ||||
| 1035 | /* Set pointer to control packet structure */ | |||
| 1036 | cpp = &HD(j)((struct hostdata *) &sh[j]->hostdata)->cp[i]; | |||
| 1037 | ||||
| 1038 | memset(cpp, 0, sizeof(struct mscp) - sizeof(struct sg_list *))(__builtin_constant_p(0) ? (__builtin_constant_p((sizeof(struct mscp) - sizeof(struct sg_list *))) ? __constant_c_and_count_memset (((cpp)),((0x01010101UL*(unsigned char)(0))),((sizeof(struct mscp ) - sizeof(struct sg_list *)))) : __constant_c_memset(((cpp)) ,((0x01010101UL*(unsigned char)(0))),((sizeof(struct mscp) - sizeof (struct sg_list *))))) : (__builtin_constant_p((sizeof(struct mscp) - sizeof(struct sg_list *))) ? __memset_generic((((cpp ))),(((0))),(((sizeof(struct mscp) - sizeof(struct sg_list *) )))) : __memset_generic(((cpp)),((0)),((sizeof(struct mscp) - sizeof(struct sg_list *)))))); | |||
| 1039 | SCpnt->scsi_done = done; | |||
| 1040 | cpp->index = i; | |||
| 1041 | SCpnt->host_scribble = (unsigned char *) &cpp->index; | |||
| 1042 | ||||
| 1043 | if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n", | |||
| 1044 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i, SCpnt->channel, SCpnt->target, | |||
| 1045 | SCpnt->lun, SCpnt->pid); | |||
| 1046 | ||||
| 1047 | cpp->xdir = DTD_IN0x1; | |||
| 1048 | ||||
| 1049 | for (k = 0; k < ARRAY_SIZE(data_out_cmds)(sizeof (data_out_cmds) / sizeof (data_out_cmds)[0]); k++) | |||
| 1050 | if (SCpnt->cmnd[0] == data_out_cmds[k]) { | |||
| 1051 | cpp->xdir = DTD_OUT0x2; | |||
| 1052 | break; | |||
| 1053 | } | |||
| 1054 | ||||
| 1055 | if (cpp->xdir == DTD_IN0x1) | |||
| 1056 | for (k = 0; k < ARRAY_SIZE(data_none_cmds)(sizeof (data_none_cmds) / sizeof (data_none_cmds)[0]); k++) | |||
| 1057 | if (SCpnt->cmnd[0] == data_none_cmds[k]) { | |||
| 1058 | cpp->xdir = DTD_NONE0x3; | |||
| 1059 | break; | |||
| 1060 | } | |||
| 1061 | ||||
| 1062 | cpp->opcode = OP_SCSI0x2; | |||
| 1063 | cpp->channel = SCpnt->channel; | |||
| 1064 | cpp->target = SCpnt->target; | |||
| 1065 | cpp->lun = SCpnt->lun; | |||
| 1066 | cpp->SCpnt = SCpnt; | |||
| 1067 | cpp->sense_addr = V2DEV(SCpnt->sense_buffer)((SCpnt->sense_buffer) ? (virt_to_phys((void *)SCpnt->sense_buffer )) : 0); | |||
| 1068 | cpp->sense_len = sizeof SCpnt->sense_buffer; | |||
| 1069 | ||||
| 1070 | if (SCpnt->use_sg) { | |||
| 1071 | cpp->sg = TRUE1; | |||
| 1072 | build_sg_list(cpp, SCpnt); | |||
| 1073 | } | |||
| 1074 | else { | |||
| 1075 | cpp->data_address = V2DEV(SCpnt->request_buffer)((SCpnt->request_buffer) ? (virt_to_phys((void *)SCpnt-> request_buffer)) : 0); | |||
| 1076 | cpp->data_len = H2DEV(SCpnt->request_bufflen)(SCpnt->request_bufflen); | |||
| 1077 | } | |||
| 1078 | ||||
| 1079 | cpp->scsi_cdbs_len = SCpnt->cmd_len; | |||
| 1080 | memcpy(cpp->scsi_cdbs, SCpnt->cmnd, cpp->scsi_cdbs_len)(__builtin_constant_p(cpp->scsi_cdbs_len) ? __constant_memcpy ((cpp->scsi_cdbs),(SCpnt->cmnd),(cpp->scsi_cdbs_len) ) : __memcpy((cpp->scsi_cdbs),(SCpnt->cmnd),(cpp->scsi_cdbs_len ))); | |||
| 1081 | ||||
| 1082 | if (linked_comm && SCpnt->device->queue_depth > 2 | |||
| 1083 | && TLDEV(SCpnt->device->type)((SCpnt->device->type) == 0x00 || (SCpnt->device-> type) == 0x05)) { | |||
| 1084 | HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] = READY5; | |||
| 1085 | flush_dev(SCpnt->device, SCpnt->request.sector, j, FALSE0); | |||
| 1086 | return 0; | |||
| 1087 | } | |||
| 1088 | ||||
| 1089 | if (wait_on_busy(sh[j]->io_port, MAXLOOP10000)) { | |||
| 1090 | SCpnt->host_scribble = NULL((void *) 0); | |||
| 1091 | printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy.\n", | |||
| 1092 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid); | |||
| 1093 | return 1; | |||
| 1094 | } | |||
| 1095 | ||||
| 1096 | /* Store pointer in OGM address bytes */ | |||
| 1097 | outl(V2DEV(cpp), sh[j]->io_port + REG_OGM)((__builtin_constant_p((sh[j]->io_port + 8)) && (sh [j]->io_port + 8) < 256) ? __outlc((((cpp) ? (virt_to_phys ((void *)cpp)) : 0)),(sh[j]->io_port + 8)) : __outl((((cpp ) ? (virt_to_phys((void *)cpp)) : 0)),(sh[j]->io_port + 8) )); | |||
| 1098 | ||||
| 1099 | /* Issue OGM interrupt */ | |||
| 1100 | outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR)((__builtin_constant_p((sh[j]->io_port + 1)) && (sh [j]->io_port + 1) < 256) ? __outbc((0x01),(sh[j]->io_port + 1)) : __outb((0x01),(sh[j]->io_port + 1))); | |||
| 1101 | ||||
| 1102 | HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] = IN_USE1; | |||
| 1103 | return 0; | |||
| 1104 | } | |||
| 1105 | ||||
| 1106 | int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) { | |||
| 1107 | int rtn; | |||
| 1108 | IRQ_FLAGSunsigned long irq_flags; | |||
| 1109 | ||||
| 1110 | IRQ_LOCK_SAVEdo {__asm__ __volatile__("pushf ; pop %0" : "=r" (irq_flags): :"memory"); __asm__ __volatile__ ("cli": : :"memory");} while (0); | |||
| 1111 | rtn = do_qcomm(SCpnt, done); | |||
| 1112 | IRQ_UNLOCK_RESTOREdo {__asm__ __volatile__("push %0 ; popf": :"g" (irq_flags):"memory" );} while (0); | |||
| 1113 | return rtn; | |||
| 1114 | } | |||
| 1115 | ||||
| 1116 | static inlineinline __attribute__((always_inline)) int do_old_abort(Scsi_Cmnd *SCarg) { | |||
| 1117 | unsigned int i, j; | |||
| 1118 | ||||
| 1119 | j = ((struct hostdata *) SCarg->host->hostdata)->board_number; | |||
| 1120 | ||||
| 1121 | if (SCarg->host_scribble == NULL((void *) 0) || | |||
| 1122 | (SCarg->serial_number_at_timeout && | |||
| 1123 | (SCarg->serial_number != SCarg->serial_number_at_timeout))) { | |||
| 1124 | printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n", | |||
| 1125 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); | |||
| 1126 | return SCSI_ABORT_NOT_RUNNING4; | |||
| 1127 | } | |||
| 1128 | ||||
| 1129 | i = *(unsigned int *)SCarg->host_scribble; | |||
| 1130 | printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n", | |||
| 1131 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); | |||
| 1132 | ||||
| 1133 | if (i >= sh[j]->can_queue) | |||
| 1134 | panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name )); | |||
| 1135 | ||||
| 1136 | if (wait_on_busy(sh[j]->io_port, MAXLOOP10000)) { | |||
| 1137 | printk("%s: abort, timeout error.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name )); | |||
| 1138 | return SCSI_ABORT_ERROR5; | |||
| 1139 | } | |||
| 1140 | ||||
| 1141 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == FREE0) { | |||
| 1142 | printk("%s: abort, mbox %d is free.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i); | |||
| 1143 | return SCSI_ABORT_NOT_RUNNING4; | |||
| 1144 | } | |||
| 1145 | ||||
| 1146 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == IN_USE1) { | |||
| 1147 | printk("%s: abort, mbox %d is in use.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i); | |||
| 1148 | ||||
| 1149 | if (SCarg != HD(j)((struct hostdata *) &sh[j]->hostdata)->cp[i].SCpnt) | |||
| 1150 | panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n", | |||
| 1151 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i, SCarg, HD(j)((struct hostdata *) &sh[j]->hostdata)->cp[i].SCpnt); | |||
| 1152 | ||||
| 1153 | if (inb(sh[j]->io_port + REG_SYS_INTR)((__builtin_constant_p((sh[j]->io_port + 3)) && (sh [j]->io_port + 3) < 256) ? __inbc(sh[j]->io_port + 3 ) : __inb(sh[j]->io_port + 3)) & IRQ_ASSERTED0x01) | |||
| 1154 | printk("%s: abort, mbox %d, interrupt pending.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i); | |||
| 1155 | ||||
| 1156 | return SCSI_ABORT_SNOOZE0; | |||
| 1157 | } | |||
| 1158 | ||||
| 1159 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == IN_RESET3) { | |||
| 1160 | printk("%s: abort, mbox %d is in reset.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i); | |||
| 1161 | return SCSI_ABORT_ERROR5; | |||
| 1162 | } | |||
| 1163 | ||||
| 1164 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == LOCKED2) { | |||
| 1165 | printk("%s: abort, mbox %d is locked.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i); | |||
| 1166 | return SCSI_ABORT_NOT_RUNNING4; | |||
| 1167 | } | |||
| 1168 | ||||
| 1169 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == READY5 || HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == ABORTING6) { | |||
| 1170 | SCarg->result = DID_ABORT0x05 << 16; | |||
| 1171 | SCarg->host_scribble = NULL((void *) 0); | |||
| 1172 | HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] = FREE0; | |||
| 1173 | printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n", | |||
| 1174 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i, SCarg->pid); | |||
| 1175 | SCarg->scsi_done(SCarg); | |||
| 1176 | return SCSI_ABORT_SUCCESS1; | |||
| 1177 | } | |||
| 1178 | ||||
| 1179 | panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i); | |||
| 1180 | } | |||
| 1181 | ||||
| 1182 | int u14_34f_old_abort(Scsi_Cmnd *SCarg) { | |||
| 1183 | int rtn; | |||
| 1184 | IRQ_FLAGSunsigned long irq_flags; | |||
| 1185 | ||||
| 1186 | IRQ_LOCK_SAVEdo {__asm__ __volatile__("pushf ; pop %0" : "=r" (irq_flags): :"memory"); __asm__ __volatile__ ("cli": : :"memory");} while (0); | |||
| 1187 | rtn = do_old_abort(SCarg); | |||
| 1188 | IRQ_UNLOCK_RESTOREdo {__asm__ __volatile__("push %0 ; popf": :"g" (irq_flags):"memory" );} while (0); | |||
| 1189 | return rtn; | |||
| 1190 | } | |||
| 1191 | ||||
| 1192 | #if LINUX_VERSION_CODE131108 >= LinuxVersionCode(2,1,101)(((2)<<16)+((1)<<8)+(101)) | |||
| 1193 | ||||
| 1194 | static inlineinline __attribute__((always_inline)) int do_abort(Scsi_Cmnd *SCarg) { | |||
| 1195 | unsigned int i, j; | |||
| 1196 | ||||
| 1197 | j = ((struct hostdata *) SCarg->host->hostdata)->board_number; | |||
| 1198 | ||||
| 1199 | if (SCarg->host_scribble == NULL((void *) 0)) { | |||
| 1200 | printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n", | |||
| 1201 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); | |||
| 1202 | return SUCCESS; | |||
| 1203 | } | |||
| 1204 | ||||
| 1205 | i = *(unsigned int *)SCarg->host_scribble; | |||
| 1206 | printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n", | |||
| 1207 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); | |||
| 1208 | ||||
| 1209 | if (i >= sh[j]->can_queue) | |||
| 1210 | panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name )); | |||
| 1211 | ||||
| 1212 | if (wait_on_busy(sh[j]->io_port, MAXLOOP10000)) { | |||
| 1213 | printk("%s: abort, timeout error.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name )); | |||
| 1214 | return FAILED; | |||
| 1215 | } | |||
| 1216 | ||||
| 1217 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == FREE0) { | |||
| 1218 | printk("%s: abort, mbox %d is free.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i); | |||
| 1219 | return SUCCESS; | |||
| 1220 | } | |||
| 1221 | ||||
| 1222 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == IN_USE1) { | |||
| 1223 | printk("%s: abort, mbox %d is in use.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i); | |||
| 1224 | ||||
| 1225 | if (SCarg != HD(j)((struct hostdata *) &sh[j]->hostdata)->cp[i].SCpnt) | |||
| 1226 | panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n", | |||
| 1227 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i, SCarg, HD(j)((struct hostdata *) &sh[j]->hostdata)->cp[i].SCpnt); | |||
| 1228 | ||||
| 1229 | if (inb(sh[j]->io_port + REG_SYS_INTR)((__builtin_constant_p((sh[j]->io_port + 3)) && (sh [j]->io_port + 3) < 256) ? __inbc(sh[j]->io_port + 3 ) : __inb(sh[j]->io_port + 3)) & IRQ_ASSERTED0x01) | |||
| 1230 | printk("%s: abort, mbox %d, interrupt pending.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i); | |||
| 1231 | ||||
| 1232 | if (SCarg->eh_state == SCSI_STATE_TIMEOUT) { | |||
| 1233 | SCarg->host_scribble = NULL((void *) 0); | |||
| 1234 | HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] = FREE0; | |||
| 1235 | printk("%s, abort, mbox %d, eh_state timeout, pid %ld.\n", | |||
| 1236 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i, SCarg->pid); | |||
| 1237 | return SUCCESS; | |||
| 1238 | } | |||
| 1239 | ||||
| 1240 | return FAILED; | |||
| 1241 | } | |||
| 1242 | ||||
| 1243 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == IN_RESET3) { | |||
| 1244 | printk("%s: abort, mbox %d is in reset.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i); | |||
| 1245 | return FAILED; | |||
| 1246 | } | |||
| 1247 | ||||
| 1248 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == LOCKED2) { | |||
| 1249 | printk("%s: abort, mbox %d is locked.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i); | |||
| 1250 | return SUCCESS; | |||
| 1251 | } | |||
| 1252 | ||||
| 1253 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == READY5 || HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == ABORTING6) { | |||
| 1254 | SCarg->result = DID_ABORT0x05 << 16; | |||
| 1255 | SCarg->host_scribble = NULL((void *) 0); | |||
| 1256 | HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] = FREE0; | |||
| 1257 | printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n", | |||
| 1258 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i, SCarg->pid); | |||
| 1259 | SCarg->scsi_done(SCarg); | |||
| 1260 | return SUCCESS; | |||
| 1261 | } | |||
| 1262 | ||||
| 1263 | panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i); | |||
| 1264 | } | |||
| 1265 | ||||
| 1266 | int u14_34f_abort(Scsi_Cmnd *SCarg) { | |||
| 1267 | ||||
| 1268 | return do_abort(SCarg); | |||
| 1269 | } | |||
| 1270 | ||||
| 1271 | #endif /* new_eh_code */ | |||
| 1272 | ||||
| 1273 | static inlineinline __attribute__((always_inline)) int do_old_reset(Scsi_Cmnd *SCarg) { | |||
| 1274 | unsigned int i, j, time, k, c, limit = 0; | |||
| 1275 | int arg_done = FALSE0; | |||
| 1276 | Scsi_Cmnd *SCpnt; | |||
| 1277 | ||||
| 1278 | j = ((struct hostdata *) SCarg->host->hostdata)->board_number; | |||
| 1279 | printk("%s: reset, enter, target %d.%d:%d, pid %ld.\n", | |||
| 1280 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); | |||
| 1281 | ||||
| 1282 | if (SCarg->host_scribble == NULL((void *) 0)) | |||
| 1283 | printk("%s: reset, pid %ld inactive.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), SCarg->pid); | |||
| 1284 | ||||
| 1285 | if (SCarg->serial_number_at_timeout && | |||
| 1286 | (SCarg->serial_number != SCarg->serial_number_at_timeout)) { | |||
| 1287 | printk("%s: reset, pid %ld, reset not running.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), SCarg->pid); | |||
| 1288 | return SCSI_RESET_NOT_RUNNING5; | |||
| 1289 | } | |||
| 1290 | ||||
| 1291 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->in_reset) { | |||
| 1292 | printk("%s: reset, exit, already in reset.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name )); | |||
| 1293 | return SCSI_RESET_ERROR6; | |||
| 1294 | } | |||
| 1295 | ||||
| 1296 | if (wait_on_busy(sh[j]->io_port, MAXLOOP10000)) { | |||
| 1297 | printk("%s: reset, exit, timeout error.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name )); | |||
| 1298 | return SCSI_RESET_ERROR6; | |||
| 1299 | } | |||
| 1300 | ||||
| 1301 | HD(j)((struct hostdata *) &sh[j]->hostdata)->retries = 0; | |||
| 1302 | ||||
| 1303 | for (c = 0; c <= sh[j]->max_channel; c++) | |||
| 1304 | for (k = 0; k < sh[j]->max_id; k++) { | |||
| 1305 | HD(j)((struct hostdata *) &sh[j]->hostdata)->target_redo[k][c] = TRUE1; | |||
| 1306 | HD(j)((struct hostdata *) &sh[j]->hostdata)->target_to[k][c] = 0; | |||
| 1307 | } | |||
| 1308 | ||||
| 1309 | for (i = 0; i < sh[j]->can_queue; i++) { | |||
| 1310 | ||||
| 1311 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == FREE0) continue; | |||
| 1312 | ||||
| 1313 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == LOCKED2) { | |||
| 1314 | HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] = FREE0; | |||
| 1315 | printk("%s: reset, locked mbox %d forced free.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i); | |||
| 1316 | continue; | |||
| 1317 | } | |||
| 1318 | ||||
| 1319 | if (!(SCpnt = HD(j)((struct hostdata *) &sh[j]->hostdata)->cp[i].SCpnt)) | |||
| 1320 | panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i); | |||
| 1321 | ||||
| 1322 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == READY5 || HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == ABORTING6) { | |||
| 1323 | HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] = ABORTING6; | |||
| 1324 | printk("%s: reset, mbox %d aborting, pid %ld.\n", | |||
| 1325 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i, SCpnt->pid); | |||
| 1326 | } | |||
| 1327 | ||||
| 1328 | else { | |||
| 1329 | HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] = IN_RESET3; | |||
| 1330 | printk("%s: reset, mbox %d in reset, pid %ld.\n", | |||
| 1331 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i, SCpnt->pid); | |||
| 1332 | } | |||
| 1333 | ||||
| 1334 | if (SCpnt->host_scribble == NULL((void *) 0)) | |||
| 1335 | panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i); | |||
| 1336 | ||||
| 1337 | if (*(unsigned int *)SCpnt->host_scribble != i) | |||
| 1338 | panic("%s: reset, mbox %d, index mismatch.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i); | |||
| 1339 | ||||
| 1340 | if (SCpnt->scsi_done == NULL((void *) 0)) | |||
| 1341 | panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i); | |||
| 1342 | ||||
| 1343 | if (SCpnt == SCarg) arg_done = TRUE1; | |||
| 1344 | } | |||
| 1345 | ||||
| 1346 | if (wait_on_busy(sh[j]->io_port, MAXLOOP10000)) { | |||
| 1347 | printk("%s: reset, cannot reset, timeout error.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name )); | |||
| 1348 | return SCSI_RESET_ERROR6; | |||
| 1349 | } | |||
| 1350 | ||||
| 1351 | outb(CMD_RESET, sh[j]->io_port + REG_LCL_INTR)((__builtin_constant_p((sh[j]->io_port + 1)) && (sh [j]->io_port + 1) < 256) ? __outbc((0xc0),(sh[j]->io_port + 1)) : __outb((0xc0),(sh[j]->io_port + 1))); | |||
| 1352 | printk("%s: reset, board reset done, enabling interrupts.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name )); | |||
| 1353 | ||||
| 1354 | #if defined(DEBUG_RESET) | |||
| 1355 | do_trace = TRUE1; | |||
| 1356 | #endif | |||
| 1357 | ||||
| 1358 | HD(j)((struct hostdata *) &sh[j]->hostdata)->in_reset = TRUE1; | |||
| 1359 | SPIN_UNLOCK | |||
| 1360 | IRQ_UNLOCK__asm__ __volatile__ ("sti": : :"memory"); | |||
| 1361 | time = jiffies; | |||
| 1362 | while ((jiffies - time) < (10 * HZ100) && limit++ < 200000) udelay(100L)(__builtin_constant_p(100L) ? __const_udelay((100L) * 0x10c6ul ) : __udelay(100L)); | |||
| 1363 | IRQ_LOCK__asm__ __volatile__ ("cli": : :"memory"); | |||
| 1364 | SPIN_LOCK | |||
| 1365 | printk("%s: reset, interrupts disabled, loops %d.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), limit); | |||
| 1366 | ||||
| 1367 | for (i = 0; i < sh[j]->can_queue; i++) { | |||
| 1368 | ||||
| 1369 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == IN_RESET3) { | |||
| 1370 | SCpnt = HD(j)((struct hostdata *) &sh[j]->hostdata)->cp[i].SCpnt; | |||
| 1371 | SCpnt->result = DID_RESET0x08 << 16; | |||
| 1372 | SCpnt->host_scribble = NULL((void *) 0); | |||
| 1373 | ||||
| 1374 | /* This mailbox is still waiting for its interrupt */ | |||
| 1375 | HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] = LOCKED2; | |||
| 1376 | ||||
| 1377 | printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n", | |||
| 1378 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i, SCpnt->pid); | |||
| 1379 | } | |||
| 1380 | ||||
| 1381 | else if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == ABORTING6) { | |||
| 1382 | SCpnt = HD(j)((struct hostdata *) &sh[j]->hostdata)->cp[i].SCpnt; | |||
| 1383 | SCpnt->result = DID_RESET0x08 << 16; | |||
| 1384 | SCpnt->host_scribble = NULL((void *) 0); | |||
| 1385 | ||||
| 1386 | /* This mailbox was never queued to the adapter */ | |||
| 1387 | HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] = FREE0; | |||
| 1388 | ||||
| 1389 | printk("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n", | |||
| 1390 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i, SCpnt->pid); | |||
| 1391 | } | |||
| 1392 | ||||
| 1393 | else | |||
| 1394 | ||||
| 1395 | /* Any other mailbox has already been set free by interrupt */ | |||
| 1396 | continue; | |||
| 1397 | ||||
| 1398 | SCpnt->scsi_done(SCpnt); | |||
| 1399 | IRQ_LOCK__asm__ __volatile__ ("cli": : :"memory"); | |||
| 1400 | } | |||
| 1401 | ||||
| 1402 | HD(j)((struct hostdata *) &sh[j]->hostdata)->in_reset = FALSE0; | |||
| 1403 | do_trace = FALSE0; | |||
| 1404 | ||||
| 1405 | if (arg_done) { | |||
| 1406 | printk("%s: reset, exit, success.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name )); | |||
| 1407 | return SCSI_RESET_SUCCESS2; | |||
| 1408 | } | |||
| 1409 | else { | |||
| 1410 | printk("%s: reset, exit, wakeup.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name )); | |||
| 1411 | return SCSI_RESET_PUNT1; | |||
| 1412 | } | |||
| 1413 | } | |||
| 1414 | ||||
| 1415 | int u14_34f_old_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { | |||
| 1416 | int rtn; | |||
| 1417 | IRQ_FLAGSunsigned long irq_flags; | |||
| 1418 | ||||
| 1419 | IRQ_LOCK_SAVEdo {__asm__ __volatile__("pushf ; pop %0" : "=r" (irq_flags): :"memory"); __asm__ __volatile__ ("cli": : :"memory");} while (0); | |||
| 1420 | rtn = do_old_reset(SCarg); | |||
| 1421 | IRQ_UNLOCK_RESTOREdo {__asm__ __volatile__("push %0 ; popf": :"g" (irq_flags):"memory" );} while (0); | |||
| 1422 | return rtn; | |||
| 1423 | } | |||
| 1424 | ||||
| 1425 | #if LINUX_VERSION_CODE131108 >= LinuxVersionCode(2,1,101)(((2)<<16)+((1)<<8)+(101)) | |||
| 1426 | ||||
| 1427 | static inlineinline __attribute__((always_inline)) int do_reset(Scsi_Cmnd *SCarg) { | |||
| 1428 | unsigned int i, j, time, k, c, limit = 0; | |||
| 1429 | int arg_done = FALSE0; | |||
| 1430 | Scsi_Cmnd *SCpnt; | |||
| 1431 | ||||
| 1432 | j = ((struct hostdata *) SCarg->host->hostdata)->board_number; | |||
| 1433 | printk("%s: reset, enter, target %d.%d:%d, pid %ld.\n", | |||
| 1434 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); | |||
| 1435 | ||||
| 1436 | if (SCarg->host_scribble == NULL((void *) 0)) | |||
| 1437 | printk("%s: reset, pid %ld inactive.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), SCarg->pid); | |||
| 1438 | ||||
| 1439 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->in_reset) { | |||
| 1440 | printk("%s: reset, exit, already in reset.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name )); | |||
| 1441 | return FAILED; | |||
| 1442 | } | |||
| 1443 | ||||
| 1444 | if (wait_on_busy(sh[j]->io_port, MAXLOOP10000)) { | |||
| 1445 | printk("%s: reset, exit, timeout error.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name )); | |||
| 1446 | return FAILED; | |||
| 1447 | } | |||
| 1448 | ||||
| 1449 | HD(j)((struct hostdata *) &sh[j]->hostdata)->retries = 0; | |||
| 1450 | ||||
| 1451 | for (c = 0; c <= sh[j]->max_channel; c++) | |||
| 1452 | for (k = 0; k < sh[j]->max_id; k++) { | |||
| 1453 | HD(j)((struct hostdata *) &sh[j]->hostdata)->target_redo[k][c] = TRUE1; | |||
| 1454 | HD(j)((struct hostdata *) &sh[j]->hostdata)->target_to[k][c] = 0; | |||
| 1455 | } | |||
| 1456 | ||||
| 1457 | for (i = 0; i < sh[j]->can_queue; i++) { | |||
| 1458 | ||||
| 1459 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == FREE0) continue; | |||
| 1460 | ||||
| 1461 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == LOCKED2) { | |||
| 1462 | HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] = FREE0; | |||
| 1463 | printk("%s: reset, locked mbox %d forced free.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i); | |||
| 1464 | continue; | |||
| 1465 | } | |||
| 1466 | ||||
| 1467 | if (!(SCpnt = HD(j)((struct hostdata *) &sh[j]->hostdata)->cp[i].SCpnt)) | |||
| 1468 | panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i); | |||
| 1469 | ||||
| 1470 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == READY5 || HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == ABORTING6) { | |||
| 1471 | HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] = ABORTING6; | |||
| 1472 | printk("%s: reset, mbox %d aborting, pid %ld.\n", | |||
| 1473 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i, SCpnt->pid); | |||
| 1474 | } | |||
| 1475 | ||||
| 1476 | else { | |||
| 1477 | HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] = IN_RESET3; | |||
| 1478 | printk("%s: reset, mbox %d in reset, pid %ld.\n", | |||
| 1479 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i, SCpnt->pid); | |||
| 1480 | } | |||
| 1481 | ||||
| 1482 | if (SCpnt->host_scribble == NULL((void *) 0)) | |||
| 1483 | panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i); | |||
| 1484 | ||||
| 1485 | if (*(unsigned int *)SCpnt->host_scribble != i) | |||
| 1486 | panic("%s: reset, mbox %d, index mismatch.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i); | |||
| 1487 | ||||
| 1488 | if (SCpnt->scsi_done == NULL((void *) 0)) | |||
| 1489 | panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i); | |||
| 1490 | ||||
| 1491 | if (SCpnt == SCarg) arg_done = TRUE1; | |||
| 1492 | } | |||
| 1493 | ||||
| 1494 | if (wait_on_busy(sh[j]->io_port, MAXLOOP10000)) { | |||
| 1495 | printk("%s: reset, cannot reset, timeout error.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name )); | |||
| 1496 | return FAILED; | |||
| 1497 | } | |||
| 1498 | ||||
| 1499 | outb(CMD_RESET, sh[j]->io_port + REG_LCL_INTR)((__builtin_constant_p((sh[j]->io_port + 1)) && (sh [j]->io_port + 1) < 256) ? __outbc((0xc0),(sh[j]->io_port + 1)) : __outb((0xc0),(sh[j]->io_port + 1))); | |||
| 1500 | printk("%s: reset, board reset done, enabling interrupts.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name )); | |||
| 1501 | ||||
| 1502 | #if defined(DEBUG_RESET) | |||
| 1503 | do_trace = TRUE1; | |||
| 1504 | #endif | |||
| 1505 | ||||
| 1506 | HD(j)((struct hostdata *) &sh[j]->hostdata)->in_reset = TRUE1; | |||
| 1507 | SPIN_UNLOCK | |||
| 1508 | IRQ_UNLOCK__asm__ __volatile__ ("sti": : :"memory"); | |||
| 1509 | time = jiffies; | |||
| 1510 | while ((jiffies - time) < (10 * HZ100) && limit++ < 200000) udelay(100L)(__builtin_constant_p(100L) ? __const_udelay((100L) * 0x10c6ul ) : __udelay(100L)); | |||
| 1511 | IRQ_LOCK__asm__ __volatile__ ("cli": : :"memory"); | |||
| 1512 | SPIN_LOCK | |||
| 1513 | printk("%s: reset, interrupts disabled, loops %d.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), limit); | |||
| 1514 | ||||
| 1515 | for (i = 0; i < sh[j]->can_queue; i++) { | |||
| 1516 | ||||
| 1517 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == IN_RESET3) { | |||
| 1518 | SCpnt = HD(j)((struct hostdata *) &sh[j]->hostdata)->cp[i].SCpnt; | |||
| 1519 | SCpnt->result = DID_RESET0x08 << 16; | |||
| 1520 | SCpnt->host_scribble = NULL((void *) 0); | |||
| 1521 | ||||
| 1522 | /* This mailbox is still waiting for its interrupt */ | |||
| 1523 | HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] = LOCKED2; | |||
| 1524 | ||||
| 1525 | printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n", | |||
| 1526 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i, SCpnt->pid); | |||
| 1527 | } | |||
| 1528 | ||||
| 1529 | else if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == ABORTING6) { | |||
| 1530 | SCpnt = HD(j)((struct hostdata *) &sh[j]->hostdata)->cp[i].SCpnt; | |||
| 1531 | SCpnt->result = DID_RESET0x08 << 16; | |||
| 1532 | SCpnt->host_scribble = NULL((void *) 0); | |||
| 1533 | ||||
| 1534 | /* This mailbox was never queued to the adapter */ | |||
| 1535 | HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] = FREE0; | |||
| 1536 | ||||
| 1537 | printk("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n", | |||
| 1538 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i, SCpnt->pid); | |||
| 1539 | } | |||
| 1540 | ||||
| 1541 | else | |||
| 1542 | ||||
| 1543 | /* Any other mailbox has already been set free by interrupt */ | |||
| 1544 | continue; | |||
| 1545 | ||||
| 1546 | SCpnt->scsi_done(SCpnt); | |||
| 1547 | IRQ_LOCK__asm__ __volatile__ ("cli": : :"memory"); | |||
| 1548 | } | |||
| 1549 | ||||
| 1550 | HD(j)((struct hostdata *) &sh[j]->hostdata)->in_reset = FALSE0; | |||
| 1551 | do_trace = FALSE0; | |||
| 1552 | ||||
| 1553 | if (arg_done) printk("%s: reset, exit, pid %ld done.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), SCarg->pid); | |||
| 1554 | else printk("%s: reset, exit.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name )); | |||
| 1555 | ||||
| 1556 | return SUCCESS; | |||
| 1557 | } | |||
| 1558 | ||||
| 1559 | int u14_34f_reset(Scsi_Cmnd *SCarg) { | |||
| 1560 | ||||
| 1561 | return do_reset(SCarg); | |||
| 1562 | } | |||
| 1563 | ||||
| 1564 | #endif /* new_eh_code */ | |||
| 1565 | ||||
| 1566 | int u14_34f_biosparam(Disk *disk, kdev_t dev, int *dkinfo) { | |||
| 1567 | unsigned int j = 0; | |||
| 1568 | int size = disk->capacity; | |||
| 1569 | ||||
| 1570 | dkinfo[0] = HD(j)((struct hostdata *) &sh[j]->hostdata)->heads; | |||
| 1571 | dkinfo[1] = HD(j)((struct hostdata *) &sh[j]->hostdata)->sectors; | |||
| 1572 | dkinfo[2] = size / (HD(j)((struct hostdata *) &sh[j]->hostdata)->heads * HD(j)((struct hostdata *) &sh[j]->hostdata)->sectors); | |||
| 1573 | ||||
| 1574 | if (ext_tran && (scsicam_bios_param(disk, dev, dkinfo) < 0)) { | |||
| 1575 | dkinfo[0] = 255; | |||
| 1576 | dkinfo[1] = 63; | |||
| 1577 | dkinfo[2] = size / (dkinfo[0] * dkinfo[1]); | |||
| 1578 | } | |||
| 1579 | ||||
| 1580 | #if defined (DEBUG_GEOMETRY) | |||
| 1581 | printk ("%s: biosparam, head=%d, sec=%d, cyl=%d.\n", driver_name, | |||
| 1582 | dkinfo[0], dkinfo[1], dkinfo[2]); | |||
| 1583 | #endif | |||
| 1584 | ||||
| 1585 | return FALSE0; | |||
| 1586 | } | |||
| 1587 | ||||
| 1588 | static void sort(unsigned long sk[], unsigned int da[], unsigned int n, | |||
| 1589 | unsigned int rev) { | |||
| 1590 | unsigned int i, j, k, y; | |||
| 1591 | unsigned long x; | |||
| 1592 | ||||
| 1593 | for (i = 0; i < n - 1; i++) { | |||
| 1594 | k = i; | |||
| 1595 | ||||
| 1596 | for (j = k + 1; j < n; j++) | |||
| 1597 | if (rev) { | |||
| 1598 | if (sk[j] > sk[k]) k = j; | |||
| 1599 | } | |||
| 1600 | else { | |||
| 1601 | if (sk[j] < sk[k]) k = j; | |||
| 1602 | } | |||
| 1603 | ||||
| 1604 | if (k != i) { | |||
| 1605 | x = sk[k]; sk[k] = sk[i]; sk[i] = x; | |||
| 1606 | y = da[k]; da[k] = da[i]; da[i] = y; | |||
| 1607 | } | |||
| 1608 | } | |||
| 1609 | ||||
| 1610 | return; | |||
| 1611 | } | |||
| 1612 | ||||
| 1613 | static inlineinline __attribute__((always_inline)) int reorder(unsigned int j, unsigned long cursec, | |||
| 1614 | unsigned int ihdlr, unsigned int il[], unsigned int n_ready) { | |||
| 1615 | Scsi_Cmnd *SCpnt; | |||
| 1616 | struct mscp *cpp; | |||
| 1617 | unsigned int k, n; | |||
| 1618 | unsigned int rev = FALSE0, s = TRUE1, r = TRUE1; | |||
| 1619 | unsigned int input_only = TRUE1, overlap = FALSE0; | |||
| 1620 | unsigned long sl[n_ready], pl[n_ready], ll[n_ready]; | |||
| 1621 | unsigned long maxsec = 0, minsec = ULONG_MAX(~0UL), seek = 0, iseek = 0; | |||
| 1622 | unsigned long ioseek = 0; | |||
| 1623 | ||||
| 1624 | static unsigned int flushcount = 0, batchcount = 0, sortcount = 0; | |||
| 1625 | static unsigned int readycount = 0, ovlcount = 0, inputcount = 0; | |||
| 1626 | static unsigned int readysorted = 0, revcount = 0; | |||
| 1627 | static unsigned long seeksorted = 0, seeknosort = 0; | |||
| 1628 | ||||
| 1629 | if (link_statistics && !(++flushcount % link_statistics)) | |||
| 1630 | printk("fc %d bc %d ic %d oc %d rc %d rs %d sc %d re %d"\ | |||
| 1631 | " av %ldK as %ldK.\n", flushcount, batchcount, inputcount, | |||
| 1632 | ovlcount, readycount, readysorted, sortcount, revcount, | |||
| 1633 | seeknosort / (readycount + 1), | |||
| 1634 | seeksorted / (readycount + 1)); | |||
| 1635 | ||||
| 1636 | if (n_ready <= 1) return FALSE0; | |||
| 1637 | ||||
| 1638 | for (n = 0; n < n_ready; n++) { | |||
| 1639 | k = il[n]; cpp = &HD(j)((struct hostdata *) &sh[j]->hostdata)->cp[k]; SCpnt = cpp->SCpnt; | |||
| 1640 | ||||
| 1641 | if (!(cpp->xdir == DTD_IN0x1)) input_only = FALSE0; | |||
| 1642 | ||||
| 1643 | if (SCpnt->request.sector < minsec) minsec = SCpnt->request.sector; | |||
| 1644 | if (SCpnt->request.sector > maxsec) maxsec = SCpnt->request.sector; | |||
| 1645 | ||||
| 1646 | sl[n] = SCpnt->request.sector; | |||
| 1647 | ioseek += SCpnt->request.nr_sectors; | |||
| 1648 | ||||
| 1649 | if (!n) continue; | |||
| 1650 | ||||
| 1651 | if (sl[n] < sl[n - 1]) s = FALSE0; | |||
| 1652 | if (sl[n] > sl[n - 1]) r = FALSE0; | |||
| 1653 | ||||
| 1654 | if (link_statistics) { | |||
| 1655 | if (sl[n] > sl[n - 1]) | |||
| 1656 | seek += sl[n] - sl[n - 1]; | |||
| 1657 | else | |||
| 1658 | seek += sl[n - 1] - sl[n]; | |||
| 1659 | } | |||
| 1660 | ||||
| 1661 | } | |||
| 1662 | ||||
| 1663 | if (link_statistics) { | |||
| 1664 | if (cursec > sl[0]) seek += cursec - sl[0]; else seek += sl[0] - cursec; | |||
| 1665 | } | |||
| 1666 | ||||
| 1667 | if (cursec > ((maxsec + minsec) / 2)) rev = TRUE1; | |||
| 1668 | ||||
| 1669 | if (ioseek > ((maxsec - minsec) / 2)) rev = FALSE0; | |||
| 1670 | ||||
| 1671 | if (!((rev && r) || (!rev && s))) sort(sl, il, n_ready, rev); | |||
| 1672 | ||||
| 1673 | if (!input_only) for (n = 0; n < n_ready; n++) { | |||
| 1674 | k = il[n]; cpp = &HD(j)((struct hostdata *) &sh[j]->hostdata)->cp[k]; SCpnt = cpp->SCpnt; | |||
| 1675 | ll[n] = SCpnt->request.nr_sectors; pl[n] = SCpnt->pid; | |||
| 1676 | ||||
| 1677 | if (!n) continue; | |||
| 1678 | ||||
| 1679 | if ((sl[n] == sl[n - 1]) || (!rev && ((sl[n - 1] + ll[n - 1]) > sl[n])) | |||
| 1680 | || (rev && ((sl[n] + ll[n]) > sl[n - 1]))) overlap = TRUE1; | |||
| 1681 | } | |||
| 1682 | ||||
| 1683 | if (overlap) sort(pl, il, n_ready, FALSE0); | |||
| 1684 | ||||
| 1685 | if (link_statistics) { | |||
| 1686 | if (cursec > sl[0]) iseek = cursec - sl[0]; else iseek = sl[0] - cursec; | |||
| 1687 | batchcount++; readycount += n_ready, seeknosort += seek / 1024; | |||
| 1688 | if (input_only) inputcount++; | |||
| 1689 | if (overlap) { ovlcount++; seeksorted += iseek / 1024; } | |||
| 1690 | else seeksorted += (iseek + maxsec - minsec) / 1024; | |||
| 1691 | if (rev && !r) { revcount++; readysorted += n_ready; } | |||
| 1692 | if (!rev && !s) { sortcount++; readysorted += n_ready; } | |||
| 1693 | } | |||
| 1694 | ||||
| 1695 | #if defined(DEBUG_LINKED_COMMANDS) | |||
| 1696 | if (link_statistics && (overlap || !(flushcount % link_statistics))) | |||
| 1697 | for (n = 0; n < n_ready; n++) { | |||
| 1698 | k = il[n]; cpp = &HD(j)((struct hostdata *) &sh[j]->hostdata)->cp[k]; SCpnt = cpp->SCpnt; | |||
| 1699 | printk("%s %d.%d:%d pid %ld mb %d fc %d nr %d sec %ld ns %ld"\ | |||
| 1700 | " cur %ld s:%c r:%c rev:%c in:%c ov:%c xd %d.\n", | |||
| 1701 | (ihdlr ? "ihdlr" : "qcomm"), SCpnt->channel, SCpnt->target, | |||
| 1702 | SCpnt->lun, SCpnt->pid, k, flushcount, n_ready, | |||
| 1703 | SCpnt->request.sector, SCpnt->request.nr_sectors, cursec, | |||
| 1704 | YESNO(s)((s) ? 'y' : 'n'), YESNO(r)((r) ? 'y' : 'n'), YESNO(rev)((rev) ? 'y' : 'n'), YESNO(input_only)((input_only) ? 'y' : 'n'), | |||
| 1705 | YESNO(overlap)((overlap) ? 'y' : 'n'), cpp->xdir); | |||
| 1706 | } | |||
| 1707 | #endif | |||
| 1708 | return overlap; | |||
| 1709 | } | |||
| 1710 | ||||
| 1711 | static void flush_dev(Scsi_Device *dev, unsigned long cursec, unsigned int j, | |||
| 1712 | unsigned int ihdlr) { | |||
| 1713 | Scsi_Cmnd *SCpnt; | |||
| 1714 | struct mscp *cpp; | |||
| 1715 | unsigned int k, n, n_ready = 0, il[MAX_MAILBOXES16]; | |||
| 1716 | ||||
| 1717 | for (k = 0; k < sh[j]->can_queue; k++) { | |||
| 1718 | ||||
| 1719 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[k] != READY5 && HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[k] != IN_USE1) continue; | |||
| 1720 | ||||
| 1721 | cpp = &HD(j)((struct hostdata *) &sh[j]->hostdata)->cp[k]; SCpnt = cpp->SCpnt; | |||
| 1722 | ||||
| 1723 | if (SCpnt->device != dev) continue; | |||
| 1724 | ||||
| 1725 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[k] == IN_USE1) return; | |||
| 1726 | ||||
| 1727 | il[n_ready++] = k; | |||
| 1728 | } | |||
| 1729 | ||||
| 1730 | if (reorder(j, cursec, ihdlr, il, n_ready)) n_ready = 1; | |||
| 1731 | ||||
| 1732 | for (n = 0; n < n_ready; n++) { | |||
| 1733 | k = il[n]; cpp = &HD(j)((struct hostdata *) &sh[j]->hostdata)->cp[k]; SCpnt = cpp->SCpnt; | |||
| 1734 | ||||
| 1735 | if (wait_on_busy(sh[j]->io_port, MAXLOOP10000)) { | |||
| 1736 | printk("%s: %s, target %d.%d:%d, pid %ld, mbox %d, adapter"\ | |||
| 1737 | " busy, will abort.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), (ihdlr ? "ihdlr" : "qcomm"), | |||
| 1738 | SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid, k); | |||
| 1739 | HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[k] = ABORTING6; | |||
| 1740 | continue; | |||
| 1741 | } | |||
| 1742 | ||||
| 1743 | outl(V2DEV(cpp), sh[j]->io_port + REG_OGM)((__builtin_constant_p((sh[j]->io_port + 8)) && (sh [j]->io_port + 8) < 256) ? __outlc((((cpp) ? (virt_to_phys ((void *)cpp)) : 0)),(sh[j]->io_port + 8)) : __outl((((cpp ) ? (virt_to_phys((void *)cpp)) : 0)),(sh[j]->io_port + 8) )); | |||
| 1744 | outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR)((__builtin_constant_p((sh[j]->io_port + 1)) && (sh [j]->io_port + 1) < 256) ? __outbc((0x01),(sh[j]->io_port + 1)) : __outb((0x01),(sh[j]->io_port + 1))); | |||
| 1745 | HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[k] = IN_USE1; | |||
| 1746 | } | |||
| 1747 | ||||
| 1748 | } | |||
| 1749 | ||||
| 1750 | static inlineinline __attribute__((always_inline)) void ihdlr(int irq, unsigned int j) { | |||
| 1751 | Scsi_Cmnd *SCpnt; | |||
| 1752 | unsigned int i, k, c, status, tstatus, reg, ret; | |||
| 1753 | struct mscp *spp, *cpp; | |||
| 1754 | ||||
| 1755 | if (sh[j]->irq != irq) | |||
| 1756 | panic("%s: ihdlr, irq %d, sh[j]->irq %d.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), irq, sh[j]->irq); | |||
| 1757 | ||||
| 1758 | /* Check if this board need to be serviced */ | |||
| 1759 | if (!((reg = inb(sh[j]->io_port + REG_SYS_INTR)((__builtin_constant_p((sh[j]->io_port + 3)) && (sh [j]->io_port + 3) < 256) ? __inbc(sh[j]->io_port + 3 ) : __inb(sh[j]->io_port + 3))) & IRQ_ASSERTED0x01)) return; | |||
| 1760 | ||||
| 1761 | HD(j)((struct hostdata *) &sh[j]->hostdata)->iocount++; | |||
| 1762 | ||||
| 1763 | if (do_trace) printk("%s: ihdlr, enter, irq %d, count %d.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), irq, | |||
| 1764 | HD(j)((struct hostdata *) &sh[j]->hostdata)->iocount); | |||
| 1765 | ||||
| 1766 | /* Check if this board is still busy */ | |||
| 1767 | if (wait_on_busy(sh[j]->io_port, 20 * MAXLOOP10000)) { | |||
| 1768 | outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR)((__builtin_constant_p((sh[j]->io_port + 3)) && (sh [j]->io_port + 3) < 256) ? __outbc((0x01),(sh[j]->io_port + 3)) : __outb((0x01),(sh[j]->io_port + 3))); | |||
| 1769 | printk("%s: ihdlr, busy timeout error, irq %d, reg 0x%x, count %d.\n", | |||
| 1770 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), irq, reg, HD(j)((struct hostdata *) &sh[j]->hostdata)->iocount); | |||
| 1771 | return; | |||
| 1772 | } | |||
| 1773 | ||||
| 1774 | ret = inl(sh[j]->io_port + REG_ICM)((__builtin_constant_p((sh[j]->io_port + 12)) && ( sh[j]->io_port + 12) < 256) ? __inlc(sh[j]->io_port + 12) : __inl(sh[j]->io_port + 12)); | |||
| 1775 | spp = (struct mscp *)DEV2V(ret)((ret) ? (phys_to_virt((unsigned long)ret)) : 0); | |||
| 1776 | cpp = spp; | |||
| 1777 | ||||
| 1778 | /* Clear interrupt pending flag */ | |||
| 1779 | outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR)((__builtin_constant_p((sh[j]->io_port + 3)) && (sh [j]->io_port + 3) < 256) ? __outbc((0x01),(sh[j]->io_port + 3)) : __outb((0x01),(sh[j]->io_port + 3))); | |||
| 1780 | ||||
| 1781 | #if defined(DEBUG_GENERATE_ABORTS) | |||
| 1782 | if ((HD(j)((struct hostdata *) &sh[j]->hostdata)->iocount > 500) && ((HD(j)((struct hostdata *) &sh[j]->hostdata)->iocount % 500) < 3)) return; | |||
| 1783 | #endif | |||
| 1784 | ||||
| 1785 | /* Find the mailbox to be serviced on this board */ | |||
| 1786 | i = cpp - HD(j)((struct hostdata *) &sh[j]->hostdata)->cp; | |||
| 1787 | ||||
| 1788 | if (cpp < HD(j)((struct hostdata *) &sh[j]->hostdata)->cp || cpp >= HD(j)((struct hostdata *) &sh[j]->hostdata)->cp + sh[j]->can_queue | |||
| 1789 | || i >= sh[j]->can_queue) | |||
| 1790 | panic("%s: ihdlr, invalid mscp bus address %p, cp0 %p.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), | |||
| 1791 | (void *)ret, HD(j)((struct hostdata *) &sh[j]->hostdata)->cp); | |||
| 1792 | ||||
| 1793 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == IGNORE4) { | |||
| 1794 | HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] = FREE0; | |||
| 1795 | return; | |||
| 1796 | } | |||
| 1797 | else if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == LOCKED2) { | |||
| 1798 | HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] = FREE0; | |||
| 1799 | printk("%s: ihdlr, mbox %d unlocked, count %d.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i, | |||
| 1800 | HD(j)((struct hostdata *) &sh[j]->hostdata)->iocount); | |||
| 1801 | return; | |||
| 1802 | } | |||
| 1803 | else if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == FREE0) { | |||
| 1804 | printk("%s: ihdlr, mbox %d is free, count %d.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i, | |||
| 1805 | HD(j)((struct hostdata *) &sh[j]->hostdata)->iocount); | |||
| 1806 | return; | |||
| 1807 | } | |||
| 1808 | else if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] == IN_RESET3) | |||
| 1809 | printk("%s: ihdlr, mbox %d is in reset.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i); | |||
| 1810 | else if (HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] != IN_USE1) | |||
| 1811 | panic("%s: ihdlr, mbox %d, invalid cp_stat: %d.\n", | |||
| 1812 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i, HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i]); | |||
| 1813 | ||||
| 1814 | HD(j)((struct hostdata *) &sh[j]->hostdata)->cp_stat[i] = FREE0; | |||
| 1815 | SCpnt = cpp->SCpnt; | |||
| 1816 | ||||
| 1817 | if (SCpnt == NULL((void *) 0)) panic("%s: ihdlr, mbox %d, SCpnt == NULL.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i); | |||
| 1818 | ||||
| 1819 | if (SCpnt->host_scribble == NULL((void *) 0)) | |||
| 1820 | panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i, | |||
| 1821 | SCpnt->pid, SCpnt); | |||
| 1822 | ||||
| 1823 | if (*(unsigned int *)SCpnt->host_scribble != i) | |||
| 1824 | panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d.\n", | |||
| 1825 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble); | |||
| 1826 | ||||
| 1827 | if (linked_comm && SCpnt->device->queue_depth > 2 | |||
| 1828 | && TLDEV(SCpnt->device->type)((SCpnt->device->type) == 0x00 || (SCpnt->device-> type) == 0x05)) | |||
| 1829 | flush_dev(SCpnt->device, SCpnt->request.sector, j, TRUE1); | |||
| 1830 | ||||
| 1831 | tstatus = status_byte(spp->target_status)(((spp->target_status) >> 1) & 0x1f); | |||
| 1832 | ||||
| 1833 | #if defined(DEBUG_GENERATE_ERRORS) | |||
| 1834 | if ((HD(j)((struct hostdata *) &sh[j]->hostdata)->iocount > 500) && ((HD(j)((struct hostdata *) &sh[j]->hostdata)->iocount % 200) < 2)) | |||
| 1835 | spp->adapter_status = 0x01; | |||
| 1836 | #endif | |||
| 1837 | ||||
| 1838 | switch (spp->adapter_status) { | |||
| 1839 | case ASOK0x00: /* status OK */ | |||
| 1840 | ||||
| 1841 | /* Forces a reset if a disk drive keeps returning BUSY */ | |||
| 1842 | if (tstatus == BUSY0x04 && SCpnt->device->type != TYPE_TAPE0x01) | |||
| 1843 | status = DID_ERROR0x07 << 16; | |||
| 1844 | ||||
| 1845 | /* If there was a bus reset, redo operation on each target */ | |||
| 1846 | else if (tstatus != GOOD0x00 && SCpnt->device->type == TYPE_DISK0x00 | |||
| 1847 | && HD(j)((struct hostdata *) &sh[j]->hostdata)->target_redo[SCpnt->target][SCpnt->channel]) | |||
| 1848 | status = DID_BUS_BUSY0x02 << 16; | |||
| 1849 | ||||
| 1850 | /* Works around a flaw in scsi.c */ | |||
| 1851 | else if (tstatus == CHECK_CONDITION0x01 | |||
| 1852 | && SCpnt->device->type == TYPE_DISK0x00 | |||
| 1853 | && (SCpnt->sense_buffer[2] & 0xf) == RECOVERED_ERROR0x01) | |||
| 1854 | status = DID_BUS_BUSY0x02 << 16; | |||
| 1855 | ||||
| 1856 | else | |||
| 1857 | status = DID_OK0x00 << 16; | |||
| 1858 | ||||
| 1859 | if (tstatus == GOOD0x00) | |||
| 1860 | HD(j)((struct hostdata *) &sh[j]->hostdata)->target_redo[SCpnt->target][SCpnt->channel] = FALSE0; | |||
| 1861 | ||||
| 1862 | if (spp->target_status && SCpnt->device->type == TYPE_DISK0x00) | |||
| 1863 | printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\ | |||
| 1864 | "target_status 0x%x, sense key 0x%x.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), | |||
| 1865 | SCpnt->channel, SCpnt->target, SCpnt->lun, | |||
| 1866 | SCpnt->pid, spp->target_status, | |||
| 1867 | SCpnt->sense_buffer[2]); | |||
| 1868 | ||||
| 1869 | HD(j)((struct hostdata *) &sh[j]->hostdata)->target_to[SCpnt->target][SCpnt->channel] = 0; | |||
| 1870 | ||||
| 1871 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->last_retried_pid == SCpnt->pid) HD(j)((struct hostdata *) &sh[j]->hostdata)->retries = 0; | |||
| 1872 | ||||
| 1873 | break; | |||
| 1874 | case ASST0x91: /* Selection Time Out */ | |||
| 1875 | ||||
| 1876 | if (HD(j)((struct hostdata *) &sh[j]->hostdata)->target_to[SCpnt->target][SCpnt->channel] > 1) | |||
| 1877 | status = DID_ERROR0x07 << 16; | |||
| 1878 | else { | |||
| 1879 | status = DID_TIME_OUT0x03 << 16; | |||
| 1880 | HD(j)((struct hostdata *) &sh[j]->hostdata)->target_to[SCpnt->target][SCpnt->channel]++; | |||
| 1881 | } | |||
| 1882 | ||||
| 1883 | break; | |||
| 1884 | ||||
| 1885 | /* Perform a limited number of internal retries */ | |||
| 1886 | case 0x93: /* Unexpected bus free */ | |||
| 1887 | case 0x94: /* Target bus phase sequence failure */ | |||
| 1888 | case 0x96: /* Illegal SCSI command */ | |||
| 1889 | case 0xa3: /* SCSI bus reset error */ | |||
| 1890 | ||||
| 1891 | for (c = 0; c <= sh[j]->max_channel; c++) | |||
| 1892 | for (k = 0; k < sh[j]->max_id; k++) | |||
| 1893 | HD(j)((struct hostdata *) &sh[j]->hostdata)->target_redo[k][c] = TRUE1; | |||
| 1894 | ||||
| 1895 | ||||
| 1896 | case 0x92: /* Data over/under-run */ | |||
| 1897 | ||||
| 1898 | if (SCpnt->device->type != TYPE_TAPE0x01 | |||
| 1899 | && HD(j)((struct hostdata *) &sh[j]->hostdata)->retries < MAX_INTERNAL_RETRIES64) { | |||
| 1900 | ||||
| 1901 | #if defined(DID_SOFT_ERROR) | |||
| 1902 | status = DID_SOFT_ERROR << 16; | |||
| 1903 | #else | |||
| 1904 | status = DID_BUS_BUSY0x02 << 16; | |||
| 1905 | #endif | |||
| 1906 | ||||
| 1907 | HD(j)((struct hostdata *) &sh[j]->hostdata)->retries++; | |||
| 1908 | HD(j)((struct hostdata *) &sh[j]->hostdata)->last_retried_pid = SCpnt->pid; | |||
| 1909 | } | |||
| 1910 | else | |||
| 1911 | status = DID_ERROR0x07 << 16; | |||
| 1912 | ||||
| 1913 | break; | |||
| 1914 | case 0x01: /* Invalid command */ | |||
| 1915 | case 0x02: /* Invalid parameters */ | |||
| 1916 | case 0x03: /* Invalid data list */ | |||
| 1917 | case 0x84: /* SCSI bus abort error */ | |||
| 1918 | case 0x9b: /* Auto request sense error */ | |||
| 1919 | case 0x9f: /* Unexpected command complete message error */ | |||
| 1920 | case 0xff: /* Invalid parameter in the S/G list */ | |||
| 1921 | default: | |||
| 1922 | status = DID_ERROR0x07 << 16; | |||
| 1923 | break; | |||
| 1924 | } | |||
| 1925 | ||||
| 1926 | SCpnt->result = status | spp->target_status; | |||
| 1927 | ||||
| 1928 | #if defined(DEBUG_INTERRUPT) | |||
| 1929 | if (SCpnt->result || do_trace) | |||
| 1930 | #else | |||
| 1931 | if ((spp->adapter_status != ASOK0x00 && HD(j)((struct hostdata *) &sh[j]->hostdata)->iocount > 1000) || | |||
| 1932 | (spp->adapter_status != ASOK0x00 && | |||
| 1933 | spp->adapter_status != ASST0x91 && HD(j)((struct hostdata *) &sh[j]->hostdata)->iocount <= 1000) || | |||
| 1934 | do_trace || msg_byte(spp->target_status)(((spp->target_status) >> 8) & 0xff)) | |||
| 1935 | #endif | |||
| 1936 | printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\ | |||
| 1937 | " target %d.%d:%d, pid %ld, reg 0x%x, count %d.\n", | |||
| 1938 | BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), i, spp->adapter_status, spp->target_status, | |||
| 1939 | SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid, | |||
| 1940 | reg, HD(j)((struct hostdata *) &sh[j]->hostdata)->iocount); | |||
| 1941 | ||||
| 1942 | /* Set the command state to inactive */ | |||
| 1943 | SCpnt->host_scribble = NULL((void *) 0); | |||
| 1944 | ||||
| 1945 | SCpnt->scsi_done(SCpnt); | |||
| 1946 | ||||
| 1947 | if (do_trace) printk("%s: ihdlr, exit, irq %d, count %d.\n", BN(j)(((struct hostdata *) &sh[j]->hostdata)->board_name ), irq, | |||
| 1948 | HD(j)((struct hostdata *) &sh[j]->hostdata)->iocount); | |||
| 1949 | ||||
| 1950 | return; | |||
| 1951 | } | |||
| 1952 | ||||
| 1953 | static void do_interrupt_handler(int irq, void *shap, struct pt_regs *regs) { | |||
| 1954 | unsigned int j; | |||
| 1955 | IRQ_FLAGSunsigned long irq_flags; | |||
| 1956 | SPIN_FLAGS | |||
| 1957 | ||||
| 1958 | /* Check if the interrupt must be processed by this handler */ | |||
| 1959 | if ((j = (unsigned int)((char *)shap - sha)) >= num_boards) return; | |||
| 1960 | ||||
| 1961 | SPIN_LOCK_SAVE | |||
| 1962 | IRQ_LOCK_SAVEdo {__asm__ __volatile__("pushf ; pop %0" : "=r" (irq_flags): :"memory"); __asm__ __volatile__ ("cli": : :"memory");} while (0); | |||
| 1963 | ihdlr(irq, j); | |||
| 1964 | IRQ_UNLOCK_RESTOREdo {__asm__ __volatile__("push %0 ; popf": :"g" (irq_flags):"memory" );} while (0); | |||
| 1965 | SPIN_UNLOCK_RESTORE | |||
| 1966 | } | |||
| 1967 | ||||
| 1968 | int u14_34f_release(struct Scsi_Host *shpnt) { | |||
| 1969 | unsigned int i, j; | |||
| 1970 | IRQ_FLAGSunsigned long irq_flags; | |||
| 1971 | ||||
| 1972 | IRQ_LOCK_SAVEdo {__asm__ __volatile__("pushf ; pop %0" : "=r" (irq_flags): :"memory"); __asm__ __volatile__ ("cli": : :"memory");} while (0); | |||
| 1973 | ||||
| 1974 | for (j = 0; sh[j] != NULL((void *) 0) && sh[j] != shpnt; j++); | |||
| 1975 | ||||
| 1976 | if (sh[j] == NULL((void *) 0)) panic("%s: release, invalid Scsi_Host pointer.\n", | |||
| 1977 | driver_name); | |||
| 1978 | ||||
| 1979 | for (i = 0; i < sh[j]->can_queue; i++) | |||
| 1980 | if ((&HD(j)((struct hostdata *) &sh[j]->hostdata)->cp[i])->sglist) kfreelinux_kfree((&HD(j)((struct hostdata *) &sh[j]->hostdata)->cp[i])->sglist); | |||
| 1981 | ||||
| 1982 | free_irq(sh[j]->irq, &sha[j]); | |||
| 1983 | ||||
| 1984 | if (sh[j]->dma_channel != NO_DMA0xff) free_dma(sh[j]->dma_channel); | |||
| 1985 | ||||
| 1986 | release_region(sh[j]->io_port, sh[j]->n_io_port); | |||
| 1987 | scsi_unregister(sh[j]); | |||
| 1988 | IRQ_UNLOCK_RESTOREdo {__asm__ __volatile__("push %0 ; popf": :"g" (irq_flags):"memory" );} while (0); | |||
| 1989 | return FALSE0; | |||
| 1990 | } | |||
| 1991 | ||||
| 1992 | #if defined(MODULE) | |||
| 1993 | Scsi_Host_Template driver_template = ULTRASTOR_14_34F{ name: "UltraStor 14F/34F rev. " "4.33.00" " ", detect: u14_34f_detect , release: u14_34f_release, queuecommand: u14_34f_queuecommand , abort: u14_34f_old_abort, reset: u14_34f_old_reset, bios_param : u14_34f_biosparam, this_id: 7, unchecked_isa_dma: 1, use_clustering : 1 }; | |||
| 1994 | ||||
| 1995 | #include "scsi_module.c" | |||
| 1996 | #endif |